Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}