Index: fbsd-6.1/libexec/rtld-elf/rtld.c =================================================================== --- fbsd-6.1.orig/libexec/rtld-elf/rtld.c +++ fbsd-6.1/libexec/rtld-elf/rtld.c @@ -894,6 +894,103 @@ find_library(const char *xname, const Ob return NULL; } +#define MAX_LIBRARIES_HITS 255 + +struct fill_library_paths_args { + const char *name; + size_t namelen; + char **libraries; + size_t *count; +}; + +static void * +fill_library_paths(const char *dir, size_t dirlen, void *param) +{ + struct fill_library_paths_args *arg; + + arg = param; + if (*(arg->count) > MAX_LIBRARIES_HITS) + return (NULL); + + if (*dir == '/' || trust) { + arg->libraries[*(arg->count)] = malloc(sizeof(char)*(dirlen + 1 + arg->namelen + 1)); + strncpy(arg->libraries[*(arg->count)], dir, dirlen); + arg->libraries[*(arg->count)][dirlen] = '/'; + strncpy(arg->libraries[*(arg->count)] + dirlen + 1, arg->name, arg->namelen+1); + + dbg(" Trying \"%s\"\n", arg->libraries[*(arg->count)]); + if (access(arg->libraries[*(arg->count)], F_OK) == 0) { + *(arg->count) += 1; + } + } + return (NULL); +} + +/** + * Find all libraries matching xname for the object refobj (if not null), like + * find_library but find all the matching libraries in the paths. + * + * The returned pointer has to be free()'d (as well as the contained strings) + * if it's non-NULL. + * The end of the array is found when the pointer gets NULL. + */ +static char **find_libraries(const char *xname, const Obj_Entry *refobj) +{ + char **libraries; + size_t libraries_count; + struct fill_library_paths_args arg; + char *name; + + if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ + if (xname[0] != '/' && !trust) { + _rtld_error("Absolute pathname required for shared object \"%s\"", + xname); + return NULL; + } + libraries = malloc(sizeof(char*)*2); + libraries[0] = xstrdup(xname); + libraries[1] = NULL; + return libraries; + } + + if (libmap_disable || (refobj == NULL) || + (name = lm_find(refobj->path, xname)) == NULL) + name = (char *)xname; + + dbg(" Searching for \"%s\"", name); + + /* look up at maximum 255 libraries, would be crazy going over that */ + libraries = malloc(sizeof(char*)*(MAX_LIBRARIES_HITS+1)); + libraries_count = 0; + + arg.name = name; + arg.namelen = strlen(name); + arg.libraries = libraries; + arg.count = &libraries_count; + + path_enumerate(ld_library_path, fill_library_paths, &arg); + if(refobj != NULL) + path_enumerate(refobj->rpath, fill_library_paths, &arg); + path_enumerate(gethints(), fill_library_paths, &arg); + path_enumerate(STANDARD_LIBRARY_PATH, fill_library_paths, &arg); + + libraries[libraries_count] = NULL; + + if(libraries_count == 0) { + if(refobj != NULL && refobj->path != NULL) { + _rtld_error("Shared object \"%s\" not found, required by \"%s\"", + name, basename(refobj->path)); + } else { + _rtld_error("Shared object \"%s\" not found", name); + } + + free(libraries); + return NULL; + } + + return libraries; +} + /* * Given a symbol number in a referencing object, find the corresponding * definition of the symbol. Returns a pointer to the symbol, or NULL if @@ -1165,17 +1262,29 @@ load_needed_objects(Obj_Entry *first) for (needed = obj->needed; needed != NULL; needed = needed->next) { const char *name = obj->strtab + needed->name; - char *path = find_library(name, obj); + char **paths = find_libraries(name, obj); + char **curpath = paths; needed->obj = NULL; - if (path == NULL && !ld_tracing) + if (paths == NULL) return -1; - - if (path) { - needed->obj = load_object(path); - if (needed->obj == NULL && !ld_tracing) - return -1; /* XXX - cleanup */ + + while(*curpath) { + if (needed->obj == NULL) { + needed->obj = load_object(*curpath); + curpath++; + continue; + } + + /* Continue, so that we can free the whole lot */ + free(*curpath); + curpath++; } + + free(paths); + + if (needed->obj == NULL && !ld_tracing) + return -1; /* XXX - cleanup */ } }