2 * Copyright (c) 2002 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/types.h>
35 #include <machine/elf.h>
37 #ifndef PT_IA_64_UNWIND
38 #define PT_IA_64_UNWIND 0x70000001
43 struct ia64_unwind_entry
50 struct ia64_unwind_entry *
51 _Unwind_FindTableEntry(const void *pc, unsigned long *pseg, unsigned long *pgp)
58 struct ia64_unwind_entry *unw, *res;
59 register unsigned long gp __asm__("gp"); /* XXX assumes gcc */
60 unsigned long reloc, vaddr;
63 if (!dladdr(pc, &info))
66 ehdr = (Elf_Ehdr*)info.dli_fbase;
69 assert(IS_ELF(*ehdr));
70 assert(ehdr->e_ident[EI_CLASS] == ELFCLASS64);
71 assert(ehdr->e_ident[EI_DATA] == ELFDATA2LSB);
72 assert(ehdr->e_machine == EM_IA_64);
75 reloc = (ehdr->e_type == ET_DYN) ? (uintptr_t)info.dli_fbase : 0;
80 p = (char*)info.dli_fbase + ehdr->e_phoff;
81 p_top = p + ehdr->e_phnum * ehdr->e_phentsize;
84 vaddr = phdr->p_vaddr + reloc;
86 switch (phdr->p_type) {
88 dyn = (Elf_Dyn*)vaddr;
89 while (dyn->d_tag != DT_NULL) {
90 if (dyn->d_tag == DT_PLTGOT) {
91 *pgp = dyn->d_un.d_ptr + reloc;
98 if (pc >= (void*)vaddr &&
99 pc < (void*)(vaddr + phdr->p_memsz))
102 case PT_IA_64_UNWIND:
104 assert(*pseg != 0UL);
107 unw = (struct ia64_unwind_entry*)vaddr;
109 r = phdr->p_memsz / sizeof(struct ia64_unwind_entry);
113 if (pc < (void*)(res->start + *pseg))
115 else if (pc >= (void*)(res->end + *pseg))
125 p += ehdr->e_phentsize;