aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--elf/dl-load.c8
-rw-r--r--elf/ldsodefs.h23
-rw-r--r--elf/link.h4
-rw-r--r--nss/nsswitch.c2
-rw-r--r--resolv/netdb.h6
-rw-r--r--sysdeps/generic/dl-sysdep.c119
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;
}