diff options
author | Tor Lillqvist <tml@iki.fi> | 2012-09-13 13:02:53 +0300 |
---|---|---|
committer | Tor Lillqvist <tml@iki.fi> | 2012-09-24 17:32:03 +0300 |
commit | bc9a4133af3cf49495f616bf3eff9d56e55ed214 (patch) | |
tree | 3f5e0fa5536f0dba74a316ad251ed227284fb489 | |
parent | d08fa24320cd4c6ad16e88eaa2f7c2d03ac4bbe1 (diff) |
Further hacks to use an add-on Bionic linker copy, unfinished
private/tml/android-use-bionic-linker-copy
Change-Id: I7c7e06ad172fc95912958c1f46baa74071f5d613
-rw-r--r-- | android/Bootstrap/src/org/libreoffice/android/Bootstrap.java | 2 | ||||
-rw-r--r-- | sal/android/bionic/linker/dlfcn.c | 74 | ||||
-rw-r--r-- | sal/android/bionic/linker/linker.cxx | 10 | ||||
-rw-r--r-- | sal/android/bionic/linker/linker.h | 2 | ||||
-rw-r--r-- | sal/android/bionic/linker/linker_debug.h | 3 | ||||
-rw-r--r-- | sal/android/lo-bootstrap.c | 99 |
6 files changed, 133 insertions, 57 deletions
diff --git a/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java b/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java index b97adfb6261a..db8745b8863a 100644 --- a/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java +++ b/android/Bootstrap/src/org/libreoffice/android/Bootstrap.java @@ -292,8 +292,6 @@ public class Bootstrap extends NativeActivity // time by the package manager. static { System.loadLibrary("lo-bootstrap"); - System.loadLibrary("gnustl_shared"); - System.loadLibrary("libotouchlo"); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/android/bionic/linker/dlfcn.c b/sal/android/bionic/linker/dlfcn.c index a476092daec1..04eb8f7ffa3b 100644 --- a/sal/android/bionic/linker/dlfcn.c +++ b/sal/android/bionic/linker/dlfcn.c @@ -19,8 +19,6 @@ #include "linker.h" #include "linker_format.h" -/* This file hijacks the symbols stubbed out in libdl.so. */ - #define DL_SUCCESS 0 #define DL_ERR_CANNOT_LOAD_LIBRARY 1 #define DL_ERR_INVALID_LIBRARY_HANDLE 2 @@ -169,24 +167,45 @@ int __lo_dlclose(void* handle) { return result; } -/* Dummy replacement for the libdl_info in the real system dlfcn.c. */ +// 0000000000 11111111112 222222222 3 +// 0123456789 01234567890 123456789 0 +#define LO_LIBLO_BOOTSTRAP_STRTAB \ + "lo_dlopen\0lo_dlclose\0lo_dlsym\0lo_dladdr\0" void __lo_dummy_foo(void) { } -#define ANDROID_LIBDL_STRTAB \ - "__lo_dummy_foo\0" +/* The wrappers in lo-bootstrap.c */ +extern void *lo_dlopen(const char *path, int flags); +extern void *lo_dlsym(void *handle, const char *symbol); +extern int lo_dlclose(void *handle); +extern int lo_dladdr(void *addr, Dl_info *info); -static Elf32_Sym libdl_symtab[] = { - // total length of libdl_info.strtab, including trailing 0 +static Elf32_Sym liblo_bootstrap_symtab[] = { + // total length of liblo_bootstrap_info.strtab, including trailing 0 // This is actually the the STH_UNDEF entry. Technically, it's // supposed to have st_name == 0, but instead, it points to an index // in the strtab with a \0 to make iterating through the symtab easier. - { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, + { st_name: sizeof(LO_LIBLO_BOOTSTRAP_STRTAB) - 1, + }, + { st_name: 0, // starting index of the name in liblo_bootstrap_info.strtab + st_value: (Elf32_Addr) &lo_dlopen, + st_info: STB_GLOBAL << 4, + st_shndx: 1, }, - { st_name: 0, // starting index of the name in libdl_info.strtab - st_value: (Elf32_Addr) &__lo_dummy_foo, + { st_name: 10, + st_value: (Elf32_Addr) &lo_dlclose, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 21, + st_value: (Elf32_Addr) &lo_dlsym, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 30, + st_value: (Elf32_Addr) &lo_dladdr, st_info: STB_GLOBAL << 4, st_shndx: 1, }, @@ -194,35 +213,32 @@ static Elf32_Sym libdl_symtab[] = { /* Fake out a hash table with a single bucket. * A search of the hash table will look through - * libdl_symtab starting with index [1], then - * use libdl_chains to find the next index to - * look at. libdl_chains should be set up to - * walk through every element in libdl_symtab, + * liblo_bootstrap_symtab starting with index [1], then + * use liblo_bootstrap_chains to find the next index to + * look at. liblo_bootstrap_chains should be set up to + * walk through every element in liblo_bootstrap_symtab, * and then end with 0 (sentinel value). * - * I.e., libdl_chains should look like + * I.e., liblo_bootstrap_chains should look like * { 0, 2, 3, ... N, 0 } where N is the number - * of actual symbols, or nelems(libdl_symtab)-1 - * (since the first element of libdl_symtab is not + * of actual symbols, or nelems(liblo_bootstrap_symtab)-1 + * (since the first element of liblo_bootstrap_symtab is not * a real symbol). * * (see _elf_lookup()) - * - * Note that adding any new symbols here requires - * stubbing them out in libdl. */ -static unsigned libdl_buckets[1] = { 1 }; -static unsigned libdl_chains[3] = { 0, 2, 0 }; +static unsigned liblo_bootstrap_buckets[1] = { 1 }; +static unsigned liblo_bootstrap_chains[5] = { 0, 2, 3, 4, 0 }; -soinfo libdl_info = { - name: "lo-dummy-libdl.so", +soinfo liblo_bootstrap_info = { + name: "liblo-bootstrap.so", flags: FLAG_LINKED, - strtab: ANDROID_LIBDL_STRTAB, - symtab: libdl_symtab, + strtab: LO_LIBLO_BOOTSTRAP_STRTAB, + symtab: liblo_bootstrap_symtab, nbucket: 1, - nchain: 3, - bucket: libdl_buckets, - chain: libdl_chains, + nchain: 5, + bucket: liblo_bootstrap_buckets, + chain: liblo_bootstrap_chains, }; diff --git a/sal/android/bionic/linker/linker.cxx b/sal/android/bionic/linker/linker.cxx index d43eedbf9be7..edcbf5e70d21 100644 --- a/sal/android/bionic/linker/linker.cxx +++ b/sal/android/bionic/linker/linker.cxx @@ -79,10 +79,10 @@ static int soinfo_link_image(soinfo *si); static int socount = 0; static soinfo sopool[SO_MAX]; static soinfo *freelist = NULL; -static soinfo *solist = &libdl_info; -static soinfo *sonext = &libdl_info; +static soinfo *solist = &liblo_bootstrap_info; +static soinfo *sonext = &liblo_bootstrap_info; #if ALLOW_SYMBOLS_FROM_MAIN -static soinfo *somain; /* main process, always the one after libdl_info */ +static soinfo *somain; /* main process, always the one after liblo_bootstrap_info */ #endif @@ -90,7 +90,7 @@ static char ldpaths_buf[LDPATH_BUFSIZE]; static const char *ldpaths[LDPATH_MAX + 1]; #if LINKER_DEBUG -int debug_verbosity; +int debug_verbosity = 2; #endif static int pid; @@ -300,7 +300,7 @@ static void soinfo_free(soinfo* si) } /* prev will never be NULL, because the first entry in solist is - always the static libdl_info. + always the static liblo_bootstrap_info. */ prev->next = si->next; if (si == sonext) sonext = prev; diff --git a/sal/android/bionic/linker/linker.h b/sal/android/bionic/linker/linker.h index 59c9530d6429..f826746ea027 100644 --- a/sal/android/bionic/linker/linker.h +++ b/sal/android/bionic/linker/linker.h @@ -169,7 +169,7 @@ struct soinfo }; -extern soinfo libdl_info; +extern soinfo liblo_bootstrap_info; #include <asm/elf.h> diff --git a/sal/android/bionic/linker/linker_debug.h b/sal/android/bionic/linker/linker_debug.h index 48a7abf0d2c1..49919931a37e 100644 --- a/sal/android/bionic/linker/linker_debug.h +++ b/sal/android/bionic/linker/linker_debug.h @@ -33,6 +33,9 @@ #ifndef LINKER_DEBUG #error LINKER_DEBUG should be defined to either 1 or 0 in Android.mk +#else +#undef LINKER_DEBUG +#define LINKER_DEBUG 1 #endif /* set LINKER_DEBUG_TO_LOG to 1 to send the logs to logcat, diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c index 4703b900a3f9..02229a153b66 100644 --- a/sal/android/lo-bootstrap.c +++ b/sal/android/lo-bootstrap.c @@ -69,6 +69,9 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) +/* The functions from our tweaked copy of the run-time linker, in + * sal/android/bionic/linker + */ extern void *__lo_dlopen(const char *path, int flags); extern const char *__lo_dlerror(void); extern void *__lo_dlsym(void *handle, const char *symbol); @@ -76,12 +79,6 @@ extern int __lo_dlclose(void *handle); extern int __lo_dladdr(void *addr, Dl_info *info); extern void __lo_linker_init(void); -#define dlopen __lo_dlopen -#define dlerror __lo_dlerror -#define dlsym __lo_dlsym -#define dlclose __lo_dlclose -#define dladdr __lo_dladdr - struct engine { int dummy; }; @@ -869,6 +866,13 @@ lo_dlopen(const char *library) struct timeval tv0, tv1, tvdiff; + FILE *maps; + char line[200]; + + /* libdl.so is special */ + if (strcmp(library, "libdl.so") == 0) + return (void *) 42; /* ??? */ + rover = loaded_libraries; while (rover != NULL && strcmp(rover->name, library) != 0) @@ -923,16 +927,48 @@ lo_dlopen(const char *library) } free_ptrarray((void **) needed); + /* Find out if the real system run-time linker has loaded it */ + maps = fopen("/proc/self/maps", "r"); + if (maps == NULL) { + LOGE("lo_dladdr: Could not open /proc/self/maps: %s", strerror(errno)); + return NULL; + } + + found = 0; + while (fgets(line, sizeof(line), maps) != NULL && + line[strlen(line)-1] == '\n') { + char file[sizeof(line)]; + file[0] = '\0'; + if (sscanf(line, "%*x-%*x %*s %*x %*x:%*x %*d %[^\n]", file) == 1) { + if (strcmp(file, full_name) == 0) { + found = 1; + break; + } + } + } + fclose(maps); + gettimeofday(&tv0, NULL); - p = dlopen(full_name, RTLD_LOCAL); + if (found) { + /* It is already mapped, but it wasn't in our loaded_libraries list, + * presumably it's the system run-time linker that has loaded it. + */ + LOGI("lo_dlopen: Using system dlopen()"); + p = dlopen(full_name, RTLD_LOCAL); + } else { + /* Call our tweaked copy of the run-time linker to load it. */ + LOGI("lo_dlopen: Using our tweaked__lo_dlopen()"); + p = __lo_dlopen(full_name, RTLD_LOCAL); + } gettimeofday(&tv1, NULL); timersub(&tv1, &tv0, &tvdiff); - LOGI("dlopen(%s) = %p, %ld.%03lds", + LOGI("%s(%s) = %p, %ld.%03lds", + (found ? "dlopen" : "__lo_dlopen"), full_name, p, (long) tvdiff.tv_sec, (long) tvdiff.tv_usec / 1000); free(full_name); if (p == NULL) - LOGE("lo_dlopen: Error from dlopen(%s): %s", library, dlerror()); + LOGE("lo_dlopen: Error from __lo_dlopen(%s): %s", library, (found ? dlerror() : __lo_dlerror())); new_loaded_lib = malloc(sizeof(*new_loaded_lib)); new_loaded_lib->name = strdup(library); @@ -949,10 +985,20 @@ void * lo_dlsym(void *handle, const char *symbol) { - void *p = dlsym(handle, symbol); - /* LOGI("dlsym(%p, %s) = %p", handle, symbol, p); */ + int used_system_dlsym = 0; + void *p; + + p = __lo_dlsym(handle, symbol); + LOGI("__lo_dlsym(%p, %s) = %p", handle, symbol, p); + + if (p == NULL) { + used_system_dlsym = 1; + p = dlsym(handle, symbol); + LOGI("dlsym(%p, %s) = %p", handle, symbol, p); + } + if (p == NULL) - LOGE("lo_dlsym: %s", dlerror()); + LOGE("lo_dlsym: %s", (used_system_dlsym ? dlerror() : __lo_dlerror())); return p; } @@ -966,12 +1012,17 @@ lo_dladdr(void *addr, int result; int found; - result = dladdr(addr, info); + result = __lo_dladdr(addr, info); + LOGI("__lo_dladdr(%p) = 0", addr); + if (result == 0) { - /* LOGI("dladdr(%p) = 0", addr); */ - return 0; + result = dladdr(addr, info); + LOGI("dladdr(%p) = 0", addr); } + if (result == 0) + return 0; + maps = fopen("/proc/self/maps", "r"); if (maps == NULL) { LOGE("lo_dladdr: Could not open /proc/self/maps: %s", strerror(errno)); @@ -1368,13 +1419,21 @@ patch(const char *symbol, * containing lo_main() already, libgnustl_shared.so will have * been brought in, too. */ - libgnustl_shared = dlopen("libgnustl_shared.so", RTLD_LOCAL); + libgnustl_shared = __lo_dlopen("libgnustl_shared.so", RTLD_LOCAL); + + if (libgnustl_shared == NULL) + libgnustl_shared = dlopen("libgnustl_shared.so", RTLD_LOCAL); + if (libgnustl_shared == NULL) { LOGF("android_main: libgnustl_shared.so not mapped??"); exit(0); } - code = dlsym(libgnustl_shared, symbol); + code = __lo_dlsym(libgnustl_shared, symbol); + + if (code == NULL) + code = dlsym(libgnustl_shared, symbol); + if (code == NULL) { LOGF("android_main: %s not found!?", plaintext); exit(0); @@ -1586,7 +1645,7 @@ Java_org_libreoffice_android_Bootstrap_initVCL(JNIEnv* env, /* This obviously should be called only after libvcllo.so has been loaded */ - InitVCLWrapper = dlsym(RTLD_DEFAULT, "InitVCLWrapper"); + InitVCLWrapper = __lo_dlsym(RTLD_DEFAULT, "InitVCLWrapper"); if (InitVCLWrapper == NULL) { LOGE("InitVCL: InitVCLWrapper not found"); return; @@ -1626,7 +1685,7 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, c_argv[0] = new_argv0; } - osl_setCommandArgs = dlsym(RTLD_DEFAULT, "osl_setCommandArgs"); + osl_setCommandArgs = __lo_dlsym(RTLD_DEFAULT, "osl_setCommandArgs"); if (osl_setCommandArgs == NULL) { LOGE("setCommandArgs: osl_setCommandArgs not found"); return; @@ -1644,7 +1703,7 @@ Java_org_libreoffice_android_Bootstrap_createWindowFoo(JNIEnv* env, (void) clazz; lo_dlopen("libvcllo.so"); - createWindowFoo = dlsym(RTLD_DEFAULT, "createWindowFoo"); + createWindowFoo = __lo_dlsym(RTLD_DEFAULT, "createWindowFoo"); if (createWindowFoo == NULL) { LOGE("createWindowFoo: createWindowFoo not found"); return 0; |