diff options
Diffstat (limited to 'sal/android/lo-bootstrap.c')
-rw-r--r-- | sal/android/lo-bootstrap.c | 99 |
1 files changed, 79 insertions, 20 deletions
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; |