Revert "Fix unwinding of pre-linked libraries"

This reverts commit a4014f3377. The
implementation of the pre-linking support is wrong. It assumes that only
pre-linked libraries will have the virtual address of the LOAD ELF section set
to non-zero.

On arm-linux-gnueabi, without pre-linking, we have:

  LOAD           0x000000 0x00010000 0x00010000 0x267fc 0x267fc R E 0x10000

Which means that load_offset is set to 0x10000 and incorrectly substracted
from ip - ip_base. It also seems that pre-linking support is vastly
deprecated.

Reverting that one fixes .debug_frame based unwinding of arm-linux-gnueabi.
This commit is contained in:
Mathieu Othacehe
2025-06-02 17:00:56 +02:00
committed by Stephen M. Webb
parent 5b195ffd50
commit 62dfb32339
4 changed files with 8 additions and 38 deletions

View File

@@ -371,8 +371,6 @@ struct unw_debug_frame_list
/* The start (inclusive) and end (exclusive) of the described region. */
unw_word_t start;
unw_word_t end;
/* ELF load offset */
unw_word_t load_offset;
/* The debug frame itself. */
char *debug_frame;
size_t debug_frame_size;

View File

@@ -141,7 +141,6 @@ typedef struct unw_dyn_info
unw_word_t gp; /* global-pointer in effect for this entry */
int32_t format; /* real type: unw_dyn_info_format_t */
int32_t pad;
unw_word_t load_offset; /* ELF load offset */
union
{
unw_dyn_proc_info_t pi;

View File

@@ -107,17 +107,13 @@ 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)
{
struct elf_image ei;
Elf_W (Ehdr) *ehdr;
Elf_W (Phdr) *phdr;
Elf_W (Shdr) *shdr;
int i;
int ret;
ei.image = NULL;
*load_offset = 0;
ret = elf_w (load_debuginfo) (file, &ei, is_local);
if (ret != 0)
@@ -192,20 +188,6 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local, u
#if defined(SHF_COMPRESSED)
}
#endif
ehdr = ei.image;
phdr = (Elf_W (Phdr) *) ((char *) ei.image + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; ++i)
if (phdr[i].p_type == PT_LOAD)
{
*load_offset = phdr[i].p_vaddr;
Debug (4, "%s load offset is 0x%zx\n", file, *load_offset);
break;
}
mi_munmap(ei.image, ei.size);
return 0;
}
@@ -258,7 +240,6 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
int err;
char *buf;
size_t bufsize;
unw_word_t load_offset;
/* First, see if we loaded this frame already. */
@@ -285,7 +266,7 @@ 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);
if (!err)
{
@@ -298,7 +279,6 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
fdesc->start = start;
fdesc->end = end;
fdesc->load_offset = load_offset;
fdesc->debug_frame = buf;
fdesc->debug_frame_size = bufsize;
fdesc->index = NULL;
@@ -494,7 +474,6 @@ dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
di->format = UNW_INFO_FORMAT_TABLE;
di->start_ip = fdesc->start;
di->end_ip = fdesc->end;
di->load_offset = fdesc->load_offset;
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);
@@ -957,14 +936,12 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
ip_base = segbase;
}
Debug (6, "lookup IP 0x%lx\n", (long) (ip - ip_base - di->load_offset));
#ifndef UNW_REMOTE_ONLY
if (as == unw_local_addr_space)
{
e = lookup (table, table_len, ip - ip_base - di->load_offset);
e = lookup (table, table_len, ip - ip_base);
if (e && &e[1] < &table[table_len / sizeof (struct table_entry)])
last_ip = e[1].start_ip_offset + ip_base + di->load_offset;
last_ip = e[1].start_ip_offset + ip_base;
else
last_ip = di->end_ip;
}
@@ -972,7 +949,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
#endif
{
#ifndef UNW_LOCAL_ONLY
int32_t last_ip_offset = (int32_t) (di->end_ip - ip_base - di->load_offset);
int32_t last_ip_offset = (int32_t) (di->end_ip - ip_base);
segbase = di->u.rti.segbase;
if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
(int32_t) (ip - ip_base), &ent, &last_ip_offset, arg)) < 0)
@@ -980,7 +957,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
if (ret)
{
e = &ent;
last_ip = last_ip_offset + ip_base + di->load_offset;
last_ip = last_ip_offset + ip_base;
}
else
e = NULL; /* no info found */
@@ -994,8 +971,8 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unwind info. */
return -UNW_ENOINFO;
}
Debug (15, "ip=0x%lx, load_offset=0x%lx, start_ip=0x%lx\n",
(long) ip, (long) di->load_offset, (long) (e->start_ip_offset));
Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
(long) ip, (long) (e->start_ip_offset));
if (debug_frame_base)
fde_addr = e->fde_offset + debug_frame_base;
else
@@ -1019,9 +996,6 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
}
pi->start_ip += di->load_offset;
pi->end_ip += di->load_offset;
#if defined(NEED_LAST_IP)
pi->last_ip = last_ip;
#else

View File

@@ -206,7 +206,6 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi,
edi->di_cache.start_ip = start_ip;
edi->di_cache.end_ip = end_ip;
edi->di_cache.load_offset = 0;
edi->di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE;
edi->di_cache.u.rti.name_ptr = 0;
/* two 32-bit values (ip_offset/fde_offset) per table-entry: */