summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2009-04-27 18:53:06 +0200
committerPetr Machata <pmachata@redhat.com>2009-04-27 18:53:06 +0200
commit5b3534b62cbd45fe4f11dd1be3e492237938cce0 (patch)
tree4814e6d9ae8739b48b1abd6fbee3e2597998c94f
parent9e265d71d0eb900e76d6fdb0196ef4fc6507f3a7 (diff)
downloadelfutils-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.am2
-rw-r--r--libdw/dwarf_formaddr.c7
-rw-r--r--libdw/dwarf_formref_die.c5
-rw-r--r--libdw/dwarf_getlocation.c13
-rw-r--r--libdw/dwarf_getpubnames.c9
-rw-r--r--libdw/libdwP.h95
-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;
}