1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-15 20:58:13 +01:00

Add include of dwarf_i.h now that we need dwarf_reads32().

Drop DWARF-parsing debug prints from level 16 to 15.
(struct table_entry): Change member types from unw_word_t to int32_t.  The members
	need to be of a signed type and forcing them to 32 bits makes the type
	work for both 32-bit and 64-bit executables (up to 4GB of text-size).
(callback): Only allow search tables which have 32-bit members.
	Fix initialization of di->u.rti.table_len to express table-length as a count
	of unw_word_t, as it's defined to be (we get lucky here: even with 32-bit
	members, each table-entry contains two members so we're guaranteed that the
	table has a size that is an integer-multiple of unw_word_t even on 64-bit
	platforms).
(lookup): Change type of "rel_ip" from unw_word_t to int32_t.  Simplify the
	code a bit.
(remote_read): Delete.
(remote_lookup): Use dwarf_reads32() instead of remote_read() to read out table
	members.  Simplify code a bit.

(Logical change 1.248)
This commit is contained in:
homeip.net!davidm 2004-08-19 12:26:11 +00:00
parent 5742642c24
commit e9045e3cca

View file

@ -1,5 +1,5 @@
/* libunwind - a platform-independent unwind library /* libunwind - a platform-independent unwind library
Copyright (c) 2003 Hewlett-Packard Development Company, L.P. Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com> Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind. This file is part of libunwind.
@ -31,13 +31,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include "dwarf_i.h"
#include "dwarf-eh.h" #include "dwarf-eh.h"
#include "tdep.h" #include "tdep.h"
struct table_entry struct table_entry
{ {
unw_word_t start_ip_offset; int32_t start_ip_offset;
unw_word_t fde_offset; int32_t fde_offset;
}; };
#ifndef UNW_REMOTE_ONLY #ifndef UNW_REMOTE_ONLY
@ -63,7 +64,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
+ sizeof (info->dlpi_phnum)) + sizeof (info->dlpi_phnum))
return -1; return -1;
Debug (16, "checking %s, base=0x%lx)\n", Debug (15, "checking %s, base=0x%lx)\n",
info->dlpi_name, (long) info->dlpi_addr); info->dlpi_name, (long) info->dlpi_addr);
phdr = info->dlpi_phdr; phdr = info->dlpi_phdr;
@ -148,12 +149,8 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
return 0; return 0;
} }
/* For now, only support binary-search tables which are /* For now, only support binary-search tables which are
data-relative and whose entries have the size of a pointer. */ data-relative and whose entries are 32 bits wide. */
if (!(hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_ptr) if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|| ((sizeof (unw_word_t) == 4
&& hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4)))
|| ((sizeof (unw_word_t) == 8
&& hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata8)))))
{ {
Debug (1, "search table in `%s' has unexpected encoding 0x%x\n", Debug (1, "search table in `%s' has unexpected encoding 0x%x\n",
info->dlpi_name, hdr->table_enc); info->dlpi_name, hdr->table_enc);
@ -181,7 +178,9 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz; di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
di->u.rti.name_ptr = (unw_word_t) info->dlpi_name; di->u.rti.name_ptr = (unw_word_t) info->dlpi_name;
di->u.rti.table_data = addr; di->u.rti.table_data = addr;
di->u.rti.table_len = fde_count + 2 * sizeof (unw_word_t); assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
/ sizeof (unw_word_t));
/* For the binary-search table in the eh_frame_hdr, data-relative /* For the binary-search table in the eh_frame_hdr, data-relative
means relative to the start of that section... */ means relative to the start of that section... */
di->u.rti.segbase = (unw_word_t) hdr; di->u.rti.segbase = (unw_word_t) hdr;
@ -219,12 +218,11 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
} }
static inline const struct table_entry * static inline const struct table_entry *
lookup (struct table_entry *table, size_t table_size, unw_word_t rel_ip) lookup (struct table_entry *table, size_t table_size, int32_t rel_ip)
{ {
unsigned long table_len = table_size / sizeof (struct table_entry); unsigned long table_len = table_size / sizeof (struct table_entry);
const struct table_entry *e = 0; const struct table_entry *e = 0;
unsigned long lo, hi, mid; unsigned long lo, hi, mid;
unw_word_t end = 0;
/* do a binary search for right entry: */ /* do a binary search for right entry: */
for (lo = 0, hi = table_len; lo < hi;) for (lo = 0, hi = table_len; lo < hi;)
@ -235,29 +233,18 @@ lookup (struct table_entry *table, size_t table_size, unw_word_t rel_ip)
hi = mid; hi = mid;
else else
{ {
if (mid + 1 >= table_len) if (mid + 1 >= table_len
break; || rel_ip < table[mid + 1].start_ip_offset)
return e;
end = table[mid + 1].start_ip_offset;
if (rel_ip >= end)
lo = mid + 1;
else else
break; lo = mid + 1;
} }
} }
if (rel_ip < e->start_ip_offset || rel_ip >= end) return NULL;
return NULL;
return e;
} }
#endif /* !UNW_REMOTE_ONLY */ #endif /* !UNW_REMOTE_ONLY */
/* Helper macro for reading an table_entry from remote memory. */
#define remote_read(addr, member) \
(*a->access_mem) (as, (addr) + offsetof (struct table_entry, \
member), &member, 0, arg)
#ifndef UNW_LOCAL_ONLY #ifndef UNW_LOCAL_ONLY
/* Lookup an unwind-table entry in remote memory. Returns 1 if an /* Lookup an unwind-table entry in remote memory. Returns 1 if an
@ -269,10 +256,10 @@ remote_lookup (unw_addr_space_t as,
struct table_entry *e, void *arg) struct table_entry *e, void *arg)
{ {
unsigned long table_len = table_size / sizeof (struct table_entry); unsigned long table_len = table_size / sizeof (struct table_entry);
unw_word_t e_addr = 0, start_ip_offset, fde_offset;
unw_word_t start = ~(unw_word_t) 0, end = 0; unw_word_t start = ~(unw_word_t) 0, end = 0;
unw_accessors_t *a = unw_get_accessors (as); unw_accessors_t *a = unw_get_accessors (as);
unsigned long lo, hi, mid; unsigned long lo, hi, mid;
unw_word_t e_addr = 0;
int ret; int ret;
/* do a binary search for right entry: */ /* do a binary search for right entry: */
@ -280,10 +267,9 @@ remote_lookup (unw_addr_space_t as,
{ {
mid = (lo + hi) / 2; mid = (lo + hi) / 2;
e_addr = table + mid * sizeof (struct table_entry); e_addr = table + mid * sizeof (struct table_entry);
if ((ret = remote_read (e_addr, start_ip_offset)) < 0) if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
return ret; return ret;
start = start_ip_offset;
if (rel_ip < start) if (rel_ip < start)
hi = mid; hi = mid;
else else
@ -291,10 +277,9 @@ remote_lookup (unw_addr_space_t as,
if (mid + 1 >= table_len) if (mid + 1 >= table_len)
break; break;
if ((ret = remote_read (e_addr + sizeof (struct table_entry), e_addr += 4; /* skip over fde_offset to next table-entry */
start_ip_offset)) < 0) if ((ret = dwarf_reads32 (as, a, &e_addr, &end, arg)) < 0)
return ret; return ret;
end = start_ip_offset;
if (rel_ip >= end) if (rel_ip >= end)
lo = mid + 1; lo = mid + 1;
@ -302,17 +287,15 @@ remote_lookup (unw_addr_space_t as,
break; break;
} }
} }
if (rel_ip < start || rel_ip >= end) if (rel_ip < start)
return 0; return 0;
e->start_ip_offset = start; e->start_ip_offset = start;
if ((ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0)
if ((ret = remote_read (e_addr, fde_offset)) < 0)
return ret; return ret;
e->fde_offset = fde_offset;
return 1; return 1;
} }
#endif /* UNW_LOCAL_ONLY */ #endif /* !UNW_LOCAL_ONLY */
PROTECTED int PROTECTED int
dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
@ -366,7 +349,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unwind info. */ unwind info. */
return -UNW_ENOINFO; return -UNW_ENOINFO;
} }
Debug (16, "ip=0x%lx, start_ip=0x%lx\n", Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
(long) ip, (long) (e->start_ip_offset + segbase)); (long) ip, (long) (e->start_ip_offset + segbase));
fde_addr = e->fde_offset + segbase; fde_addr = e->fde_offset + segbase;
return dwarf_parse_fde (as, a, &fde_addr, pi, &pi->extra.dwarf_info, arg); return dwarf_parse_fde (as, a, &fde_addr, pi, &pi->extra.dwarf_info, arg);