diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 721fe89..2eebf22 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -474,6 +474,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) /* Initialize a fake symbol for resolving undefined weak references. */ sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); sym_zero.st_shndx = SHN_UNDEF; + sym_zero.st_value = -(uintptr_t)obj_main->relocbase; if (!libmap_disable) libmap_disable = (bool)lm_init(libmap_override); @@ -991,26 +992,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 +1022,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 +1030,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; } } diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h index e5c95f7..88f4398 100644 --- a/sys/amd64/include/elf.h +++ b/sys/amd64/include/elf.h @@ -106,4 +106,10 @@ __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 ET_DYN_LOAD_ADDR 0x01021000 +#endif + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h index ee2843f..0660ba6 100644 --- a/sys/arm/include/elf.h +++ b/sys/arm/include/elf.h @@ -97,4 +97,7 @@ __ElfType(Auxinfo); * value. */ #define MAGIC_TRAMP_NUMBER 0x5c000003 + +#define ET_DYN_LOAD_ADDR 0x12000 + #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/ia64/include/elf.h b/sys/ia64/include/elf.h index 65802aa..c6a43fc 100644 --- a/sys/ia64/include/elf.h +++ b/sys/ia64/include/elf.h @@ -141,4 +141,6 @@ __ElfType(Auxinfo); #define DT_IA_64_PLT_RESERVE 0x70000000 +#define ET_DYN_LOAD_ADDR 0x2500000000000000 + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 4ed7382..e112fe1 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -635,7 +635,8 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr, } for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) { - if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */ + if (phdr[i].p_type == PT_LOAD && phdr[i].p_memsz != 0) { + /* Loadable segment */ prot = 0; if (phdr[i].p_flags & PF_X) prot |= VM_PROT_EXECUTE; @@ -687,7 +688,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 +736,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; @@ -764,6 +768,8 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) for (i = 0; i < hdr->e_phnum; i++) { switch (phdr[i].p_type) { case PT_LOAD: /* Loadable segment */ + if (phdr[i].p_memsz == 0) + break; prot = 0; if (phdr[i].p_flags & PF_X) prot |= VM_PROT_EXECUTE; @@ -783,7 +789,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 +803,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 +830,7 @@ __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; + entry = (u_long)hdr->e_entry + et_dyn_addr; } else { data_size = seg_size; data_addr = seg_addr; @@ -831,7 +838,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; diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h index 3a31daa..995862c 100644 --- a/sys/mips/include/elf.h +++ b/sys/mips/include/elf.h @@ -250,4 +250,6 @@ __ElfType(Auxinfo); #define AT_COUNT 16 /* Count of defined aux entry types. */ +#define ET_DYN_LOAD_ADDR 0x0120000 + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h index 1224fbb..e01488d 100644 --- a/sys/powerpc/include/elf.h +++ b/sys/powerpc/include/elf.h @@ -96,4 +96,6 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_PPC #define ELF_TARG_VER 1 +#define ET_DYN_LOAD_ADDR 0x01010000 + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h index c0fcbee..d35d736 100644 --- a/sys/sparc64/include/elf.h +++ b/sys/sparc64/include/elf.h @@ -97,4 +97,6 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH ELF_ARCH #define ELF_TARG_VER 1 +#define ET_DYN_LOAD_ADDR 0x150000000 + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/sun4v/include/elf.h b/sys/sun4v/include/elf.h index c0fcbee..d35d736 100644 --- a/sys/sun4v/include/elf.h +++ b/sys/sun4v/include/elf.h @@ -97,4 +97,6 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH ELF_ARCH #define ELF_TARG_VER 1 +#define ET_DYN_LOAD_ADDR 0x150000000 + #endif /* !_MACHINE_ELF_H_ */