mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-23 03:53:43 +01: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:
parent
546463d1e7
commit
46e10c5abe
4 changed files with 39 additions and 8 deletions
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue