diff options
author | Jari Vetoniemi <mailroxas@gmail.com> | 2018-04-19 18:29:09 +0300 |
---|---|---|
committer | Jari Vetoniemi <mailroxas@gmail.com> | 2018-04-19 18:29:09 +0300 |
commit | a846dc40e4596fbf3d061392149a1676e7cdc304 (patch) | |
tree | 5076f8413f061d76e24cb20466455541227dc442 /src | |
parent | 0dc63f8fa9be289a196c03e4ee668ff9f891c483 (diff) |
wrapper/linker: __cxa_demangle from linker
We want to use android's libstdc++, so we need to pass __cxa_demangle
from linker.
Diffstat (limited to 'src')
-rw-r--r-- | src/linker/linker.c | 12 | ||||
-rw-r--r-- | src/wrapper/wrapper.c | 22 | ||||
-rw-r--r-- | src/wrapper/wrapper.h | 3 |
3 files changed, 29 insertions, 8 deletions
diff --git a/src/linker/linker.c b/src/linker/linker.c index b5b782d..f91316c 100644 --- a/src/linker/linker.c +++ b/src/linker/linker.c @@ -1271,10 +1271,16 @@ soinfo *apkenv_find_library(const char *name, const bool try_glibc) } TRACE("[ %5d '%s' has not been loaded yet. Locating...]\n", apkenv_pid, name); - si = apkenv_load_library(name, try_glibc); - if(si == NULL) + if (!(si = apkenv_load_library(name, try_glibc)) || !(si = apkenv_init_library(si))) return NULL; - return apkenv_init_library(si); + + if (!strstr(bname, "libstdc++.so")) { + Elf32_Sym *sym = apkenv_lookup_in_library(si, "__cxa_demangle"); + if (sym && ELF32_ST_BIND(sym->st_info) == STB_GLOBAL && sym->st_shndx != 0) + wrapper_set_cpp_demangler((void*)(intptr_t)(sym->st_value + si->base)); + } + + return si; } /* TODO: diff --git a/src/wrapper/wrapper.c b/src/wrapper/wrapper.c index 2d61519..51d17a6 100644 --- a/src/wrapper/wrapper.c +++ b/src/wrapper/wrapper.c @@ -2,11 +2,10 @@ #include <stdio.h> #include <stdarg.h> #include <stdbool.h> -#include <stdint.h> #include <stddef.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> -#include <dlfcn.h> #include <assert.h> #include <sys/mman.h> #include "verbose.h" @@ -61,17 +60,33 @@ trace(const char *const symbol) char *demangled; static __thread char *data; static __thread size_t size; + static __thread bool skip_trace; + + // Avoid infinite recursion and tracing calls made by __cxa_demangle.fun + if (skip_trace) + return; + + skip_trace = true; if ((demangled = __cxa_demangle.fun(symbol, data, &size, &status))) { data = (data != demangled ? demangled : data); verbose("trace: %s", demangled); return; } + skip_trace = false; } verbose("trace: %s", symbol); } #endif +void +wrapper_set_cpp_demangler(void *function) +{ +#ifdef WRAPPER_TRACE + __cxa_demangle.ptr = function; +#endif +} + void* wrapper_create(const char *const symbol, void *function) { @@ -83,9 +98,6 @@ wrapper_create(const char *const symbol, void *function) } #ifdef WRAPPER_TRACE - if (!__cxa_demangle.ptr) - __cxa_demangle.ptr = dlsym(RTLD_DEFAULT, "__cxa_demangle"); - const size_t sz = &wrapper_end - &wrapper_start; unsigned char *fun = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); assert(fun != MAP_FAILED); diff --git a/src/wrapper/wrapper.h b/src/wrapper/wrapper.h index c75ef33..c28c71e 100644 --- a/src/wrapper/wrapper.h +++ b/src/wrapper/wrapper.h @@ -2,3 +2,6 @@ void* wrapper_create(const char *const symbol, void *function); + +void +wrapper_set_cpp_demangler(void *function); |