diff options
author | marcel <marcel@FreeBSD.org> | 2003-11-08 05:29:49 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-11-08 05:29:49 +0000 |
commit | 6ae3d37f99625464fbfb4d3c6fadb4a61c4bd333 (patch) | |
tree | 5894fbde5a1c97d5b7ddc717ae6c691a2dda261a /lib/libc/ia64 | |
parent | a9efed458bca1d3b746b4a2791f1bb5c63633fea (diff) | |
download | FreeBSD-src-6ae3d37f99625464fbfb4d3c6fadb4a61c4bd333.zip FreeBSD-src-6ae3d37f99625464fbfb4d3c6fadb4a61c4bd333.tar.gz |
Virtual addresses in headers of ELF files for dynamic objects need
to be relocated before they can be used as pointers.
Diffstat (limited to 'lib/libc/ia64')
-rw-r--r-- | lib/libc/ia64/gen/unwind.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/lib/libc/ia64/gen/unwind.c b/lib/libc/ia64/gen/unwind.c index 566d113..7afd0ef 100644 --- a/lib/libc/ia64/gen/unwind.c +++ b/lib/libc/ia64/gen/unwind.c @@ -57,6 +57,7 @@ _Unwind_FindTableEntry(const void *pc, unsigned long *pseg, unsigned long *pgp) char *p, *p_top; struct ia64_unwind_entry *unw, *res; register unsigned long gp __asm__("gp"); /* XXX assumes gcc */ + unsigned long reloc, vaddr; size_t l, m, r; if (!dladdr(pc, &info)) @@ -71,6 +72,7 @@ _Unwind_FindTableEntry(const void *pc, unsigned long *pseg, unsigned long *pgp) assert(ehdr->e_machine == EM_IA_64); #endif + reloc = (ehdr->e_type == ET_DYN) ? (uintptr_t)info.dli_fbase : 0; *pgp = gp; *pseg = 0UL; res = NULL; @@ -79,29 +81,30 @@ _Unwind_FindTableEntry(const void *pc, unsigned long *pseg, unsigned long *pgp) p_top = p + ehdr->e_phnum * ehdr->e_phentsize; while (p < p_top) { phdr = (Elf_Phdr*)p; + vaddr = phdr->p_vaddr + reloc; switch (phdr->p_type) { case PT_DYNAMIC: - dyn = (Elf_Dyn*)phdr->p_vaddr; + dyn = (Elf_Dyn*)vaddr; while (dyn->d_tag != DT_NULL) { if (dyn->d_tag == DT_PLTGOT) { - *pgp = dyn->d_un.d_ptr; + *pgp = dyn->d_un.d_ptr + reloc; break; } dyn++; } break; case PT_LOAD: - if (pc >= (void*)phdr->p_vaddr && - pc < (void*)(phdr->p_vaddr + phdr->p_memsz)) - *pseg = phdr->p_vaddr; + if (pc >= (void*)vaddr && + pc < (void*)(vaddr + phdr->p_memsz)) + *pseg = vaddr; break; case PT_IA_64_UNWIND: #if SANITY assert(*pseg != 0UL); assert(res == NULL); #endif - unw = (struct ia64_unwind_entry*)phdr->p_vaddr; + unw = (struct ia64_unwind_entry*)vaddr; l = 0; r = phdr->p_memsz / sizeof(struct ia64_unwind_entry); while (l < r) { |