mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-25 08: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:
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_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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue