diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | elf/dl-load.c | 8 | ||||
-rw-r--r-- | elf/ldsodefs.h | 23 | ||||
-rw-r--r-- | elf/link.h | 4 | ||||
-rw-r--r-- | nss/nsswitch.c | 2 | ||||
-rw-r--r-- | resolv/netdb.h | 6 | ||||
-rw-r--r-- | sysdeps/generic/dl-sysdep.c | 119 |
7 files changed, 138 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog index 5400d1ac11..7b28c906cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 1998-03-30 Ulrich Drepper <drepper@cygnus.com> + * nss/nsswitch.c (__nss_lookup): Adjust comment. + * sysdeps/generic/dl-sysdep.c (_dl_important_hwcaps): New function. diff --git a/elf/dl-load.c b/elf/dl-load.c index c75a91392e..212b22307a 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -331,6 +331,10 @@ _dl_init_paths (const char *llp) variable. */ struct link_map *l; + /* Names of important hardware capabilities. */ + char **hwcap_names; + size_t nhwcap_names; + /* Number of elements in the library path. */ size_t nllp; @@ -347,6 +351,10 @@ _dl_init_paths (const char *llp) else nllp = 0; + /* Get the capabilities. */ + hwcap_names = _dl_important_hwcaps (&nhwcap_names, + _dl_platform, _dl_platformlen); + l = _dl_loaded; if (l != NULL) { diff --git a/elf/ldsodefs.h b/elf/ldsodefs.h index 3154bf2a2b..578e085d75 100644 --- a/elf/ldsodefs.h +++ b/elf/ldsodefs.h @@ -53,20 +53,22 @@ enum r_dir_status { unknown, nonexisting, existing }; struct r_search_path_elem { - const char *dirname; - - size_t dirnamelen; - enum r_dir_status dirstatus; - - size_t machdirnamelen; - enum r_dir_status machdirstatus; + /* This link is only used in the `all_dirs' member of `r_search_path'. */ + struct r_search_path_elem *next; /* Strings saying where the definition came from. */ const char *what; const char *where; - /* This link is only used in the `all_dirs' member of `r_search_path'. */ - struct r_search_path_elem *next; + const char *dirname; + + enum r_dir_status exists[0]; + }; + +struct r_strlenpair + { + const char *str; + size_t len; }; @@ -383,6 +385,9 @@ extern void _dl_show_auxv (void); other. */ extern char *_dl_next_ld_env_entry (char ***position); +/* Return an array with the names of the important hardware capabilities. */ +extern char **_dl_important_hwcap (size_t *sz); + __END_DECLS #endif /* ldsodefs.h */ diff --git a/elf/link.h b/elf/link.h index 30efa0ed25..edf1303595 100644 --- a/elf/link.h +++ b/elf/link.h @@ -156,6 +156,10 @@ struct link_map /* Collected information about own RPATH directories. */ 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. */ ElfW(Addr) *l_reloc_result; diff --git a/nss/nsswitch.c b/nss/nsswitch.c index ab0f850091..c968502cdf 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -135,7 +135,7 @@ __nss_database_lookup (const char *database, const char *alternate_name, /* -1 == not found - 0 == adjusted for next function + 0 == function found 1 == finished */ int __nss_lookup (service_user **ni, const char *fct_name, void **fctp) diff --git a/resolv/netdb.h b/resolv/netdb.h index fdfc056750..9282be334a 100644 --- a/resolv/netdb.h +++ b/resolv/netdb.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it @@ -49,13 +49,11 @@ extern int h_errno; extern int *__h_errno_location __P ((void)) __attribute__ ((__const__)); #ifdef _LIBC -/* Retain some binary compatibility with old libraries by having both the - global variable and the per-thread variable set on error. */ # ifdef _LIBC_REENTRANT static inline int __set_h_errno (int __err) { - return *__h_errno_location () = h_errno = __err; + return *__h_errno_location () = __err; } # else # define __set_h_errno(x) (h_errno = (x)) diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c index 7f5e32193a..a113c14c42 100644 --- a/sysdeps/generic/dl-sysdep.c +++ b/sysdeps/generic/dl-sysdep.c @@ -272,28 +272,123 @@ _dl_next_ld_env_entry (char ***position) } /* Return an array of useful/necessary hardware capability names. */ -char ** -_dl_important_hwcaps (size_t *sz) +const struct r_strlenpair * +_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz) { /* Determine how many important bits are set. */ unsigned long int important = hwcap & HWCAP_IMPORTANT; - size_t cnt = 0; - size_t n; - char **result; + size_t cnt = platform != NULL; + size_t n, m; + size_t total; + struct r_strlenpair *temp; + struct r_strlenpair *result; for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n) if ((important & (1UL << n)) != 0) ++cnt; - *sz = 0; if (cnt == 0) - return NULL; + { + /* If we have platform name and no important capability we only have + the base directory to search. */ + result = (struct r_strlenpair *) malloc (sizeof (*result)); + if (result == NULL) + { + no_memory: + _dl_signal_error (ENOMEM, NULL, "cannot create capability list"); + } + + result[0]->str = (char *) result; /* Does not really matter. */ + result[0]->len = 0; + + *sz = 1; + return &only_base; + } + + /* Create temporary data structure to generate result table. */ + temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp)); + m = 0; + for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n) + if ((important & (1UL << n)) != 0) + { + temp[m].str = _dl_hwcap_string (n); + temp[m].len = strlen (temp[m].str); + ++m + } + if (platform != NULL) + { + temp[m].str = platform; + temp[m].len = platform_len; + ++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. */ + total = cnt * (temp[0].len + temp[cnt - 1].len + 2); + for (n = 1; n + 1 < cnt; ++n) + total += 2 * (temp[n].len + 1); + + /* The result structure: we use a very compressed way to store the + various combinations of capability names. */ + result = (struct r_strlenpair *) malloc (1 << (cnt - 2) * sizeof (*result) + + total); + if (result == NULL) + goto no_memory; + + /* Fill in the information. This follows the following scheme + (indeces from TEMP for four strings): + entry #0: 0, 1, 2, 3 binary: 1111 + #1: 0, 1, 3 1101 + #2: 0, 2, 3 1011 + #3: 0, 3 1001 + This allows to represent all possible combinations of capability + names in the string. First generate the strings. */ + n = 1 << cnt; + cp = result[0].str = (char *) (result + 1 << (cnt - 2)); + do + { +#define add(idx) \ + cp = __mempcpy (__mempcpy (cp, "/", 1), temp[idx].str, temp[idx].len) + + 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; cnt > 0; --cnt) + if ((n & (1 << m)) != 0) + add (m); + + /* Always add the first string. */ + add (0); + } + while (n != 0); + + /* Now we are ready to install the string pointers and length. + The first string contains all strings. */ + result[0].len = 0; + for (n = 0; n < cnt; ++n) + result[0].len += temp[n].len; - result = (char **) malloc (cnt * sizeof (char *)); - if (result != NULL) - for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n) - if ((important & (1UL << n)) != 0) - result[*sz++] = _dl_hwcap_string (n); + I KNOW THIS DOES NOT YET WORK --drepper return result; } |