1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-22 07:37:38 +01:00

Add an option to have start_ip_offset be relative to start_ip

By default, the start_ip_offset in libunwind's table_entry struct is
relative to the unw_dyn_info_t's segbase. This presents a problem
for us in conjunction with using LLVM's MCJIT because it likes to
spread text sections and the corresponding eh_frame sections quite
far apart. This represents my attempt to support this use case in the
simplest manner that is backwards compatible, by adding a new format
kind (UNW_INFO_FORMAT_REMOTE_TABLE2) that indicates that the
`start_ip_offset` should be interpreted as relative to `start_ip`
rather than segbase.
This commit is contained in:
Keno Fischer 2015-10-06 19:56:49 -04:00 committed by Arun Sharma
parent d1a8ca6d84
commit 8afc33ce9f
4 changed files with 29 additions and 9 deletions

View file

@ -76,7 +76,11 @@ typedef enum
UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */ UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */ UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */
UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */ UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */
UNW_INFO_FORMAT_ARM_EXIDX /* ARM specific unwind info */ UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */
UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but
table entries are considered
relative to di->start_ip, rather
than di->segbase */
} }
unw_dyn_info_format_t; unw_dyn_info_format_t;

View file

@ -819,13 +819,19 @@ remote_lookup (unw_addr_space_t as,
#endif /* !UNW_LOCAL_ONLY */ #endif /* !UNW_LOCAL_ONLY */
static int is_remote_table(int format)
{
return (format == UNW_INFO_FORMAT_REMOTE_TABLE ||
format == UNW_INFO_FORMAT_IP_OFFSET);
}
PROTECTED int PROTECTED int
dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unw_dyn_info_t *di, unw_proc_info_t *pi, unw_dyn_info_t *di, unw_proc_info_t *pi,
int need_unwind_info, void *arg) int need_unwind_info, void *arg)
{ {
const struct table_entry *e = NULL, *table; const struct table_entry *e = NULL, *table;
unw_word_t segbase = 0, fde_addr; unw_word_t ip_base = 0, segbase = 0, fde_addr;
unw_accessors_t *a; unw_accessors_t *a;
#ifndef UNW_LOCAL_ONLY #ifndef UNW_LOCAL_ONLY
struct table_entry ent; struct table_entry ent;
@ -835,14 +841,14 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
size_t table_len; size_t table_len;
#ifdef UNW_REMOTE_ONLY #ifdef UNW_REMOTE_ONLY
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE); assert (is_remote_table(di->format));
#else #else
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE assert (is_remote_table(di->format)
|| di->format == UNW_INFO_FORMAT_TABLE); || di->format == UNW_INFO_FORMAT_TABLE);
#endif #endif
assert (ip >= di->start_ip && ip < di->end_ip); assert (ip >= di->start_ip && ip < di->end_ip);
if (di->format == UNW_INFO_FORMAT_REMOTE_TABLE) if (is_remote_table(di->format))
{ {
table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data; table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
table_len = di->u.rti.table_len * sizeof (unw_word_t); table_len = di->u.rti.table_len * sizeof (unw_word_t);
@ -850,6 +856,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
} }
else else
{ {
assert(di->format == UNW_INFO_FORMAT_TABLE);
#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;
@ -866,11 +873,17 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
a = unw_get_accessors (as); a = unw_get_accessors (as);
segbase = di->u.rti.segbase;
if (di->format == UNW_INFO_FORMAT_IP_OFFSET) {
ip_base = di->start_ip;
} else {
ip_base = segbase;
}
#ifndef UNW_REMOTE_ONLY #ifndef UNW_REMOTE_ONLY
if (as == unw_local_addr_space) if (as == unw_local_addr_space)
{ {
segbase = di->u.rti.segbase; e = lookup (table, table_len, ip - ip_base);
e = lookup (table, table_len, ip - segbase);
} }
else else
#endif #endif
@ -878,7 +891,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
#ifndef UNW_LOCAL_ONLY #ifndef UNW_LOCAL_ONLY
segbase = di->u.rti.segbase; segbase = di->u.rti.segbase;
if ((ret = remote_lookup (as, (uintptr_t) table, table_len, if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
ip - segbase, &ent, arg)) < 0) ip - ip_base, &ent, arg)) < 0)
return ret; return ret;
if (ret) if (ret)
e = &ent; e = &ent;

View file

@ -49,6 +49,7 @@ unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
case UNW_INFO_FORMAT_TABLE: case UNW_INFO_FORMAT_TABLE:
case UNW_INFO_FORMAT_REMOTE_TABLE: case UNW_INFO_FORMAT_REMOTE_TABLE:
case UNW_INFO_FORMAT_IP_OFFSET:
#ifdef tdep_search_unwind_table #ifdef tdep_search_unwind_table
/* call platform-specific search routine: */ /* call platform-specific search routine: */
return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);

View file

@ -168,8 +168,10 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
/* validate address */ /* validate address */
const struct cursor *c = (const struct cursor *)arg; const struct cursor *c = (const struct cursor *)arg;
if (likely (c != NULL) && unlikely (c->validate) if (likely (c != NULL) && unlikely (c->validate)
&& unlikely (validate_mem (addr))) && unlikely (validate_mem (addr))) {
Debug (16, "mem[%016lx] -> invalid\n", addr);
return -1; return -1;
}
*val = *(unw_word_t *) addr; *val = *(unw_word_t *) addr;
Debug (16, "mem[%016lx] -> %lx\n", addr, *val); Debug (16, "mem[%016lx] -> %lx\n", addr, *val);
} }