mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-01-06 01:23:41 +01:00
find_proc_info_refactoring
This commit is contained in:
parent
7d6f41048c
commit
06564bd0b9
6 changed files with 89 additions and 76 deletions
|
@ -390,7 +390,8 @@ extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
|
|||
unw_accessors_t *a,
|
||||
unw_word_t *addr,
|
||||
unsigned char encoding,
|
||||
const unw_proc_info_t *pi,
|
||||
unw_word_t gp,
|
||||
unw_word_t start_ip,
|
||||
unw_word_t *valp, void *arg);
|
||||
extern int dwarf_step (struct dwarf_cursor *c);
|
||||
|
||||
|
|
|
@ -345,7 +345,7 @@ dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
|||
static ALWAYS_INLINE int
|
||||
dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, unsigned char encoding,
|
||||
const unw_proc_info_t *pi,
|
||||
unw_word_t gp, unw_word_t start_ip,
|
||||
unw_word_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val, initial_addr = *addr;
|
||||
|
@ -449,11 +449,11 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
|||
case DW_EH_PE_datarel:
|
||||
/* XXX For now, assume that data-relative addresses are relative
|
||||
to the global pointer. */
|
||||
val += pi->gp;
|
||||
val += gp;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_funcrel:
|
||||
val += pi->start_ip;
|
||||
val += start_ip;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_textrel:
|
||||
|
|
|
@ -182,7 +182,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
|||
if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0)
|
||||
return ret;
|
||||
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding,
|
||||
pi, &dci->handler, arg)) < 0)
|
||||
pi->gp, pi->start_ip, &dci->handler, arg)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
|
@ -303,9 +303,9 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK;
|
||||
|
||||
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding,
|
||||
pi, &start_ip, arg)) < 0
|
||||
pi->gp, pi->start_ip, &start_ip, arg)) < 0
|
||||
|| (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding,
|
||||
pi, &ip_range, arg)) < 0)
|
||||
pi->gp, pi->start_ip, &ip_range, arg)) < 0)
|
||||
return ret;
|
||||
pi->start_ip = start_ip;
|
||||
pi->end_ip = start_ip + ip_range;
|
||||
|
@ -319,7 +319,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
|||
}
|
||||
|
||||
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding,
|
||||
pi, &pi->lsda, arg)) < 0)
|
||||
pi->gp, pi->start_ip, &pi->lsda, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n",
|
||||
|
|
|
@ -51,42 +51,50 @@ struct callback_data
|
|||
{
|
||||
/* in: */
|
||||
unw_word_t ip; /* instruction-pointer we're looking for */
|
||||
int need_unwind_info;
|
||||
unw_addr_space_t as; /* address space */
|
||||
void *arg;
|
||||
/* out: */
|
||||
unw_proc_info_t *pi; /* proc-info pointer */
|
||||
unw_word_t fde_addr; /* FDE address */
|
||||
unw_word_t fde_base; /* FDE base */
|
||||
unw_word_t ip_offset; /* ip offset */
|
||||
unw_word_t gp; /* global-pointer value for this procedure */
|
||||
};
|
||||
|
||||
static int
|
||||
linear_search (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_word_t eh_frame_start, unw_word_t eh_frame_end,
|
||||
unw_word_t fde_count,
|
||||
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
||||
unw_word_t *fde_addr, void *arg)
|
||||
{
|
||||
unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
|
||||
unw_word_t i = 0, fde_addr, addr = eh_frame_start;
|
||||
unw_word_t i = 0, faddr, addr = eh_frame_start;
|
||||
unw_proc_info_t pi;
|
||||
int ret;
|
||||
|
||||
while (i++ < fde_count && addr < eh_frame_end)
|
||||
{
|
||||
fde_addr = addr;
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
|
||||
faddr = addr;
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, &pi, 0, 0, arg))
|
||||
< 0)
|
||||
return ret;
|
||||
|
||||
if (ip >= pi->start_ip && ip < pi->end_ip)
|
||||
{
|
||||
if (!need_unwind_info)
|
||||
return 1;
|
||||
addr = fde_addr;
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
|
||||
need_unwind_info, 0,
|
||||
arg))
|
||||
< 0)
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
if (ip >= pi.start_ip && ip < pi.end_ip)
|
||||
{
|
||||
*fde_addr = faddr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if (!need_unwind_info)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// addr = faddr;
|
||||
// if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
|
||||
// need_unwind_info, 0,
|
||||
// arg))
|
||||
// < 0)
|
||||
// return ret;
|
||||
// return 1;
|
||||
}
|
||||
return -UNW_ENOINFO;
|
||||
}
|
||||
|
@ -409,8 +417,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
|
||||
unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip;
|
||||
Elf_W(Addr) load_base, segbase = 0, max_load_addr = 0;
|
||||
int ret, need_unwind_info = cb_data->need_unwind_info;
|
||||
unw_proc_info_t *pi = cb_data->pi;
|
||||
int ret;
|
||||
struct dwarf_eh_frame_hdr *hdr;
|
||||
unw_accessors_t *a;
|
||||
long n;
|
||||
|
@ -490,7 +497,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
{
|
||||
/* Assume that _DYNAMIC is writable and GLIBC has
|
||||
relocated it (true for x86 at least). */
|
||||
pi->gp = dyn->d_un.d_ptr;
|
||||
cb_data->gp = dyn->d_un.d_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -498,7 +505,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
/* Otherwise this is a static executable with no _DYNAMIC. Assume
|
||||
that data-relative addresses are relative to 0, i.e.,
|
||||
absolute. */
|
||||
pi->gp = 0;
|
||||
cb_data->gp = 0;
|
||||
|
||||
hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
|
||||
if (hdr->version != DW_EH_VERSION)
|
||||
|
@ -513,18 +520,20 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
|
||||
/* (Optionally) read eh_frame_ptr: */
|
||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||
&addr, hdr->eh_frame_ptr_enc, pi,
|
||||
&addr, hdr->eh_frame_ptr_enc, cb_data->gp, 0,
|
||||
&eh_frame_start, NULL)) < 0)
|
||||
return ret;
|
||||
|
||||
/* (Optionally) read fde_count: */
|
||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||
&addr, hdr->fde_count_enc, pi,
|
||||
&addr, hdr->fde_count_enc, cb_data->gp, 0,
|
||||
&fde_count, NULL)) < 0)
|
||||
return ret;
|
||||
|
||||
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
||||
{
|
||||
int err;
|
||||
|
||||
/* If there is no search table or it has an unsupported
|
||||
encoding, fall back on linear search. */
|
||||
if (hdr->table_enc == DW_EH_PE_omit)
|
||||
|
@ -543,44 +552,41 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
|
||||
/* XXX we know how to build a local binary search table for
|
||||
.debug_frame, so we could do that here too. */
|
||||
found = linear_search (unw_local_addr_space, ip,
|
||||
eh_frame_start, eh_frame_end, fde_count,
|
||||
pi, need_unwind_info, NULL);
|
||||
err = linear_search (unw_local_addr_space, ip,
|
||||
eh_frame_start, eh_frame_end, fde_count,
|
||||
&cb_data->fde_addr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cb_data->fde_base = 0;
|
||||
cb_data->ip_offset = 0;
|
||||
|
||||
if (found != 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int err;
|
||||
unw_word_t fde_addr;
|
||||
|
||||
size_t table_len = (fde_count * sizeof (struct table_entry)
|
||||
/ sizeof (unw_word_t));
|
||||
/* For the binary-search table in the eh_frame_hdr, data-relative
|
||||
means relative to the start of that section... */
|
||||
unw_word_t segbase = (unw_word_t) (uintptr_t) hdr;
|
||||
unw_word_t sbase = (unw_word_t) (uintptr_t) hdr;
|
||||
|
||||
Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
|
||||
Debug (15, "found table `%s': sbase=0x%lx, len=%lu, gp=0x%lx, "
|
||||
"table_data=0x%lx\n", (char *) (uintptr_t) info->dlpi_name,
|
||||
(long) segbase, (long) table_len,
|
||||
(long) pi->gp, (long) addr);
|
||||
(long) sbase, (long) table_len,
|
||||
(long) cb_data->gp, (long) addr);
|
||||
|
||||
err = dwarf_search_unwind_table_ (cb_data->as, cb_data->ip,
|
||||
segbase, table_len,
|
||||
err = dwarf_search_unwind_table_ (unw_local_addr_space, cb_data->ip,
|
||||
sbase, table_len,
|
||||
addr, 0,
|
||||
&fde_addr, need_unwind_info, cb_data->arg);
|
||||
&cb_data->fde_addr, cb_data->arg);
|
||||
if(err < 0)
|
||||
return err;
|
||||
|
||||
if ((err = dwarf_extract_proc_info_from_fde (cb_data->as, a, &fde_addr, pi,
|
||||
need_unwind_info,
|
||||
0, cb_data->arg)) < 0)
|
||||
return err;
|
||||
|
||||
if (cb_data->ip < pi->start_ip || cb_data->ip >= pi->end_ip)
|
||||
return -UNW_ENOINFO;
|
||||
cb_data->fde_base = 0;
|
||||
cb_data->ip_offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -709,29 +715,19 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
|||
(char *) (uintptr_t) info->dlpi_name,
|
||||
(unw_word_t) (uintptr_t) info->dlpi_addr,
|
||||
(long) sizeof (*fdesc) / sizeof (unw_word_t),
|
||||
(long) pi->gp, (long) fdesc);
|
||||
(long) cb_data->gp, (long) fdesc);
|
||||
|
||||
err = dwarf_search_unwind_table_local (cb_data->as, cb_data->ip, fdesc,
|
||||
err = dwarf_search_unwind_table_local (unw_local_addr_space, cb_data->ip, fdesc,
|
||||
(unw_word_t) (uintptr_t) info->dlpi_addr,
|
||||
&fde_addr,
|
||||
need_unwind_info, cb_data->arg);
|
||||
&cb_data->fde_addr,
|
||||
cb_data->arg);
|
||||
if(err < 0)
|
||||
return err;
|
||||
|
||||
if ((ret = dwarf_extract_proc_info_from_fde (cb_data->as, a, &fde_addr, pi,
|
||||
need_unwind_info,
|
||||
(uintptr_t) fdesc->debug_frame,
|
||||
cb_data->arg)) < 0)
|
||||
return ret;
|
||||
|
||||
/* .debug_frame uses an absolute encoding that does not know about any
|
||||
shared library relocation. */
|
||||
pi->start_ip += segbase;
|
||||
pi->end_ip += segbase;
|
||||
|
||||
if (cb_data->ip < pi->start_ip || cb_data->ip >= pi->end_ip)
|
||||
return -UNW_ENOINFO;
|
||||
|
||||
cb_data->ip_offset = segbase;
|
||||
cb_data->fde_base = (uintptr_t) fdesc->debug_frame;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -743,13 +739,12 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
|||
struct callback_data cb_data;
|
||||
intrmask_t saved_mask;
|
||||
int ret;
|
||||
unw_accessors_t *a;
|
||||
|
||||
Debug (14, "looking for IP=0x%lx\n", (long) ip);
|
||||
|
||||
memset (&cb_data, 0, sizeof (cb_data));
|
||||
cb_data.ip = ip;
|
||||
cb_data.pi = pi;
|
||||
cb_data.need_unwind_info = need_unwind_info;
|
||||
cb_data.as = as;
|
||||
cb_data.arg = arg;
|
||||
|
||||
|
@ -763,6 +758,22 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
|||
return -UNW_ENOINFO;
|
||||
}
|
||||
|
||||
pi->gp = cb_data.gp;
|
||||
|
||||
a = unw_get_accessors (unw_local_addr_space);
|
||||
ret = dwarf_extract_proc_info_from_fde (as, a, &cb_data.fde_addr, pi,
|
||||
need_unwind_info,
|
||||
cb_data.fde_base,
|
||||
arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
pi->start_ip += cb_data.ip_offset;
|
||||
pi->end_ip += cb_data.ip_offset;
|
||||
|
||||
if (ip < pi->start_ip || ip >= pi->end_ip)
|
||||
return -UNW_ENOINFO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -840,7 +851,7 @@ dwarf_search_unwind_table_ (unw_addr_space_t as, unw_word_t ip,
|
|||
const struct table_entry *table,
|
||||
unw_word_t debug_frame_base,
|
||||
unw_word_t *fde_addr,
|
||||
int need_unwind_info, void *arg)
|
||||
void *arg)
|
||||
{
|
||||
const struct table_entry *e = NULL;
|
||||
unw_accessors_t *a;
|
||||
|
@ -898,7 +909,7 @@ PROTECTED int
|
|||
dwarf_search_unwind_table_local (unw_addr_space_t as, unw_word_t ip,
|
||||
struct unw_debug_frame_list *fdesc,
|
||||
unw_word_t segbase, unw_word_t *fde_addr,
|
||||
int need_unwind_info, void *arg)
|
||||
void *arg)
|
||||
{
|
||||
/* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is currently only
|
||||
supported for the local address space. Both the index and
|
||||
|
@ -915,7 +926,7 @@ dwarf_search_unwind_table_local (unw_addr_space_t as, unw_word_t ip,
|
|||
return dwarf_search_unwind_table_ (as, ip,
|
||||
segbase, table_len,
|
||||
table, debug_frame_base,
|
||||
fde_addr, need_unwind_info, arg);
|
||||
fde_addr, arg);
|
||||
}
|
||||
|
||||
PROTECTED int
|
||||
|
|
|
@ -198,7 +198,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
|||
case DW_CFA_set_loc:
|
||||
fde_encoding = dci->fde_encoding;
|
||||
if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding,
|
||||
&c->pi, &curr_ip,
|
||||
c->pi.gp, c->pi.start_ip, &curr_ip,
|
||||
arg)) < 0)
|
||||
goto fail;
|
||||
Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip);
|
||||
|
|
|
@ -31,9 +31,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
HIDDEN int
|
||||
dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, unsigned char encoding,
|
||||
const unw_proc_info_t *pi,
|
||||
unw_word_t gp,
|
||||
unw_word_t start_ip,
|
||||
unw_word_t *valp, void *arg)
|
||||
{
|
||||
return dwarf_read_encoded_pointer_inlined (as, a, addr, encoding,
|
||||
pi, valp, arg);
|
||||
gp, start_ip, valp, arg);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue