Tue Nov 7 12:29:46 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* elf/linux-compat.c: New file.
	* elf/Makefile (distribute): Add linux-compat.c.
	(generated): Add librtld.so.
	[$(config-os)=linux*] (extra-objs): Add linux-compat.so.
	[$(config-os)=linux*] (extra-objs): Add ld-linux.so.1.
	(librtld.so): New target.
	(ld.so, ld-linux.so.1): Make from librtld.so.

	* elf/rtld.c (dl_main): Instead of weak call to _dl_compat_init,
	call our own DT_INIT if we have one (and then clear it).
	(__dgettext): New weak function.

	* intl/localealias.c (read_alias_file): Avoid sprintf; use memcpy
	by hand instead.

	* sysdeps/generic/_strerror.c (_strerror_internal): Use _itoa
	instead of snprintf.

	* sysdeps/mach/_strerror.c (_strerror_internal): Don't write
	BUF[BUFLEN].

	* elf/rtld.c (rtld_map): New static variable.
	(_dl_start): Use a differently named local BOOTSTRAP_MAP for the
	bootstrapping.  Then copy data into `rtld_map'.
	(dl_main): Finish filling in rtld_map and link it into the chain,
	instead of allocating a new structure.
	(dl_main): Call _dl_compat_init if it is defined (use weak ref).

	* elf/dlsym.c: Fix last change: move REF out of `doit'.


	control.
	using it.

	and cwdir ports.
	functions.
	these.
	$(libdir)(rtld-installed-name).

	leading zeroes.

	in the rhs.
	pattern rule.


	never know.
	(fork): Use symbol_set_* macros for _hurd_fork_locks.
	* sysdeps/unix/sysv/sysv4/linux/i386/sysdep.S (__syscall_error):
 	instead of unix/sysv.

	-dynamic-linker.

	(__printf_fp): Last arg ARGS is now `const void **const';

	locale/C-ctype.c.
	* sysdeps/mach/hurd/sigsuspend.c: Likewise.
	* sysdeps/mach/hurd/mips/sigreturn.c: Likewise.
	alias gethostname.
	setitmr
	setpgrp
	(_S_msg_get_exec_flags, _S_msg_set_exec_flags,
	(abort_thread, abort_rpcs): Take same new arg and pass it through.
This commit is contained in:
Roland McGrath 1995-11-07 21:46:52 +00:00
parent 51093422b2
commit 86d2c878ac
8 changed files with 199 additions and 69 deletions

View File

@ -1,3 +1,35 @@
Tue Nov 7 12:29:46 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* elf/linux-compat.c: New file.
* elf/Makefile (distribute): Add linux-compat.c.
(generated): Add librtld.so.
[$(config-os)=linux*] (extra-objs): Add linux-compat.so.
[$(config-os)=linux*] (extra-objs): Add ld-linux.so.1.
(librtld.so): New target.
(ld.so, ld-linux.so.1): Make from librtld.so.
* elf/rtld.c (dl_main): Instead of weak call to _dl_compat_init,
call our own DT_INIT if we have one (and then clear it).
(__dgettext): New weak function.
* intl/localealias.c (read_alias_file): Avoid sprintf; use memcpy
by hand instead.
* sysdeps/generic/_strerror.c (_strerror_internal): Use _itoa
instead of snprintf.
* sysdeps/mach/_strerror.c (_strerror_internal): Don't write
BUF[BUFLEN].
* elf/rtld.c (rtld_map): New static variable.
(_dl_start): Use a differently named local BOOTSTRAP_MAP for the
bootstrapping. Then copy data into `rtld_map'.
(dl_main): Finish filling in rtld_map and link it into the chain,
instead of allocating a new structure.
(dl_main): Call _dl_compat_init if it is defined (use weak ref).
* elf/dlsym.c: Fix last change: move REF out of `doit'.
Mon Nov 6 16:20:14 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* elf/dlsym.c: Return the proper value, not just the defining

View File

@ -31,24 +31,42 @@ libdl-inhibit-o = $(filter-out .so,$(object-suffixes)) # Build only shared.
rtld-routines := rtld $(addprefix dl-,load lookup object reloc \
runtime sysdep error init fini)
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h \
soinit.c sofini.c ldd.sh.in
soinit.c sofini.c ldd.sh.in linux-compat.c
include ../Makeconfig
ifeq (yes,$(build-shared))
extra-objs = $(rtld-routines:=.so) soinit.so sofini.so
generated = librtld.so
install-others = $(libdir)/$(rtld-installed-name)
install-bin = ldd
ifneq (,$(filter linux%,$(config-os)))
extra-objs += linux-compat.so
install-lib += ld-linux.so.1
endif
endif
include ../Rules
$(objpfx)ld.so: $(rtld-routines:%=$(objpfx)%.so) \
# Link together the dynamic linker into a single relocatable object.
# We use this to produce both the ABI-compliant and Linux-compatible
# dynamic linker shared objects below.
$(objpfx)librtld.so: $(rtld-routines:%=$(objpfx)%.so) \
$(patsubst %,$(common-objpfx)lib%_pic.a,\
elf c $(LDLIBS-c.so:-l%=%))
$(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
$(LINK.o) -nostdlib -nostartfiles -r -o $@ \
'-Wl,-(' $^ -lgcc '-Wl,-)'
$(objpfx)ld.so $(objpfx)ld-linux.so.1: $(objpfx)librtld.so
$(LINK.o) -nostdlib -nostartfiles -shared -o $@ $^
# The Linux-compatible dynamic linker shared object is just the same
# with one object file of compatibility initialization code added.
$(objpfx)ld-linux.so.1: $(objpfx)linux-compat.so
$(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so
$(patsubst %/,cd %;,$(objpfx)) \
$(LINK.o) -shared -o $(@:$(objpfx)%=%) \

View File

@ -29,10 +29,10 @@ dlsym (void *handle, const char *name)
struct link_map *map = handle;
struct link_map *real_next;
Elf32_Addr loadbase;
const Elf32_Sym *ref = NULL;
int lose;
void doit (void)
{
const Elf32_Sym *ref = NULL;
loadbase = _dl_lookup_symbol (name, &ref, map, map->l_name, 1);
}

40
elf/linux-compat.c Normal file
View File

@ -0,0 +1,40 @@
/* Initializer for Linux-compatible dynamic linker `/lib/ld-linux.so.1'.
Copyright (C) 1995 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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <link.h>
#include <stdlib.h>
/* This function will be the DT_INIT initializer for the ld-linux.so.1
shared object. This is called from rtld.c before shlib initializers.
The old Linux ELF startup code expects the dynamic linker to magically
call atexit to arrange for shared object finalizers to run. (The
ABI-compliant startup code does this itself.) We build a compatible
version of the dynamic linker to install as /lib/ld-linux.so.1, the
name old Linux ELF binaries use. */
void
_init (void)
{
const Elf32_Sym *ref = NULL;
Elf32_Addr loadbase = _dl_lookup_symbol ("atexit", &ref, _dl_loaded,
"<ld-linux.so.1 initialization>",
1);
(*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini);
}

View File

@ -50,22 +50,24 @@ static void dl_main (const Elf32_Phdr *phdr,
Elf32_Word phent,
Elf32_Addr *user_entry);
static struct link_map rtld_map;
Elf32_Addr
_dl_start (void *arg)
{
struct link_map rtld_map;
struct link_map bootstrap_map;
/* Figure out the run-time load address of the dynamic linker itself. */
rtld_map.l_addr = elf_machine_load_address ();
bootstrap_map.l_addr = elf_machine_load_address ();
/* Read our own dynamic section and fill in the info array.
Conveniently, the first element of the GOT contains the
offset of _DYNAMIC relative to the run-time load address. */
rtld_map.l_ld = (void *) rtld_map.l_addr + *elf_machine_got ();
elf_get_dynamic_info (rtld_map.l_ld, rtld_map.l_info);
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + *elf_machine_got ();
elf_get_dynamic_info (bootstrap_map.l_ld, bootstrap_map.l_info);
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
ELF_MACHINE_BEFORE_RTLD_RELOC (rtld_map.l_info);
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
#endif
/* Relocate ourselves so we can do normal function calls and
@ -77,8 +79,8 @@ _dl_start (void *arg)
bootstrapping, so it must anti-perform each bootstrapping relocation
before applying the final relocation when ld.so is linked in as
normal a shared library. */
rtld_map.l_type = lt_library;
ELF_DYNAMIC_RELOCATE (&rtld_map, 0, NULL);
bootstrap_map.l_type = lt_library;
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, NULL);
/* Now life is sane; we can call functions and access global data.
@ -86,7 +88,12 @@ _dl_start (void *arg)
the operating system's program loader where to find the program
header table in core. */
dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address. */
/* Transfer data about ourselves to the permanent link_map structure. */
rtld_map.l_addr = bootstrap_map.l_addr;
rtld_map.l_ld = bootstrap_map.l_ld;
memcpy (rtld_map.l_info, bootstrap_map.l_info, sizeof rtld_map.l_info);
/* Call the OS-dependent function to set up life so we can do things like
file access. It will call `dl_main' (below) to do all the real work
@ -228,8 +235,14 @@ of this helper program; chances are you did not intend to run this program.\n",
will set up later to communicate with the debugger. */
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
l = _dl_new_object ((char *) interpreter_name, interpreter_name,
lt_interpreter);
/* Put the link_map for ourselves on the chain so it can be found by
name. */
rtld_map.l_name = (char *) rtld_map.l_libname = interpreter_name;
rtld_map.l_type = lt_interpreter;
while (l->l_next)
l = l->l_next;
l->l_next = &rtld_map;
rtld_map.l_prev = l;
/* Now process all the DT_NEEDED entries and map in the objects.
Each new link_map will go on the end of the chain, so we will
@ -248,16 +261,13 @@ of this helper program; chances are you did not intend to run this program.\n",
l->l_deps_loaded = 1;
}
l = _dl_loaded->l_next;
while (l->l_type != lt_interpreter)
l = l->l_next;
if (l->l_opencount == 0)
if (rtld_map.l_opencount == 0)
{
/* No DT_NEEDED entry referred to the interpreter object itself.
Remove it from the maps we will use for symbol resolution. */
l->l_prev->l_next = l->l_next;
if (l->l_next)
l->l_next->l_prev = l->l_prev;
rtld_map.l_prev->l_next = rtld_map.l_next;
if (rtld_map.l_next)
rtld_map.l_next->l_prev = rtld_map.l_prev;
}
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
@ -276,6 +286,7 @@ of this helper program; chances are you did not intend to run this program.\n",
/* Tell the debugger where to find the map of loaded objects. */
dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address. */
dl_r_debug.r_map = _dl_loaded;
dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
@ -301,6 +312,19 @@ of this helper program; chances are you did not intend to run this program.\n",
_exit (0);
}
if (rtld_map.l_info[DT_INIT])
{
/* Call the initializer for the compatibility version of the
dynamic linker. There is no additional initialization
required for the ABI-compliant dynamic linker. */
(*(void (*) (void)) (rtld_map.l_addr +
rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
/* Clear the field so a future dlopen won't run it again. */
rtld_map.l_info[DT_INIT] = NULL;
}
}
const char *errstring;
const char *errobj;
@ -325,6 +349,18 @@ _dl_r_debug_state (void)
{
}
/* Define our own stub for the localization function used by strerror.
English-only in the dynamic linker keeps it smaller. */
char *
__dgettext (const char *domainname, const char *msgid)
{
assert (domainname == _libc_intl_domainname);
return (char *) msgid;
}
weak_symbol (__dgettext)
weak_alias (__dgettext, dgettext)
#ifndef NDEBUG
/* Define (weakly) our own assert failure function which doesn't use stdio.

View File

@ -150,9 +150,11 @@ read_alias_file (fname, fname_len)
FILE *fp;
char *full_fname;
size_t added;
static const char aliasfile[] = "/locale.alias";
full_fname = (char *) alloca (fname_len + sizeof ("/locale.alias"));
sprintf (full_fname, "%.*s/locale.alias", fname_len, fname);
full_fname = (char *) alloca (fname_len + sizeof aliasfile);
memcpy (full_fname, fname, fname_len);
memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
fp = fopen (full_fname, "r");
if (fp == NULL)

View File

@ -18,6 +18,7 @@ Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <string.h>
#include "../stdio-common/_itoa.h"
#ifndef HAVE_GNU_LD
#define _sys_errlist sys_errlist
@ -31,13 +32,14 @@ _strerror_internal (errnum, buf, buflen)
char *buf;
size_t buflen;
{
if (errnum < 0 || errnum > _sys_nerr)
if (errnum < 0 || errnum >= _sys_nerr)
{
int len = __snprintf (buf, buflen, _("Unknown error %d"), errnum);
if (len < 0)
return NULL;
buf[len - 1] = '\0';
return buf;
const char *unk = _("Unknown error ");
const size_t unklen = strlen (unk);
char *p = buf + buflen;
*--p = '\0';
p = _itoa (errnum, p, 10, 0);
return memcpy (p - unklen, unk, unklen);
}
return (char *) _(_sys_errlist[errnum]);

View File

@ -43,7 +43,7 @@ _strerror_internal (int errnum, char *buf, size_t buflen)
const char *unk = _("Error in unknown error system: ");
const size_t unklen = strlen (unk);
char *p = buf + buflen;
*p-- = '\0';
*--p = '\0';
p = _itoa (errnum, p, 16, 1);
return memcpy (p - unklen, unk, unklen);
}
@ -59,7 +59,7 @@ _strerror_internal (int errnum, char *buf, size_t buflen)
const size_t unklen = strlen (unk);
char *p = buf + buflen;
size_t len = strlen (es->subsystem[sub].subsys_name);
*p-- = '\0';
*--p = '\0';
p = _itoa (errnum, p, 16, 1);
*p-- = ' ';
p = memcpy (p - len, es->subsystem[sub].subsys_name, len);