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.
This commit is contained in:
John Polstra 1999-08-30 01:54:13 +00:00
parent 7360ae0f2a
commit a607e5d7f8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=50610
3 changed files with 31 additions and 12 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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 */