summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1999-08-30 01:54:13 +0000
committerjdp <jdp@FreeBSD.org>1999-08-30 01:54:13 +0000
commit3e8e2eed47d9851854f20f21c338340dd059810d (patch)
treec08e1c0e928782fcbf639b9566d64f1e81937ee2 /libexec/rtld-elf
parent7a67a7ee048e83361dbd4afda5c84ff0b8646542 (diff)
downloadFreeBSD-src-3e8e2eed47d9851854f20f21c338340dd059810d.zip
FreeBSD-src-3e8e2eed47d9851854f20f21c338340dd059810d.tar.gz
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.
Diffstat (limited to 'libexec/rtld-elf')
-rw-r--r--libexec/rtld-elf/map_object.c18
-rw-r--r--libexec/rtld-elf/rtld.c24
-rw-r--r--libexec/rtld-elf/rtld.h1
3 files changed, 31 insertions, 12 deletions
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 */
OpenPOWER on IntegriCloud