diff options
author | Petr Machata <pmachata@redhat.com> | 2009-04-27 18:53:06 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2009-04-27 18:53:06 +0200 |
commit | 5b3534b62cbd45fe4f11dd1be3e492237938cce0 (patch) | |
tree | 4814e6d9ae8739b48b1abd6fbee3e2597998c94f | |
parent | 9e265d71d0eb900e76d6fdb0196ef4fc6507f3a7 (diff) | |
download | elfutils-5b3534b62cbd45fe4f11dd1be3e492237938cce0.tar.gz |
Rewrites in read hooks
* Have the checking and reading logic itself in the header so that it gets
optimized out/inlined. Call external relocating hook from there, there
will presumably be more work to do, and we presumably don't want to keep
this in the header.
-rw-r--r-- | libdw/Makefile.am | 2 | ||||
-rw-r--r-- | libdw/dwarf_formaddr.c | 7 | ||||
-rw-r--r-- | libdw/dwarf_formref_die.c | 5 | ||||
-rw-r--r-- | libdw/dwarf_getlocation.c | 13 | ||||
-rw-r--r-- | libdw/dwarf_getpubnames.c | 9 | ||||
-rw-r--r-- | libdw/libdwP.h | 95 | ||||
-rw-r--r-- | libdw/libdw_readhooks.c (renamed from libdw/dwarf_readhooks.c) | 55 |
7 files changed, 115 insertions, 71 deletions
diff --git a/libdw/Makefile.am b/libdw/Makefile.am index 6d8d533f..3ccd41e3 100644 --- a/libdw/Makefile.am +++ b/libdw/Makefile.am @@ -83,7 +83,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \ dwarf_func_inline.c dwarf_getsrc_file.c \ libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \ libdw_visit_scopes.c \ - dwarf_entry_breakpoints.c dwarf_readhooks.c + dwarf_entry_breakpoints.c libdw_readhooks.c if MAINTAINER_MODE BUILT_SOURCES = $(srcdir)/known-dwarf.h diff --git a/libdw/dwarf_formaddr.c b/libdw/dwarf_formaddr.c index aff54915..9938be7e 100644 --- a/libdw/dwarf_formaddr.c +++ b/libdw/dwarf_formaddr.c @@ -70,9 +70,10 @@ dwarf_formaddr (attr, return_addr) return -1; } - if (__libdw_read_addr (attr->cu->dbg, return_addr, attr->valp, - attr->cu->address_size == 8)) - return -1l; + if (__libdw_read_address (attr->cu->dbg, + IDX_debug_info, attr->valp, + attr->cu->address_size, return_addr)) + return -1; return 0; } diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c index 3bd89fc1..128ee137 100644 --- a/libdw/dwarf_formref_die.c +++ b/libdw/dwarf_formref_die.c @@ -72,8 +72,9 @@ dwarf_formref_die (attr, die_mem) ? attr->cu->address_size : attr->cu->offset_size); - if (__libdw_read_addr (attr->cu->dbg, &offset, - attr->valp, ref_size == 8)) + if (__libdw_read_address (attr->cu->dbg, + IDX_debug_info, attr->valp, + ref_size, &offset)) return NULL; } else diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index 5df8cc6f..77f70ab9 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -415,11 +415,14 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs) Dwarf_Addr begin; Dwarf_Addr end; - bool addr64 = attr->cu->address_size == 8; - Dwarf_Addr escape = addr64 ? (Elf64_Addr)-1 : (Elf64_Addr)(Elf32_Addr)-1; - - if (__libdw_read_addr_inc (attr->cu->dbg, &begin, &readp, addr64) - || __libdw_read_addr_inc (attr->cu->dbg, &end, &readp, addr64)) + Dwarf_Addr escape = ADDR_ESCAPE (attr->cu->address_size); + + if (__libdw_read_address_inc (attr->cu->dbg, + IDX_debug_line, &readp, + attr->cu->address_size, &begin) + || __libdw_read_address_inc (attr->cu->dbg, + IDX_debug_line, &readp, + attr->cu->address_size, &end)) goto invalid; if (begin == escape) diff --git a/libdw/dwarf_getpubnames.c b/libdw/dwarf_getpubnames.c index 2ad0e22c..f8f34c50 100644 --- a/libdw/dwarf_getpubnames.c +++ b/libdw/dwarf_getpubnames.c @@ -124,8 +124,8 @@ get_offsets (Dwarf *dbg) } /* Get the CU offset. */ - if (__libdw_read_addr (dbg, &mem[cnt].cu_offset, - readp + 2, len_bytes == 8)) + if (__libdw_read_address (dbg, IDX_debug_pubnames, readp + 2, len_bytes, + &mem[cnt].cu_offset)) /* Error has been already set in reader. */ goto err_return; @@ -222,8 +222,9 @@ dwarf_getpubnames (dbg, callback, arg, offset) while (1) { /* READP points to the next offset/name pair. */ - if (__libdw_read_addr_inc (dbg, &gl.die_offset, &readp, - dbg->pubnames_sets[cnt].address_len == 8)) + if (__libdw_read_address_inc (dbg, IDX_debug_pubnames, &readp, + dbg->pubnames_sets[cnt].address_len, + &gl.die_offset)) return -1l; /* If the offset is zero we reached the end of the set. */ diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 79321343..fb9045f0 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -53,6 +53,7 @@ #include <libintl.h> #include <stdbool.h> +#include <assert.h> #include <libdw.h> @@ -421,27 +422,93 @@ extern int __dwarf_errno_internal (void); /* Reader hooks. */ +static inline int +__libdw_in_section (Dwarf *dbg, int sec_index, + unsigned char *addr, int width) +{ + Elf_Data *data = dbg->sectiondata[sec_index]; -int __libdw_read_addr_inc (Dwarf *dbg, Dwarf_Word *ret, - unsigned char **addr, - bool addr64) - internal_function; + if ((void *)addr < data->d_buf + || (void *)addr + width > data->d_buf + data->d_size) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return 1; + } -int __libdw_read_off_inc (Dwarf *dbg, Dwarf_Word *ret, - int sec_index, Dwarf_Word *offset, - bool addr64) - internal_function; + return 0; +} -int __libdw_read_addr (Dwarf *dbg, Dwarf_Word *ret, - unsigned char *addr, - bool addr64) +int __libdw_relocate_address (Dwarf *dbg, + int sec_index, uintptr_t addr, + int width, Dwarf_Addr *val) internal_function; -int __libdw_read_off (Dwarf *dbg, Dwarf_Word *ret, - int sec_index, Dwarf_Word offset, - bool addr64) +int __libdw_relocate_offset (Dwarf *dbg, + int sec_index, uintptr_t addr, + int width, Dwarf_Addr *val) internal_function; +#define READ_AND_RELOCATE(RELOC_HOOK) \ + { \ + int status; \ + if ((status = __libdw_in_section (dbg, sec_index, *addr, width))) \ + return status; \ + \ + uintptr_t addr0 = (uintptr_t)*addr; \ + Dwarf_Addr val; \ + \ + if (width == 4) \ + val = read_4ubyte_unaligned_inc (dbg, *addr); \ + else \ + { \ + assert (width == 8); \ + val = read_8ubyte_unaligned_inc (dbg, *addr); \ + } \ + \ + if ((status = RELOC_HOOK (dbg, sec_index, addr0, width, &val))) \ + return status; \ + \ + *ret = val; \ + return 0; \ + } + +static inline int +__libdw_read_address_inc (Dwarf *dbg, + int sec_index, unsigned char **addr, + int width, Dwarf_Addr *ret) +{ + READ_AND_RELOCATE (__libdw_relocate_address) +} + +static inline int +__libdw_read_offset_inc (Dwarf *dbg, + int sec_index, unsigned char **addr, + int width, Dwarf_Addr *ret) +{ + READ_AND_RELOCATE (__libdw_relocate_offset) +} + +#undef READ_AND_RELOCATE + +static inline int +__libdw_read_address (Dwarf *dbg, + int sec_index, unsigned char *addr, + int width, Dwarf_Addr *ret) +{ + return __libdw_read_address_inc (dbg, sec_index, &addr, width, ret); +} + +static inline int +__libdw_read_offset (Dwarf *dbg, + int sec_index, unsigned char *addr, + int width, Dwarf_Addr *ret) +{ + return __libdw_read_offset_inc (dbg, sec_index, &addr, width, ret); +} + +#define ADDR_ESCAPE(width) \ + (width == 8 ? (Elf64_Addr)-1 : (Elf64_Addr)(Elf32_Addr)-1) + /* Aliases to avoid PLTs. */ diff --git a/libdw/dwarf_readhooks.c b/libdw/libdw_readhooks.c index 705a9730..20a5e1e8 100644 --- a/libdw/dwarf_readhooks.c +++ b/libdw/libdw_readhooks.c @@ -51,53 +51,24 @@ # include <config.h> #endif -#include <dwarf.h> #include "libdwP.h" -int -__libdw_read_addr_inc (Dwarf *dbg, Dwarf_Word *ret, - unsigned char **addr, - bool addr64) +internal_function int +__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)), + int sec_index __attribute__ ((unused)), + uintptr_t addr __attribute__ ((unused)), + int width __attribute__ ((unused)), + Dwarf_Addr *val __attribute__ ((unused))) { - if (addr64) - *ret = read_8ubyte_unaligned_inc (dbg, *addr); - else - *ret = read_4ubyte_unaligned_inc (dbg, *addr); return 0; } -int -__libdw_read_off_inc (Dwarf *dbg, Dwarf_Word *ret, - int sec_index, Dwarf_Word *offset, - bool addr64) +internal_function int +__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)), + int sec_index __attribute__ ((unused)), + uintptr_t addr __attribute__ ((unused)), + int width __attribute__ ((unused)), + Dwarf_Addr *val __attribute__ ((unused))) { - Elf_Data *data = dbg->sectiondata[sec_index]; - if (*offset >= data->d_size - || *offset + addr64 ? 8 : 4 >= data->d_size) - { - __libdw_seterrno (DWARF_E_INVALID_OFFSET); - return 1; - } - - unsigned char *buf = data->d_buf; - unsigned char *addr = buf + *offset; - int status = __libdw_read_addr_inc (dbg, ret, &addr, addr64); - *offset = addr - buf; - return status; -} - -int -__libdw_read_addr (Dwarf *dbg, Dwarf_Word *ret, - unsigned char *addr, - bool addr64) -{ - return __libdw_read_addr_inc (dbg, ret, &addr, addr64); -} - -int -__libdw_read_off (Dwarf *dbg, Dwarf_Word *ret, - int sec_index, Dwarf_Word offset, - bool addr64) -{ - return __libdw_read_off_inc (dbg, ret, sec_index, &offset, addr64); + return 0; } |