1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2025-01-24 17:20:30 +01:00

arm: Use dwarf_find_proc_info for arm dwarf processing

Rather than using a copy of dwarf_find_proc_info that differs from it slightly.
By using dwarf_find_proc_info, a potential search of the di table is
allowed, where it is omitted now.  Also, for ARM, avoid runtime
checks about which kind of unwind table search to use after dl_iterate_phdr.

A couple of Debug() warnings about ip lookup failure are lost here.
The dwarf callback struct defintion is moved to Gfind_proc_info-lsb.c,
which becomes the only source file that needs it.
This commit is contained in:
Doug Moore 2017-06-20 11:47:27 -05:00 committed by Dave Watson
parent 4f14d9714f
commit 0e74e583ae
3 changed files with 94 additions and 117 deletions

View file

@ -382,18 +382,6 @@ struct unw_debug_frame_list
struct unw_debug_frame_list *next;
};
struct dwarf_callback_data
{
/* in: */
unw_word_t ip; /* instruction-pointer we're looking for */
unw_proc_info_t *pi; /* proc-info pointer */
int need_unwind_info;
/* out: */
int single_fde; /* did we find a single FDE? (vs. a table) */
unw_dyn_info_t di; /* table info (if single_fde is false) */
unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
};
/* Convenience macros: */
#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
#define dwarf_callback UNW_OBJ (dwarf_callback)

View file

@ -381,6 +381,69 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
return nbuf;
}
PROTECTED int
arm_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)
{
/* The .ARM.exidx section contains a sorted list of key-value pairs -
the unwind entries. The 'key' is a prel31 offset to the start of a
function. We binary search this section in order to find the
appropriate unwind entry. */
unw_word_t first = di->u.rti.table_data;
unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
unw_word_t entry, val;
if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
return -UNW_ENOINFO;
if (prel31_to_addr (as, arg, last, &val) < 0)
return -UNW_EINVAL;
if (ip >= val)
{
entry = last;
if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
return -UNW_EINVAL;
pi->end_ip = di->end_ip -1;
}
else
{
while (first < last - 8)
{
entry = first + (((last - first) / 8 + 1) >> 1) * 8;
if (prel31_to_addr (as, arg, entry, &val) < 0)
return -UNW_EINVAL;
if (ip < val)
last = entry;
else
first = entry;
}
entry = first;
if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
return -UNW_EINVAL;
if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
return -UNW_EINVAL;
pi->end_ip--;
}
if (need_unwind_info)
{
pi->unwind_info_size = 8;
pi->unwind_info = (void *) entry;
pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
}
return 0;
}
PROTECTED int
tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unw_dyn_info_t *di, unw_proc_info_t *pi,
@ -388,64 +451,7 @@ tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
{
if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
&& di->format == UNW_INFO_FORMAT_ARM_EXIDX)
{
/* The .ARM.exidx section contains a sorted list of key-value pairs -
the unwind entries. The 'key' is a prel31 offset to the start of a
function. We binary search this section in order to find the
appropriate unwind entry. */
unw_word_t first = di->u.rti.table_data;
unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
unw_word_t entry, val;
if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
return -UNW_ENOINFO;
if (prel31_to_addr (as, arg, last, &val) < 0)
return -UNW_EINVAL;
if (ip >= val)
{
entry = last;
if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
return -UNW_EINVAL;
pi->end_ip = di->end_ip -1;
}
else
{
while (first < last - 8)
{
entry = first + (((last - first) / 8 + 1) >> 1) * 8;
if (prel31_to_addr (as, arg, entry, &val) < 0)
return -UNW_EINVAL;
if (ip < val)
last = entry;
else
first = entry;
}
entry = first;
if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
return -UNW_EINVAL;
if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
return -UNW_EINVAL;
pi->end_ip--;
}
if (need_unwind_info)
{
pi->unwind_info_size = 8;
pi->unwind_info = (void *) entry;
pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
}
return 0;
}
return arm_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)
&& di->format != UNW_INFO_FORMAT_ARM_EXIDX)
return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
@ -509,33 +515,7 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
Debug (14, "looking for IP=0x%lx\n", (long) ip);
if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
{
struct dwarf_callback_data cb_data;
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.di.format = -1;
cb_data.di_debug.format = -1;
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
ret = dl_iterate_phdr (dwarf_callback, &cb_data);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (ret > 0)
{
if (cb_data.single_fde)
/* already got the result in *pi */
return 0;
if (cb_data.di_debug.format != -1)
ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi,
need_unwind_info, arg);
else
ret = -UNW_ENOINFO;
}
}
ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg);
if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
{
@ -551,15 +531,12 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (cb_data.di.format != -1)
ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi,
need_unwind_info, arg);
ret = arm_search_unwind_table (as, ip, &cb_data.di, pi,
need_unwind_info, arg);
else
ret = -UNW_ENOINFO;
}
if (ret < 0)
Debug (14, "IP=0x%lx not found\n", (long) ip);
return ret;
}

View file

@ -453,6 +453,18 @@ out:
return eh_frame;
}
struct dwarf_callback_data
{
/* in: */
unw_word_t ip; /* instruction-pointer we're looking for */
unw_proc_info_t *pi; /* proc-info pointer */
int need_unwind_info;
/* out: */
int single_fde; /* did we find a single FDE? (vs. a table) */
unw_dyn_info_t di; /* table info (if single_fde is false) */
unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
};
/* ptr is a pointer to a dwarf_callback_data structure and, on entry,
member ip contains the instruction-pointer we're looking
for. */
@ -685,26 +697,26 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
ret = dl_iterate_phdr (dwarf_callback, &cb_data);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (ret <= 0)
if (ret > 0)
{
Debug (14, "IP=0x%lx not found\n", (long) ip);
return -UNW_ENOINFO;
if (cb_data.single_fde)
/* already got the result in *pi */
return 0;
/* search the table: */
if (cb_data.di.format != -1)
ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
pi, need_unwind_info, arg);
else
ret = -UNW_ENOINFO;
if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
need_unwind_info, arg);
}
if (cb_data.single_fde)
/* already got the result in *pi */
return 0;
/* search the table: */
if (cb_data.di.format != -1)
ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
pi, need_unwind_info, arg);
else
ret = -UNW_ENOINFO;
if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
need_unwind_info, arg);
return ret;
}