aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-error.c51
-rw-r--r--elf/elf.h54
-rw-r--r--elf/rtld.c468
3 files changed, 321 insertions, 252 deletions
diff --git a/elf/dl-error.c b/elf/dl-error.c
index a5c861190f..737bba7421 100644
--- a/elf/dl-error.c
+++ b/elf/dl-error.c
@@ -1,5 +1,5 @@
/* Error handling for runtime dynamic linker.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 1996 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
@@ -20,18 +20,47 @@ Cambridge, MA 02139, USA. */
#include <stddef.h>
#include <link.h>
#include <setjmp.h>
+#include <string.h>
+
+/* This structure communicates state between _dl_catch_error and
+ _dl_signal_error. */
+struct catch
+ {
+ const char *errstring, *objname; /* Error detail filled in here. */
+ jmp_buf env; /* longjmp here on error. */
+ };
+
+/* This points to such a structure during a call to _dl_catch_error.
+ During implicit startup and run-time work for needed shared libraries,
+ this is null. */
+static struct catch *catch;
-static jmp_buf catch_env;
-static const char *signalled_errstring, *signalled_objname;
void
_dl_signal_error (int errcode,
const char *objname,
const char *errstring)
{
- signalled_errstring = errstring ?: "DYNAMIC LINKER BUG!!!";
- signalled_objname = objname;
- longjmp (catch_env, errcode ?: -1);
+ if (! errstring)
+ errstring = "DYNAMIC LINKER BUG!!!";
+
+ if (catch)
+ {
+ /* We are inside _dl_catch_error. Return to it. */
+ catch->errstring = errstring;
+ catch->objname = objname;
+ longjmp (catch->env, errcode ?: -1);
+ }
+ else
+ {
+ /* Lossage while resolving the program's own symbols is always fatal. */
+ extern char **_dl_argv; /* Set in rtld.c at startup. */
+ _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
+ ": error in loading shared libraries\n",
+ objname ?: "", objname ? ": " : "",
+ errstring, errcode ? ": " : "",
+ errcode ? strerror (errcode) : "", "\n", NULL);
+ }
}
int
@@ -40,18 +69,20 @@ _dl_catch_error (const char **errstring,
void (*operate) (void))
{
int errcode;
+ struct catch c = { errstring: NULL, objname: NULL };
- signalled_errstring = signalled_objname = NULL;
- errcode = setjmp (catch_env);
+ errcode = setjmp (c.env);
if (errcode == 0)
{
+ catch = &c;
(*operate) ();
+ catch = NULL;
*errstring = *objname = NULL;
return 0;
}
/* We get here only if we longjmp'd out of OPERATE. */
- *errstring = signalled_errstring;
- *objname = signalled_objname;
+ *errstring = c.errstring;
+ *objname = c.objname;
return errcode == -1 ? 0 : errcode;
}
diff --git a/elf/elf.h b/elf/elf.h
index a78432039f..2b41ff0cbc 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -119,6 +119,7 @@ typedef struct
#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */
#define EM_PARISC 15 /* HPPA */
+#define EM_PPC 20 /* PowerPC */
/* If it is necessary to assign new unofficial EM_* values, please
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
@@ -255,6 +256,10 @@ typedef struct
#define ELF32_R_TYPE(val) ((val) & 0xff)
#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type))
+
/* Program segment header. */
typedef struct {
@@ -288,6 +293,17 @@ typedef struct {
#define PF_R (1 << 2) /* Segment is readable */
#define PF_MASKPROC 0xf0000000 /* Processor-specific */
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+
+/* Legal values for the note segment descriptor types for object files. */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+
/* Dynamic section entry. */
typedef struct
@@ -521,9 +537,17 @@ typedef struct
#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
+/* Legal values for MIPS architecture level. */
+
+#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+
/* Special section indices. */
#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
+#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbol. */
+#define SHN_MIPS_DATA 0xff02 /* Allocated data symbol. */
#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
@@ -535,6 +559,9 @@ typedef struct
#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information */
#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
+#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
+#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
+#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
/* Legal values for sh_flags field of Elf32_Shdr. */
@@ -602,7 +629,8 @@ typedef struct
#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
-#define DT_MIPS_NUM 0x15
+#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
+#define DT_MIPS_NUM 0x17
/* Legal values for DT_MIPS_FLAG Elf32_Dyn entry. */
@@ -632,4 +660,28 @@ typedef struct
typedef Elf32_Addr Elf32_Conflict;
+/* HPPA specific definitions. */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */
+#define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */
+#define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */
+#define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */
+#define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */
+#define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */
+#define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */
+#define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */
+#define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */
+#define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
+
+
#endif /* elf.h */
diff --git a/elf/rtld.c b/elf/rtld.c
index d727e1361f..edd9c514d8 100644
--- a/elf/rtld.c
+++ b/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;
+ 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)
- {
- /* 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...
-
- 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 ("\
+ 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...
+
+ 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)
+ 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;
+ }
+
+ /* 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])
{
- 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;
+ 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 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.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;
- }
+ 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. */
+ 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;
+ 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);
- }
+ 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);
+ 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);
}
- 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. */
+ _exit (0);
+ }
- (*(void (*) (void)) (rtld_map.l_addr +
- rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
+ 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. */
- /* Clear the field so a future dlopen won't run it again. */
- rtld_map.l_info[DT_INIT] = NULL;
- }
+ (*(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;
- 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);
/* Once we return, _dl_sysdep_start will invoke
the DT_INIT functions and then *USER_ENTRY. */