Exemple #1
0
/* This function's behavior must exactly match that
 * in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
search_for_named_library(const char *name, unsigned int rflags, const char *path_list,
	struct dyn_elf **rpnt, const char* origin)
{
	char *mylibname;
	struct elf_resolve *tpnt;
	const char *p, *pn;
	int plen;

	if (path_list==NULL)
		return NULL;

	/* another bit of local storage */
	mylibname = alloca(2050);

	/* Unlike ldd.c, don't bother to eliminate double //s */

	/* Replace colons with zeros in path_list */
	/* : at the beginning or end of path maps to CWD */
	/* :: anywhere maps CWD */
	/* "" maps to CWD */
	for (p = path_list; p != NULL; p = pn) {
		pn = _dl_strchr(p + 1, ':');
		if (pn != NULL) {
			plen = pn - p;
			pn++;
		} else
			plen = _dl_strlen(p);

		if (plen >= 7 && _dl_memcmp(p, "$ORIGIN", 7) == 0) {
			int olen;
			/* $ORIGIN is not expanded for SUID/GUID programs
			   (except if it is $ORIGIN alone) */
			if ((rflags & __RTLD_SECURE) && plen != 7)
				continue;
			if (origin == NULL)
				continue;
			for (olen = _dl_strlen(origin) - 1; olen >= 0 && origin[olen] != '/'; olen--)
				;
			if (olen <= 0)
				continue;
			_dl_memcpy(&mylibname[0], origin, olen);
			_dl_memcpy(&mylibname[olen], p + 7, plen - 7);
			mylibname[olen + plen - 7] = 0;
		} else if (plen != 0) {
			_dl_memcpy(mylibname, p, plen);
			mylibname[plen] = 0;
		} else {
			_dl_strcpy(mylibname, ".");
		}
		_dl_strcat(mylibname, "/");
		_dl_strcat(mylibname, name);
#ifdef __LDSO_SAFE_RUNPATH__
		if (*mylibname == '/')
#endif
		if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
			return tpnt;
	}
	return NULL;
}
Exemple #2
0
int
_dl_trace_plt(const elf_object_t *object, const char *symname)
{
	if (!_dl_trace_match(symname, &_dl_tracefunc, 0))
		return 0;

	_dl_utrace(".plt object",
	    object->load_name, _dl_strlen(object->load_name));
	_dl_utrace(".plt symbol",
	    symname, _dl_strlen(symname));

	return 1;	/* keep tracing */
}
Exemple #3
0
/*
 * Extract a trace specification field, and setup the tracespec struct
 * accordingly.
 */
const char *
_dl_trace_parse_spec(const char *var, struct tracespec *spec)
{
	const char *start, *end;

	if (*var == '!') {
		spec->inverse = 1;
		var++;
	}

	start = var;
	end = _dl_strchr(start, ':');
	if (end == NULL)
		end = start + _dl_strlen(start);

	if (end != start) {
		spec->spec = _dl_malloc(1 + end - start);
		if (spec->spec == NULL)
			_dl_exit(8);

		_dl_bcopy(start, spec->spec, end - start);
		spec->spec[end - start] = '\0';
	}

	if (*end == ':')
		end++;

	return end;
}
Exemple #4
0
/* This function's behavior must exactly match that
 * in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
search_for_named_library(const char *name, unsigned rflags, const char *path_list,
	struct dyn_elf **rpnt)
{
	char *path, *path_n, *mylibname;
	struct elf_resolve *tpnt;
	int done;

	if (path_list==NULL)
		return NULL;

	/* We need a writable copy of this string, but we don't
	 * need this allocated permanently since we don't want
	 * to leak memory, so use alloca to put path on the stack */
	done = _dl_strlen(path_list);
	path = alloca(done + 1);

	/* another bit of local storage */
	mylibname = alloca(2050);

	_dl_memcpy(path, path_list, done+1);

	/* Unlike ldd.c, don't bother to eliminate double //s */

	/* Replace colons with zeros in path_list */
	/* : at the beginning or end of path maps to CWD */
	/* :: anywhere maps CWD */
	/* "" maps to CWD */
	done = 0;
	path_n = path;
	do {
		if (*path == 0) {
			*path = ':';
			done = 1;
		}
		if (*path == ':') {
			*path = 0;
			if (*path_n)
				_dl_strcpy(mylibname, path_n);
			else
				_dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
			_dl_strcat(mylibname, "/");
			_dl_strcat(mylibname, name);
#ifdef __LDSO_SAFE_RUNPATH__
			if (*mylibname == '/')
#endif
				if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
					return tpnt;
			path_n = path+1;
		}
		path++;
	} while (!done);
	return NULL;
}
Exemple #5
0
/*
 * Check if a given name matches a trace specification list.
 */
static int
_dl_trace_match(const char *name, struct tracespec *spec, int allow_so)
{
	const char *list, *end, *next;
	size_t span;
	int match;

	/* no spec means trace everything */
	if (spec->spec == NULL)
		return 1;

	match = 0;
	list = spec->spec;
	end = list + _dl_strlen(list);

	while (*list != '\0') {
		next = _dl_strchr(list, ',');
		if (next == NULL)
			next = end;

		span = next - list;
		if (span != 0 && *(next - 1) == '*')
			span--;

		if (span != 0 && _dl_strncmp(name, list, span) == 0) {
			/*
			 * If the object name matches the specification
			 * fragment so far, it's a match if:
			 *   + the specification ends in a star (wildcard
			 *     match)
			 *   + there are no remaining chars in both the
			 *     object name and the specification (exact
			 *     match)
			 *   + the specification ends (no star) and the
			 *     object name continues with ".so" (radix
			 *     match) and `allow_so' is nonzero.
			 */
			if (list[span] == '*' ||
			    name[span] == '\0' ||
			    (allow_so &&
			    _dl_strncmp(name + span, ".so", 3) == 0)) {
				match = 1;
				break;
			}
		}

		while (*next == ',')
			next++;
		list = next;
	}

	return spec->inverse ? !match : match;
}
Exemple #6
0
struct elf_resolve *_dl_load_shared_library(unsigned int rflags, struct dyn_elf **rpnt,
	struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
{
	char *pnt;
	struct elf_resolve *tpnt1;
	char *libname;

	_dl_internal_error_number = 0;
	libname = full_libname;

	/* quick hack to ensure mylibname buffer doesn't overflow.  don't
	   allow full_libname or any directory to be longer than 1024. */
	if (_dl_strlen(full_libname) > 1024)
		goto goof;

	/* Skip over any initial initial './' and '/' stuff to
	 * get the short form libname with no path garbage */
	pnt = _dl_strrchr(libname, '/');
	if (pnt) {
		libname = pnt + 1;
	}

	_dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
	/* If the filename has any '/', try it straight and leave it at that.
	   For IBCS2 compatibility under linux, we substitute the string
	   /usr/i486-sysv4/lib for /usr/lib in library names. */

	if (libname != full_libname) {
		_dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
		tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, full_libname);
		if (tpnt1) {
			return tpnt1;
		}
	}

	/*
	 * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
	 * the default path of /usr/lib.  Check in rpath directories.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt,
						      tpnt->libname)) != NULL)
			return tpnt1;

	}
#endif

#ifdef __LDSO_LD_LIBRARY_PATH__
	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
	if (_dl_library_path) {
		_dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
		if ((tpnt1 = search_for_named_library(libname, rflags, _dl_library_path, rpnt, NULL)) != NULL)
		{
			return tpnt1;
		}
	}
#endif
	/*
	 * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
			return tpnt1;
	}
#ifdef __LDSO_RUNPATH_OF_EXECUTABLE__
        /*
         * Try the DT_RPATH of the executable itself.
         */
        pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH];
        if (pnt) {
                pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB];
                _dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt);
                if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
                        return tpnt1;
        }
#endif
#endif

	/*
	 * Where should the cache be searched?  There is no such concept in the
	 * ABI, so we have some flexibility here.  For now, search it before
	 * the hard coded paths that follow (i.e before /lib and /usr/lib).
	 */
#ifdef __LDSO_CACHE_SUPPORT__
	if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
		int i;
		header_t *header = (header_t *) _dl_cache_addr;
		libentry_t *libent = (libentry_t *) & header[1];
		char *strs = (char *) &libent[header->nlibs];

		_dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
		for (i = 0; i < header->nlibs; i++) {
			if ((libent[i].flags == LIB_ELF
			     || libent[i].flags == LIB_ELF_LIBC0
			     ||	libent[i].flags == LIB_ELF_LIBC5)
			 && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
			 && (tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, strs + libent[i].liboffset))
			) {
				return tpnt1;
			}
		}
	}
#endif

#ifdef LDSO_MULTILIB_DIR
	/* If multilib directory is selected, search it before falling back to
	   standard lib directories. */
	_dl_if_debug_dprint("\tsearching multilib lib path list\n");
	tpnt1 = search_for_named_library(libname, rflags,
					UCLIBC_RUNTIME_PREFIX LDSO_MULTILIB_DIR ":"
					UCLIBC_RUNTIME_PREFIX "usr/" LDSO_MULTILIB_DIR,
					rpnt, NULL);
	if (tpnt1 != NULL)
		return tpnt1;
#endif

#if defined SHARED && defined __LDSO_SEARCH_INTERP_PATH__
	/* Look for libraries wherever the shared library loader
	 * was installed */
	_dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
	tpnt1 = search_for_named_library(libname, rflags, _dl_ldsopath, rpnt, NULL);
	if (tpnt1 != NULL)
		return tpnt1;
#endif

	/* Lastly, search the standard list of paths for the library.
	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
	_dl_if_debug_dprint("\tsearching full lib path list\n");
	tpnt1 = search_for_named_library(libname, rflags,
					UCLIBC_RUNTIME_PREFIX "lib:"
					UCLIBC_RUNTIME_PREFIX "usr/lib"
#ifndef __LDSO_CACHE_SUPPORT__
					":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
#endif
					, rpnt, NULL);
	if (tpnt1 != NULL)
		return tpnt1;

#ifdef __LDSO_RUNPATH_OF_EXECUTABLE__
	/* Very last resort, try the executable's DT_RUNPATH and DT_RPATH */
	/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies
	 * The set of directories specified by a given DT_RUNPATH entry is
	 * used to find only the immediate dependencies of the executable or
	 * shared object containing the DT_RUNPATH entry. That is, it is
	 * used only for those dependencies contained in the DT_NEEDED
	 * entries of the dynamic structure containing the DT_RUNPATH entry,
	 * itself. One object's DT_RUNPATH entry does not affect the search
	 * for any other object's dependencies.
	 *
	 * glibc (around 2.19) violates this and the usual suspects are
	 * abusing this bug^Wrelaxed, user-friendly behaviour.
	 */

	pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RUNPATH];
	if (pnt) {
		pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching exe's RUNPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
			return tpnt1;
	}
	pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH];
	if (pnt) {
		pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
			return tpnt1;
	}
#endif


goof:
	/* Well, we shot our wad on that one.  All we can do now is punt */
	if (_dl_internal_error_number)
		_dl_error_number = _dl_internal_error_number;
	else
		_dl_error_number = LD_ERROR_NOFILE;
	_dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
	return NULL;
}
/* This function's behavior must exactly match that
 * in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
search_for_named_library(const char *name, int secure, const char *path_list,
	struct dyn_elf **rpnt)
{
	char *path, *path_n, *mylibname;
	struct elf_resolve *tpnt;
	int done;

	if (path_list==NULL)
		return NULL;

	/* We need a writable copy of this string, but we don't
	 * need this allocated permanently since we don't want
	 * to leak memory, so use alloca to put path on the stack */
	done = _dl_strlen(path_list);
	path = alloca(done + 1);

	/* another bit of local storage */
	mylibname = alloca(2050);

	/* gcc inlines alloca using a single instruction adjusting
	 * the stack pointer and no stack overflow check and thus
	 * no NULL error return.  No point leaving in dead code... */
#if 0
	if (!path || !mylibname) {
		_dl_dprintf(2, "Out of memory!\n");
		_dl_exit(0);
	}
#endif

	_dl_memcpy(path, path_list, done+1);

	/* Unlike ldd.c, don't bother to eliminate double //s */

	/* Replace colons with zeros in path_list */
	/* : at the beginning or end of path maps to CWD */
	/* :: anywhere maps CWD */
	/* "" maps to CWD */ 
	done = 0;
	path_n = path;
	do {
		if (*path == 0) {
			*path = ':';
			done = 1;
		}
		if (*path == ':') {
			*path = 0;
			if (*path_n)
				_dl_strcpy(mylibname, path_n);
			else
				_dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
			_dl_strcat(mylibname, "/");
			_dl_strcat(mylibname, name);
			if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL)
				return tpnt;
			path_n = path+1;
		}
		path++;
	} while (!done);
	return NULL;
}
Exemple #8
0
/*
 * char *dl_realpath(const char *path, char resolved[PATH_MAX]);
 *
 * Find the real name of path, by removing all ".", ".." and symlink
 * components.  Returns (resolved) on success, or (NULL) on failure,
 * in which case the path which caused trouble is left in (resolved).
 */
char *
_dl_realpath(const char *path, char *resolved)
{
	struct stat sb;
	const char *p, *s;
	char *q;
	size_t left_len, resolved_len;
	unsigned symlinks;
	int slen, mem_allocated, ret;
	char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];

	if (path[0] == '\0') {
		return (NULL);
	}

	if (resolved == NULL) {
		resolved = _dl_malloc(PATH_MAX);
		if (resolved == NULL)
			return (NULL);
		mem_allocated = 1;
	} else
		mem_allocated = 0;

	symlinks = 0;
	if (path[0] == '/') {
		resolved[0] = '/';
		resolved[1] = '\0';
		if (path[1] == '\0')
			return (resolved);
		resolved_len = 1;
		left_len = _dl_strlcpy(left, path + 1, sizeof(left));
	} else {
		if (_dl_getcwd(resolved, PATH_MAX) <= 0) {
			if (mem_allocated)
				_dl_free(resolved);
			else
				_dl_strlcpy(resolved, ".", PATH_MAX);
			return (NULL);
		}
		resolved_len = _dl_strlen(resolved);
		left_len = _dl_strlcpy(left, path, sizeof(left));
	}
	if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
		goto err;
	}

	/*
	 * Iterate over path components in `left'.
	 */
	while (left_len != 0) {
		/*
		 * Extract the next path component and adjust `left'
		 * and its length.
		 */
		p = _dl_strchr(left, '/');
		s = p ? p : left + left_len;
		if (s - left >= sizeof(next_token)) {
			goto err;
		}
		_dl_bcopy(left, next_token, s - left);
		next_token[s - left] = '\0';
		left_len -= s - left;
		if (p != NULL)
			_dl_bcopy(s + 1, left, left_len + 1);
		if (resolved[resolved_len - 1] != '/') {
			if (resolved_len + 1 >= PATH_MAX) {
				goto err;
			}
			resolved[resolved_len++] = '/';
			resolved[resolved_len] = '\0';
		}
		if (next_token[0] == '\0')
			continue;
		else if (_dl_strcmp(next_token, ".") == 0)
			continue;
		else if (_dl_strcmp(next_token, "..") == 0) {
			/*
			 * Strip the last path component except when we have
			 * single "/"
			 */
			if (resolved_len > 1) {
				resolved[resolved_len - 1] = '\0';
				q = _dl_strrchr(resolved, '/') + 1;
				*q = '\0';
				resolved_len = q - resolved;
			}
			continue;
		}

		/*
		 * Append the next path component and lstat() it. If
		 * lstat() fails we still can return successfully if
		 * there are no more path components left.
		 */
		resolved_len = _dl_strlcat(resolved, next_token, PATH_MAX);
		if (resolved_len >= PATH_MAX) {
			goto err;
		}
		if ((ret = _dl_lstat(resolved, &sb)) != 0) {
			if (ret == ENOENT && p == NULL) {
				return (resolved);
			}
			goto err;
		}
		if (S_ISLNK(sb.st_mode)) {
			if (symlinks++ > SYMLOOP_MAX) {
				goto err;
			}
			slen = _dl_readlink(resolved, symlink, sizeof(symlink) - 1);
			if (slen < 0)
				goto err;
			symlink[slen] = '\0';
			if (symlink[0] == '/') {
				resolved[1] = 0;
				resolved_len = 1;
			} else if (resolved_len > 1) {
				/* Strip the last path component. */
				resolved[resolved_len - 1] = '\0';
				q = _dl_strrchr(resolved, '/') + 1;
				*q = '\0';
				resolved_len = q - resolved;
			}

			/*
			 * If there are any path components left, then
			 * append them to symlink. The result is placed
			 * in `left'.
			 */
			if (p != NULL) {
				if (symlink[slen - 1] != '/') {
					if (slen + 1 >= sizeof(symlink)) {
						goto err;
					}
					symlink[slen] = '/';
					symlink[slen + 1] = 0;
				}
				left_len = _dl_strlcat(symlink, left, sizeof(symlink));
				if (left_len >= sizeof(left)) {
					goto err;
				}
			}
			left_len = _dl_strlcpy(left, symlink, sizeof(left));
		}
	}

	/*
	 * Remove trailing slash except when the resolved pathname
	 * is a single "/".
	 */
	if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
		resolved[resolved_len - 1] = '\0';
	return (resolved);

err:
	if (mem_allocated)
		_dl_free(resolved);
	return (NULL);
}
Exemple #9
0
/* This is a real hack.  We need access to the dynamic linker, but we
also need to make it possible to link against this library without any
unresolved externals.  We provide these weak symbols to make the link
possible, but at run time the normal symbols are accessed. */
static void __attribute__ ((unused)) foobar(void)
{
	const char msg[]="libdl library not correctly linked\n";
	_dl_write(2, msg, _dl_strlen(msg));
	_dl_exit(1);
}
Exemple #10
0
struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
	struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
{
	char *pnt;
	struct elf_resolve *tpnt1;
	char *libname;

	_dl_internal_error_number = 0;
	libname = full_libname;

	/* quick hack to ensure mylibname buffer doesn't overflow.  don't
	   allow full_libname or any directory to be longer than 1024. */
	if (_dl_strlen(full_libname) > 1024)
		goto goof;

	/* Skip over any initial initial './' and '/' stuff to
	 * get the short form libname with no path garbage */
	pnt = _dl_strrchr(libname, '/');
	if (pnt) {
		libname = pnt + 1;
	}

	_dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
	/* If the filename has any '/', try it straight and leave it at that.
	   For IBCS2 compatibility under linux, we substitute the string
	   /usr/i486-sysv4/lib for /usr/lib in library names. */

	if (libname != full_libname) {
		_dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
		tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname);
		if (tpnt1) {
			return tpnt1;
		}
	}

	/*
	 * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
	 * the default path of /usr/lib.  Check in rpath directories.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
			return tpnt1;
	}
#endif

	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
	if (_dl_library_path) {
		_dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
		if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
		{
			return tpnt1;
		}
	}

	/*
	 * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
			return tpnt1;
	}
#endif

	/*
	 * Where should the cache be searched?  There is no such concept in the
	 * ABI, so we have some flexibility here.  For now, search it before
	 * the hard coded paths that follow (i.e before /lib and /usr/lib).
	 */
#ifdef __LDSO_CACHE_SUPPORT__
	if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
		int i;
		header_t *header = (header_t *) _dl_cache_addr;
		libentry_t *libent = (libentry_t *) & header[1];
		char *strs = (char *) &libent[header->nlibs];

		_dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
		for (i = 0; i < header->nlibs; i++) {
			if ((libent[i].flags == LIB_ELF
			     || libent[i].flags == LIB_ELF_LIBC0
			     ||	libent[i].flags == LIB_ELF_LIBC5)
			 && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
			 && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset))
			) {
				return tpnt1;
			}
		}
	}
#endif

	/* Look for libraries wherever the shared library loader
	 * was installed */
	_dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
	tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt);
	if (tpnt1 != NULL)
		return tpnt1;

	/* Lastly, search the standard list of paths for the library.
	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
	_dl_if_debug_dprint("\tsearching full lib path list\n");
	tpnt1 = search_for_named_library(libname, secure,
					UCLIBC_RUNTIME_PREFIX "lib:"
					UCLIBC_RUNTIME_PREFIX "usr/lib"
#ifndef __LDSO_CACHE_SUPPORT__
					":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
#endif
					, rpnt);
	if (tpnt1 != NULL)
		return tpnt1;

goof:
	/* Well, we shot our wad on that one.  All we can do now is punt */
	if (_dl_internal_error_number)
		_dl_error_number = _dl_internal_error_number;
	else
		_dl_error_number = LD_ERROR_NOFILE;
	_dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
	return NULL;
}
Exemple #11
0
/*
 * Perform $ORIGIN substitutions on path
 */
static void
_dl_origin_subst_path(elf_object_t *object, const char *origin_path,
    char **path)
{
	char tmp_path[PATH_MAX];
	char *new_path, *tp;
	const char *pp, *name, *value;
	static struct utsname uts;
	size_t value_len;
	int skip_brace;

	if (uts.sysname[0] == '\0') {
		if (_dl_uname(&uts) != 0)
			return;
	}

	tp = tmp_path;
	pp = *path;

	while (*pp != '\0' && (tp - tmp_path) < sizeof(tmp_path)) {

		/* copy over chars up to but not including $ */
		while (*pp != '\0' && *pp != '$' &&
		    (tp - tmp_path) < sizeof(tmp_path))
			*tp++ = *pp++;

		/* substitution sequence detected */
		if (*pp == '$' && (tp - tmp_path) < sizeof(tmp_path)) {
			pp++;

			if ((skip_brace = (*pp == '{')))
				pp++;

			/* skip over name */
			name = pp;
			while (_dl_isalnum((unsigned char)*pp) || *pp == '_')
				pp++;

			switch (_dl_subst_name(name, pp - name)) {
			case SUBST_ORIGIN:
				value = origin_path;
				break;
			case SUBST_OSNAME:
				value = uts.sysname;
				break;
			case SUBST_OSREL:
				value = uts.release;
				break;
			case SUBST_PLATFORM:
				value = uts.machine;
				break;
			default:
				value = "";
			}

			value_len = _dl_strlen(value);
			if (value_len >= sizeof(tmp_path) - (tp - tmp_path))
				return;

			_dl_bcopy(value, tp, value_len);
			tp += value_len;

			if (skip_brace && *pp == '}')
				pp++;
		}
	}

	/* no substitution made if result exceeds sizeof(tmp_path) */
	if (tp - tmp_path >= sizeof(tmp_path))
		return;

	/* NULL terminate tmp_path */
	*tp = '\0';

	if (_dl_strcmp(tmp_path, *path) == 0)
		return;

	new_path = _dl_strdup(tmp_path);
	if (new_path == NULL)
		return;

	DL_DEB(("orig_path %s\n", *path));
	DL_DEB(("new_path  %s\n", new_path));

	_dl_free(*path);
	*path = new_path;
}