Patchwork Handle PIEs in libbacktrace

login
register
mail settings
Submitter Jakub Jelinek
Date Dec. 6, 2013, 9:53 a.m.
Message ID <20131206095337.GH892@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/297661/
State New
Headers show

Comments

Jakub Jelinek - Dec. 6, 2013, 9:53 a.m.
On Fri, Dec 06, 2013 at 12:53:02PM +0400, Alexey Samsonov wrote:
> ASan calls this function only for global variables (not functions). It
> is needed because
> we use a different machinery to pass global names to ASan runtime - we
> register globals
> by a call from instrumented code, which also tells runtime the
> (mangled) global name.

Well, given that it demangled just fine even function names, I guess it
calls it always and just it would do nothing for function names demangled
already by llvm-symbolizer if using the external symbolizer.

> OTOH, in TSan we rely on symbolization to demangle names of global variables.

Then we need something like following, with which all tests pass.  I'm not
using Demangle method from the symbolizer, because getting it requires a
mutex that is already held.

The alternative would be to just (perhaps under #ifdef SANITIZER_CP_DEMANGLE)
compile in libiberty/cp-demangle.c (similarly how libstdc++ compiles it in)
as part of libsanitizer/libiberty/ or even libsanitizer/libbacktrace/,
and tweak it, so that like libsanitizer/libbacktrace it uses internal_memcpy
etc. and uses InternalAlloc/InternalFree.  The problem is that cp-demangle.c
uses only realloc and free, and doesn't provide any hint on how large the
previously allocated memory chunk is.  So, either there is some easy way
how to query the size of InternalAlloc returned allocation, or we would need
to allocate uptr extra and store there number of bytes allocated
and emulate realloc/free that way.



	Jakub
Ian Taylor - Dec. 6, 2013, 2:40 p.m.
On Fri, Dec 6, 2013 at 1:53 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>
> The alternative would be to just (perhaps under #ifdef SANITIZER_CP_DEMANGLE)
> compile in libiberty/cp-demangle.c (similarly how libstdc++ compiles it in)
> as part of libsanitizer/libiberty/ or even libsanitizer/libbacktrace/,
> and tweak it, so that like libsanitizer/libbacktrace it uses internal_memcpy
> etc. and uses InternalAlloc/InternalFree.  The problem is that cp-demangle.c
> uses only realloc and free, and doesn't provide any hint on how large the
> previously allocated memory chunk is.  So, either there is some easy way
> how to query the size of InternalAlloc returned allocation, or we would need
> to allocate uptr extra and store there number of bytes allocated
> and emulate realloc/free that way.

There was a recent buggy patch to the demangler that added calls to
malloc and realloc (2013-10-25 Gary Benson <gbenson@redhat.com>).
That patch must be fixed or reverted before the 4.9 release.  The main
code in the demangler must not call malloc/realloc.

When that patch is fixed, you can use the cplus_demangle_v3_callback
function to get a demangler that never calls malloc.

Ian

Patch

--- libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc.jj	2013-12-05 12:04:28.000000000 +0100
+++ libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc	2013-12-06 10:36:02.285059188 +0100
@@ -25,6 +25,15 @@ 
 # endif
 #endif
 
+// C++ demangling function, as required by Itanium C++ ABI. This is weak,
+// because we do not require a C++ ABI library to be linked to a program
+// using sanitizers; if it's not present, we'll just use the mangled name.
+namespace __cxxabiv1 {
+  extern "C" SANITIZER_WEAK_ATTRIBUTE
+  char *__cxa_demangle(const char *mangled, char *buffer,
+		       size_t *length, int *status);
+}
+
 namespace __sanitizer {
 
 #if SANITIZER_LIBBACKTRACE
@@ -39,6 +48,19 @@  struct SymbolizeCodeData {
   uptr module_offset;
 };
 
+char *MaybeDemangleAndDup(const char *symname) {
+  const char *demangled = symname;
+  if (symname[0] == '_' && symname[1] == 'Z' && __cxxabiv1::__cxa_demangle) {
+    demangled = __cxxabiv1::__cxa_demangle(symname, 0, 0, 0);
+    if (demangled == NULL)
+      demangled = symname;
+  }                      
+  char *ret = internal_strdup(demangled);
+  if (demangled != symname)
+    __builtin_free ((void *) demangled);
+  return ret;
+}
+
 extern "C" {
 static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
                                        const char *filename, int lineno,
@@ -49,7 +71,7 @@  static int SymbolizeCodePCInfoCallback(v
     info->Clear();
     info->FillAddressAndModuleInfo(addr, cdata->module_name,
                                    cdata->module_offset);
-    info->function = internal_strdup(function);
+    info->function = MaybeDemangleAndDup(function);
     if (filename)
       info->file = internal_strdup(filename);
     info->line = lineno;
@@ -67,7 +89,7 @@  static void SymbolizeCodeCallback(void *
     info->Clear();
     info->FillAddressAndModuleInfo(addr, cdata->module_name,
                                    cdata->module_offset);
-    info->function = internal_strdup(symname);
+    info->function = MaybeDemangleAndDup(symname);
     cdata->n_frames = 1;
   }
 }
@@ -76,7 +98,7 @@  static void SymbolizeDataCallback(void *
                                   uintptr_t symval, uintptr_t symsize) {
   DataInfo *info = (DataInfo *)vdata;
   if (symname && symval) {
-    info->name = internal_strdup(symname);
+    info->name = MaybeDemangleAndDup(symname);
     info->start = symval;
     info->size = symsize;
   }