1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-29 10:17:38 +01:00

Capture the address of the first byte after the instructionless gap

that follows the procedure.
This commit is contained in:
Doug Moore 2017-05-08 21:52:00 -05:00
parent 06d230d732
commit bbdc4b12da
3 changed files with 23 additions and 5 deletions

View file

@ -31,6 +31,12 @@ following members:
instruction \emph{beyond} the end of the procedure. If this address instruction \emph{beyond} the end of the procedure. If this address
cannot be determined (e.g., due to lack of unwind information), cannot be determined (e.g., due to lack of unwind information),
the \Var{end\_ip} member is cleared to 0. \\ the \Var{end\_ip} member is cleared to 0. \\
\item[\Type{unw\_word\_t} \Var{last\_ip}] The address of the first
instruction that could begin another procedure. Addresses from
end\_ip up to last\_ip are addresses where there are no
instructions. If this address cannot be determined (e.g., due to
lack of unwind information), the \Var{end\_ip} member is cleared to
0. \\
\item[\Type{unw\_word\_t} \Var{lsda}] The address of the \item[\Type{unw\_word\_t} \Var{lsda}] The address of the
language-specific data-area (LSDA). This area normally contains language-specific data-area (LSDA). This area normally contains
language-specific information needed during exception handling. If language-specific information needed during exception handling. If

View file

@ -126,6 +126,7 @@ typedef struct unw_proc_info
{ {
unw_word_t start_ip; /* first IP covered by this procedure */ unw_word_t start_ip; /* first IP covered by this procedure */
unw_word_t end_ip; /* first IP NOT covered by this procedure */ unw_word_t end_ip; /* first IP NOT covered by this procedure */
unw_word_t last_ip; /* first IP that could begin another procedure */
unw_word_t lsda; /* address of lang.-spec. data area (if any) */ unw_word_t lsda; /* address of lang.-spec. data area (if any) */
unw_word_t handler; /* optional personality routine */ unw_word_t handler; /* optional personality routine */
unw_word_t gp; /* global-pointer value for this procedure */ unw_word_t gp; /* global-pointer value for this procedure */

View file

@ -742,7 +742,7 @@ lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
static int static int
remote_lookup (unw_addr_space_t as, remote_lookup (unw_addr_space_t as,
unw_word_t table, size_t table_size, int32_t rel_ip, unw_word_t table, size_t table_size, int32_t rel_ip,
struct table_entry *e, void *arg) struct table_entry *e, int32_t *last_ip_offset, void *arg)
{ {
unsigned long table_len = table_size / sizeof (struct table_entry); unsigned long table_len = table_size / sizeof (struct table_entry);
unw_accessors_t *a = unw_get_accessors (as); unw_accessors_t *a = unw_get_accessors (as);
@ -768,7 +768,9 @@ remote_lookup (unw_addr_space_t as,
return 0; return 0;
e_addr = table + (hi - 1) * sizeof (struct table_entry); e_addr = table + (hi - 1) * sizeof (struct table_entry);
if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0 if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0
|| (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0) || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0
|| (hi < table_len &&
(ret = dwarf_reads32 (as, a, &e_addr, last_ip_offset, arg)) < 0))
return ret; return ret;
return 1; return 1;
} }
@ -787,7 +789,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
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 ip_base = 0, segbase = 0, fde_addr; unw_word_t ip_base = 0, segbase = 0, last_ip, 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;
@ -840,17 +842,25 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
if (as == unw_local_addr_space) if (as == unw_local_addr_space)
{ {
e = lookup (table, table_len, ip - ip_base); e = lookup (table, table_len, ip - ip_base);
if (e && &e[1] < &table[table_len])
last_ip = e[1].start_ip_offset + ip_base;
else
last_ip = di->end_ip;
} }
else else
#endif #endif
{ {
#ifndef UNW_LOCAL_ONLY #ifndef UNW_LOCAL_ONLY
int32_t last_ip_offset = di->end_ip - ip_base;
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 - ip_base, &ent, arg)) < 0) ip - ip_base, &ent, &last_ip_offset, arg)) < 0)
return ret; return ret;
if (ret) if (ret)
{
e = &ent; e = &ent;
last_ip = last_ip_offset + ip_base;
}
else else
e = NULL; /* no info found */ e = NULL; /* no info found */
#endif #endif
@ -888,6 +898,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
pi->flags = UNW_PI_FLAG_DEBUG_FRAME; pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
} }
pi->last_ip = last_ip;
if (ip < pi->start_ip || ip >= pi->end_ip) if (ip < pi->start_ip || ip >= pi->end_ip)
return -UNW_ENOINFO; return -UNW_ENOINFO;