1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-12-23 03:53:43 +01:00

Prevent the use of struct dl_phdr_info outside of dl_iterate_phdr

Since the dl_iterate_phdr is required for local unwinding only the use of
struct dl_phdr_info can be eliminated in case libunwind gets compiled for
remote unwinding. This enhances libunwinds portability to targets that
don't provide any dl_iterate_phdr functionality.

Signed-off-by: Ken Werner <ken.werner@linaro.org>
This commit is contained in:
Ken Werner 2011-10-20 08:57:00 +00:00 committed by Arun Sharma
parent 0fed502a81
commit 059676cb00
3 changed files with 58 additions and 69 deletions

View file

@ -387,7 +387,9 @@ extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
int need_unwind_info, void *arg);
#endif /* !UNW_REMOTE_ONLY */
extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
struct dl_phdr_info *info, unw_word_t ip);
unw_word_t ip, unw_word_t segbase,
const char* obj_name, unw_word_t start,
unw_word_t end);
extern int dwarf_search_unwind_table (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,

View file

@ -26,7 +26,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/* Locate an FDE via the ELF data-structures defined by LSB v1.3
(http://www.linuxbase.org/spec/). */
#ifndef UNW_REMOTE_ONLY
#include <link.h>
#endif /* !UNW_REMOTE_ONLY */
#include <stddef.h>
#include <stdio.h>
#include <limits.h>
@ -269,17 +271,15 @@ find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
pointer to debug frame descriptor, or zero if not found. */
static struct unw_debug_frame_list *
locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info,
unw_word_t addr, const char *dlname)
locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
unw_word_t start, unw_word_t end)
{
struct unw_debug_frame_list *w, *fdesc = 0;
char path[PATH_MAX];
char *name = path;
int err;
uint64_t start = 0, end = 0;
char *buf;
size_t bufsize;
unsigned int i;
/* First, see if we loaded this frame already. */
@ -306,29 +306,6 @@ locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info,
else
name = (char*) dlname;
/* Find the start/end of the described region by parsing the
dl_phdr_info structure. */
start = info->dlpi_addr + info->dlpi_phdr[0].p_vaddr;
end = start;
for (i = 0; i < info->dlpi_phnum; i++)
{
Elf_W (Addr) hdrbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
Elf_W (Addr) hdrlimit = hdrbase + info->dlpi_phdr[i].p_memsz;
if (info->dlpi_phdr[i].p_type != PT_LOAD)
continue;
if (hdrbase < start)
start = hdrbase;
if (hdrlimit > end)
end = hdrlimit;
}
Debug (4, "calculated bounds of %lx-%lx for '%s'\n", (long)start, (long)end,
name);
err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
if (!err)
@ -409,19 +386,19 @@ debug_frame_tab_compare (const void *a, const void *b)
}
PROTECTED int
dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
struct dl_phdr_info *info, unw_word_t ip)
dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
unw_word_t segbase, const char* obj_name,
unw_word_t start, unw_word_t end)
{
unw_dyn_info_t *di;
struct unw_debug_frame_list *fdesc = 0;
unw_accessors_t *a;
unw_word_t addr;
Debug (15, "Trying to find .debug_frame info->dlpi_name=%s\n",
info->dlpi_name);
Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
di = di_debug;
fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name);
fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
if (!fdesc)
{
@ -539,10 +516,10 @@ dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
di->format = UNW_INFO_FORMAT_TABLE;
di->start_ip = fdesc->start;
di->end_ip = fdesc->end;
di->u.ti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
di->u.ti.table_data = (unw_word_t *) fdesc;
di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
di->u.ti.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr;
di->u.ti.segbase = segbase;
found = 1;
Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, "
@ -567,7 +544,7 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
struct dwarf_callback_data *cb_data = ptr;
unw_dyn_info_t *di = &cb_data->di;
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;
unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip, start, end;
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;
@ -733,9 +710,29 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
}
#ifdef CONFIG_DEBUG_FRAME
{
found = dwarf_find_debug_frame (found, &cb_data->di_debug, info, ip);
}
/* Find the start/end of the described region by parsing the phdr_info
structure. */
start = (unw_word_t) -1;
end = 0;
for (n = 0; n < info->dlpi_phnum; n++)
{
if (info->dlpi_phdr[n].p_type == PT_LOAD)
{
unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
if (seg_start < start)
start = seg_start;
if (seg_end > end)
end = seg_end;
}
}
found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
info->dlpi_addr, info->dlpi_name, start,
end);
#endif /* CONFIG_DEBUG_FRAME */
return found;

View file

@ -172,6 +172,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
unw_word_t addr, eh_frame_start, fde_count, load_base;
unw_word_t max_load_addr = 0;
unw_word_t start_ip = (unw_word_t) -1;
unw_word_t end_ip = 0;
struct dwarf_eh_frame_hdr *hdr;
unw_proc_info_t pi;
unw_accessors_t *a;
@ -194,6 +196,12 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
switch (phdr[i].p_type)
{
case PT_LOAD:
if (phdr[i].p_vaddr < start_ip)
start_ip = phdr[i].p_vaddr;
if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip)
end_ip = phdr[i].p_vaddr + phdr[i].p_memsz;
if (phdr[i].p_offset == mapoff)
ptxt = phdr + i;
if ((uintptr_t) ui->ei.image + phdr->p_filesz > max_load_addr)
@ -222,6 +230,10 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
if (!ptxt)
return 0;
load_base = segbase - ptxt->p_vaddr;
start_ip += load_base;
end_ip += load_base;
if (peh_hdr)
{
if (pdyn)
@ -305,10 +317,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
#endif
}
load_base = segbase - ptxt->p_vaddr;
ui->di_cache.start_ip = segbase;
ui->di_cache.end_ip = ui->di_cache.start_ip + ptxt->p_memsz;
ui->di_cache.start_ip = start_ip;
ui->di_cache.end_ip = end_ip;
ui->di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE;
ui->di_cache.u.rti.name_ptr = 0;
/* two 32-bit values (ip_offset/fde_offset) per table-entry: */
@ -329,39 +339,19 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
if (parm_exidx)
{
ui->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX;
ui->di_arm.start_ip = segbase;
ui->di_arm.end_ip = ui->di_arm.start_ip + ptxt->p_memsz;
ui->di_arm.start_ip = start_ip;
ui->di_arm.end_ip = end_ip;
ui->di_arm.u.rti.name_ptr = (unw_word_t) path;
ui->di_arm.u.rti.table_data = parm_exidx->p_vaddr + segbase -
ptxt->p_vaddr;
ui->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr;
ui->di_arm.u.rti.table_len = parm_exidx->p_memsz;
found = 1;
}
#endif
#ifdef CONFIG_DEBUG_FRAME
{
/* Try .debug_frame. */
struct dl_phdr_info info;
info.dlpi_name = path;
info.dlpi_phdr = phdr;
info.dlpi_phnum = ehdr->e_phnum;
/* Fixup segbase to match correct base address. */
for (i = 0; i < info.dlpi_phnum; i++)
{
if (info.dlpi_phdr[i].p_type == PT_LOAD &&
info.dlpi_phdr[i].p_offset == 0)
{
segbase -= info.dlpi_phdr[i].p_vaddr;
break;
}
}
info.dlpi_addr = segbase;
found = dwarf_find_debug_frame (found, &ui->di_debug, &info, ip);
}
/* Try .debug_frame. */
found = dwarf_find_debug_frame (found, &ui->di_debug, ip, segbase, path,
start_ip, end_ip);
#endif
return found;