1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-06-26 03:11:44 +02:00

Support .debug_frame based unwinding in _UPTi_find_unwind_table()

Signed-off-by: Andris Zeila <andris.zeila@accenture.com>
This commit is contained in:
Arun Sharma 2010-05-26 19:25:41 -07:00
parent 546463d1e7
commit 46e10c5abe
4 changed files with 39 additions and 8 deletions

View file

@ -119,6 +119,8 @@ typedef struct unw_addr_space *unw_addr_space_t;
/* Each target may define it's own set of flags, but bits 0-15 are
reserved for general libunwind-use. */
#define UNW_PI_FLAG_FIRST_TDEP_BIT 16
/* The information comes from a .debug_frame section. */
#define UNW_PI_FLAG_DEBUG_FRAME 32
typedef struct unw_proc_info
{

View file

@ -895,13 +895,11 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
#ifndef UNW_REMOTE_ONLY
struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
/* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is currently only
supported for the local address space. Both the index and
the unwind tables live in local memory, but the address space
to check for properties like the address size and endianness
is the target one. When the ptrace code adds support for
.debug_frame something will have to change. */
assert (as == unw_local_addr_space);
/* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
space. Both the index and the unwind tables live in local memory, but
the address space to check for properties like the address size and
endianness is the target one. */
as = unw_local_addr_space;
table = fdesc->index;
table_len = fdesc->index_size * sizeof (struct table_entry);
debug_frame_base = (uintptr_t) fdesc->debug_frame;
@ -958,6 +956,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
{
pi->start_ip += segbase;
pi->end_ip += segbase;
pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
}
if (ip < pi->start_ip || ip >= pi->end_ip)

View file

@ -73,6 +73,12 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
as = c->as;
arg = c->as_arg;
if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
{
/* .debug_frame CFI is stored in local address space. */
as = unw_local_addr_space;
arg = NULL;
}
a = unw_get_accessors (as);
curr_ip = c->pi.start_ip;

View file

@ -210,7 +210,31 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
}
}
if (!ptxt || !peh_hdr)
return NULL;
{
/* No .eh_frame found, try .debug_frame. */
struct dl_phdr_info info;
info.dlpi_name = path;
info.dlpi_phdr = phdr;
info.dlpi_phnum = ehdr->e_phnum;
/* Fixup segbase to match correct base address. */
for (i = 0; i < info.dlpi_phnum; i++)
{
if (info.dlpi_phdr[i].p_type == PT_LOAD &&
info.dlpi_phdr[i].p_offset == 0)
{
segbase -= info.dlpi_phdr[i].p_vaddr;
break;
}
}
info.dlpi_addr = segbase;
if (dwarf_find_debug_frame (0, &ui->di_cache, &info, ip))
return &ui->di_cache;
else
return NULL;
}
if (pdyn)
{