1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00
1998-03-31 18:11  Ulrich Drepper  <drepper@cygnus.com>

	* include/mntent.h: New file.

	* elf/Makefile (trusted-dirs.h): Append slash to filename.
	* elf/dl-load.c: Rewrite search path handling.
	* elf/ldsodefs.h (struct r_search_path_elem): Change for rewrite.
	* elf/rtld.c (process_envvars): Recognize LD_HWCAP_MASK.
	* sysdeps/generic/dl-sysdep.h (_dl_important_hwcap): New function.
	* elf/ldsodefs.h: Add prototype.
This commit is contained in:
Ulrich Drepper
1998-03-31 18:24:48 +00:00
parent 4317f9e137
commit 12264bd7fa
8 changed files with 257 additions and 252 deletions

View File

@ -1,3 +1,14 @@
1998-03-31 18:11 Ulrich Drepper <drepper@cygnus.com>
* include/mntent.h: New file.
* elf/Makefile (trusted-dirs.h): Append slash to filename.
* elf/dl-load.c: Rewrite search path handling.
* elf/ldsodefs.h (struct r_search_path_elem): Change for rewrite.
* elf/rtld.c (process_envvars): Recognize LD_HWCAP_MASK.
* sysdeps/generic/dl-sysdep.h (_dl_important_hwcap): New function.
* elf/ldsodefs.h: Add prototype.
1998-03-30 Ulrich Drepper <drepper@cygnus.com> 1998-03-30 Ulrich Drepper <drepper@cygnus.com>
* nss/nsswitch.c (__nss_lookup): Adjust comment. * nss/nsswitch.c (__nss_lookup): Adjust comment.

View File

@ -141,7 +141,7 @@ $(objpfx)trusted-dirs.h: Makefile $(..)Makeconfig
$(make-target-directory) $(make-target-directory)
(for dir in `echo "$(default-rpath) $(user-defined-trusted-dirs)" | \ (for dir in `echo "$(default-rpath) $(user-defined-trusted-dirs)" | \
sed 's/:/ /g'`; do \ sed 's/:/ /g'`; do \
echo " \"$$dir\","; \ echo " \"$$dir/\","; \
done;) > $@T done;) > $@T
mv -f $@T $@ mv -f $@T $@
$(objpfx)rtldtbl.h: Makefile $(..)Makeconfig genrtldtbl.awk $(objpfx)rtldtbl.h: Makefile $(..)Makeconfig genrtldtbl.awk

View File

@ -100,6 +100,11 @@ extern size_t _dl_platformlen;
binaries. */ binaries. */
static struct r_search_path_elem **fake_path_list; static struct r_search_path_elem **fake_path_list;
/* List of the hardware capabilities we might end up using. */
static const struct r_strlenpair *capstr;
static size_t ncapstr;
static size_t max_capstrlen;
/* Local version of `strdup' function. */ /* Local version of `strdup' function. */
static inline char * static inline char *
@ -119,6 +124,7 @@ local_strdup (const char *s)
be freed if the shared object already has this name. be freed if the shared object already has this name.
Returns false if the object already had this name. */ Returns false if the object already had this name. */
static int static int
internal_function
add_name_to_object (struct link_map *l, char *name) add_name_to_object (struct link_map *l, char *name)
{ {
struct libname_list *lnp, *lastp; struct libname_list *lnp, *lastp;
@ -156,9 +162,11 @@ add_name_to_object (struct link_map *l, char *name)
return 1; return 1;
} }
/* All known directories in sorted order. */
static struct r_search_path_elem *all_dirs;
/* Implement cache for search path lookup. */ /* Standard search directories. */
#include "rtldtbl.h" static struct r_search_path_elem **rtld_search_dirs;
static size_t max_dirnamelen; static size_t max_dirnamelen;
@ -173,6 +181,11 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
{ {
struct r_search_path_elem *dirp; struct r_search_path_elem *dirp;
size_t len = strlen (cp); size_t len = strlen (cp);
/* `strsep' can pass an empty string. */
if (len == 0)
continue;
/* Remove trailing slashes. */ /* Remove trailing slashes. */
while (len > 1 && cp[len - 1] == '/') while (len > 1 && cp[len - 1] == '/')
--len; --len;
@ -187,7 +200,8 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
continue; continue;
while (*trun != NULL while (*trun != NULL
&& (memcmp (*trun, cp, len) != 0 || (*trun)[len] != '\0')) && (memcmp (*trun, cp, len) != 0
|| ((*trun)[len] != '/' && (*trun)[len + 1] != '\0')))
++trun; ++trun;
if (*trun == NULL) if (*trun == NULL)
@ -201,12 +215,12 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
/* See if this directory is already known. */ /* See if this directory is already known. */
for (dirp = all_dirs; dirp != NULL; dirp = dirp->next) for (dirp = all_dirs; dirp != NULL; dirp = dirp->next)
if (dirp->dirnamelen == len && strcmp (cp, dirp->dirname) == 0) if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
break; break;
if (dirp != NULL) if (dirp != NULL)
{ {
/* It is available, see whether it's in our own list. */ /* It is available, see whether it's on our own list. */
size_t cnt; size_t cnt;
for (cnt = 0; cnt < nelems; ++cnt) for (cnt = 0; cnt < nelems; ++cnt)
if (result[cnt] == dirp) if (result[cnt] == dirp)
@ -217,57 +231,30 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
} }
else else
{ {
size_t cnt;
/* It's a new directory. Create an entry and add it. */ /* It's a new directory. Create an entry and add it. */
dirp = (struct r_search_path_elem *) malloc (sizeof (*dirp)); dirp = (struct r_search_path_elem *)
malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status));
if (dirp == NULL) if (dirp == NULL)
_dl_signal_error (ENOMEM, NULL, _dl_signal_error (ENOMEM, NULL,
"cannot create cache for search path"); "cannot create cache for search path");
dirp->dirname = cp;
dirp->dirnamelen = len; dirp->dirnamelen = len;
if (len > max_dirnamelen)
max_dirnamelen = len;
/* We have to make sure all the relative directories are never /* We have to make sure all the relative directories are never
ignored. The current directory might change and all our ignored. The current directory might change and all our
saved information would be void. */ saved information would be void. */
dirp->dirstatus = cp[0] != '/' ? existing : unknown; if (cp[0] != '/')
for (cnt = 0; cnt < ncapstr; ++cnt)
/* Add the name of the machine dependent directory if a machine dirp->status[cnt] = existing;
is defined. */
if (_dl_platform != NULL)
{
char *tmp;
dirp->machdirnamelen = len + _dl_platformlen + 1;
tmp = (char *) malloc (len + _dl_platformlen + 2);
if (tmp == NULL)
_dl_signal_error (ENOMEM, NULL,
"cannot create cache for search path");
dirp->dirname = tmp;
tmp = __mempcpy (tmp, cp, len);
tmp = __mempcpy (tmp, _dl_platform, _dl_platformlen);
*tmp++ = '/';
*tmp = '\0';
dirp->machdirstatus = dirp->dirstatus;
if (max_dirnamelen < dirp->machdirnamelen)
max_dirnamelen = dirp->machdirnamelen;
}
else else
{ for (cnt = 0; cnt < ncapstr; ++cnt)
char *tmp; dirp->status[cnt] = unknown;
dirp->machdirnamelen = len;
dirp->machdirstatus = nonexisting;
tmp = (char *) malloc (len + 1);
if (tmp == NULL)
_dl_signal_error (ENOMEM, NULL,
"cannot create cache for search path");
dirp->dirname = tmp;
*((char *) __mempcpy (tmp, cp, len)) = '\0';
if (max_dirnamelen < dirp->dirnamelen)
max_dirnamelen = dirp->dirnamelen;
}
dirp->what = what; dirp->what = what;
dirp->where = where; dirp->where = where;
@ -288,6 +275,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
static struct r_search_path_elem ** static struct r_search_path_elem **
internal_function
decompose_rpath (const char *rpath, size_t additional_room, decompose_rpath (const char *rpath, size_t additional_room,
const char *what, const char *where) const char *what, const char *where)
{ {
@ -317,13 +305,14 @@ decompose_rpath (const char *rpath, size_t additional_room,
void void
_dl_init_paths (const char *llp) _dl_init_paths (const char *llp)
{ {
static const char *trusted_dirs[] = static const char *system_dirs[] =
{ {
#include "trusted-dirs.h" #include "trusted-dirs.h"
NULL NULL
}; };
const char **strp;
struct r_search_path_elem **pelem; struct r_search_path_elem *pelem, **aelem;
size_t round_size;
/* We have in `search_path' the information about the RPATH of the /* We have in `search_path' the information about the RPATH of the
dynamic loader. Now fill in the information about the applications dynamic loader. Now fill in the information about the applications
@ -331,10 +320,6 @@ _dl_init_paths (const char *llp)
variable. */ variable. */
struct link_map *l; struct link_map *l;
/* Names of important hardware capabilities. */
char **hwcap_names;
size_t nhwcap_names;
/* Number of elements in the library path. */ /* Number of elements in the library path. */
size_t nllp; size_t nllp;
@ -352,8 +337,47 @@ _dl_init_paths (const char *llp)
nllp = 0; nllp = 0;
/* Get the capabilities. */ /* Get the capabilities. */
hwcap_names = _dl_important_hwcaps (&nhwcap_names, capstr = _dl_important_hwcaps (_dl_platform, _dl_platformlen,
_dl_platform, _dl_platformlen); &ncapstr, &max_capstrlen);
/* First set up the rest of the default search directory entries. */
aelem = rtld_search_dirs = (struct r_search_path_elem **)
malloc ((ncapstr + 1) * sizeof (struct r_search_path_elem *));
round_size = ((2 * sizeof (struct r_search_path_elem) - 1
+ ncapstr * sizeof (enum r_dir_status))
/ sizeof (struct r_search_path_elem));
rtld_search_dirs[0] = (struct r_search_path_elem *)
malloc ((sizeof (system_dirs) / sizeof (system_dirs[0]) - 1)
* round_size * sizeof (struct r_search_path_elem));
if (rtld_search_dirs[0] == NULL)
_dl_signal_error (ENOMEM, NULL, "cannot create cache for search path");
pelem = all_dirs= rtld_search_dirs[0];
for (strp = system_dirs; *strp != NULL; ++strp, pelem += round_size)
{
size_t cnt;
*aelem++ = pelem;
pelem->next = *(strp + 1) == NULL ? NULL : (pelem + round_size);
pelem->what = "system search path";
pelem->where = NULL;
pelem->dirnamelen = strlen (pelem->dirname = *strp);
if (pelem->dirnamelen > max_dirnamelen)
max_dirnamelen = pelem->dirnamelen;
if (pelem->dirname[0] != '/')
for (cnt = 0; cnt < ncapstr; ++cnt)
pelem->status[cnt] = existing;
else
for (cnt = 0; cnt < ncapstr; ++cnt)
pelem->status[cnt] = unknown;
}
*aelem = NULL;
l = _dl_loaded; l = _dl_loaded;
if (l != NULL) if (l != NULL)
@ -391,7 +415,7 @@ _dl_init_paths (const char *llp)
if (nllp > 0) if (nllp > 0)
{ {
char *copy = strdupa (llp); char *copy = local_strdup (llp);
/* Decompose the LD_LIBRARY_PATH and fill in the result. /* Decompose the LD_LIBRARY_PATH and fill in the result.
First search for the next place to enter elements. */ First search for the next place to enter elements. */
@ -402,7 +426,7 @@ _dl_init_paths (const char *llp)
/* We need to take care that the LD_LIBRARY_PATH environment /* We need to take care that the LD_LIBRARY_PATH environment
variable can contain a semicolon. */ variable can contain a semicolon. */
(void) fillin_rpath (copy, result, ":;", (void) fillin_rpath (copy, result, ":;",
__libc_enable_secure ? trusted_dirs : NULL, __libc_enable_secure ? system_dirs : NULL,
"LD_LIBRARY_PATH", NULL); "LD_LIBRARY_PATH", NULL);
} }
} }
@ -424,50 +448,10 @@ _dl_init_paths (const char *llp)
"cannot create cache for search path"); "cannot create cache for search path");
(void) fillin_rpath (local_strdup (llp), fake_path_list, ":;", (void) fillin_rpath (local_strdup (llp), fake_path_list, ":;",
__libc_enable_secure ? trusted_dirs : NULL, __libc_enable_secure ? system_dirs : NULL,
"LD_LIBRARY_PATH", NULL); "LD_LIBRARY_PATH", NULL);
} }
} }
/* Now set up the rest of the rtld_search_dirs. */
for (pelem = rtld_search_dirs; *pelem != NULL; ++pelem)
{
struct r_search_path_elem *relem = *pelem;
if (_dl_platform != NULL)
{
char *tmp, *orig;
relem->machdirnamelen = relem->dirnamelen + _dl_platformlen + 1;
tmp = (char *) malloc (relem->machdirnamelen + 1);
if (tmp == NULL)
_dl_signal_error (ENOMEM, NULL,
"cannot create cache for search path");
orig = tmp;
tmp = __mempcpy (tmp, relem->dirname, relem->dirnamelen);
tmp = __mempcpy (tmp, _dl_platform, _dl_platformlen);
*tmp++ = '/';
*tmp = '\0';
relem->dirname = orig;
relem->machdirstatus = unknown;
if (max_dirnamelen < relem->machdirnamelen)
max_dirnamelen = relem->machdirnamelen;
}
else
{
relem->machdirnamelen = relem->dirnamelen;
relem->machdirstatus = nonexisting;
if (max_dirnamelen < relem->dirnamelen)
max_dirnamelen = relem->dirnamelen;
}
relem->what = "system search path";
relem->where = NULL;
}
} }
@ -844,26 +828,26 @@ static void
print_search_path (struct r_search_path_elem **list, print_search_path (struct r_search_path_elem **list,
const char *what, const char *name) const char *what, const char *name)
{ {
char buf[max_dirnamelen + max_capstrlen];
char *endp;
int first = 1; int first = 1;
_dl_debug_message (1, " search path=", NULL); _dl_debug_message (1, " search path=", NULL);
while (*list != NULL && (*list)->what == what) /* Yes, ==. */ while (*list != NULL && (*list)->what == what) /* Yes, ==. */
{ {
char *buf = strdupa ((*list)->dirname); char *endp = __mempcpy (buf, (*list)->dirname, (*list)->dirnamelen);
size_t cnt;
for (cnt = 0; cnt < ncapstr; ++cnt)
if ((*list)->status[cnt] != nonexisting)
{
char *cp = __mempcpy (endp, capstr[cnt].str, capstr[cnt].len);
cp[-1] = '\0';
_dl_debug_message (0, first ? "" : ":", buf, NULL);
first = 0;
}
if ((*list)->machdirstatus != nonexisting)
{
buf[(*list)->machdirnamelen - 1] = '\0';
_dl_debug_message (0, first ? "" : ":", buf, NULL);
first = 0;
}
if ((*list)->dirstatus != nonexisting)
{
buf[(*list)->dirnamelen - 1] = '\0';
_dl_debug_message (0, first ? "" : ":", buf, NULL);
first = 0;
}
++list; ++list;
} }
@ -893,11 +877,12 @@ open_path (const char *name, size_t namelen, int preloaded,
return -1; return -1;
} }
buf = __alloca (max_dirnamelen + namelen); buf = __alloca (max_dirnamelen + max_capstrlen + namelen + 1);
do do
{ {
struct r_search_path_elem *this_dir = *dirs; struct r_search_path_elem *this_dir = *dirs;
size_t buflen = 0; size_t buflen = 0;
size_t cnt;
/* If we are debugging the search for libraries print the path /* If we are debugging the search for libraries print the path
now if it hasn't happened now. */ now if it hasn't happened now. */
@ -907,95 +892,43 @@ open_path (const char *name, size_t namelen, int preloaded,
print_search_path (dirs, current_what, this_dir->where); print_search_path (dirs, current_what, this_dir->where);
} }
if (this_dir->machdirstatus != nonexisting) for (cnt = 0; fd == -1 && cnt < ncapstr; ++cnt)
{ {
/* Construct the pathname to try. */ /* Skip this directory if we know it does not exist. */
buflen = ((char *) __mempcpy (__mempcpy (buf, this_dir->dirname, if (this_dir->status[cnt] == nonexisting)
this_dir->machdirnamelen), continue;
name, namelen)
- buf);
/* Print name we try if this is wanted. */ buflen =
if (_dl_debug_libs) ((char *) __mempcpy (__mempcpy (__mempcpy (buf, this_dir->dirname,
_dl_debug_message (1, " trying file=", buf, "\n", NULL); this_dir->dirnamelen),
capstr[cnt].str, capstr[cnt].len),
fd = __open (buf, O_RDONLY); name, namelen)
if (this_dir->machdirstatus == unknown) - buf);
if (fd != -1)
this_dir->machdirstatus = existing;
else
{
/* We failed to open machine dependent library. Let's
test whether there is any directory at all. */
struct stat st;
buf[this_dir->machdirnamelen - 1] = '\0';
if (__xstat (_STAT_VER, buf, &st) != 0
|| ! S_ISDIR (st.st_mode))
/* The directory does not exist ot it is no directory. */
this_dir->machdirstatus = nonexisting;
else
this_dir->machdirstatus = existing;
}
if (fd != -1 && preloaded && __libc_enable_secure)
{
/* This is an extra security effort to make sure nobody can
preload broken shared objects which are in the trusted
directories and so exploit the bugs. */
struct stat st;
if (__fxstat (_STAT_VER, fd, &st) != 0
|| (st.st_mode & S_ISUID) == 0)
{
/* The shared object cannot be tested for being SUID
or this bit is not set. In this case we must not
use this object. */
__close (fd);
fd = -1;
/* We simply ignore the file, signal this by setting
the error value which would have been set by `open'. */
errno = ENOENT;
}
}
}
else
errno = ENOENT;
if (fd == -1 && errno == ENOENT && this_dir->dirstatus != nonexisting)
{
/* Construct the pathname to try. */
buflen = ((char *) __mempcpy (__mempcpy (buf, this_dir->dirname,
this_dir->dirnamelen),
name, namelen)
- buf);
/* Print name we try if this is wanted. */ /* Print name we try if this is wanted. */
if (_dl_debug_libs) if (_dl_debug_libs)
_dl_debug_message (1, " trying file=", buf, "\n", NULL); _dl_debug_message (1, " trying file=", buf, "\n", NULL);
fd = __open (buf, O_RDONLY); fd = __open (buf, O_RDONLY);
if (this_dir->dirstatus == unknown) if (this_dir->status[cnt] == unknown)
if (fd != -1) if (fd != -1)
this_dir->dirstatus = existing; this_dir->status[cnt] = existing;
else else
/* We failed to open library. Let's test whether there {
is any directory at all. */ /* We failed to open machine dependent library. Let's
if (this_dir->dirnamelen <= 1) test whether there is any directory at all. */
this_dir->dirstatus = existing; struct stat st;
else
{
struct stat st;
buf[this_dir->dirnamelen - 1] = '\0'; buf[this_dir->dirnamelen + capstr[cnt].len] = '\0';
if (__xstat (_STAT_VER, buf, &st) != 0
|| ! S_ISDIR (st.st_mode))
/* The directory does not exist ot it is no directory. */
this_dir->status[cnt] = nonexisting;
else
this_dir->status[cnt] = existing;
}
if (__xstat (_STAT_VER, buf, &st) != 0
|| ! S_ISDIR (st.st_mode))
/* The directory does not exist ot it is no directory. */
this_dir->dirstatus = nonexisting;
else
this_dir->dirstatus = existing;
}
if (fd != -1 && preloaded && __libc_enable_secure) if (fd != -1 && preloaded && __libc_enable_secure)
{ {
/* This is an extra security effort to make sure nobody can /* This is an extra security effort to make sure nobody can

View File

@ -60,9 +60,12 @@ struct r_search_path_elem
const char *what; const char *what;
const char *where; const char *where;
/* Basename for this search path element. The string must end with
a slash character. */
const char *dirname; const char *dirname;
size_t dirnamelen;
enum r_dir_status exists[0]; enum r_dir_status status[0];
}; };
struct r_strlenpair struct r_strlenpair
@ -137,6 +140,9 @@ extern int _dl_debug_files;
/* Expect cache ID. */ /* Expect cache ID. */
extern int _dl_correct_cache_id; extern int _dl_correct_cache_id;
/* Mask for important hardware capabilities we honour. */
extern unsigned long int _dl_hwcap_mask;
/* File deccriptor to write debug messages to. */ /* File deccriptor to write debug messages to. */
extern int _dl_debug_fd; extern int _dl_debug_fd;
@ -386,7 +392,10 @@ extern void _dl_show_auxv (void);
extern char *_dl_next_ld_env_entry (char ***position); extern char *_dl_next_ld_env_entry (char ***position);
/* Return an array with the names of the important hardware capabilities. */ /* Return an array with the names of the important hardware capabilities. */
extern char **_dl_important_hwcap (size_t *sz); extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
size_t paltform_len,
size_t *sz,
size_t *max_capstrlen);
__END_DECLS __END_DECLS

View File

@ -156,10 +156,6 @@ struct link_map
/* Collected information about own RPATH directories. */ /* Collected information about own RPATH directories. */
struct r_search_path_elem **l_rpath_dirs; struct r_search_path_elem **l_rpath_dirs;
/* Directory names composed from capability names. */
struct r_strlenpair *l_capstrs;
size_t l_ncapstrs;
/* Collected results of relocation while profiling. */ /* Collected results of relocation while profiling. */
ElfW(Addr) *l_reloc_result; ElfW(Addr) *l_reloc_result;

View File

@ -1112,6 +1112,12 @@ process_envvars (enum mode *modep, int *lazyp)
_dl_show_auxv (); _dl_show_auxv ();
break; break;
case 10:
/* mask for the important hardware capabilities. */
if (memcmp (&envline[3], "HWCAP_MASK", 10) == 0)
_dl_hwcap_mask = strtoul (&envline[14], NULL, 0);
break;
case 12: case 12:
/* Where to place the profiling data file. */ /* Where to place the profiling data file. */
if (memcmp (&envline[3], "DEBUG_OUTPUT", 12) == 0) if (memcmp (&envline[3], "DEBUG_OUTPUT", 12) == 0)

1
include/mntent.h Normal file
View File

@ -0,0 +1 @@
#include <misc/mntent.h>

View File

@ -18,7 +18,10 @@
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#include <elf.h> #include <elf.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -45,7 +48,8 @@ int __libc_enable_secure;
int __libc_multiple_libcs; /* Defining this here avoids the inclusion int __libc_multiple_libcs; /* Defining this here avoids the inclusion
of init-first. */ of init-first. */
static ElfW(auxv_t) *_dl_auxv; static ElfW(auxv_t) *_dl_auxv;
static unsigned long hwcap; static unsigned long int hwcap;
unsigned long int _dl_hwcap_mask = HWCAP_IMPORTANT;
#ifndef DL_FIND_ARG_COMPONENTS #ifndef DL_FIND_ARG_COMPONENTS
@ -273,18 +277,21 @@ _dl_next_ld_env_entry (char ***position)
/* Return an array of useful/necessary hardware capability names. */ /* Return an array of useful/necessary hardware capability names. */
const struct r_strlenpair * const struct r_strlenpair *
_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz) _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
size_t *max_capstrlen)
{ {
/* Determine how many important bits are set. */ /* Determine how many important bits are set. */
unsigned long int important = hwcap & HWCAP_IMPORTANT; unsigned long int mask = _dl_hwcap_mask;
size_t cnt = platform != NULL; size_t cnt = platform != NULL;
size_t n, m; size_t n, m;
size_t total; size_t total;
struct r_strlenpair *temp; struct r_strlenpair *temp;
struct r_strlenpair *result; struct r_strlenpair *result;
struct r_strlenpair *rp;
char *cp;
for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n) for (n = 0; (~((1UL << n) - 1) & mask) != 0; ++n)
if ((important & (1UL << n)) != 0) if ((mask & (1UL << n)) != 0)
++cnt; ++cnt;
if (cnt == 0) if (cnt == 0)
@ -298,22 +305,23 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz)
_dl_signal_error (ENOMEM, NULL, "cannot create capability list"); _dl_signal_error (ENOMEM, NULL, "cannot create capability list");
} }
result[0]->str = (char *) result; /* Does not really matter. */ result[0].str = (char *) result; /* Does not really matter. */
result[0]->len = 0; result[0].len = 0;
*sz = 1; *sz = 1;
return &only_base; return result;
} }
/* Create temporary data structure to generate result table. */ /* Create temporary data structure to generate result table. */
temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp)); temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
m = 0; m = 0;
for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n) for (n = 0; mask != 0; ++n)
if ((important & (1UL << n)) != 0) if ((mask & (1UL << n)) != 0)
{ {
temp[m].str = _dl_hwcap_string (n); temp[m].str = _dl_hwcap_string (n);
temp[m].len = strlen (temp[m].str); temp[m].len = strlen (temp[m].str);
++m mask ^= 1UL << n;
++m;
} }
if (platform != NULL) if (platform != NULL)
{ {
@ -322,36 +330,37 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz)
++m; ++m;
} }
if (cnt == 1)
{
result = (struct r_strlenpair *) malloc (2 * sizeof (*result)
+ temp[0].len + 1);
if (result == NULL)
goto no_memory;
result[0].str = (char *) (result + 1);
result[0].len = len;
result[1].str = (char *) (result + 1);
result[1].len = 0;
result[0].str[0] = '/';
memcpy (&result[0].str[1], temp[0].str, temp[0].len);
*sz = 2;
return result;
}
/* Determine the total size of all strings together. */ /* Determine the total size of all strings together. */
total = cnt * (temp[0].len + temp[cnt - 1].len + 2); if (cnt == 1)
for (n = 1; n + 1 < cnt; ++n) total = temp[0].len;
total += 2 * (temp[n].len + 1); else
{
total = (1 << (cnt - 2)) * (temp[0].len = temp[cnt - 1].len + 2);
for (n = 1; n + 1 < cnt; ++n)
total += (1 << (cnt - 3)) * (temp[n].len + 1);
}
/* The result structure: we use a very compressed way to store the /* The result structure: we use a very compressed way to store the
various combinations of capability names. */ various combinations of capability names. */
result = (struct r_strlenpair *) malloc (1 << (cnt - 2) * sizeof (*result) *sz = 1 << cnt;
+ total); result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
if (result == NULL) if (result == NULL)
goto no_memory; goto no_memory;
if (cnt == 1)
{
result[0].str = (char *) (result + *sz);
result[0].len = temp[0].len + 1;
result[1].str = (char *) (result + *sz);
result[1].len = 0;
cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
*cp = '/';
*sz = 2;
*max_capstrlen = result[0].len;
return result;
}
/* Fill in the information. This follows the following scheme /* Fill in the information. This follows the following scheme
(indeces from TEMP for four strings): (indeces from TEMP for four strings):
entry #0: 0, 1, 2, 3 binary: 1111 entry #0: 0, 1, 2, 3 binary: 1111
@ -360,35 +369,75 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz)
#3: 0, 3 1001 #3: 0, 3 1001
This allows to represent all possible combinations of capability This allows to represent all possible combinations of capability
names in the string. First generate the strings. */ names in the string. First generate the strings. */
n = 1 << cnt; result[1].str = result[0].str = cp = (char *) (result + *sz);
cp = result[0].str = (char *) (result + 1 << (cnt - 2)); #define add(idx) \
cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
if (cnt == 2)
{
add (1);
add (0);
}
else
{
n = 1 << cnt;
do
{
n -= 2;
/* We always add the last string. */
add (cnt - 1);
/* Add the strings which have the bit set in N. */
for (m = cnt - 2; m > 0; --m)
if ((n & (1 << m)) != 0)
add (m);
/* Always add the first string. */
add (0);
}
while (n != 0);
}
#undef add
/* Now we are ready to install the string pointers and length. */
for (n = 0; n < (1 << cnt); ++n)
result[n].len = 0;
n = cnt;
do do
{ {
#define add(idx) \ size_t mask = 1 << --n;
cp = __mempcpy (__mempcpy (cp, "/", 1), temp[idx].str, temp[idx].len)
n -= 2; rp = result;
for (m = 1 << cnt; m > 0; ++rp)
/* We always add the last string. */ if ((--m & mask) != 0)
add (cnt - 1); rp->len += temp[n].len + 1;
/* Add the strings which have the bit set in N. */
for (m = cnt - 2; cnt > 0; --cnt)
if ((n & (1 << m)) != 0)
add (m);
/* Always add the first string. */
add (0);
} }
while (n != 0); while (n != 0);
/* Now we are ready to install the string pointers and length. /* The first half of the strings all include the first string. */
The first string contains all strings. */ n = (1 << cnt) - 2;
result[0].len = 0; rp = &result[2];
for (n = 0; n < cnt; ++n) while (n != (1 << (cnt - 1)))
result[0].len += temp[n].len; {
if ((n & 1) != 0)
rp[0].str = rp[-2].str + rp[-2].len;
else
rp[0].str = rp[-1].str;
++rp;
--n;
}
I KNOW THIS DOES NOT YET WORK --drepper /* The second have starts right after the first part of the string of
corresponding entry in the first half. */
do
{
rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
++rp;
}
while (--n != 0);
/* The maximum string length. */
*max_capstrlen = result[0].len;
return result; return result;
} }