diff options
32 files changed, 787 insertions, 340 deletions
@@ -1,3 +1,91 @@ +1997-07-24 03:14 Ulrich Drepper <drepper@cygnus.com> + + * elf/dl-deps.c: Complete rewrite to handle DT_AUXILIARY correctly. + + * inet/Makefile (tests): Add htontest. + * inet/htontest.c: New file. + + * inet/netinet/in.h: Cleanup optimization of ntoh/hton functions + when they are no noops. + * sysdeps/alpha/htonl.S: Don't define __ protected names. + * sysdeps/alpha/htons.S: Likewise. + * sysdeps/generic/htonl.c: Likewise. + * sysdeps/generic/htons.c: Likewise. + * sysdeps/i386/htonl.S: Likewise. + * sysdeps/i386/htons.S: Likewise. + * sysdeps/i386/i486/htonl.S: Likewise. + * sysdeps/vax/htonl.s: Likewise. + * sysdeps/vax/htons.s: Likewise. + + * string/Makefile (headers): Add byteswap.h and bits/byteswap.h. + * string/byteswap.h: New file. + * sysdeps/generic/bits/byteswap.h: New file. + * sysdeps/i386/bits/byteswap.h: New file. + * sysdeps/generic/bits/htontoh.h: Removed. + * sysdeps/i386/bits/htontoh.h: Removed. + + * misc/search.h: General cleanup. Don't define reentrant hsearch + functions uless __USE_GNU. + + * nss/nsswitch.c: Pretty print. + + * sunrpc/clnt_udp.c (clntudp_call): Initialize outlen to prevent + warning. + + * sysdeps/unix/i386/sysdep.h (DO_CALL): Use lcall, binutils have + been fixed meanwhile. + Reported by Zack Weinberg <zack@rabi.phys.columbia.edu>. + +1997-07-24 00:53 Philip Blundell <Philip.Blundell@pobox.com> + + * db/hash/hash.c (init_hash): Only use statbuf.st_blksize if it + exists for this port. + +1997-07-24 00:12 Philip Blundell <Philip.Blundell@pobox.com> + + * sysdeps/standalone/arm/bits/errno.h (ESTALE): Add. + +1997-07-22 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * manual/argp.texi (Argp Option Vectors): Use @minus, not @math, + to format a proper minus sign. + +1997-07-22 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/m68k/fpu/fraiseexcpt.c: Don't handle FE_INEXACT + specially, the standard doesn't require it. + + * math/test-fenv.c (test_exceptions): Add IGNORE_INEXACT argument, + if non-zero then don't test inexact flag. Callers changed. + (set_single_exc): Ignore inexact flag if underflow or overflow + exception is raised. + +1997-07-23 05:10 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/unix/sysv/linux/sys/fsuid.h: New file. + Provided by Michael Deutschmann <ldeutsch@mail.netshop.net>. + * sysdeps/unix/sysv/linux/Makefile (headers): Add sys/fsuid.h. + * sysdeps/unix/sysv/linux/Dist: Add sys/fsuid.h. + +1997-07-16 10:09 Fila Kolodny <fila@ibi.com> + + * resolv/gethnamaddr.c: Define MAXHOSTNAMELEN as 256, since RFC 1034 + and 1035 state that a fully qualified domain name cannot exceed 255 + octets in length. + * resolv/nss_dns/dns-host.c: Likewise. + +1997-07-22 09:54 H.J. Lu <hjl@gnu.ai.mit.edu> + + * inet/netinet/in.h (htons): Fix typos. + + * sysdeps/i386/bits/htontoh.h (__ntohs): Return the value. + +1997-07-22 11:47 Ulrich Drepper <drepper@cygnus.com> + + * nss/nsswitch.c (nss_lookup_function): Include function.def, not + functions.def. + Patch by Klaus Espenlaub <kespenla@hydra.informatik.uni-ulm.de>. + 1997-07-22 01:35 Ulrich Drepper <drepper@cygnus.com> * Makerules (+make-deps): Use $(CFLAGS) in run of $(+mkdep) so diff --git a/bits/byteswap.h b/bits/byteswap.h new file mode 100644 index 0000000000..9404cc452e --- /dev/null +++ b/bits/byteswap.h @@ -0,0 +1,43 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +/* Swap bytes in 32 bit value. */ +#define __bswap_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_64(x) \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __v, __r; \ + __v.__ll = (x); \ + __r.__l[0] = __bswap_32 (__v.__l[1]); \ + __r.__l[1] = __bswap_32 (__v.__l[0]); \ + __r.__ll; }) +#endif + +#endif /* bits/byteswap.h */ diff --git a/elf/dl-deps.c b/elf/dl-deps.c index e2fd340822..36f5ee0606 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -22,17 +22,27 @@ #include <dlfcn.h> #include <stdlib.h> +#include <assert.h> + +/* Whether an shared object references one or more auxiliary objects + is signaled by the AUXTAG entry in l_info. */ +#define AUXTAG (DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM \ + + DT_EXTRATAGIDX (DT_AUXILIARY)) + + +/* When loading auxiliary objects we must ignore errors. It's ok if + an object is missing. */ struct openaux_args -{ - /* The arguments to openaux. */ - struct link_map *map; - int trace_mode; - const char *strtab; - ElfW(Dyn) *d; + { + /* The arguments to openaux. */ + struct link_map *map; + int trace_mode; + const char *strtab; + const ElfW(Dyn) *d; - /* The return value of openaux. */ - struct link_map *aux; -}; + /* The return value of openaux. */ + struct link_map *aux; + }; static void openaux (void *a) @@ -45,78 +55,56 @@ openaux (void *a) args->trace_mode); } + + +/* We use a very special kind of list to track the three kinds paths + through the list of loaded shared objects. We have to + + - go through all objects in the correct order, which includes the + possible recursive loading of auxiliary objects and dependencies + + - produce a flat list with unique members of all involved objects + + - produce a flat list of all shared objects. +*/ +struct list + { + int done; /* Nonzero if this map was processed. */ + struct link_map *map; /* The data. */ + + struct list *unique; /* Elements for normal list. */ + struct list *dup; /* Elements in complete list. */ + }; + + void _dl_map_object_deps (struct link_map *map, struct link_map **preloads, unsigned int npreloads, int trace_mode) { - struct list - { - struct link_map *map; - struct list *next; - }; - struct list *head, *tailp, *scanp; - struct list duphead, *duptailp; - unsigned int nduplist; - unsigned int nlist, naux, i; + struct list known[1 + npreloads + 1]; + struct list *runp, *head, *utail, *dtail; + unsigned int nlist, nduplist, i; + inline void preload (struct link_map *map) { - head[nlist].next = &head[nlist + 1]; - head[nlist++].map = map; + known[nlist].done = 0; + known[nlist].map = map; + + known[nlist].unique = &known[nlist + 1]; + known[nlist].dup = &known[nlist + 1]; + ++nlist; /* We use `l_reserved' as a mark bit to detect objects we have already put in the search list and avoid adding duplicate elements later in the list. */ map->l_reserved = 1; } - naux = nlist = 0; - - /* XXX The AUXILIARY implementation isn't correct in the moment. XXX - XXX The problem is that we currently do not handle auxiliary XXX - XXX entries in the loaded objects. XXX */ - -#define AUXTAG (DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM \ - + DT_EXTRATAGIDX (DT_AUXILIARY)) - - /* First determine the number of auxiliary objects we have to load. */ - if (map->l_info[AUXTAG]) - { - ElfW(Dyn) *d; - for (d = map->l_ld; d->d_tag != DT_NULL; ++d) - if (d->d_tag == DT_AUXILIARY) - ++naux; - } - - /* Now we can allocate the array for the linker maps. */ - head = (struct list *) alloca (sizeof (struct list) - * (naux + npreloads + 2)); - - /* Load the auxiliary objects, even before the object itself. */ - if (map->l_info[AUXTAG]) - { - /* There is at least one auxiliary library specified. We try to - load it, and if we can, use its symbols in preference to our - own. But if we can't load it, we just silently ignore it. */ - struct openaux_args args; - args.strtab - = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr); - args.map = map; - args.trace_mode = trace_mode; - - for (args.d = map->l_ld; args.d->d_tag != DT_NULL; ++args.d) - if (args.d->d_tag == DT_AUXILIARY) - { - char *errstring; - const char *objname; - if (! _dl_catch_error (&errstring, &objname, openaux, &args)) - /* The auxiliary object is actually there. Use it as - the first search element, even before MAP itself. */ - preload (args.aux); - } - } + /* No loaded object so far. */ + nlist = 0; - /* Next load MAP itself. */ + /* First load MAP itself. */ preload (map); /* Add the preloaded items after MAP but before any of its dependencies. */ @@ -124,30 +112,51 @@ _dl_map_object_deps (struct link_map *map, preload (preloads[i]); /* Terminate the lists. */ - head[nlist - 1].next = NULL; - duphead.next = NULL; + known[nlist - 1].unique = NULL; + known[nlist - 1].dup = NULL; + + /* Pointer to the first member of the unique and duplicate list. */ + head = known; - /* Start here for adding dependencies to the list. */ - tailp = &head[nlist - 1]; + /* Pointer to last unique object. */ + utail = &known[nlist - 1]; + /* Pointer to last loaded object. */ + dtail = &known[nlist - 1]; /* Until now we have the same number of libraries in the normal and the list with duplicates. */ nduplist = nlist; - duptailp = &duphead; - /* Process each element of the search list, loading each of its immediate - dependencies and appending them to the list as we step through it. - This produces a flat, ordered list that represents a breadth-first - search of the dependency tree. */ - for (scanp = head; scanp; scanp = scanp->next) + /* Process each element of the search list, loading each of its + auxiliary objects and immediate dependencies. Auxiliary objects + will be added in the list before the object itself and + dependencies will be appended to the list as we step through it. + This produces a flat, ordered list that represents a + breadth-first search of the dependency tree. + + The whole process is complicated by the fact that we better + should use alloca for the temporary list elements. But using + alloca means we cannot use recursive function calls. */ + for (runp = known; runp; ) { - struct link_map *l = scanp->map; + struct link_map *l = runp->map; - if (l->l_info[DT_NEEDED]) + if (runp->done == 0 && (l->l_info[AUXTAG] || l->l_info[DT_NEEDED])) { - const char *strtab - = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); + const char *strtab = ((void *) l->l_addr + + l->l_info[DT_STRTAB]->d_un.d_ptr); + struct openaux_args args; + struct list *orig; const ElfW(Dyn) *d; + + /* Mark map as processed. */ + runp->done = 1; + + args.strtab = strtab; + args.map = l; + args.trace_mode = trace_mode; + orig = runp; + for (d = l->l_ld; d->d_tag != DT_NULL; ++d) if (d->d_tag == DT_NEEDED) { @@ -156,32 +165,182 @@ _dl_map_object_deps (struct link_map *map, = _dl_map_object (l, strtab + d->d_un.d_val, l->l_type == lt_executable ? lt_library : l->l_type, trace_mode); + /* Allocate new entry. */ + struct list *newp = alloca (sizeof (struct list)); + + /* Add it in any case to the duplicate list. */ + newp->map = dep; + newp->dup = NULL; + dtail->dup = newp; + dtail = newp; + ++nduplist; if (dep->l_reserved) /* This object is already in the search list we are - building. Don't add a duplicate pointer. Release the - reference just added by _dl_map_object. */ + building. Don't add a duplicate pointer. + Release the reference just added by + _dl_map_object. */ --dep->l_opencount; else { - /* Append DEP to the search list. */ - tailp->next = alloca (sizeof *tailp); - tailp = tailp->next; - tailp->map = dep; - tailp->next = NULL; + /* Append DEP to the unique list. */ + newp->done = 0; + newp->unique = NULL; + utail->unique = newp; + utail = newp; ++nlist; /* Set the mark bit that says it's already in the list. */ dep->l_reserved = 1; } + } + else if (d->d_tag == DT_AUXILIARY) + { + char *errstring; + const char *objname; - /* In any case append DEP to the duplicates search list. */ - duptailp->next = alloca (sizeof *duptailp); - duptailp = duptailp->next; - duptailp->map = dep; - duptailp->next = NULL; - ++nduplist; + /* Store the tag in the argument structure. */ + args.d = d; + + if (_dl_catch_error (&errstring, &objname, openaux, &args)) + { + /* We are not interested in the error message. */ + assert (errstring != NULL); + free (errstring); + } + else + { + /* The auxiliary object is actually available. + Incorporate the map in all the lists. */ + + /* Allocate new entry. This always has to be done. */ + struct list *newp = alloca (sizeof (struct list)); + + /* Copy the content of the current entry over. */ + memcpy (newp, orig, sizeof (*newp)); + + /* Initialize new entry. */ + orig->done = 0; + orig->map = args.aux; + orig->dup = newp; + + /* We must handle two situations here: the map is new, + so we must add it in all three lists. If the map + is already known, we have two further possibilities: + - if the object is before the current map in the + search list, we do nothing. It is already found + early + - if the object is after the current one, we must + move it just before the current map to make sure + the symbols are found early enough + */ + if (args.aux->l_reserved) + { + /* The object is already somewhere in the + list. Locate it first. */ + struct list *late; + + /* This object is already in the search list + we are building. Don't add a duplicate + pointer. Release the reference just added + by _dl_map_object. */ + --args.aux->l_opencount; + + for (late = orig; late->unique; late = late->unique) + if (late->unique->map == args.aux) + break; + + if (late->unique) + { + /* The object is somewhere behind the current + position in the search path. We have to + move it to this earlier position. */ + orig->unique = newp; + + /* Now remove the later entry from the unique + list. */ + late->unique = late->unique->unique; + + /* We must move the earlier in the chain. */ + if (args.aux->l_prev) + args.aux->l_prev->l_next = args.aux->l_next; + if (args.aux->l_next) + args.aux->l_next->l_prev = args.aux->l_prev; + + args.aux->l_prev = newp->map->l_prev; + newp->map->l_prev = args.aux; + if (args.aux->l_prev != NULL) + args.aux->l_prev->l_next = args.aux; + args.aux->l_next = newp->map; + } + else + { + /* The object must be somewhere earlier in + the list. That's good, we only have to + insert an entry for the duplicate list. */ + orig->unique = NULL; /* Never used. */ + + /* Now we have a problem. The element pointing + to ORIG in the unique list must point to + NEWP now. This is the only place where we + need this backreference and this situation + is really not that frequent. So we don't + use a double-linked list but instead search + for the preceding element. */ + late = head; + while (late->unique != orig) + late = late->unique; + late->unique = newp; + } + } + else + { + /* This is easy. We just add the symbol right + here. */ + orig->unique = newp; + ++nlist; + /* Set the mark bit that says it's already in + the list. */ + args.aux->l_reserved = 1; + + /* The only problem is that in the double linked + list of |
