mirror of
https://sourceware.org/git/glibc.git
synced 2025-09-01 05:02:03 +03:00
Tue May 28 04:38:10 1996 Ulrich Drepper <drepper@cygnus.com>
* limits.h: Change MB_LEN_MAX to 6. A 31-bit ISO 10646 character in UTF-8 encoding has that many bytes. * locale/langinfo.h: New element _NL_CTYPE_MB_CUR_MAX. * locale/categories.def: Add description of field _NL_CTYPE_MB_CUR_MAX. * locale/Makefile (routines): Add mb_cur_max. * locale/mb_cur_max.c: New file. This function gets called when the macro MB_CUR_MAX is used. * locale/C-ctype.c: Initialize new mb_cur_max field. * locale/localeinfo.h: Change magic value because of incompatible change. * locale/programs/ld-ctype.c: Determine value of mb_cur_max according to current character set and write it out with the rest. * stdlib/stdlib.h (MB_CUR_MAX): Not constant anymore. Get value according to currently used locale for catefory LC_CTYPE by calling the function __ctype_get_mb_cur_max. Tue May 28 03:27:46 1996 Ulrich Drepper <drepper@cygnus.com> * FAQ: Fix some typos. Tell that for Linux the kernel header files are necessary. * PROJECTS: New file. List of open jobs for glibc. * Makefile (distribute): Add PROJECTS. * crypt/GNUmakefile (headers): New variable. Mention crypt.h. * crypt/crypt.h: Header for crypt functions. * elf/elf.h: Add some new constants from recent Cygnus ELF header files. * login/getutid_r.c: Test for correct type. Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined. Make really compliant with specification. * login/getutline_r.c, login/pututline_r.c: Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined. Make really compliant with specification. * login/setutent_r.c: Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined. * login/login.c, login/logout.c, login/logwtmp.c: Complete rewrite. Now based on getut*/setut* functions. * stdlib/strtol.c: Undo changes of Wed May 22 01:48:54 1996. This prevented using this file in other GNU packages. * sysdeps/gnu/utmpbits.h: Define _HAVE_UT_TYPE, _HAVE_UT_ID, and _HAVE_UT_TV because struct utmp has these members. * sysdeps/libm-i387/e_exp.S: Correct exp(+-Inf) case. * utmp.h: New file. Wrapper around login/utmp.h. * elf/dl-error.c (struct catch): New type. (catch): New static variable, struct catch *. (catch_env, signalled_errstring, signalled_objname): Variables removed. (_dl_signal_error): If CATCH is non-null, set its errstring and objname members and jump to CATCH->env. If it is null, call _dl_sysdep_fatal with a standard message. * elf/rtld.c (dl_main): Explode `doit' function into dl_main's body. No longer use _dl_catch_error.
This commit is contained in:
486
elf/rtld.c
486
elf/rtld.c
@@ -123,33 +123,31 @@ dl_main (const Elf32_Phdr *phdr,
|
||||
Elf32_Word phent,
|
||||
Elf32_Addr *user_entry)
|
||||
{
|
||||
void doit (void)
|
||||
const Elf32_Phdr *ph;
|
||||
struct link_map *l, *last, *before_rtld;
|
||||
const char *interpreter_name;
|
||||
int lazy;
|
||||
int list_only = 0;
|
||||
|
||||
if (*user_entry == (Elf32_Addr) &_start)
|
||||
{
|
||||
const Elf32_Phdr *ph;
|
||||
struct link_map *l, *last, *before_rtld;
|
||||
const char *interpreter_name;
|
||||
int lazy;
|
||||
int list_only = 0;
|
||||
/* Ho ho. We are not the program interpreter! We are the program
|
||||
itself! This means someone ran ld.so as a command. Well, that
|
||||
might be convenient to do sometimes. We support it by
|
||||
interpreting the args like this:
|
||||
|
||||
if (*user_entry == (Elf32_Addr) &_start)
|
||||
{
|
||||
/* Ho ho. We are not the program interpreter! We are the program
|
||||
itself! This means someone ran ld.so as a command. Well, that
|
||||
might be convenient to do sometimes. We support it by
|
||||
interpreting the args like this:
|
||||
ld.so PROGRAM ARGS...
|
||||
|
||||
ld.so PROGRAM ARGS...
|
||||
|
||||
The first argument is the name of a file containing an ELF
|
||||
executable we will load and run with the following arguments.
|
||||
To simplify life here, PROGRAM is searched for using the
|
||||
normal rules for shared objects, rather than $PATH or anything
|
||||
like that. We just load it and use its entry point; we don't
|
||||
pay attention to its PT_INTERP command (we are the interpreter
|
||||
ourselves). This is an easy way to test a new ld.so before
|
||||
installing it. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
The first argument is the name of a file containing an ELF
|
||||
executable we will load and run with the following arguments.
|
||||
To simplify life here, PROGRAM is searched for using the
|
||||
normal rules for shared objects, rather than $PATH or anything
|
||||
like that. We just load it and use its entry point; we don't
|
||||
pay attention to its PT_INTERP command (we are the interpreter
|
||||
ourselves). This is an easy way to test a new ld.so before
|
||||
installing it. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
Usage: ld.so [--list] EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
||||
You have invoked `ld.so', the helper program for shared library executables.\n\
|
||||
This program usually lives in the file `/lib/ld.so', and special directives\n\
|
||||
@@ -162,243 +160,231 @@ that file itself, but always uses this helper program from the file you\n\
|
||||
specified, instead of the helper program file specified in the executable\n\
|
||||
file you run. This is mostly of use for maintainers to test new versions\n\
|
||||
of this helper program; chances are you did not intend to run this program.\n",
|
||||
NULL);
|
||||
NULL);
|
||||
|
||||
interpreter_name = _dl_argv[0];
|
||||
interpreter_name = _dl_argv[0];
|
||||
|
||||
if (! strcmp (_dl_argv[1], "--list"))
|
||||
{
|
||||
list_only = 1;
|
||||
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
}
|
||||
if (! strcmp (_dl_argv[1], "--list"))
|
||||
{
|
||||
list_only = 1;
|
||||
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
|
||||
l = _dl_map_object (NULL, _dl_argv[0]);
|
||||
phdr = l->l_phdr;
|
||||
phent = l->l_phnum;
|
||||
l->l_name = (char *) "";
|
||||
*user_entry = l->l_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a link_map for the executable itself.
|
||||
This will be what dlopen on "" returns. */
|
||||
l = _dl_new_object ((char *) "", "", lt_executable);
|
||||
l->l_phdr = phdr;
|
||||
l->l_phnum = phent;
|
||||
interpreter_name = 0;
|
||||
l->l_entry = *user_entry;
|
||||
}
|
||||
|
||||
if (l != _dl_loaded)
|
||||
{
|
||||
/* GDB assumes that the first element on the chain is the
|
||||
link_map for the executable itself, and always skips it.
|
||||
Make sure the first one is indeed that one. */
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
l->l_prev = NULL;
|
||||
l->l_next = _dl_loaded;
|
||||
_dl_loaded->l_prev = l;
|
||||
_dl_loaded = l;
|
||||
}
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
|
||||
/* Scan the program header table for the dynamic section. */
|
||||
for (ph = phdr; ph < &phdr[phent]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
case PT_DYNAMIC:
|
||||
/* This tells us where to find the dynamic section,
|
||||
which tells us everything we need to do. */
|
||||
l->l_ld = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
find the program interpreter, which is this program itself, the
|
||||
dynamic linker. We note what name finds us, so that a future
|
||||
dlopen call or DT_NEEDED entry, for something that wants to link
|
||||
against the dynamic linker as a shared library, will know that
|
||||
the shared object is already loaded. */
|
||||
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
}
|
||||
assert (interpreter_name); /* How else did we get here? */
|
||||
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
if (l->l_info[DT_HASH])
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
_dl_setup_hash (l);
|
||||
|
||||
if (l->l_info[DT_DEBUG])
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure, which we
|
||||
will set up later to communicate with the debugger. */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
|
||||
|
||||
/* 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
|
||||
come across it later in the loop to map in its dependencies. */
|
||||
before_rtld = NULL;
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
{
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
const char *strtab
|
||||
= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
|
||||
const Elf32_Dyn *d;
|
||||
last = l;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
struct link_map *new;
|
||||
new = _dl_map_object (l, strtab + d->d_un.d_val);
|
||||
if (!before_rtld && new == &rtld_map)
|
||||
before_rtld = last;
|
||||
last = new;
|
||||
}
|
||||
}
|
||||
l->l_deps_loaded = 1;
|
||||
}
|
||||
|
||||
/* If any DT_NEEDED entry referred to the interpreter object itself,
|
||||
reorder the list so it appears after its dependent. If not,
|
||||
remove it from the maps we will use for symbol resolution. */
|
||||
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;
|
||||
if (before_rtld)
|
||||
{
|
||||
rtld_map.l_prev = before_rtld;
|
||||
rtld_map.l_next = before_rtld->l_next;
|
||||
before_rtld->l_next = &rtld_map;
|
||||
if (rtld_map.l_next)
|
||||
rtld_map.l_next->l_prev = &rtld_map;
|
||||
}
|
||||
|
||||
if (list_only)
|
||||
{
|
||||
/* We were run just to list the shared libraries. It is
|
||||
important that we do this before real relocation, because the
|
||||
functions we call below for output may no longer work properly
|
||||
after relocation. */
|
||||
|
||||
int i;
|
||||
|
||||
if (! _dl_loaded->l_info[DT_NEEDED])
|
||||
_dl_sysdep_message ("\t", "statically linked\n", NULL);
|
||||
else
|
||||
for (l = _dl_loaded->l_next; l; l = l->l_next)
|
||||
{
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (l->l_addr, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof l->l_addr * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message ("\t", l->l_libname, " => ", l->l_name,
|
||||
" (0x", bp, ")\n", NULL);
|
||||
}
|
||||
|
||||
for (i = 1; i < _dl_argc; ++i)
|
||||
{
|
||||
const Elf32_Sym *ref = NULL;
|
||||
Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||
_dl_loaded, "argument",
|
||||
1);
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (_dl_argv[i], " found at 0x", bp, NULL);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (loadbase, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
|
||||
}
|
||||
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||
|
||||
/* Now we have all the objects loaded. Relocate them all except for
|
||||
the dynamic linker itself. We do this in reverse order so that
|
||||
copy relocs of earlier objects overwrite the data written by later
|
||||
objects. We do not re-relocate the dynamic linker itself in this
|
||||
loop because that could result in the GOT entries for functions we
|
||||
call being changed, and that would break us. It is safe to
|
||||
relocate the dynamic linker out of order because it has no copy
|
||||
relocs (we know that because it is self-contained). */
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
do
|
||||
{
|
||||
if (l != &rtld_map)
|
||||
_dl_relocate_object (l, lazy);
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
|
||||
/* Do any necessary cleanups for the startup OS interface code.
|
||||
We do these now so that no calls are made after rtld re-relocation
|
||||
which might be resolved to different functions than we expect.
|
||||
We cannot do this before relocating the other objects because
|
||||
_dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */
|
||||
_dl_sysdep_start_cleanup ();
|
||||
|
||||
if (rtld_map.l_opencount > 0)
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||
_dl_relocate_object (&rtld_map, lazy);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
l = _dl_map_object (NULL, _dl_argv[0]);
|
||||
phdr = l->l_phdr;
|
||||
phent = l->l_phnum;
|
||||
l->l_name = (char *) "";
|
||||
*user_entry = l->l_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a link_map for the executable itself.
|
||||
This will be what dlopen on "" returns. */
|
||||
l = _dl_new_object ((char *) "", "", lt_executable);
|
||||
l->l_phdr = phdr;
|
||||
l->l_phnum = phent;
|
||||
interpreter_name = 0;
|
||||
l->l_entry = *user_entry;
|
||||
}
|
||||
const char *errstring;
|
||||
const char *errobj;
|
||||
int err;
|
||||
|
||||
err = _dl_catch_error (&errstring, &errobj, &doit);
|
||||
if (errstring)
|
||||
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
|
||||
": error in loading shared libraries\n",
|
||||
errobj ?: "", errobj ? ": " : "",
|
||||
errstring, err ? ": " : "",
|
||||
err ? strerror (err) : "", "\n", NULL);
|
||||
if (l != _dl_loaded)
|
||||
{
|
||||
/* GDB assumes that the first element on the chain is the
|
||||
link_map for the executable itself, and always skips it.
|
||||
Make sure the first one is indeed that one. */
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
l->l_prev = NULL;
|
||||
l->l_next = _dl_loaded;
|
||||
_dl_loaded->l_prev = l;
|
||||
_dl_loaded = l;
|
||||
}
|
||||
|
||||
/* Scan the program header table for the dynamic section. */
|
||||
for (ph = phdr; ph < &phdr[phent]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
case PT_DYNAMIC:
|
||||
/* This tells us where to find the dynamic section,
|
||||
which tells us everything we need to do. */
|
||||
l->l_ld = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
find the program interpreter, which is this program itself, the
|
||||
dynamic linker. We note what name finds us, so that a future
|
||||
dlopen call or DT_NEEDED entry, for something that wants to link
|
||||
against the dynamic linker as a shared library, will know that
|
||||
the shared object is already loaded. */
|
||||
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
}
|
||||
assert (interpreter_name); /* How else did we get here? */
|
||||
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
if (l->l_info[DT_HASH])
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
_dl_setup_hash (l);
|
||||
|
||||
if (l->l_info[DT_DEBUG])
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure, which we
|
||||
will set up later to communicate with the debugger. */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
|
||||
|
||||
/* 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
|
||||
come across it later in the loop to map in its dependencies. */
|
||||
before_rtld = NULL;
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
{
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
const char *strtab
|
||||
= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
|
||||
const Elf32_Dyn *d;
|
||||
last = l;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
struct link_map *new;
|
||||
new = _dl_map_object (l, strtab + d->d_un.d_val);
|
||||
if (!before_rtld && new == &rtld_map)
|
||||
before_rtld = last;
|
||||
last = new;
|
||||
}
|
||||
}
|
||||
l->l_deps_loaded = 1;
|
||||
}
|
||||
|
||||
/* If any DT_NEEDED entry referred to the interpreter object itself,
|
||||
reorder the list so it appears after its dependent. If not,
|
||||
remove it from the maps we will use for symbol resolution. */
|
||||
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;
|
||||
if (before_rtld)
|
||||
{
|
||||
rtld_map.l_prev = before_rtld;
|
||||
rtld_map.l_next = before_rtld->l_next;
|
||||
before_rtld->l_next = &rtld_map;
|
||||
if (rtld_map.l_next)
|
||||
rtld_map.l_next->l_prev = &rtld_map;
|
||||
}
|
||||
|
||||
if (list_only)
|
||||
{
|
||||
/* We were run just to list the shared libraries. It is
|
||||
important that we do this before real relocation, because the
|
||||
functions we call below for output may no longer work properly
|
||||
after relocation. */
|
||||
|
||||
int i;
|
||||
|
||||
if (! _dl_loaded->l_info[DT_NEEDED])
|
||||
_dl_sysdep_message ("\t", "statically linked\n", NULL);
|
||||
else
|
||||
for (l = _dl_loaded->l_next; l; l = l->l_next)
|
||||
{
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (l->l_addr, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof l->l_addr * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message ("\t", l->l_libname, " => ", l->l_name,
|
||||
" (0x", bp, ")\n", NULL);
|
||||
}
|
||||
|
||||
for (i = 1; i < _dl_argc; ++i)
|
||||
{
|
||||
const Elf32_Sym *ref = NULL;
|
||||
Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||
_dl_loaded, "argument",
|
||||
1);
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (_dl_argv[i], " found at 0x", bp, NULL);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (loadbase, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
|
||||
}
|
||||
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||
|
||||
/* Now we have all the objects loaded. Relocate them all except for
|
||||
the dynamic linker itself. We do this in reverse order so that
|
||||
copy relocs of earlier objects overwrite the data written by later
|
||||
objects. We do not re-relocate the dynamic linker itself in this
|
||||
loop because that could result in the GOT entries for functions we
|
||||
call being changed, and that would break us. It is safe to
|
||||
relocate the dynamic linker out of order because it has no copy
|
||||
relocs (we know that because it is self-contained). */
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
do
|
||||
{
|
||||
if (l != &rtld_map)
|
||||
_dl_relocate_object (l, lazy);
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
|
||||
/* Do any necessary cleanups for the startup OS interface code.
|
||||
We do these now so that no calls are made after rtld re-relocation
|
||||
which might be resolved to different functions than we expect.
|
||||
We cannot do this before relocating the other objects because
|
||||
_dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */
|
||||
_dl_sysdep_start_cleanup ();
|
||||
|
||||
if (rtld_map.l_opencount > 0)
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||
_dl_relocate_object (&rtld_map, lazy);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Once we return, _dl_sysdep_start will invoke
|
||||
the DT_INIT functions and then *USER_ENTRY. */
|
||||
|
Reference in New Issue
Block a user