1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-12-23 20:03: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:
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 /* Each target may define it's own set of flags, but bits 0-15 are
reserved for general libunwind-use. */ reserved for general libunwind-use. */
#define UNW_PI_FLAG_FIRST_TDEP_BIT 16 #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 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 #ifndef UNW_REMOTE_ONLY
struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data; struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
/* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is currently only /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
supported for the local address space. Both the index and space. Both the index and the unwind tables live in local memory, but
the unwind tables live in local memory, but the address space the address space to check for properties like the address size and
to check for properties like the address size and endianness endianness is the target one. */
is the target one. When the ptrace code adds support for as = unw_local_addr_space;
.debug_frame something will have to change. */
assert (as == unw_local_addr_space);
table = fdesc->index; table = fdesc->index;
table_len = fdesc->index_size * sizeof (struct table_entry); table_len = fdesc->index_size * sizeof (struct table_entry);
debug_frame_base = (uintptr_t) fdesc->debug_frame; 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->start_ip += segbase;
pi->end_ip += segbase; pi->end_ip += segbase;
pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
} }
if (ip < pi->start_ip || ip >= pi->end_ip) 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; as = c->as;
arg = c->as_arg; 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); a = unw_get_accessors (as);
curr_ip = c->pi.start_ip; 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) if (!ptxt || !peh_hdr)
{
/* 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; return NULL;
}
if (pdyn) if (pdyn)
{ {