diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index 5e9729c..31325a4 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -11,6 +11,7 @@ MAN= rtld.1 CSTD?= gnu99 CFLAGS+= -Wall -DFREEBSD_ELF -DIN_RTLD CFLAGS+= -I${.CURDIR}/${MACHINE_ARCH} -I${.CURDIR} +CFLAGS+= -g -DDEBUG LDFLAGS+= -nostdlib -e .rtld_start INSTALLFLAGS= -C -b PRECIOUSPROG= diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 721fe89..5a4da3f 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -991,26 +991,26 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) obj = obj_new(); for (ph = phdr; ph < phlimit; ph++) { - switch (ph->p_type) { + if (ph->p_type != PT_PHDR) + continue; - case PT_PHDR: - if ((const Elf_Phdr *)ph->p_vaddr != phdr) { - _rtld_error("%s: invalid PT_PHDR", path); - return NULL; - } - obj->phdr = (const Elf_Phdr *) ph->p_vaddr; - obj->phsize = ph->p_memsz; - break; + obj->phdr = phdr; + obj->phsize = ph->p_memsz; + obj->relocbase = (caddr_t)phdr - ph->p_vaddr; + break; + } + + for (ph = phdr; ph < phlimit; ph++) { + switch (ph->p_type) { case PT_INTERP: - obj->interp = (const char *) ph->p_vaddr; + obj->interp = (const char *)(ph->p_vaddr + obj->relocbase); break; case PT_LOAD: if (nsegs == 0) { /* First load segment */ obj->vaddrbase = trunc_page(ph->p_vaddr); - obj->mapbase = (caddr_t) obj->vaddrbase; - obj->relocbase = obj->mapbase - obj->vaddrbase; + obj->mapbase = obj->vaddrbase + obj->relocbase; obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) - obj->vaddrbase; } else { /* Last load segment */ @@ -1021,7 +1021,7 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) break; case PT_DYNAMIC: - obj->dynamic = (const Elf_Dyn *) ph->p_vaddr; + obj->dynamic = (const Elf_Dyn *)(ph->p_vaddr + obj->relocbase); break; case PT_TLS: @@ -1029,7 +1029,7 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) obj->tlssize = ph->p_memsz; obj->tlsalign = ph->p_align; obj->tlsinitsize = ph->p_filesz; - obj->tlsinit = (void*) ph->p_vaddr; + obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase); break; } } @@ -1038,6 +1038,8 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) return NULL; } + dbg("mapbase %p relocbase %p vaddrbase %x", + obj->mapbase, obj->relocbase, obj->vaddrbase); obj->entry = entry; return obj; } diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h index e5c95f7..9d96b96 100644 --- a/sys/amd64/include/elf.h +++ b/sys/amd64/include/elf.h @@ -106,4 +106,11 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_X86_64 #define ELF_TARG_VER 1 +#if __ELF_WORD_SIZE == 32 +#define ET_DYN_LOAD_ADDR 0x01001000 +#else +#define +#define ET_DYN_LOAD_ADDR 0x01021000 +#endif + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h index af71ab8..37ee279 100644 --- a/sys/i386/include/elf.h +++ b/sys/i386/include/elf.h @@ -105,4 +105,6 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_386 #define ELF_TARG_VER 1 +#define ET_DYN_LOAD_ADDR 0x01001000 + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 4ed7382..2cc2841 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -687,7 +687,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) u_long text_size = 0, data_size = 0, total_size = 0; u_long text_addr = 0, data_addr = 0; u_long seg_size, seg_addr; - u_long addr, entry = 0, proghdr = 0; + u_long addr, et_dyn_addr, entry = 0, proghdr = 0; int32_t osrel = 0; int error = 0, i; const char *interp = NULL, *newinterp = NULL; @@ -735,9 +735,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) hdr->e_ident[EI_OSABI]); return (ENOEXEC); } - if (hdr->e_type == ET_DYN && - (brand_info->flags & BI_CAN_EXEC_DYN) == 0) - return (ENOEXEC); + if (hdr->e_type == ET_DYN) { + if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) + return (ENOEXEC); + et_dyn_addr = ET_DYN_LOAD_ADDR; + } else + et_dyn_addr = 0; sv = brand_info->sysvec; if (interp != NULL && brand_info->interp_newpath != NULL) newinterp = brand_info->interp_newpath; @@ -783,7 +786,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) if ((error = __elfN(load_section)(vmspace, imgp->object, phdr[i].p_offset, - (caddr_t)(uintptr_t)phdr[i].p_vaddr, + (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr, phdr[i].p_memsz, phdr[i].p_filesz, prot, sv->sv_pagesize)) != 0) return (error); @@ -797,11 +800,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) if (phdr[i].p_offset == 0 && hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize <= phdr[i].p_filesz) - proghdr = phdr[i].p_vaddr + hdr->e_phoff; + proghdr = phdr[i].p_vaddr + hdr->e_phoff + + et_dyn_addr; - seg_addr = trunc_page(phdr[i].p_vaddr); + seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr); seg_size = round_page(phdr[i].p_memsz + - phdr[i].p_vaddr - seg_addr); + phdr[i].p_vaddr + et_dyn_addr - seg_addr); /* * Is this .text or .data? We can't use @@ -823,7 +827,11 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) phdr[i].p_memsz)) { text_size = seg_size; text_addr = seg_addr; - entry = (u_long)hdr->e_entry; + /* XXXKIB + * should check whether linux ld.so requires + * relocated entry + */ + entry = (u_long)hdr->e_entry + et_dyn_addr; } else { data_size = seg_size; data_addr = seg_addr; @@ -831,7 +839,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) total_size += seg_size; break; case PT_PHDR: /* Program header table info */ - proghdr = phdr[i].p_vaddr; + proghdr = phdr[i].p_vaddr + et_dyn_addr; break; default: break;