mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-24 16:27:37 +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:
parent
d1a8ca6d84
commit
8afc33ce9f
4 changed files with 29 additions and 9 deletions
|
@ -76,7 +76,11 @@ typedef enum
|
|||
UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
|
||||
UNW_INFO_FORMAT_TABLE, /* unw_dyn_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;
|
||||
|
||||
|
|
|
@ -819,13 +819,19 @@ remote_lookup (unw_addr_space_t as,
|
|||
|
||||
#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
|
||||
dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg)
|
||||
{
|
||||
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;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
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;
|
||||
|
||||
#ifdef UNW_REMOTE_ONLY
|
||||
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE);
|
||||
assert (is_remote_table(di->format));
|
||||
#else
|
||||
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
|
||||
assert (is_remote_table(di->format)
|
||||
|| di->format == UNW_INFO_FORMAT_TABLE);
|
||||
#endif
|
||||
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_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
|
||||
{
|
||||
assert(di->format == UNW_INFO_FORMAT_TABLE);
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
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);
|
||||
|
||||
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
|
||||
if (as == unw_local_addr_space)
|
||||
{
|
||||
segbase = di->u.rti.segbase;
|
||||
e = lookup (table, table_len, ip - segbase);
|
||||
e = lookup (table, table_len, ip - ip_base);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -878,7 +891,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
|||
#ifndef UNW_LOCAL_ONLY
|
||||
segbase = di->u.rti.segbase;
|
||||
if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
|
||||
ip - segbase, &ent, arg)) < 0)
|
||||
ip - ip_base, &ent, arg)) < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
e = &ent;
|
||||
|
|
|
@ -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_REMOTE_TABLE:
|
||||
case UNW_INFO_FORMAT_IP_OFFSET:
|
||||
#ifdef tdep_search_unwind_table
|
||||
/* call platform-specific search routine: */
|
||||
return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
|
||||
|
|
|
@ -168,8 +168,10 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
|||
/* validate address */
|
||||
const struct cursor *c = (const struct cursor *)arg;
|
||||
if (likely (c != NULL) && unlikely (c->validate)
|
||||
&& unlikely (validate_mem (addr)))
|
||||
&& unlikely (validate_mem (addr))) {
|
||||
Debug (16, "mem[%016lx] -> invalid\n", addr);
|
||||
return -1;
|
||||
}
|
||||
*val = *(unw_word_t *) addr;
|
||||
Debug (16, "mem[%016lx] -> %lx\n", addr, *val);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue