diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-error.c | 10 | ||||
-rw-r--r-- | elf/dl-fini.c | 2 | ||||
-rw-r--r-- | elf/dl-init.c | 10 | ||||
-rw-r--r-- | elf/dl-load.c | 21 | ||||
-rw-r--r-- | elf/dl-lookup.c | 11 | ||||
-rw-r--r-- | elf/dl-reloc.c | 2 | ||||
-rw-r--r-- | elf/do-rel.h | 53 | ||||
-rw-r--r-- | elf/dynamic-link.h | 12 | ||||
-rw-r--r-- | elf/rtld.c | 9 |
9 files changed, 76 insertions, 54 deletions
diff --git a/elf/dl-error.c b/elf/dl-error.c index acb21a0414..b5af2e323f 100644 --- a/elf/dl-error.c +++ b/elf/dl-error.c @@ -43,8 +43,14 @@ _dl_catch_error (const char **errstring, signalled_errstring = signalled_objname = NULL; errcode = setjmp (catch_env); - (*operate) (); + if (errcode == 0) + { + (*operate) (); + return 0; + } + + /* We get here only if we longjmp'd out of OPERATE. */ *errstring = signalled_errstring; *objname = signalled_objname; - return *errstring ? errcode : 0; + return errcode == -1 ? 0 : errcode; } diff --git a/elf/dl-fini.c b/elf/dl-fini.c index cbc05252d2..69ff83d488 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -26,5 +26,5 @@ _dl_fini (void) for (l = _dl_loaded; l; l = l->l_next) if (l->l_init_called && l->l_info[DT_FINI]) - (*(void (*) (void)) l->l_info[DT_FINI]->d_un.d_ptr) (); + (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) (); } diff --git a/elf/dl-init.c b/elf/dl-init.c index e3bfc2ccea..36eb32aa78 100644 --- a/elf/dl-init.c +++ b/elf/dl-init.c @@ -46,15 +46,17 @@ _dl_init_next (void) { /* Find each dependency in order, and see if it needs to run an initializer. */ + const char *strtab + = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); const Elf32_Dyn *d; for (d = l->l_ld; d->d_tag != DT_NULL; ++d) if (d->d_tag == DT_NEEDED) { - struct link_map *needed = _dl_map_object - (l, (const char *) (l->l_addr + d->d_un.d_ptr), NULL); + struct link_map *needed + = _dl_map_object (l, strtab + d->d_un.d_val, NULL); Elf32_Addr init; --needed->l_opencount; - init = next_init (l); /* Recurse on this dependency. */ + init = next_init (needed); /* Recurse on this dependency. */ if (init != 0) return init; } @@ -74,7 +76,7 @@ _dl_init_next (void) } /* Look for the first initializer not yet called. */ - l = _dl_loaded; + l = _dl_loaded->l_next; /* Skip the executable itself. */ do { init = next_init (l); diff --git a/elf/dl-load.c b/elf/dl-load.c index f8b37ba346..bb1ad972d4 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -158,11 +158,12 @@ _dl_map_object (struct link_map *loader, const char *name, size_t namelen = strlen (name) + 1; - void trypath (const char *dirpath) + inline void trypath (const char *dirpath) { fd = open_path (name, namelen, dirpath, &realname); } + fd = -1; if (loader && loader->l_info[DT_RPATH]) trypath ((const char *) (loader->l_addr + loader->l_info[DT_RPATH]->d_un.d_ptr)); @@ -317,14 +318,14 @@ _dl_map_object (struct link_map *loader, const char *name, if (ph->p_memsz > ph->p_filesz) { /* Extra zero pages should appear at the end of this segment, - after the data mapped from the file. Adjust MAPEND to map - only the data from the file. We will later allocate zero - pages following the data mapping. */ - caddr_t zero = mapat - mapstart + ph->p_filesz; - caddr_t zeroend = mapat - mapstart + ph->p_memsz; - caddr_t zeropage - = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1) - & ~(pagesize - 1)); + after the data mapped from the file. */ + caddr_t zero, zeroend, zeropage; + + mapat += ph->p_vaddr - mapstart; + zero = mapat + ph->p_filesz; + zeroend = mapat + ph->p_memsz; + zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1) + & ~(pagesize - 1)); if (zeroend < zeropage) /* All the extra data is in the last page of the segment. @@ -342,7 +343,7 @@ _dl_map_object (struct link_map *loader, const char *name, prot|PROT_WRITE) < 0) lose (errno, "cannot change memory protections"); } - memset (zero, 0, zeroend - zero); + memset (zero, 0, zeropage - zero); if ((prot & PROT_WRITE) == 0) mprotect ((caddr_t) ((Elf32_Addr) zero & ~(pagesize - 1)), diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index a7afcc79bb..4d5d795ee5 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */ #include <stddef.h> #include <libelf.h> #include <link.h> +#include <assert.h> /* Search loaded objects' symbol tables for a definition of the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since @@ -70,13 +71,13 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, continue; } - if (sym == *ref) + if (sym->st_shndx == SHN_UNDEF) /* This is the same symbol we are looking for the value for. If it is a PLT entry, it will have a value of its own; but that is not what we are looking for. */ - continue; + continue; - if (strcmp (strtab + sym->st_name, undef_name)) + if (sym != *ref && strcmp (strtab + sym->st_name, undef_name)) /* Not the symbol we are looking for. */ continue; @@ -106,8 +107,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, const char msg[] = "undefined symbol: "; char buf[sizeof msg + strlen (undef_name)]; memcpy (buf, msg, sizeof msg - 1); - memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg); - _dl_signal_error (0, reference_name, msg); + memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1); + _dl_signal_error (0, reference_name, buf); } *ref = weak_value.s; diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 94ffb71759..ebc31d07fa 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -83,7 +83,7 @@ _dl_relocate_object (struct link_map *l, int lazy) l->l_prev->l_next = l; } - if (l->l_info[DT_JMPREL] && ! lazy) + if (l->l_info[DT_JMPREL] && lazy) /* Set up the PLT so its unrelocated entries will jump to _dl_runtime_resolve, which will relocate them. */ elf_machine_runtime_setup (l); diff --git a/elf/do-rel.h b/elf/do-rel.h index 04643e8fac..acef25d3f8 100644 --- a/elf/do-rel.h +++ b/elf/do-rel.h @@ -30,37 +30,46 @@ Cambridge, MA 02139, USA. */ /* Perform the relocations in MAP on the running program image as specified by RELTAG, SZTAG. *RESOLVE is called to resolve symbol values; it modifies its argument pointer to point to the defining symbol, and - returns the base load address of the defining object. */ + returns the base load address of the defining object. If LAZY is + nonzero, this is the first pass on PLT relocations; they should be set + up to call _dl_runtime_resolve, rather than fully resolved now. */ static inline void elf_dynamic_do_rel (struct link_map *map, int reltag, int sztag, - Elf32_Addr (*resolve) (const Elf32_Sym **)) + Elf32_Addr (*resolve) (const Elf32_Sym **), + int lazy) { const Elf32_Sym *const symtab - = (const Elf32_Sym *) map->l_info[DT_SYMTAB]->d_un.d_ptr; - const Elf32_Rel *r = (const Elf32_Rel *) map->l_info[reltag]->d_un.d_ptr; + = (const Elf32_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); + const Elf32_Rel *r + = (const Elf32_Rel *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr); const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r]; - for (; r < end; ++r) - { - const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)]; - Elf32_Addr loadbase; + if (lazy) + /* Doing lazy PLT relocations; they need very little info. */ + for (; r < end; ++r) + elf_machine_lazy_rel (map, r); + else + for (; r < end; ++r) + { + const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)]; + Elf32_Addr loadbase; - if (ELF32_R_SYM (r->r_info) == STN_UNDEF) - loadbase = 0; /* This value will not be consulted. */ - else - { - if (resolve) - loadbase = (*resolve) (&definer); - else - { - assert (definer->st_shndx != SHN_UNDEF); - loadbase = map->l_addr; - } - } - elf_machine_rel (map, r, loadbase, definer); - } + if (ELF32_R_SYM (r->r_info) == STN_UNDEF) + loadbase = 0; /* This value will not be consulted. */ + else + { + if (resolve) + loadbase = (*resolve) (&definer); + else + { + assert (definer->st_shndx != SHN_UNDEF); + loadbase = map->l_addr; + } + } + elf_machine_rel (map, r, loadbase, definer); + } } #undef elf_dynamic_do_rel diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index fc5c585356..a7316eefe8 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -56,9 +56,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM]) #include "do-rel.h" #define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \ if ((map)->l_info[DT_REL]) \ - elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve)); \ - if (!(lazy) && (map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \ - elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve)); + elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve), 0); \ + if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \ + elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy)); #else #define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */ #endif @@ -68,9 +68,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM]) #include "do-rel.h" #define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \ if ((map)->l_info[DT_RELA]) \ - elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve)); \ - if (!(lazy) && (map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \ - elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve); + elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve), 0); \ + if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \ + elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy)); #else #define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */ #endif diff --git a/elf/rtld.c b/elf/rtld.c index 85f258a948..409b9705d8 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -93,6 +93,8 @@ _dl_start (void *arg) void _start (void); +static int rtld_command; /* Nonzero if we were run directly. */ + static void dl_main (const Elf32_Phdr *phdr, Elf32_Word phent, @@ -138,6 +140,7 @@ 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" ); + rtld_command = 1; interpreter_name = _dl_argv[0]; --_dl_argc; ++_dl_argv; @@ -164,7 +167,7 @@ of this helper program; chances are you did not intend to run this program.\n" case PT_DYNAMIC: /* This tells us where to find the dynamic section, which tells us everything we need to do. */ - l->l_ld = (void *) ph->p_vaddr; + l->l_ld = (void *) l->l_addr + ph->p_vaddr; break; case PT_INTERP: /* This "interpreter segment" was used by the program loader to @@ -173,7 +176,7 @@ of this helper program; chances are you did not intend to run this program.\n" 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 *) ph->p_vaddr; + interpreter_name = (void *) l->l_addr + ph->p_vaddr; break; } assert (interpreter_name); /* How else did we get here? */ @@ -220,7 +223,7 @@ of this helper program; chances are you did not intend to run this program.\n" l->l_next->l_prev = l->l_prev; } - lazy = _dl_secure || *(getenv ("LD_BIND_NOW") ?: ""); + lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0'; /* Now we have all the objects loaded. Relocate them all. We do this in reverse order so that copy relocs of earlier |