From 3e8e2eed47d9851854f20f21c338340dd059810d Mon Sep 17 00:00:00 2001 From: jdp Date: Mon, 30 Aug 1999 01:54:13 +0000 Subject: Get the actual pathname of the dynamic linker from the executable's PT_INTERP program header entry, to ensure that gdb always finds the right dynamic linker. Use obj->relocbase to simplify a few calculations where appropriate. --- libexec/rtld-elf/map_object.c | 18 +++++++++++------- libexec/rtld-elf/rtld.c | 24 +++++++++++++++++++----- libexec/rtld-elf/rtld.h | 1 + 3 files changed, 31 insertions(+), 12 deletions(-) (limited to 'libexec/rtld-elf') diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index ca353c7..d7b6978 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -62,6 +62,7 @@ map_object(int fd, const char *path, const struct stat *sb) int nsegs; Elf_Phdr *phdyn; Elf_Phdr *phphdr; + Elf_Phdr *phinterp; caddr_t mapbase; size_t mapsize; Elf_Off base_offset; @@ -136,11 +137,14 @@ map_object(int fd, const char *path, const struct stat *sb) phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff); phlimit = phdr + u.hdr.e_phnum; nsegs = 0; - phdyn = NULL; - phphdr = NULL; + phdyn = phphdr = phinterp = NULL; while (phdr < phlimit) { switch (phdr->p_type) { + case PT_INTERP: + phinterp = phdr; + break; + case PT_LOAD: if (nsegs >= 2) { _rtld_error("%s: too many PT_LOAD segments", path); @@ -239,15 +243,15 @@ map_object(int fd, const char *path, const struct stat *sb) base_vaddr; obj->vaddrbase = base_vaddr; obj->relocbase = mapbase - base_vaddr; - obj->dynamic = (const Elf_Dyn *) - (mapbase + (phdyn->p_vaddr - base_vaddr)); + obj->dynamic = (const Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr); if (u.hdr.e_entry != 0) - obj->entry = (caddr_t) (mapbase + (u.hdr.e_entry - base_vaddr)); + obj->entry = (caddr_t) (obj->relocbase + u.hdr.e_entry); if (phphdr != NULL) { - obj->phdr = (const Elf_Phdr *) - (mapbase + (phphdr->p_vaddr - base_vaddr)); + obj->phdr = (const Elf_Phdr *) (obj->relocbase + phphdr->p_vaddr); obj->phsize = phphdr->p_memsz; } + if (phinterp != NULL) + obj->interp = (const char *) (obj->relocbase + phinterp->p_vaddr); return obj; } diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index ef5f917..1885383 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -61,11 +61,8 @@ #define msg(s) (write(1, s, strlen(s))) #define trace() msg("trace: " __XSTRING(__LINE__) "\n"); -#ifndef _PATH_RTLD -#define _PATH_RTLD "/usr/libexec/ld-elf.so.1" -#endif - #define END_SYM "_end" +#define PATH_RTLD "/usr/libexec/ld-elf.so.1" /* Types. */ typedef void (*func_ptr_type)(); @@ -269,6 +266,19 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) obj_main->path = xstrdup(argv0); obj_main->mainprog = true; + + /* + * Get the actual dynamic linker pathname from the executable if + * possible. (It should always be possible.) That ensures that + * gdb will find the right dynamic linker even if a non-standard + * one is being used. + */ + if (obj_main->interp != NULL && + strcmp(obj_main->interp, obj_rtld.path) != 0) { + free(obj_rtld.path); + obj_rtld.path = xstrdup(obj_main->interp); + } + digest_dynamic(obj_main); linkmap_add(obj_main); @@ -585,6 +595,10 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) obj->phsize = ph->p_memsz; break; + case PT_INTERP: + obj->interp = (const char *) ph->p_vaddr; + break; + case PT_LOAD: if (nsegs >= 2) { _rtld_error("%s: too many PT_LOAD segments", path); @@ -867,7 +881,7 @@ init_rtld(caddr_t mapbase) * aren't yet initialized sufficiently to do that. Below we will * replace the static version with a dynamically-allocated copy. */ - obj_rtld.path = _PATH_RTLD; + obj_rtld.path = PATH_RTLD; obj_rtld.rtld = true; obj_rtld.mapbase = mapbase; #ifdef PIC diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index ab26d01..0cdbe4c 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -99,6 +99,7 @@ typedef struct Struct_Obj_Entry { caddr_t entry; /* Entry point */ const Elf_Phdr *phdr; /* Program header if it is mapped, else NULL */ size_t phsize; /* Size of program header in bytes */ + const char *interp; /* Pathname of the interpreter, if any */ /* Items from the dynamic section. */ Elf_Addr *pltgot; /* PLT or GOT, depending on architecture */ -- cgit v1.1