summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOle André Vadla Ravnås <oleavr@gmail.com>2020-12-01 23:43:04 +0100
committerDave Watson <dade.watson@gmail.com>2020-12-03 07:16:13 -0800
commitcee5505a99d42a423059a1add8b87b75aeb45daa (patch)
treead21d6943a518fdd10b6c67003563bd04220d31a /src
parent2c76d97f1890e9f5c477011bf520faa1540840b1 (diff)
downloadlibunwind-cee5505a99d42a423059a1add8b87b75aeb45daa.tar.gz
Fix .debug_frame load_offset calculation
Typically resulting in a crash during local unwinding on e.g. Android/arm64, where the calculated load_offset would be zero.
Diffstat (limited to 'src')
-rw-r--r--src/dwarf/Gfind_proc_info-lsb.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c
index 1311d9ab..0496ca7e 100644
--- a/src/dwarf/Gfind_proc_info-lsb.c
+++ b/src/dwarf/Gfind_proc_info-lsb.c
@@ -107,7 +107,8 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
/* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */
static int
-load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local, unw_word_t *load_offset)
+load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local,
+ unw_word_t segbase, unw_word_t *load_offset)
{
struct elf_image ei;
Elf_W (Ehdr) *ehdr;
@@ -184,7 +185,7 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local, u
for (i = 0; i < ehdr->e_phnum; ++i)
if (phdr[i].p_type == PT_LOAD)
{
- *load_offset = phdr[i].p_vaddr;
+ *load_offset = segbase - phdr[i].p_vaddr;
Debug (4, "%s load offset is 0x%zx\n", file, *load_offset);
@@ -234,8 +235,8 @@ 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, unw_word_t addr, const char *dlname,
- unw_word_t start, unw_word_t end)
+locate_debug_info (unw_addr_space_t as, unw_word_t addr, unw_word_t segbase,
+ const char *dlname, unw_word_t start, unw_word_t end)
{
struct unw_debug_frame_list *w, *fdesc = 0;
char path[PATH_MAX];
@@ -270,7 +271,8 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
else
name = (char*) dlname;
- err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space, &load_offset);
+ err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space,
+ segbase, &load_offset);
if (!err)
{
@@ -416,7 +418,8 @@ dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
- fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
+ fdesc = locate_debug_info (unw_local_addr_space, ip, segbase, obj_name, start,
+ end);
if (!fdesc)
{