void * android_dlopen(const char *library) { //added by aydin.kim - parse ld_library_path char *libraries[256]; int i1 = 0, icnt = 0; char ld_library_path[1024]; char* library_path = getenv("LD_LIBRARY_PATH"); strcpy(ld_library_path, library_path); // LOGI("LD_LIBRARY_PATH is : %s", ld_library_path); libraries[i1] = strtok(ld_library_path, ":"); //LOGI("library : %s", libraries[i1]); while(libraries[i1]) { libraries[++i1] = strtok(NULL, ":"); //LOGI("library : %s", libraries[i1]); } icnt = i1; library_locations = (const char**)malloc((icnt+2) * sizeof(char *)); for(int j = 0; j < icnt+2; j++) library_locations[j] = NULL; if(library_locations == NULL) { SET_ERROR("Cannot allocate library locations"); return 0; } library_locations[0] = "/data/data/com.example.ServoAndroid/lib"; // LOGI("added library path : %s", library_locations[0]); for(int i = 0; i < icnt; i++ ) { library_locations[i+1] = strdup(libraries[i]); // LOGI("added library path : %s", library_locations[i+1]); } /* * We should *not* try to just dlopen() the bare library name * first, as the stupid dynamic linker remembers for each library * basename if loading it has failed. Thus if you try loading it * once, and it fails because of missing needed libraries, and * your load those, and then try again, it fails with an * infuriating message "failed to load previously" in the log. * * We *must* first dlopen() all needed libraries, recursively. It * shouldn't matter if we dlopen() a library that already is * loaded, dlopen() just returns the same value then. */ struct loadedLib { const char *name; void *handle; struct loadedLib *next; }; static struct loadedLib *loaded_libraries = NULL; struct loadedLib *rover; struct loadedLib *new_loaded_lib; struct stat st; void *p; char *full_name = NULL; char **needed; int i; int found; struct timeval tv0, tv1, tvdiff; rover = loaded_libraries; while (rover != NULL && strcmp(rover->name, library) != 0) rover = rover->next; if (rover != NULL) return rover->handle; /* LOGI("android_dlopen(%s)", library); */ found = 0; if (library[0] == '/') { full_name = strdup(library); if (stat(full_name, &st) == 0 && S_ISREG(st.st_mode)) { found = 1; } else { free(full_name); full_name = NULL; } } else { for (i = 0; !found && library_locations[i] != NULL; i++) { full_name = (char*)malloc(strlen(library_locations[i]) + 1 + strlen(library) + 1); strcpy(full_name, library_locations[i]); strcat(full_name, "/"); strcat(full_name, library); if (stat(full_name, &st) == 0 && S_ISREG(st.st_mode)) { found = 1; } else { free(full_name); full_name = NULL; } } } if (!found) { SET_ERROR("Library %s not found", library); assert(full_name == NULL); // full_name was freed above if !found return NULL; } needed = android_dlneeds(full_name); if (needed == NULL) { free(full_name); return NULL; } for (i = 0; needed[i] != NULL; i++) { if (android_dlopen(needed[i]) == NULL) { free_ptrarray((void **) needed); free(full_name); return NULL; } } free_ptrarray((void **) needed); gettimeofday(&tv0, NULL); p = dlopen(full_name, RTLD_LOCAL); gettimeofday(&tv1, NULL); timersub(&tv1, &tv0, &tvdiff); LOGI("dlopen(%s) = %p, %ld.%03lds", full_name, p, (long) tvdiff.tv_sec, (long) tvdiff.tv_usec / 1000); if (p == NULL) SET_ERROR("Error from dlopen(%s): %s", full_name, dlerror()); free(full_name); full_name = NULL; new_loaded_lib = (struct loadedLib*)malloc(sizeof(*new_loaded_lib)); new_loaded_lib->name = strdup(library); new_loaded_lib->handle = p; new_loaded_lib->next = loaded_libraries; loaded_libraries = new_loaded_lib; return p; }
void * android_dlopen(const char *library) { /* * We should *not* try to just dlopen() the bare library name * first, as the stupid dynamic linker remembers for each library * basename if loading it has failed. Thus if you try loading it * once, and it fails because of missing needed libraries, and * your load those, and then try again, it fails with an * infuriating message "failed to load previously" in the log. * * We *must* first dlopen() all needed libraries, recursively. It * shouldn't matter if we dlopen() a library that already is * loaded, dlopen() just returns the same value then. */ struct loadedLib { const char *name; void *handle; struct loadedLib *next; }; static struct loadedLib *loaded_libraries = NULL; struct loadedLib *rover; struct loadedLib *new_loaded_lib; struct stat st; void *p; char *full_name; char **needed; int i; int found; struct timeval tv0, tv1, tvdiff; rover = loaded_libraries; while (rover != NULL && strcmp(rover->name, library) != 0) rover = rover->next; if (rover != NULL) return rover->handle; /* LOGI("android_dlopen(%s)", library); */ found = 0; if (library[0] == '/') { full_name = strdup(library); if (stat(full_name, &st) == 0 && S_ISREG(st.st_mode)) found = 1; else free(full_name); } else { for (i = 0; !found && library_locations[i] != NULL; i++) { full_name = (char*)malloc(strlen(library_locations[i]) + 1 + strlen(library) + 1); strcpy(full_name, library_locations[i]); strcat(full_name, "/"); strcat(full_name, library); if (stat(full_name, &st) == 0 && S_ISREG(st.st_mode)) found = 1; else free(full_name); } } if (!found) { SET_ERROR("Library %s not found", library); return NULL; } needed = android_dlneeds(full_name); if (needed == NULL) { free(full_name); return NULL; } for (i = 0; needed[i] != NULL; i++) { if (android_dlopen(needed[i]) == NULL) { free_ptrarray((void **) needed); free(full_name); return NULL; } } free_ptrarray((void **) needed); gettimeofday(&tv0, NULL); p = dlopen(full_name, RTLD_LOCAL); gettimeofday(&tv1, NULL); timersub(&tv1, &tv0, &tvdiff); LOGI("dlopen(%s) = %p, %ld.%03lds", full_name, p, (long) tvdiff.tv_sec, (long) tvdiff.tv_usec / 1000); free(full_name); if (p == NULL) SET_ERROR("Error from dlopen(%s): %s", full_name, dlerror()); new_loaded_lib = (struct loadedLib*)malloc(sizeof(*new_loaded_lib)); new_loaded_lib->name = strdup(library); new_loaded_lib->handle = p; new_loaded_lib->next = loaded_libraries; loaded_libraries = new_loaded_lib; return p; }