Date: Mon, 1 Feb 2010 15:45:25 GMT From: Jonathan Anderson <jona@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 174095 for review Message-ID: <201002011545.o11FjPiR075012@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=174095 Change 174095 by jona@jona-belle-freebsd8 on 2010/02/01 15:45:08 Implementation of ld_libdirs() Affected files ... .. //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf/Symbol.map#4 edit .. //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf/rtld.c#32 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf/Symbol.map#4 (text+ko) ==== @@ -18,6 +18,10 @@ __tls_get_addr; }; +FBSD_1.2 { + ld_libdirs; +}; + FBSDprivate_1.0 { _rtld_thread_init; _rtld_allocate_tls; ==== //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf/rtld.c#32 (text+ko) ==== @@ -78,6 +78,8 @@ #endif #endif +#define INITIAL_FDLEN 16 + /* Types. */ typedef void (*func_ptr_type)(); typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); @@ -167,6 +169,8 @@ static int object_match_name(const Obj_Entry *, const char *); static void ld_utrace_log(int, void *, void *, size_t, int, const char *); +int ld_libdirs(int *, int *); + void r_debug_state(struct r_debug *, struct link_map *); /* @@ -183,6 +187,8 @@ used to affect the libraries loaded */ static char *ld_bind_now; /* Environment variable for immediate binding */ static char *ld_debug; /* Environment variable for debugging */ +static int *ld_library_dirs = NULL; /* File descriptors of lib path (end: -1) */ +static int ld_library_dirlen; /* Capacity of ld_library_dirs */ #ifndef IN_RTLD_CAP static char *ld_library_path; /* Environment variable for search path */ static char *ld_preload; /* Environment variable for libraries to @@ -249,6 +255,8 @@ (func_ptr_type) &ld_libcache_lookup, (func_ptr_type) &ld_insandbox, #endif + (func_ptr_type) &ld_libdirs, + NULL }; @@ -2020,6 +2028,7 @@ return (NULL); } +#endif struct try_library_args { const char *name; @@ -2055,6 +2064,7 @@ return (NULL); } +#ifndef IN_RTLD_CAP static char * search_library_path(const char *name, const char *path) { @@ -2077,6 +2087,124 @@ } #endif +/* + * Add a file descriptor to ld_library_dirs. + */ +static void +add_libdir_fd(int fd) { + + if (ld_library_dirs == NULL) { + /* Initialize the FD list. */ + + ld_library_dirlen = INITIAL_FDLEN; + ld_library_dirs = xmalloc(ld_library_dirlen * sizeof(int)); + memset(ld_library_dirs, 0xff, ld_library_dirlen * sizeof(int)); + } + + /* Find the next available FD slot. */ + int i; + for (i = 0; (i < ld_library_dirlen) && (ld_library_dirs[i] != -1); i++) ; + + if (i == ld_library_dirlen) { + /* We need more space. */ + int old_size = ld_library_dirlen + sizeof(int); + + ld_library_dirlen *= 2; + ld_library_dirs = realloc(ld_library_dirs, 2 * old_size); + memset(ld_library_dirs + old_size, 0xff, old_size); + + if (ld_library_dirs == NULL) + err(-1, "realloc() failed"); + } + + ld_library_dirs[i] = fd; +} + +/* + * Add file descriptors for a path list (e.g. '/lib:/usr/lib') to ld_library_dirs. + */ +static void +add_libdir_paths(const char *path) { + + char *pathcopy, *dirname, *tokcontext; + int pathlen = strnlen(path, PATH_MAX); + + pathcopy = malloc(pathlen + 1); + strncpy(pathcopy, path, pathlen + 1); + + for (dirname = strtok_r(pathcopy, ":", &tokcontext); dirname; + dirname = strtok_r(NULL, ":", &tokcontext)) { + + int fd; + + struct try_library_args arg; + arg.name = ""; + arg.namelen = 0; + arg.buffer = xmalloc(PATH_MAX); + arg.buflen = PATH_MAX; + + if (try_library_path(dirname, strnlen(dirname, PATH_MAX), &arg)) + fd = open(dirname, O_RDONLY); + + else { + /* 'dirname' is not a directory path; perhaps it's a descriptor? */ + fd = (int) strtol(dirname, NULL, 0); + if ((fd == 0) && (errno == 0)) + continue; + } + + if (fd >= 0) + add_libdir_fd(fd); + } + + free(pathcopy); +} + +/* + * Return an array of file descriptors for the library search paths. + */ +int +ld_libdirs(int *fds, int *fdcount) { + + if (fdcount == NULL) + return (-1); + + else if (fds == NULL) { + *fdcount = -1; + return (-1); + } + + if (ld_library_dirs == NULL) { +#ifdef IN_RTLD_CAP + + char *envvar = getenv(LD_ "LIBRARY_DIRS"); + if (envvar == NULL) + err(-1, "No %s set in capability mode", LD_ "LIBRARY_DIRS"); + + add_libdir_paths(envvar); + +#else /* !IN_RTLD_CAP */ + + /* Look for directories a la find_library (TODO: refactor!). */ + add_libdir_paths(ld_library_path); + add_libdir_paths(gethints()); + add_libdir_paths(STANDARD_LIBRARY_PATH); +#endif + } + + int i = 0; + for (i = 0; (i < ld_library_dirlen) && (ld_library_dirs[i] != -1); i++) ; + + if (*fdcount < i) { + *fdcount = i; + return (-1); + } + + *fdcount = i; + memcpy(fds, ld_library_dirs, i * sizeof(int)); + return 0; +} + int dlclose(void *handle) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002011545.o11FjPiR075012>