rtld: set obj->textsize correctly
With lld-generated binaries the first PT_LOAD will usually be a read-only segment unless you pass --no-rosegment. For those binaries the textsize is determined by the next PT_LOAD. To allow both LLD and bfd 2.17 binaries to be parsed correctly use the end of the last PT_LOAD that is marked as executable instead. I noticed that the value was wrong while adding some debug prints for some rtld changes for CHERI binaries. `obj->textsize` only seems to be used by PPC so the effect is untested. However, the value before was definitely wrong and the new result matches the phdrs. Reviewed By: kib Approved By: brooks (mentor) Differential Revision: https://reviews.freebsd.org/D17117
This commit is contained in:
parent
024cdacaea
commit
4a1080a9d3
@ -93,6 +93,7 @@ map_object(int fd, const char *path, const struct stat *sb)
|
||||
Elf_Addr note_end;
|
||||
char *note_map;
|
||||
size_t note_map_len;
|
||||
Elf_Addr text_end;
|
||||
|
||||
hdr = get_elf_header(fd, path, sb);
|
||||
if (hdr == NULL)
|
||||
@ -116,6 +117,7 @@ map_object(int fd, const char *path, const struct stat *sb)
|
||||
note_map = NULL;
|
||||
segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
|
||||
stack_flags = RTLD_DEFAULT_STACK_PF_EXEC | PF_R | PF_W;
|
||||
text_end = 0;
|
||||
while (phdr < phlimit) {
|
||||
switch (phdr->p_type) {
|
||||
|
||||
@ -130,6 +132,10 @@ map_object(int fd, const char *path, const struct stat *sb)
|
||||
path, nsegs);
|
||||
goto error;
|
||||
}
|
||||
if ((segs[nsegs]->p_flags & PF_X) == PF_X) {
|
||||
text_end = MAX(text_end,
|
||||
round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz));
|
||||
}
|
||||
break;
|
||||
|
||||
case PT_PHDR:
|
||||
@ -280,8 +286,7 @@ map_object(int fd, const char *path, const struct stat *sb)
|
||||
}
|
||||
obj->mapbase = mapbase;
|
||||
obj->mapsize = mapsize;
|
||||
obj->textsize = round_page(segs[0]->p_vaddr + segs[0]->p_memsz) -
|
||||
base_vaddr;
|
||||
obj->textsize = text_end - base_vaddr;
|
||||
obj->vaddrbase = base_vaddr;
|
||||
obj->relocbase = mapbase - base_vaddr;
|
||||
obj->dynamic = (const Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr);
|
||||
|
@ -1390,13 +1390,15 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
|
||||
if (nsegs == 0) { /* First load segment */
|
||||
obj->vaddrbase = trunc_page(ph->p_vaddr);
|
||||
obj->mapbase = obj->vaddrbase + obj->relocbase;
|
||||
obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) -
|
||||
obj->vaddrbase;
|
||||
} else { /* Last load segment */
|
||||
obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) -
|
||||
obj->vaddrbase;
|
||||
}
|
||||
nsegs++;
|
||||
if ((ph->p_flags & PF_X) == PF_X) {
|
||||
obj->textsize = MAX(obj->textsize,
|
||||
round_page(ph->p_vaddr + ph->p_memsz) - obj->vaddrbase);
|
||||
}
|
||||
break;
|
||||
|
||||
case PT_DYNAMIC:
|
||||
|
Loading…
Reference in New Issue
Block a user