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:
parent
06d230d732
commit
bbdc4b12da
3 changed files with 23 additions and 5 deletions
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue