1997-07-26 04:14  Ulrich Drepper  <drepper@cygnus.com>

	* elf/Makefile (distribute): Add genrtldtbl.awk.
	(before-compile): Add rtldtbl.h.
	(GAWK): New variable.
	(generated): Add trusted-dirs.h and rtldtbl.h.
	($(objpfx)rtldtbl.h): New rule.  File is needed by dl-load.c.
	* elf/dl-load.c: Rewrite.  Now use cache and look for shared
	objects in machine dependent directories.
	* elf/dl-object.c (_dl_new_object): Initialize l_rpath_dirs member.
	* elf/dl-support.c: Rename function to non_dynamic_init and add
	initialization for _dl_platform, _dl_platformlen, _dl_pagesize
	and call to initializer for search path.
	* elf/elf.h: Add AT_PLATFORM and AT_HWCAP.
	* elf/genrtldtbl.awk: New file.
	* elf/link.h: Add type definitions and declarations for search
	path cache.
	* elf/rtld.c: Add definitions of variables used for search path cache.
	* sysdeps/generic/dl-sysdep.c: Let auxiliary vector initialize
	_dl_platform.  Initialize _dl_pagesize early and use this value.
	* sysdeps/i386/dl-machine.h: Add code for _dl_platform handling.
	* sysdeps/mach/hurd/dl-sysdep.c: Initialize _dl_pagesize.
	* sysdeps/unix/sysv/linux/dl-sysdep.c: Use _dl_pagesize instead
	of calling getpagesize.

	* elf/dl-error.c (_dl_signal_error): Make message nicer.

	* nss/libnss_files.map: Fix typo.
	Reported by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>.

	* sysdeps/generic/strsep.c: Optimize case where separator set contains
	only one character.

	* sysdeps/libm-ieee754/s_ccosh.c: Correct sign of result for real
	== +-Inf.
	* sysdeps/libm-ieee754/s_ccoshf.c: Likewise.
	* sysdeps/libm-ieee754/s_ccoshl.c: Likewise.

1997-07-25 09:15  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* sysdeps/sparc/udiv_qrnnd.S: Check PIC instead of __PIC__.
	* sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S: Likewise.
	* sysdeps/unix/mips/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/mips/clone.S: Likewise.

	* sysdeps/mips/bsd-_setjmp.S: Remove __PIC__ comment.
	* sysdeps/mips/bsd-setjmp.S: Likewise.

	* sysdeps/mips/dl-machine.h: Remove extra stuff.
	* sysdeps/mips/mips64/dl-machine.h: Likewise.

1997-07-25 18:55  Philip Blundell  <Philip.Blundell@pobox.com>

	* sysdeps/standalone/arm/sysdep.c: New file.

1997-07-25 13:25  Philip Blundell  <Philip.Blundell@pobox.com>

	* aout/Makefile: New file.
	* Makeconfig (binfmt-subdir): Assume a.out when not ELF.

	* sysdeps/generic/machine-gmon.h: Add warning about limitations of
	__builtin_return_address().
	* sysdeps/arm/machine-gmon.h: New file, use assembly to avoid
	above problem.

1997-07-25 16:24  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* elf/dl-deps.c (_dl_map_object_deps): Fix a typo.

1997-07-22  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* math/libm-test.c (ccos_test, ccosh_test): Fix sign in some
	tests.

1997-07-24  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sunrpc/clnt_udp.c (clntudp_call): Rename cu_wait from timeout to
	not shadow the variable in the outer scope.
This commit is contained in:
Ulrich Drepper 1997-07-26 02:33:30 +00:00
parent 1522c3682c
commit 0a54e4010f
36 changed files with 798 additions and 218 deletions

View File

@ -1,3 +1,82 @@
1997-07-26 04:14 Ulrich Drepper <drepper@cygnus.com>
* elf/Makefile (distribute): Add genrtldtbl.awk.
(before-compile): Add rtldtbl.h.
(GAWK): New variable.
(generated): Add trusted-dirs.h and rtldtbl.h.
($(objpfx)rtldtbl.h): New rule. File is needed by dl-load.c.
* elf/dl-load.c: Rewrite. Now use cache and look for shared
objects in machine dependent directories.
* elf/dl-object.c (_dl_new_object): Initialize l_rpath_dirs member.
* elf/dl-support.c: Rename function to non_dynamic_init and add
initialization for _dl_platform, _dl_platformlen, _dl_pagesize
and call to initializer for search path.
* elf/elf.h: Add AT_PLATFORM and AT_HWCAP.
* elf/genrtldtbl.awk: New file.
* elf/link.h: Add type definitions and declarations for search
path cache.
* elf/rtld.c: Add definitions of variables used for search path cache.
* sysdeps/generic/dl-sysdep.c: Let auxiliary vector initialize
_dl_platform. Initialize _dl_pagesize early and use this value.
* sysdeps/i386/dl-machine.h: Add code for _dl_platform handling.
* sysdeps/mach/hurd/dl-sysdep.c: Initialize _dl_pagesize.
* sysdeps/unix/sysv/linux/dl-sysdep.c: Use _dl_pagesize instead
of calling getpagesize.
* elf/dl-error.c (_dl_signal_error): Make message nicer.
* nss/libnss_files.map: Fix typo.
Reported by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>.
* sysdeps/generic/strsep.c: Optimize case where separator set contains
only one character.
* sysdeps/libm-ieee754/s_ccosh.c: Correct sign of result for real
== +-Inf.
* sysdeps/libm-ieee754/s_ccoshf.c: Likewise.
* sysdeps/libm-ieee754/s_ccoshl.c: Likewise.
1997-07-25 09:15 H.J. Lu <hjl@gnu.ai.mit.edu>
* sysdeps/sparc/udiv_qrnnd.S: Check PIC instead of __PIC__.
* sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S: Likewise.
* sysdeps/unix/mips/sysdep.S: Likewise.
* sysdeps/unix/sysv/linux/mips/clone.S: Likewise.
* sysdeps/mips/bsd-_setjmp.S: Remove __PIC__ comment.
* sysdeps/mips/bsd-setjmp.S: Likewise.
* sysdeps/mips/dl-machine.h: Remove extra stuff.
* sysdeps/mips/mips64/dl-machine.h: Likewise.
1997-07-25 18:55 Philip Blundell <Philip.Blundell@pobox.com>
* sysdeps/standalone/arm/sysdep.c: New file.
1997-07-25 13:25 Philip Blundell <Philip.Blundell@pobox.com>
* aout/Makefile: New file.
* Makeconfig (binfmt-subdir): Assume a.out when not ELF.
* sysdeps/generic/machine-gmon.h: Add warning about limitations of
__builtin_return_address().
* sysdeps/arm/machine-gmon.h: New file, use assembly to avoid
above problem.
1997-07-25 16:24 H.J. Lu <hjl@gnu.ai.mit.edu>
* elf/dl-deps.c (_dl_map_object_deps): Fix a typo.
1997-07-22 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* math/libm-test.c (ccos_test, ccosh_test): Fix sign in some
tests.
1997-07-24 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* sunrpc/clnt_udp.c (clntudp_call): Rename cu_wait from timeout to
not shadow the variable in the outer scope.
1997-07-24 03:14 Ulrich Drepper <drepper@cygnus.com> 1997-07-24 03:14 Ulrich Drepper <drepper@cygnus.com>
* elf/dl-deps.c: Complete rewrite to handle DT_AUXILIARY correctly. * elf/dl-deps.c: Complete rewrite to handle DT_AUXILIARY correctly.

View File

@ -88,7 +88,8 @@ include $(common-objpfx)config.make
ifeq ($(elf),yes) ifeq ($(elf),yes)
binfmt-subdir = elf binfmt-subdir = elf
else else
binfmt-subdir = # This is probably better than nothing.
binfmt-subdir = aout
endif endif
# Complete path to sysdep dirs. # Complete path to sysdep dirs.

View File

@ -302,7 +302,9 @@ init_hash(hashp, file, info)
if (file != NULL) { if (file != NULL) {
if (stat(file, &statbuf)) if (stat(file, &statbuf))
return (NULL); return (NULL);
#if defined _STATBUF_ST_BLKSIZE
hashp->BSIZE = statbuf.st_blksize; hashp->BSIZE = statbuf.st_blksize;
#endif
hashp->BSHIFT = __hash_log2(hashp->BSIZE); hashp->BSHIFT = __hash_log2(hashp->BSIZE);
} }

View File

@ -35,15 +35,18 @@ elide-routines.so = $(dl-routines) dl-support enbl-secure
# interpreter and operating independent of libc. # interpreter and operating independent of libc.
rtld-routines := rtld $(dl-routines) dl-sysdep dl-minimal rtld-routines := rtld $(dl-routines) dl-sysdep dl-minimal
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
dl-hash.h soinit.c sofini.c ldd.sh.in ldd.bash.in eval.c dl-hash.h soinit.c sofini.c ldd.sh.in ldd.bash.in eval.c \
genrtldtbl.awk
extra-libs = libdl extra-libs = libdl
extra-libs-others = $(extra-libs) extra-libs-others = $(extra-libs)
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr
libdl-map := libdl.map libdl-map := libdl.map
before-compile = $(objpfx)trusted-dirs.h before-compile = $(objpfx)trusted-dirs.h $(objpfx)rtldtbl.h
# We need GNU awk for the genrtldtbl.awk script.
GAWK = gawk
all: # Make this the default target; it will be defined in Rules. all: # Make this the default target; it will be defined in Rules.
@ -51,7 +54,7 @@ include ../Makeconfig
ifeq (yes,$(build-shared)) ifeq (yes,$(build-shared))
extra-objs = $(rtld-routines:=.so) soinit.so sofini.so eval.so extra-objs = $(rtld-routines:=.so) soinit.so sofini.so eval.so
generated = librtld.so dl-allobjs.so generated = librtld.so dl-allobjs.so trusted-dirs.h rtldtbl.h
install-others = $(inst_slibdir)/$(rtld-installed-name) install-others = $(inst_slibdir)/$(rtld-installed-name)
install-bin = ldd install-bin = ldd
endif endif
@ -143,6 +146,10 @@ $(objpfx)trusted-dirs.h: Makefile
echo " \"$$dir\","; \ echo " \"$$dir\","; \
done;) > $@T done;) > $@T
mv -f $@T $@ mv -f $@T $@
$(objpfx)rtldtbl.h: Makefile
$(make-target-directory)
echo "$(default-rpath)" | $(GAWK) -f genrtldtbl.awk > $@T
mv -f $@T $@
CPPFLAGS-dl-load.c = -I$(objdir)/$(subdir) CPPFLAGS-dl-load.c = -I$(objdir)/$(subdir)
CFLAGS-dl-load.c += -Wno-uninitialized CFLAGS-dl-load.c += -Wno-uninitialized

View File

@ -57,12 +57,9 @@ openaux (void *a)
/* We use a very special kind of list to track the three kinds paths /* We use a very special kind of list to track the two kinds paths
through the list of loaded shared objects. We have to 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 with unique members of all involved objects
- produce a flat list of all shared objects. - produce a flat list of all shared objects.
@ -141,7 +138,7 @@ _dl_map_object_deps (struct link_map *map,
{ {
struct link_map *l = runp->map; struct link_map *l = runp->map;
if (runp->done == 0 && (l->l_info[AUXTAG] || l->l_info[DT_NEEDED])) if (l->l_info[AUXTAG] || l->l_info[DT_NEEDED])
{ {
const char *strtab = ((void *) l->l_addr const char *strtab = ((void *) l->l_addr
+ l->l_info[DT_STRTAB]->d_un.d_ptr); + l->l_info[DT_STRTAB]->d_un.d_ptr);
@ -371,6 +368,6 @@ _dl_map_object_deps (struct link_map *map,
"cannot allocate symbol search list"); "cannot allocate symbol search list");
for (nlist = 0, runp = head; runp; runp = runp->dup) for (nlist = 0, runp = head; runp; runp = runp->dup)
map->l_searchlist[nlist++] = runp->map; map->l_dupsearchlist[nlist++] = runp->map;
} }
} }

View File

@ -75,7 +75,7 @@ _dl_signal_error (int errcode,
/* Lossage while resolving the program's own symbols is always fatal. */ /* Lossage while resolving the program's own symbols is always fatal. */
extern char **_dl_argv; /* Set in rtld.c at startup. */ extern char **_dl_argv; /* Set in rtld.c at startup. */
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>", _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
": error in loading shared libraries\n", ": error in loading shared libraries",
objname ?: "", objname ? ": " : "", objname ?: "", objname ? ": " : "",
errstring, errcode ? ": " : "", errstring, errcode ? ": " : "",
errcode ? strerror (errcode) : "", "\n", NULL); errcode ? strerror (errcode) : "", "\n", NULL);

View File

@ -1,4 +1,4 @@
/* _dl_map_object -- Map in a shared object's segments from the file. /* Map in a shared object's segments from the file.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -17,14 +17,15 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#include <link.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <link.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "dynamic-link.h" #include "dynamic-link.h"
@ -90,6 +91,8 @@ ELF_PREFERRED_ADDRESS_DATA;
size_t _dl_pagesize; size_t _dl_pagesize;
extern const char *_dl_platform;
extern size_t _dl_platformlen;
/* Local version of `strdup' function. */ /* Local version of `strdup' function. */
static inline char * static inline char *
@ -105,6 +108,292 @@ local_strdup (const char *s)
} }
/* Implement cache for search path lookup. */
#if 0
/* This is how generated should look like. I'll remove this once I'm
sure everything works correctly. */
static struct r_search_path_elem rtld_search_dir1 =
{ "/lib/", 5, unknown, 0, unknown, NULL };
static struct r_search_path_elem rtld_search_dir2 =
{ "/usr/lib/", 9, unknown, 0, unknown, &r ld_search_dir1 };
static struct r_search_path_elem *rtld_search_dirs[] =
{
&rtld_search_dir1,
&rtld_search_dir2,
NULL
};
static struct r_search_path_elem *all_dirs = &rtld_search_dir2;
#else
# include "rtldtbl.h"
#endif
static size_t max_dirnamelen;
static inline struct r_search_path_elem **
fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
const char **trusted)
{
char *cp;
size_t nelems = 0;
while ((cp = __strsep (&rpath, sep)) != NULL)
{
struct r_search_path_elem *dirp;
size_t len = strlen (cp);
/* Remove trailing slashes. */
while (len > 1 && cp[len - 1] == '/')
--len;
/* Make sure we don't use untrusted directories if we run SUID. */
if (trusted != NULL)
{
const char **trun = trusted;
/* All trusted directory must be complete name. */
if (cp[0] != '/')
continue;
while (*trun != NULL
&& (memcmp (*trun, cp, len) != 0 || (*trun)[len] != '\0'))
++trun;
if (*trun == NULL)
/* It's no trusted directory, skip it. */
continue;
}
/* Now add one. */
if (len > 0)
cp[len++] = '/';
/* See if this directory is already known. */
for (dirp = all_dirs; dirp != NULL; dirp = dirp->next)
if (dirp->dirnamelen == len && strcmp (cp, dirp->dirname) == 0)
break;
if (dirp != NULL)
{
/* It is available, see whether it's in our own list. */
size_t cnt;
for (cnt = 0; cnt < nelems; ++cnt)
if (result[cnt] == dirp)
break;
if (cnt == nelems)
result[nelems++] = dirp;
}
else
{
/* It's a new directory. Create an entry and add it. */
dirp = (struct r_search_path_elem *) malloc (sizeof (*dirp));
if (dirp == NULL)
_dl_signal_error (ENOMEM, NULL,
"cannot create cache for search path");
dirp->dirnamelen = len;
dirp->dirstatus = unknown;
/* Add the name of the machine dependent directory if a machine
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");
memcpy (tmp, cp, len);
memcpy (tmp + len, _dl_platform, _dl_platformlen);
tmp[len + _dl_platformlen] = '/';
tmp[len + _dl_platformlen + 1] = '\0';
dirp->dirname = tmp;
dirp->machdirstatus = unknown;
if (max_dirnamelen < dirp->machdirnamelen)
max_dirnamelen = dirp->machdirnamelen;
}
else
{
char *tmp;
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");
memcpy (tmp, cp, len);
tmp[len] = '\0';
if (max_dirnamelen < dirp->dirnamelen)
max_dirnamelen = dirp->dirnamelen;
dirp->dirname = tmp;
}
dirp->next = all_dirs;
all_dirs = dirp;
/* Put it in the result array. */
result[nelems++] = dirp;
}
}
/* Terminate the array. */
result[nelems] = NULL;
return result;
}
static struct r_search_path_elem **
decompose_rpath (const char *rpath, size_t additional_room)
{
/* Make a copy we can work with. */
char *copy = strdupa (rpath);
char *cp;
struct r_search_path_elem **result;
/* First count the number of necessary elements in the result array. */
size_t nelems = 0;
for (cp = copy; *cp != '\0'; ++cp)
if (*cp == ':')
++nelems;
/* Allocate room for the result. NELEMS + 1 + ADDITIONAL_ROOM is an upper
limit for the number of necessary entries. */
result = (struct r_search_path_elem **) malloc ((nelems + 1
+ additional_room + 1)
* sizeof (*result));
if (result == NULL)
_dl_signal_error (ENOMEM, NULL, "cannot create cache for search path");
return fillin_rpath (copy, result, ":", NULL);
}
void
_dl_init_paths (void)
{
struct r_search_path_elem **pelem;
/* We have in `search_path' the information about the RPATH of the
dynamic loader. Now fill in the information about the applications
RPATH and the directories addressed by the LD_LIBRARY_PATH environment
variable. */
struct link_map *l;
/* First determine how many elements the LD_LIBRARY_PATH contents has. */
const char *llp = getenv ("LD_LIBRARY_PATH");
size_t nllp;
if (llp != NULL && *llp != '\0')
{
/* Simply count the number of colons. */
const char *cp = llp;
nllp = 1;
while (*cp)
if (*cp++ == ':')
++nllp;
}
else
nllp = 0;
l = _dl_loaded;
if (l && l->l_type != lt_loaded && l->l_info[DT_RPATH])
{
/* Allocate room for the search path and fill in information from
RPATH. */
l->l_rpath_dirs =
decompose_rpath ((const char *) (l->l_addr
+ l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val),
nllp);
}
else
{
/* If we have no LD_LIBRARY_PATH and no RPATH we must tell this
somehow to prevent we look this up again and again. */
if (nllp == 0)
l->l_rpath_dirs = (struct r_search_path_elem **) -1l;
else
{
l->l_rpath_dirs =
(struct r_search_path_elem **) malloc ((nllp + 1)
* sizeof (*l->l_rpath_dirs));
if (l->l_rpath_dirs == NULL)
_dl_signal_error (ENOMEM, NULL,
"cannot create cache for search path");
l->l_rpath_dirs[0] = NULL;
}
}
if (nllp > 0)
{
static const char *trusted_dirs[] =
{
#include "trusted-dirs.h"
NULL
};
char *copy = strdupa (llp);
/* Decompose the LD_LIBRARY_PATH and fill in the result.
First search for the next place to enter elements. */
struct r_search_path_elem **result = l->l_rpath_dirs;
while (*result != NULL)
++result;
/* We need to take care that the LD_LIBRARY_PATH environement
variable can contain a semicolon. */
(void) fillin_rpath (copy, result, ":;",
__libc_enable_secure ? trusted_dirs : 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;
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");
memcpy (tmp, relem->dirname, relem->dirnamelen);
memcpy (tmp + relem->dirnamelen, _dl_platform, _dl_platformlen);
tmp[relem->dirnamelen + _dl_platformlen] = '/';
tmp[relem->dirnamelen + _dl_platformlen + 1] = '\0';
relem->dirname = tmp;
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;
}
}
}
/* Map in the shared object NAME, actually located in REALNAME, and already /* Map in the shared object NAME, actually located in REALNAME, and already
opened on FD. */ opened on FD. */
@ -131,7 +420,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
l->l_next->l_prev = l->l_prev; l->l_next->l_prev = l->l_prev;
free (l); free (l);
} }
free (name); free (name); /* XXX Can this be correct? --drepper */
free (realname); free (realname);
_dl_signal_error (code, name, msg); _dl_signal_error (code, name, msg);
} }
@ -207,9 +496,6 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
return l; return l;
} }
if (_dl_pagesize == 0)
_dl_pagesize = __getpagesize ();
/* Map in the first page to read the header. */ /* Map in the first page to read the header. */
header = map (0, sizeof *header); header = map (0, sizeof *header);
@ -458,83 +744,87 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
return l; return l;
} }
/* Try to open NAME in one of the directories in DIRPATH. /* Try to open NAME in one of the directories in DIRS.
Return the fd, or -1. If successful, fill in *REALNAME Return the fd, or -1. If successful, fill in *REALNAME
with the malloc'd full directory name. */ with the malloc'd full directory name. */
static int static int
open_path (const char *name, size_t namelen, open_path (const char *name, size_t namelen,
const char *dirpath, struct r_search_path_elem **dirs,
char **realname, char **realname)
const char *trusted_dirs[])
{ {
char *buf; char *buf;
const char *p; int fd = -1;
int fd;
p = dirpath; if (dirs == NULL || *dirs == NULL)
if (p == NULL || *p == '\0')
{ {
__set_errno (ENOENT); __set_errno (ENOENT);
return -1; return -1;
} }
buf = __alloca (strlen (dirpath) + 1 + namelen); buf = __alloca (max_dirnamelen + namelen);
do do
{ {
size_t buflen; struct r_search_path_elem *this_dir = *dirs;
size_t this_len; size_t buflen = 0;
dirpath = p; if (this_dir->machdirstatus != nonexisting)
p = strpbrk (dirpath, ":;");
if (p == NULL)
p = strchr (dirpath, '\0');
this_len = p - dirpath;
/* When we run a setuid program we do not accept any directory. */
if (__libc_enable_secure)
{
/* All trusted directory must be complete name. */
if (dirpath[0] != '/')
continue;
/* If we got a list of trusted directories only accept one
of these. */
if (trusted_dirs != NULL)
{
const char **trust = trusted_dirs;
while (*trust != NULL)
if (memcmp (dirpath, *trust, this_len) == 0
&& (*trust)[this_len] == '\0')
break;
else
++trust;
/* If directory is not trusted, ignore this directory. */
if (*trust == NULL)
continue;
}
}
if (this_len == 0)
{
/* Two adjacent colons, or a colon at the beginning or the end of
the path means to search the current directory. */
(void) memcpy (buf, name, namelen);
buflen = namelen;
}
else
{ {
/* Construct the pathname to try. */ /* Construct the pathname to try. */
(void) memcpy (buf, dirpath, this_len); (void) memcpy (buf, this_dir->dirname, this_dir->machdirnamelen);
buf[this_len] = '/'; (void) memcpy (buf + this_dir->machdirnamelen, name, namelen);
(void) memcpy (&buf[this_len + 1], name, namelen); buflen = this_dir->machdirnamelen + namelen;
buflen = this_len + 1 + namelen;
fd = __open (buf, O_RDONLY);
if (this_dir->machdirstatus == unknown)
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 (stat (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 && this_dir->dirstatus != nonexisting)
{
/* Construct the pathname to try. */
(void) memcpy (buf, this_dir->dirname, this_dir->dirnamelen);
(void) memcpy (buf + this_dir->dirnamelen, name, namelen);
buflen = this_dir->dirnamelen + namelen;
fd = __open (buf, O_RDONLY);
if (this_dir->dirstatus == unknown)
if (fd != -1)
this_dir->dirstatus = existing;
else
/* We failed to open library. Let's test whether there
is any directory at all. */
if (this_dir->dirnamelen <= 1)
this_dir->dirstatus = existing;
else
{
struct stat st;
buf[this_dir->dirnamelen - 1] = '\0';
if (stat (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;
}
} }
fd = __open (buf, O_RDONLY);
if (fd != -1) if (fd != -1)
{ {
*realname = malloc (buflen); *realname = malloc (buflen);
@ -555,7 +845,7 @@ open_path (const char *name, size_t namelen,
/* The file exists and is readable, but something went wrong. */ /* The file exists and is readable, but something went wrong. */
return -1; return -1;
} }
while (*p++ != '\0'); while (*++dirs != NULL);
return -1; return -1;
} }
@ -593,39 +883,34 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
size_t namelen = strlen (name) + 1; size_t namelen = strlen (name) + 1;
inline void trypath (const char *dirpath, const char *trusted[])
{
fd = open_path (name, namelen, dirpath, &realname, trusted);
}
fd = -1; fd = -1;
/* First try the DT_RPATH of the dependent object that caused NAME /* First try the DT_RPATH of the dependent object that caused NAME
to be loaded. Then that object's dependent, and on up. */ to be loaded. Then that object's dependent, and on up. */
for (l = loader; fd == -1 && l; l = l->l_loader) for (l = loader; fd == -1 && l; l = l->l_loader)
if (l && l->l_info[DT_RPATH]) if (l && l->l_info[DT_RPATH])
trypath ((const char *) (l->l_addr +
l->l_info[DT_STRTAB]->d_un.d_ptr +
l->l_info[DT_RPATH]->d_un.d_val), NULL);
/* If dynamically linked, try the DT_RPATH of the executable itself. */
l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded && l->l_info[DT_RPATH])
trypath ((const char *) (l->l_addr +
l->l_info[DT_STRTAB]->d_un.d_ptr +
l->l_info[DT_RPATH]->d_un.d_val), NULL);
/* Try an environment variable (unless setuid). */
if (fd == -1)
{
static const char *trusted_dirs[] =
{ {
#include "trusted-dirs.h" /* Make sure the cache information is available. */
NULL if (l->l_rpath_dirs == NULL)
}; {
const char *ld_library_path = getenv ("LD_LIBRARY_PATH"); size_t ptrval = (l->l_addr
+ l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val);
l->l_rpath_dirs =
decompose_rpath ((const char *) ptrval, 0);
}
if (l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
fd = open_path (name, namelen, l->l_rpath_dirs, &realname);
}
/* If dynamically linked, try the DT_RPATH of the executable itself
and the LD_LIBRARY_PATH environment variable. */
l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded
&& l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
fd = open_path (name, namelen, l->l_rpath_dirs, &realname);
if (ld_library_path != NULL && *ld_library_path != '\0')
trypath (ld_library_path, trusted_dirs);
}
if (fd == -1) if (fd == -1)
{ {
/* Check the list of libraries in the file /etc/ld.so.cache, /* Check the list of libraries in the file /etc/ld.so.cache,
@ -646,12 +931,10 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
} }
} }
} }
/* Finally, try the default path. */ /* Finally, try the default path. */
if (fd == -1) if (fd == -1)
{ fd = open_path (name, namelen, rtld_search_dirs, &realname);
extern const char *_dl_rpath; /* Set in rtld.c. */
trypath (_dl_rpath, NULL);
}
} }
else else
{ {

View File

@ -44,6 +44,7 @@ _dl_new_object (char *realname, const char *libname, int type)
newname->next = NULL; newname->next = NULL;
new->l_libname = newname; new->l_libname = newname;
new->l_type = type; new->l_type = type;
new->l_rpath_dirs = NULL;
if (_dl_loaded == NULL) if (_dl_loaded == NULL)
{ {

View File

@ -20,8 +20,10 @@
/* This file defines some things that for the dynamic linker are defined in /* This file defines some things that for the dynamic linker are defined in
rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */
#include <link.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <dl-machine.h>
extern char *__progname; extern char *__progname;
char **_dl_argv = &__progname; /* This is checked for some error messages. */ char **_dl_argv = &__progname; /* This is checked for some error messages. */
@ -30,15 +32,36 @@ char **_dl_argv = &__progname; /* This is checked for some error messages. */
For the dynamic linker it is set by -rpath when linking. */ For the dynamic linker it is set by -rpath when linking. */
const char *_dl_rpath = DEFAULT_RPATH; const char *_dl_rpath = DEFAULT_RPATH;
/* Name of the architecture. */
const char *_dl_platform;
size_t _dl_platformlen;
/* If nonzero print warnings about problematic situations. */ /* If nonzero print warnings about problematic situations. */
int _dl_verbose; int _dl_verbose;
/* Structure to store information about search paths. */
struct r_search_path *_dl_search_paths;
static void init_verbose (void) __attribute__ ((unused));
static void non_dynamic_init (void) __attribute__ ((unused));
static void static void
init_verbose (void) non_dynamic_init (void)
{ {
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1; _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
/* Initialize the data structures for the search paths for shared
objects. */
_dl_init_paths ();
#ifdef DL_PLATFORM_INIT
DL_PLATFORM_INIT;
#endif
/* Now determine the length of the platform string. */
if (_dl_platform != NULL)
_dl_platformlen = strlen (_dl_platform);
_dl_pagesize = __getpagesize ();
} }
text_set_element (__libc_subinit, init_verbose); text_set_element (__libc_subinit, non_dynamic_init);

View File

@ -654,6 +654,11 @@ typedef struct
#define AT_GID 13 /* Real gid */ #define AT_GID 13 /* Real gid */
#define AT_EGID 14 /* Effective gid */ #define AT_EGID 14 /* Effective gid */
/* Some more special a_type values describing the hardware. */
#define AT_PLATFORM 15 /* String identifying platform. */
#define AT_HWCAP 16 /* Machine dependent hints about
processor capabilities. */
/* Motorola 68k specific definitions. */ /* Motorola 68k specific definitions. */
/* m68k relocs. */ /* m68k relocs. */

28
elf/genrtldtbl.awk Normal file
View File

@ -0,0 +1,28 @@
#! /usr/bin/awk
BEGIN {
FS=":";
count=0;
}
{
for (i = 1; i <= NF; ++i) {
dir[count++] = gensub(/((.*)[^/])?[/]*/, "\\1", "", $i);
}
}
END {
for (i = 0; i < count; ++i) {
printf ("static struct r_search_path_elem rtld_search_dir%d =\n", i+1);
printf (" { \"%s/\", %d, unknown, 0, unknown, ",
dir[i], length (dir[i]) + 1);
if (i== 0)
printf ("NULL };\n");
else
printf ("&rtld_search_dir%d };\n", i);
}
printf ("\nstatic struct r_search_path_elem *rtld_search_dirs[] =\n{\n");
for (i = 0; i < count; ++i) {
printf (" &rtld_search_dir%d,\n", i + 1);
}
printf (" NULL\n};\n\n");
printf ("static struct r_search_path_elem *all_dirs = &rtld_search_dir%d;\n",
count);
}

View File

@ -91,6 +91,25 @@ struct r_found_version
const char *filename; const char *filename;
}; };
/* We want to cache information about the searches for shared objects. */
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;
};
/* Structure describing a loaded shared object. The `l_next' and `l_prev' /* Structure describing a loaded shared object. The `l_next' and `l_prev'
members form a chain of all the shared objects loaded at startup. members form a chain of all the shared objects loaded at startup.
@ -163,6 +182,9 @@ struct link_map
/* Array with version names. */ /* Array with version names. */
unsigned int l_nversions; unsigned int l_nversions;
struct r_found_version *l_versions; struct r_found_version *l_versions;
/* Collected information about own RPATH directories. */
struct r_search_path_elem **l_rpath_dirs;
}; };
@ -407,6 +429,10 @@ extern void _dl_debug_state (void);
in the `r_ldbase' member. Returns the address of the structure. */ in the `r_ldbase' member. Returns the address of the structure. */
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase); extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
/* Initialize the basic data structure for the search paths. */
void _dl_init_paths (void);
__END_DECLS __END_DECLS
#endif /* link.h */ #endif /* link.h */

View File

@ -58,6 +58,9 @@ int _dl_argc;
char **_dl_argv; char **_dl_argv;
const char *_dl_rpath; const char *_dl_rpath;
int _dl_verbose; int _dl_verbose;
const char *_dl_platform;
size_t _dl_platformlen;
struct r_search_path *_dl_search_paths;
/* Set nonzero during loading and initialization of executable and /* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This libraries, cleared before the executable's entry point runs. This
@ -526,6 +529,10 @@ of this helper program; chances are you did not intend to run this program.\n",
assert (i == npreloads); assert (i == npreloads);
} }
/* Initialize the data structures for the search paths for shared
objects. */
_dl_init_paths ();
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
specified some libraries to load, these are inserted before the actual specified some libraries to load, these are inserted before the actual
dependencies in the executable's searchlist for symbol resolution. */ dependencies in the executable's searchlist for symbol resolution. */

View File

@ -2907,10 +2907,10 @@ ccos_test (void)
result = FUNC(ccos) (BUILD_COMPLEX (0.0, 0.0)); result = FUNC(ccos) (BUILD_COMPLEX (0.0, 0.0));
check ("real(ccos(0 + 0i)) = 1.0", __real__ result, 1.0); check ("real(ccos(0 + 0i)) = 1.0", __real__ result, 1.0);
check ("imag(ccos(0 + 0i)) = 0", __imag__ result, 0); check ("imag(ccos(0 + 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, 0.0)); result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, 0.0));
check ("real(ccos(-0 + 0i)) = 1.0", __real__ result, 1.0); check ("real(ccos(-0 + 0i)) = 1.0", __real__ result, 1.0);
check ("imag(ccos(-0 + 0i)) = -0", __imag__ result, minus_zero); check ("imag(ccos(-0 + 0i)) = 0", __imag__ result, 0.0);
result = FUNC(ccos) (BUILD_COMPLEX (0.0, minus_zero)); result = FUNC(ccos) (BUILD_COMPLEX (0.0, minus_zero));
check ("real(ccos(0 - 0i)) = 1.0", __real__ result, 1.0); check ("real(ccos(0 - 0i)) = 1.0", __real__ result, 1.0);
check ("imag(ccos(0 - 0i)) = 0", __imag__ result, 0.0); check ("imag(ccos(0 - 0i)) = 0", __imag__ result, 0.0);
@ -2941,13 +2941,13 @@ ccos_test (void)
result = FUNC(ccos) (BUILD_COMPLEX (0.0, plus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (0.0, plus_infty));
check_isinfp ("real(ccos(0 + i Inf)) = +Inf", __real__ result); check_isinfp ("real(ccos(0 + i Inf)) = +Inf", __real__ result);
check ("imag(ccos(0 + i Inf)) = 0", __imag__ result, 0); check ("imag(ccos(0 + i Inf)) = -0", __imag__ result, minus_zero);
result = FUNC(ccos) (BUILD_COMPLEX (0.0, minus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (0.0, minus_infty));
check_isinfp ("real(ccos(0 - i Inf)) = +Inf", __real__ result); check_isinfp ("real(ccos(0 - i Inf)) = +Inf", __real__ result);
check ("imag(ccos(0 - i Inf)) = 0", __imag__ result, 0); check ("imag(ccos(0 - i Inf)) = 0", __imag__ result, 0);
result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, plus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, plus_infty));
check_isinfp ("real(ccos(-0 + i Inf)) = +Inf", __real__ result); check_isinfp ("real(ccos(-0 + i Inf)) = +Inf", __real__ result);
check ("imag(ccos(-0 + i Inf)) = -0", __imag__ result, minus_zero); check ("imag(ccos(-0 + i Inf)) = 0", __imag__ result, 0.0);
result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, minus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, minus_infty));
check_isinfp ("real(ccos(-0 - i Inf)) = +Inf", __real__ result); check_isinfp ("real(ccos(-0 - i Inf)) = +Inf", __real__ result);
check ("imag(ccos(-0 - i Inf)) = -0", __imag__ result, minus_zero); check ("imag(ccos(-0 - i Inf)) = -0", __imag__ result, minus_zero);
@ -2975,13 +2975,13 @@ ccos_test (void)
result = FUNC(ccos) (BUILD_COMPLEX (4.625, plus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (4.625, plus_infty));
check_isinfn ("real(ccos(4.625 + i Inf)) = -Inf", __real__ result); check_isinfn ("real(ccos(4.625 + i Inf)) = -Inf", __real__ result);
check_isinfn ("imag(ccos(4.625 + i Inf)) = -Inf", __imag__ result); check_isinfp ("imag(ccos(4.625 + i Inf)) = +Inf", __imag__ result);
result = FUNC(ccos) (BUILD_COMPLEX (4.625, minus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (4.625, minus_infty));
check_isinfn ("real(ccos(4.625 - i Inf)) = -Inf", __real__ result); check_isinfn ("real(ccos(4.625 - i Inf)) = -Inf", __real__ result);
check_isinfn ("imag(ccos(4.625 - i Inf)) = -Inf", __imag__ result); check_isinfn ("imag(ccos(4.625 - i Inf)) = -Inf", __imag__ result);
result = FUNC(ccos) (BUILD_COMPLEX (-4.625, plus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (-4.625, plus_infty));
check_isinfn ("real(ccos(-4.625 + i Inf)) = -Inf", __real__ result); check_isinfn ("real(ccos(-4.625 + i Inf)) = -Inf", __real__ result);
check_isinfp ("imag(ccos(-4.625 + i Inf)) = +Inf", __imag__ result); check_isinfn ("imag(ccos(-4.625 + i Inf)) = -Inf", __imag__ result);
result = FUNC(ccos) (BUILD_COMPLEX (-4.625, minus_infty)); result = FUNC(ccos) (BUILD_COMPLEX (-4.625, minus_infty));
check_isinfn ("real(ccos(-4.625 - i Inf)) = -Inf", __real__ result); check_isinfn ("real(ccos(-4.625 - i Inf)) = -Inf", __real__ result);
check_isinfp ("imag(ccos(-4.625 - i Inf)) = +Inf", __imag__ result); check_isinfp ("imag(ccos(-4.625 - i Inf)) = +Inf", __imag__ result);
@ -3077,13 +3077,13 @@ ccosh_test (void)
check ("imag(ccosh(0 + 0i)) = 0", __imag__ result, 0); check ("imag(ccosh(0 + 0i)) = 0", __imag__ result, 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, 0.0)); result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, 0.0));
check ("real(ccosh(-0 + 0i)) = 1.0", __real__ result, 1.0); check ("real(ccosh(-0 + 0i)) = 1.0", __real__ result, 1.0);
check ("imag(ccosh(-0 + 0i)) = 0", __imag__ result, 0); check ("imag(ccosh(-0 + 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_zero)); result = FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_zero));
check ("real(ccosh(0 - 0i)) = 1.0", __real__ result, 1.0); check ("real(ccosh(0 - 0i)) = 1.0", __real__ result, 1.0);
check ("imag(ccosh(0 - 0i)) = -0", __imag__ result, minus_zero); check ("imag(ccosh(0 - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_zero)); result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(ccosh(-0 - 0i)) = 1.0", __real__ result, 1.0); check ("real(ccosh(-0 - 0i)) = 1.0", __real__ result, 1.0);
check ("imag(ccosh(-0 - 0i)) = -0", __imag__ result, minus_zero); check ("imag(ccosh(-0 - 0i)) = 0", __imag__ result, 0.0);
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, plus_infty)); result = FUNC(ccosh) (BUILD_COMPLEX (0.0, plus_infty));
check_isnan_exc ("real(ccosh(0 + i Inf)) = NaN plus invalid exception", check_isnan_exc ("real(ccosh(0 + i Inf)) = NaN plus invalid exception",
@ -3111,13 +3111,13 @@ ccosh_test (void)
check ("imag(ccosh(+Inf + 0i)) = 0", __imag__ result, 0); check ("imag(ccosh(+Inf + 0i)) = 0", __imag__ result, 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 0.0)); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 0.0));
check_isinfp ("real(ccosh(-Inf + 0i)) = +Inf", __real__ result); check_isinfp ("real(ccosh(-Inf + 0i)) = +Inf", __real__ result);
check ("imag(ccosh(-Inf + 0i)) = 0", __imag__ result, 0); check ("imag(ccosh(-Inf + 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_zero)); result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_zero));
check_isinfp ("real(ccosh(+Inf - 0i)) = +Inf", __real__ result); check_isinfp ("real(ccosh(+Inf - 0i)) = +Inf", __real__ result);
check ("imag(ccosh(+Inf - 0i)) = -0", __imag__ result, minus_zero); check ("imag(ccosh(+Inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_zero)); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_zero));
check_isinfp ("real(ccosh(-Inf - 0i)) = +Inf", __real__ result); check_isinfp ("real(ccosh(-Inf - 0i)) = +Inf", __real__ result);
check ("imag(ccosh(-Inf - 0i)) = -0", __imag__ result, minus_zero); check ("imag(ccosh(-Inf - 0i)) = 0", __imag__ result, 0.0);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, plus_infty)); result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, plus_infty));
check_isinfp_exc ("real(ccosh(+Inf + i Inf)) = +Inf plus invalid exception", check_isinfp_exc ("real(ccosh(+Inf + i Inf)) = +Inf plus invalid exception",
@ -3145,13 +3145,13 @@ ccosh_test (void)
check_isinfn ("imag(ccosh(+Inf + i4.625)) = -Inf", __imag__ result); check_isinfn ("imag(ccosh(+Inf + i4.625)) = -Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 4.625)); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 4.625));
check_isinfn ("real(ccosh(-Inf + i4.625)) = -Inf", __real__ result); check_isinfn ("real(ccosh(-Inf + i4.625)) = -Inf", __real__ result);
check_isinfn ("imag(ccosh(-Inf + i4.625)) = -Inf", __imag__ result); check_isinfp ("imag(ccosh(-Inf + i4.625)) = Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, -4.625)); result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, -4.625));
check_isinfn ("real(ccosh(+Inf - i4.625)) = -Inf", __real__ result); check_isinfn ("real(ccosh(+Inf - i4.625)) = -Inf", __real__ result);
check_isinfp ("imag(ccosh(+Inf - i4.625)) = +Inf", __imag__ result); check_isinfp ("imag(ccosh(+Inf - i4.625)) = +Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, -4.625)); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, -4.625));
check_isinfn ("real(ccosh(-Inf - i4.625)) = -Inf", __real__ result); check_isinfn ("real(ccosh(-Inf - i4.625)) = -Inf", __real__ result);
check_isinfp ("imag(ccosh(-Inf - i4.625)) = +Inf", __imag__ result); check_isinfn ("imag(ccosh(-Inf - i4.625)) = -Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (6.75, plus_infty)); result = FUNC(ccosh) (BUILD_COMPLEX (6.75, plus_infty));
check_isnan_exc ("real(ccosh(6.75 + i Inf)) = NaN plus invalid exception", check_isnan_exc ("real(ccosh(6.75 + i Inf)) = NaN plus invalid exception",

View File

@ -22,7 +22,7 @@ GLIBC_2.0 {
_nss_files_setgrent; _nss_files_sethostent; _nss_files_setnetent; _nss_files_setgrent; _nss_files_sethostent; _nss_files_setnetent;
_nss_files_setnetgrent; _nss_files_setprotoent; _nss_files_setpwent; _nss_files_setnetgrent; _nss_files_setprotoent; _nss_files_setpwent;
_nss_files_setrpcent; _nss_files_setservent; _nss_files_setspent; _nss_files_setrpcent; _nss_files_setservent; _nss_files_setspent;
__nss_netgroup_parseline; _nss_netgroup_parseline;
local: local:
*; *;

View File

@ -309,10 +309,10 @@ send_again:
#endif /* def FD_SETSIZE */ #endif /* def FD_SETSIZE */
for (;;) for (;;)
{ {
struct timeval timeout = cu->cu_wait; struct timeval cu_wait = cu->cu_wait;
readfds = mask; readfds = mask;
switch (select (_rpc_dtablesize (), &readfds, (fd_set*) NULL, switch (select (_rpc_dtablesize (), &readfds, (fd_set*) NULL,
(fd_set*) NULL, &timeout)) (fd_set*) NULL, &cu_wait))
{ {
case 0: case 0:

View File

@ -0,0 +1,55 @@
/* Machine-dependent definitions for profiling support. ARM version.
Copyright (C) 1996, 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. */
/* GCC for the ARM cannot compile __builtin_return_address(N) for N != 0,
so we must use an assembly stub. */
#include <sysdep.h>
#ifndef NO_UNDERSCORES
/* The asm symbols for C functions are `_function'.
The canonical name for the counter function is `mcount', no _. */
void _mcount (void) asm ("mcount");
#else
/* The canonical name for the function is `_mcount' in both C and asm,
but some old asm code might assume it's `mcount'. */
void _mcount (void);
weak_alias (_mcount, mcount)
#endif
static void mcount_internal (u_long frompc, u_long selfpc);
#define _MCOUNT_DECL(frompc, selfpc) \
static void mcount_internal (u_long frompc, u_long selfpc)
#define MCOUNT \
void _mcount (void) \
{ \
register unsigned long int frompc, selfpc; \
__asm__("movs fp, fp; " \
"moveq %0, $0; " \
"ldrne %0, [fp, $-4]; " \
"ldrne %1, [fp, $-12]; " \
"movnes %1, %1; " \
"ldrne %1, [%1, $-4]; " \
: "=g" (selfpc), "=g" (frompc) \
: : "cc" \
); \
if (selfpc) \
mcount_internal(frompc, selfpc); \
}

View File

@ -26,11 +26,14 @@
#include <link.h> #include <link.h>
#include <unistd.h> #include <unistd.h>
#include <dl-machine.h>
extern int _dl_argc; extern int _dl_argc;
extern char **_dl_argv; extern char **_dl_argv;
extern char **_environ; extern char **_environ;
extern size_t _dl_pagesize; extern size_t _dl_pagesize;
extern const char *_dl_platform;
extern size_t _dl_platformlen;
extern void _end; extern void _end;
extern void ENTRY_POINT (void); extern void ENTRY_POINT (void);
@ -57,6 +60,7 @@ _dl_sysdep_start (void **start_argptr,
_dl_argc = *(long *) start_argptr; _dl_argc = *(long *) start_argptr;
_dl_argv = (char **) start_argptr + 1; _dl_argv = (char **) start_argptr + 1;
_environ = &_dl_argv[_dl_argc + 1]; _environ = &_dl_argv[_dl_argc + 1];
_dl_platform = NULL; /* Default to nothing known about the platform. */
start_argptr = (void **) _environ; start_argptr = (void **) _environ;
while (*start_argptr) while (*start_argptr)
++start_argptr; ++start_argptr;
@ -93,6 +97,12 @@ _dl_sysdep_start (void **start_argptr,
case AT_EGID: case AT_EGID:
egid = av->a_un.a_val; egid = av->a_un.a_val;
break; break;
case AT_PLATFORM:
_dl_platform = av->a_un.a_ptr;
break;
case AT_HWCAP:
/* Well, what shall we use? A string or an integer with bits? */
break;
} }
/* Linux doesn't provide us with any of these values on the stack /* Linux doesn't provide us with any of these values on the stack
@ -107,21 +117,28 @@ _dl_sysdep_start (void **start_argptr,
__libc_enable_secure = uid != euid || gid != egid; __libc_enable_secure = uid != euid || gid != egid;
if (_dl_pagesize == 0)
_dl_pagesize = __getpagesize ();
#ifdef DL_SYSDEP_INIT #ifdef DL_SYSDEP_INIT
DL_SYSDEP_INIT; DL_SYSDEP_INIT;
#endif #endif
if (__sbrk (0) == &_end) #ifdef DL_PLATFORM_INIT
{ DL_PLATFORM_INIT;
/* The dynamic linker was run as a program, and so the initial break #endif
starts just after our bss, at &_end. The malloc in dl-minimal.c
will consume the rest of this page, so tell the kernel to move the
break up that far. When the user program examines its break, it
will see this new value and not clobber our data. */
size_t pg = __getpagesize ();
__sbrk (pg - ((&_end - (void *) 0) & (pg - 1))); /* Determine the length of the platform name. */
} if (_dl_platform != NULL)
_dl_platformlen = strlen (_dl_platform);
if (__sbrk (0) == &_end)
/* The dynamic linker was run as a program, and so the initial break
starts just after our bss, at &_end. The malloc in dl-minimal.c
will consume the rest of this page, so tell the kernel to move the
break up that far. When the user program examines its break, it
will see this new value and not clobber our data. */
__sbrk (_dl_pagesize - ((&_end - (void *) 0) & (_dl_pagesize - 1)));
(*dl_main) (phdr, phnum, &user_entry); (*dl_main) (phdr, phnum, &user_entry);
return user_entry; return user_entry;

View File

@ -22,6 +22,10 @@
void *__builtin_return_address (unsigned int N) void *__builtin_return_address (unsigned int N)
returns the return address of the frame N frames up. */ returns the return address of the frame N frames up. */
/* Be warned that GCC cannot usefully compile __builtin_return_address(N)
for N != 0 on all machines. In this case, you may have to write
your own version of _mcount(). */
#if __GNUC__ < 2 #if __GNUC__ < 2
#error "This file uses __builtin_return_address, a GCC 2 extension." #error "This file uses __builtin_return_address, a GCC 2 extension."
#endif #endif

View File

@ -27,8 +27,27 @@ __strsep (char **stringp, const char *delim)
if (! begin || *begin == '\0') if (! begin || *begin == '\0')
return NULL; return NULL;
/* Find the end of the token. */ /* A frequent case is when the delimiter string contains only one
end = strpbrk (begin, delim); character. Here we don't need to call the expensive `strpbrk'
function and instead work using `strchr'. */
if (delim[0] == '\0' || delim[1] == '\0')
{
char ch = delim[0];
if (ch == '\0')
end = NULL;
else
{
while (*begin == ch)
++begin;
end = strchr (begin, delim[0]);
}
}
else
/* Find the end of the token. */
end = strpbrk (begin, delim);
if (end) if (end)
{ {
/* Terminate the token and set *STRINGP past NUL character. */ /* Terminate the token and set *STRINGP past NUL character. */

View File

@ -44,7 +44,7 @@ elf_machine_matches_host (Elf32_Half e_machine)
/* Return the link-time address of _DYNAMIC. Conveniently, this is the /* Return the link-time address of _DYNAMIC. Conveniently, this is the
first element of the GOT. This must be inlined in a function which first element of the GOT. This must be inlined in a function which
uses global data. */ uses global data. */
static inline Elf32_Addr static inline Elf32_Addr __attribute__ ((unused))
elf_machine_dynamic (void) elf_machine_dynamic (void)
{ {
register Elf32_Addr *got asm ("%ebx"); register Elf32_Addr *got asm ("%ebx");
@ -86,7 +86,7 @@ static ElfW(Addr) fixup (struct link_map *l, ElfW(Word) reloc_offset)
/* Set up the loaded object described by L so its unrelocated PLT /* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */ entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int static inline int __attribute__ ((unused))
elf_machine_runtime_setup (struct link_map *l, int lazy) elf_machine_runtime_setup (struct link_map *l, int lazy)
{ {
Elf32_Addr *got; Elf32_Addr *got;
@ -233,6 +233,23 @@ _dl_start_user:\n\
/* The i386 never uses Elf32_Rela relocations. */ /* The i386 never uses Elf32_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1 #define ELF_MACHINE_NO_RELA 1
/* We define an initialization functions. This is called very early in
_dl_sysdep_start. */
#define DL_PLATFORM_INIT dl_platform_init ()
extern const char *_dl_platform;
static inline void __attribute__ ((unused))
dl_platform_init (void)
{
if (_dl_platform == NULL)
/* We default to i386 since all instructions understood by the i386
are also understood by later processors. */
_dl_platform = "i386";
else if (*_dl_platform == '\0')
_dl_platform = NULL;
}
#endif /* !dl_machine_h */ #endif /* !dl_machine_h */
#ifdef RESOLVE #ifdef RESOLVE

View File

@ -32,8 +32,6 @@ __ccosh (__complex__ double x)
int rcls = fpclassify (__real__ x); int rcls = fpclassify (__real__ x);
int icls = fpclassify (__imag__ x); int icls = fpclassify (__imag__ x);
__real__ x = fabs (__real__ x);
if (rcls >= FP_ZERO) if (rcls >= FP_ZERO)
{ {
/* Real part is finite. */ /* Real part is finite. */
@ -67,7 +65,7 @@ __ccosh (__complex__ double x)
{ {
/* Imaginary part is 0.0. */ /* Imaginary part is 0.0. */
__real__ retval = HUGE_VAL; __real__ retval = HUGE_VAL;
__imag__ retval = __imag__ x; __imag__ retval = __imag__ x * __copysign (1.0, __real__ x);
} }
else if (icls > FP_ZERO) else if (icls > FP_ZERO)
{ {
@ -77,7 +75,8 @@ __ccosh (__complex__ double x)
__sincos (__imag__ x, &sinix, &cosix); __sincos (__imag__ x, &sinix, &cosix);
__real__ retval = __copysign (HUGE_VAL, cosix); __real__ retval = __copysign (HUGE_VAL, cosix);
__imag__ retval = __copysign (HUGE_VAL, sinix); __imag__ retval = (__copysign (HUGE_VAL, sinix)
* __copysign (1.0, __real__ x));
} }
else else
{ {

View File

@ -32,8 +32,6 @@ __ccoshf (__complex__ float x)
int rcls = fpclassify (__real__ x); int rcls = fpclassify (__real__ x);
int icls = fpclassify (__imag__ x); int icls = fpclassify (__imag__ x);
__real__ x = fabsf (__real__ x);
if (rcls >= FP_ZERO) if (rcls >= FP_ZERO)
{ {
/* Real part is finite. */ /* Real part is finite. */
@ -67,7 +65,7 @@ __ccoshf (__complex__ float x)
{ {
/* Imaginary part is 0.0. */ /* Imaginary part is 0.0. */
__real__ retval = HUGE_VALF; __real__ retval = HUGE_VALF;
__imag__ retval = __imag__ x; __imag__ retval = __imag__ x * __copysignf (1.0, __real__ x);
} }
else if (icls > FP_ZERO) else if (icls > FP_ZERO)
{ {
@ -77,7 +75,8 @@ __ccoshf (__complex__ float x)
__sincosf (__imag__ x, &sinix, &cosix); __sincosf (__imag__ x, &sinix, &cosix);
__real__ retval = __copysignf (HUGE_VALF, cosix); __real__ retval = __copysignf (HUGE_VALF, cosix);
__imag__ retval = __copysignf (HUGE_VALF, sinix); __imag__ retval = (__copysignf (HUGE_VALF, sinix)
* __copysignf (1.0, __real__ x));
} }
else else
{ {

View File

@ -32,8 +32,6 @@ __ccoshl (__complex__ long double x)
int rcls = fpclassify (__real__ x); int rcls = fpclassify (__real__ x);
int icls = fpclassify (__imag__ x); int icls = fpclassify (__imag__ x);
__real__ x = fabsl (__real__ x);
if (rcls >= FP_ZERO) if (rcls >= FP_ZERO)
{ {
/* Real part is finite. */ /* Real part is finite. */
@ -67,7 +65,7 @@ __ccoshl (__complex__ long double x)
{ {
/* Imaginary part is 0.0. */ /* Imaginary part is 0.0. */
__real__ retval = HUGE_VALL; __real__ retval = HUGE_VALL;
__imag__ retval = __imag__ x; __imag__ retval = __imag__ x * __copysignl (1.0, __real__ x);
} }
else if (icls > FP_ZERO) else if (icls > FP_ZERO)
{ {
@ -77,7 +75,8 @@ __ccoshl (__complex__ long double x)
__sincosl (__imag__ x, &sinix, &cosix); __sincosl (__imag__ x, &sinix, &cosix);
__real__ retval = __copysignl (HUGE_VALL, cosix); __real__ retval = __copysignl (HUGE_VALL, cosix);
__imag__ retval = __copysignl (HUGE_VALL, sinix); __imag__ retval = (__copysignl (HUGE_VALL, sinix)
* __copysignl (1.0, __real__ x));
} }
else else
{ {

View File

@ -29,7 +29,7 @@
#include <mach/mig_support.h> #include <mach/mig_support.h>
#include "hurdstartup.h" #include "hurdstartup.h"
#include <mach/host_info.h> #include <mach/host_info.h>
#include "../stdio-common/_itoa.h" #include <stdio-common/_itoa.h>
#include <hurd/auth.h> #include <hurd/auth.h>
#include <hurd/term.h> #include <hurd/term.h>
#include <stdarg.h> #include <stdarg.h>
@ -188,6 +188,9 @@ unfmh(); /* XXX */
/* Set up so we can do RPCs. */ /* Set up so we can do RPCs. */
__mach_init (); __mach_init ();
/* Initialize frequently used global variable. */
_dl_pagesize = __getpagesize ();
fmh(); /* XXX */ fmh(); /* XXX */
/* See hurd/hurdstartup.c; this deals with getting information /* See hurd/hurdstartup.c; this deals with getting information

View File

@ -23,7 +23,6 @@
#include <sysdep.h> #include <sysdep.h>
/* XXX Must this be __PIC__ ? --drepper */
#ifdef PIC #ifdef PIC
.option pic2 .option pic2
#endif #endif

View File

@ -23,7 +23,6 @@
#include <sysdep.h> #include <sysdep.h>
/* XXX Must this be __PIC__ ? --drepper */
#ifdef PIC #ifdef PIC
.option pic2 .option pic2
#endif #endif

View File

@ -96,16 +96,6 @@ elf_machine_matches_host (ElfW(Half) e_machine)
} }
} }
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ register ElfW(Addr) gp asm ("$28");
+ return * (ElfW(Addr) *) (gp - 0x7ff0);
+}
+
static inline ElfW(Addr) * static inline ElfW(Addr) *
elf_mips_got_from_gpreg (ElfW(Addr) gpreg) elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
{ {

View File

@ -96,16 +96,6 @@ elf_machine_matches_host (ElfW(Half) e_machine)
} }
} }
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ register ElfW(Addr) gp asm ("$28");
+ return * (ElfW(Addr) *) (gp - 0x7ff0);
+}
+
static inline ElfW(Addr) * static inline ElfW(Addr) *
elf_mips_got_from_gpreg (ElfW(Addr) gpreg) elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
{ {

View File

@ -44,7 +44,7 @@ ENTRY(__udiv_qrnnd)
!#PROLOGUE# 1 !#PROLOGUE# 1
st %i1,[%fp-8] st %i1,[%fp-8]
ld [%fp-8],%f10 ld [%fp-8],%f10
#ifdef __PIC__ #ifdef PIC
._XL11: ._XL11:
call ._XL1 call ._XL1
fitod %f10,%f4 fitod %f10,%f4
@ -78,7 +78,7 @@ L249:
faddd %f4,%f8,%f4 faddd %f4,%f8,%f4
L250: L250:
fdivd %f2,%f4,%f2 fdivd %f2,%f4,%f2
#ifdef __PIC__ #ifdef PIC
._XL22: ._XL22:
call ._XL2 call ._XL2
nop nop

View File

@ -19,35 +19,36 @@
/* This file defines the `errno' constants for standalone ARM machines. /* This file defines the `errno' constants for standalone ARM machines.
These constants are essentially arbitrary. */ These constants are essentially arbitrary. */
#if !defined(__Emath_defined) && (defined(_ERRNO_H) || defined(__need_Emath)) #if !defined __Emath_defined && (defined _ERRNO_H || defined __need_Emath)
#undef __need_Emath # undef __need_Emath
#define __Emath_defined 1 # define __Emath_defined 1
#define EDOM 1 # define EDOM 1
#define ERANGE 2 # define ERANGE 2
#endif #endif
#ifdef _ERRNO_H #ifdef _ERRNO_H
#define ENOSYS 3 # define ENOSYS 3
#define EINVAL 4 # define EINVAL 4
#define ESPIPE 5 # define ESPIPE 5
#define EBADF 6 # define EBADF 6
#define ENOMEM 7 # define ENOMEM 7
#define EACCES 8 # define EACCES 8
#define ENFILE 9 # define ENFILE 9
#define EMFILE 10 # define EMFILE 10
#define ENAMETOOLONG 11 /* File name too long */ # define ENAMETOOLONG 11 /* File name too long */
#define ELOOP 12 /* Too many symbolic links encountered */ # define ELOOP 12 /* Too many symbolic links encountered */
#define ENOMSG 13 /* No message of desired type */ # define ENOMSG 13 /* No message of desired type */
#define E2BIG 14 /* Arg list too long */ # define E2BIG 14 /* Arg list too long */
#define EINTR 15 # define EINTR 15
#define EILSEQ 16 # define EILSEQ 16
#define ENOEXEC 17 # define ENOEXEC 17
#define ENOENT 18 # define ENOENT 18
#define EPROTOTYPE 19 # define EPROTOTYPE 19
#define ESRCH 20 # define ESRCH 20
#define EPERM 21 # define EPERM 21
#define ENOTDIR 22 # define ENOTDIR 22
# define ESTALE 23
#endif #endif
#define __set_errno(val) errno = (val) #define __set_errno(val) errno = (val)

View File

@ -0,0 +1,32 @@
/* Copyright (C) 1995, 1996, 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. */
#include <sysdep.h>
/* errno has to be defined somewhere, and it might as well be here. */
int errno = 0;
/* The same goes for these magic signal functions. This is a standalone
environment so we do nothing. */
void _sig_dfl(int sig)
{
}
void _sig_ign(int sig)
{
}

View File

@ -29,7 +29,7 @@
.set noreorder .set noreorder
ENTRY(__syscall_error) ENTRY(__syscall_error)
#ifdef __PIC__ #ifdef PIC
.set noat .set noat
move $1, $31 move $1, $31
bltzal $0, 0f bltzal $0, 0f

View File

@ -27,18 +27,16 @@
static inline void static inline void
frob_brk (void) frob_brk (void)
{ {
extern size_t _dl_pagesize;
extern void _end; extern void _end;
__brk (0); /* Initialize the break. */ __brk (0); /* Initialize the break. */
if (__sbrk (0) == &_end) if (__sbrk (0) == &_end)
{ /* The dynamic linker was run as a program, and so the initial break
/* The dynamic linker was run as a program, and so the initial break starts just after our bss, at &_end. The malloc in dl-minimal.c
starts just after our bss, at &_end. The malloc in dl-minimal.c will consume the rest of this page, so tell the kernel to move the
will consume the rest of this page, so tell the kernel to move the break up that far. When the user program examines its break, it
break up that far. When the user program examines its break, it will see this new value and not clobber our data. */
will see this new value and not clobber our data. */ __sbrk (_dl_pagesize - ((&_end - (void *) 0) & _dl_pagesize));
size_t pg = __getpagesize ();
__sbrk (pg - ((&_end - (void *) 0) & pg));
}
} }
#include <sysdeps/generic/dl-sysdep.c> #include <sysdeps/generic/dl-sysdep.c>

View File

@ -37,7 +37,7 @@
.text .text
NESTED(__clone,4*SZREG,sp) NESTED(__clone,4*SZREG,sp)
#ifdef __PIC__ #ifdef PIC
.set noreorder .set noreorder
.cpload $25 .cpload $25
.set reorder .set reorder

View File

@ -72,7 +72,7 @@ ENTRY(____sparc_signal_trampoline)
or %g0,%g0,%g1 /*Call sys_setup */ or %g0,%g0,%g1 /*Call sys_setup */
t 0x10 t 0x10
1: 1:
#ifdef __PIC__ #ifdef PIC
/* Save return address */ /* Save return address */
mov %o7,%o4 mov %o7,%o4
___sxx: ___sxx:
@ -89,7 +89,7 @@ ___syy:
#endif #endif
sethi %hi(C_SYMBOL_NAME(____sig_table)),%o5 sethi %hi(C_SYMBOL_NAME(____sig_table)),%o5
or %o5,%lo(C_SYMBOL_NAME(____sig_table)),%o5 or %o5,%lo(C_SYMBOL_NAME(____sig_table)),%o5
#ifdef __PIC__ #ifdef PIC
add %o5,%o4,%o4 add %o5,%o4,%o4
ld [%o4],%o5 ld [%o4],%o5
#endif #endif