Calculate relocation base for the main object, and apply the relocation
adjustment for all virtual addresses encoded into the ELF structures of it. PIE binary could and should be loaded at non-zero mapbase. For sym_zero pseudosymbol used as a return value from find_symdef() for undefined weak symbols, st_value also should be adjusted, since _rtld_bind corrects symbol values by relocbase. Discussed with: bz Reviewed by: kan Tested by: bz (i386, amd64), bsam (linux) MFC after: some time
This commit is contained in:
parent
87a472715d
commit
69e50b966c
@ -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. */
|
/* Initialize a fake symbol for resolving undefined weak references. */
|
||||||
sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
|
sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
|
||||||
sym_zero.st_shndx = SHN_UNDEF;
|
sym_zero.st_shndx = SHN_UNDEF;
|
||||||
|
sym_zero.st_value = -(uintptr_t)obj_main->relocbase;
|
||||||
|
|
||||||
if (!libmap_disable)
|
if (!libmap_disable)
|
||||||
libmap_disable = (bool)lm_init(libmap_override);
|
libmap_disable = (bool)lm_init(libmap_override);
|
||||||
@ -990,27 +991,27 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
|
|||||||
int nsegs = 0;
|
int nsegs = 0;
|
||||||
|
|
||||||
obj = obj_new();
|
obj = obj_new();
|
||||||
|
for (ph = phdr; ph < phlimit; ph++) {
|
||||||
|
if (ph->p_type != PT_PHDR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
obj->phdr = phdr;
|
||||||
|
obj->phsize = ph->p_memsz;
|
||||||
|
obj->relocbase = (caddr_t)phdr - ph->p_vaddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (ph = phdr; ph < phlimit; ph++) {
|
for (ph = phdr; ph < phlimit; ph++) {
|
||||||
switch (ph->p_type) {
|
switch (ph->p_type) {
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
case PT_INTERP:
|
case PT_INTERP:
|
||||||
obj->interp = (const char *) ph->p_vaddr;
|
obj->interp = (const char *)(ph->p_vaddr + obj->relocbase);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
if (nsegs == 0) { /* First load segment */
|
if (nsegs == 0) { /* First load segment */
|
||||||
obj->vaddrbase = trunc_page(ph->p_vaddr);
|
obj->vaddrbase = trunc_page(ph->p_vaddr);
|
||||||
obj->mapbase = (caddr_t) obj->vaddrbase;
|
obj->mapbase = obj->vaddrbase + obj->relocbase;
|
||||||
obj->relocbase = obj->mapbase - obj->vaddrbase;
|
|
||||||
obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) -
|
obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) -
|
||||||
obj->vaddrbase;
|
obj->vaddrbase;
|
||||||
} else { /* Last load segment */
|
} else { /* Last load segment */
|
||||||
@ -1021,7 +1022,7 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
obj->dynamic = (const Elf_Dyn *) ph->p_vaddr;
|
obj->dynamic = (const Elf_Dyn *)(ph->p_vaddr + obj->relocbase);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_TLS:
|
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->tlssize = ph->p_memsz;
|
||||||
obj->tlsalign = ph->p_align;
|
obj->tlsalign = ph->p_align;
|
||||||
obj->tlsinitsize = ph->p_filesz;
|
obj->tlsinitsize = ph->p_filesz;
|
||||||
obj->tlsinit = (void*) ph->p_vaddr;
|
obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user