summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2009-05-05 02:53:40 +0200
committerPetr Machata <pmachata@redhat.com>2009-05-05 02:53:40 +0200
commit8273a2adaf8cb2ee203926af2849e4f96f8a6eaf (patch)
tree8590bde46e67bb9ee2feb357b44a497b794e7d2d
parent1c897f4abde1530038d332f4fc03a596a24f6aaf (diff)
downloadelfutils-8273a2adaf8cb2ee203926af2849e4f96f8a6eaf.tar.gz
Introduce __libdw_read_udata_address
* the use in dwarf_ranges is iffy, there's a functionality mismatch. Need to find some better way
-rw-r--r--libdw/ChangeLog9
-rw-r--r--libdw/dwarf_formudata.c47
-rw-r--r--libdw/dwarf_getlocation.c23
-rw-r--r--libdw/dwarf_getsrclines.c19
-rw-r--r--libdw/dwarf_ranges.c28
-rw-r--r--libdw/libdwP.h5
6 files changed, 86 insertions, 45 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 39b190f1..abea245a 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,12 @@
+2009-05-05 Petr Machata <pmachata@redhat.com>
+
+ * libdwP.h (__libdw_read_udata_addr): Declare new function.
+ * dwarf_formudata.c: Implement it here.
+ * dwarf_getlocation.c (dwarf_getlocation_addr):
+ Call it instead of hand-rolled offset handling code.
+ * dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+ * dwarf_ranges.c (dwarf_ranges): Likewise.
+
2009-05-04 Petr Machata <pmachata@redhat.com>
* libdwP.h (__libdw_read_begin_end_pair_inc): Declare new function.
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
index b346afb3..71a5e967 100644
--- a/libdw/dwarf_formudata.c
+++ b/libdw/dwarf_formudata.c
@@ -55,6 +55,45 @@
#include <dwarf.h>
#include "libdwP.h"
+internal_function unsigned char *
+__libdw_read_udata_addr (Dwarf_Attribute *attr, int sec_index,
+ int err_nodata, unsigned char **endpp)
+{
+ if (attr == NULL)
+ return NULL;
+
+ Dwarf_Word offset;
+ switch (attr->form)
+ {
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ if (__libdw_read_address (attr->cu->dbg, IDX_debug_info, attr->valp,
+ attr->form == DW_FORM_data4 ? 4 : 8,
+ &offset))
+ return NULL;
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ };
+
+ const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
+ if (unlikely (d == NULL))
+ {
+ invalid:
+ __libdw_seterrno (err_nodata);
+ return NULL;
+ }
+
+ unsigned char *readp = d->d_buf + offset;
+ unsigned char *endp = d->d_buf + d->d_size;
+ if (readp >= endp)
+ goto invalid;
+
+ *endpp = endp;
+ return readp;
+}
int
dwarf_formudata (attr, return_uval)
@@ -77,11 +116,11 @@ dwarf_formudata (attr, return_uval)
break;
case DW_FORM_data4:
+ *return_uval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
case DW_FORM_data8:
- if (__libdw_read_address (attr->cu->dbg, IDX_debug_info, attr->valp,
- attr->form == DW_FORM_data4 ? 4 : 8,
- return_uval))
- return -1;
+ *return_uval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_sdata:
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 95ad5259..3480f3dd 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -378,25 +378,17 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
return -1;
}
- /* Must have the form data4 or data8 which act as an offset. */
- Dwarf_Word offset;
- if (unlikely (INTUSE(dwarf_formudata) (attr, &offset) != 0))
+ unsigned char *endp, *readp
+ = __libdw_read_udata_addr (attr, IDX_debug_loc,
+ DWARF_E_NO_LOCLIST, &endp);
+ if (readp == NULL)
return -1;
- const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
- if (unlikely (d == NULL))
- {
- __libdw_seterrno (DWARF_E_NO_LOCLIST);
- return -1;
- }
-
Dwarf_Addr base = (Dwarf_Addr) -1;
- unsigned char *readp = d->d_buf + offset;
size_t got = 0;
while (got < maxlocs)
{
- if ((unsigned char *) d->d_buf + d->d_size - readp
- < attr->cu->address_size * 2)
+ if (endp - readp < attr->cu->address_size * 2)
{
invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
@@ -417,14 +409,13 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
else if (status < 0)
return status;
- if ((unsigned char *) d->d_buf + d->d_size - readp < 2)
+ if (endp - readp < 2)
goto invalid;
/* We have a location expression. */
block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
block.data = readp;
- if ((unsigned char *) d->d_buf + d->d_size - readp
- < (ptrdiff_t) block.length)
+ if (endp - readp < (ptrdiff_t) block.length)
goto invalid;
readp += block.length;
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 67b62aac..df510e1d 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -135,20 +135,13 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
/* Get the offset into the .debug_line section. NB: this call
also checks whether the previous dwarf_attr call failed. */
- Dwarf_Word offset;
- if (INTUSE(dwarf_formudata) (stmt_list, &offset) != 0)
+ const unsigned char *lineendp, *linep
+ = __libdw_read_udata_addr (stmt_list, IDX_debug_line,
+ DWARF_E_NO_DEBUG_LINE,
+ (unsigned char **) &lineendp);
+ if (linep == NULL)
goto out;
- Dwarf *dbg = cu->dbg;
- if (dbg->sectiondata[IDX_debug_line] == NULL)
- {
- __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
- goto out;
- }
- const uint8_t *linep = dbg->sectiondata[IDX_debug_line]->d_buf + offset;
- const uint8_t *lineendp = (dbg->sectiondata[IDX_debug_line]->d_buf
- + dbg->sectiondata[IDX_debug_line]->d_size);
-
/* Get the compilation directory. */
Dwarf_Attribute compdir_attr_mem;
Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
@@ -162,6 +155,8 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
__libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
goto out;
}
+
+ Dwarf *dbg = cu->dbg;
Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
unsigned int length = 4;
if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c
index ccb4f6b7..875068cb 100644
--- a/libdw/dwarf_ranges.c
+++ b/libdw/dwarf_ranges.c
@@ -125,11 +125,11 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
const Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_ranges];
if (d == NULL && offset != 0)
{
- no_ranges:
__libdw_seterrno (DWARF_E_NO_DEBUG_RANGES);
return -1;
}
+ unsigned char *readp, *readendp;
if (offset == 0)
{
Dwarf_Attribute attr_mem;
@@ -139,13 +139,12 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
/* No PC attributes in this DIE at all, so an empty range list. */
return 0;
- /* Must have the form data4 or data8 which act as an offset. */
- Dwarf_Word start_offset;
- if (INTUSE(dwarf_formudata) (attr, &start_offset) != 0)
+ if ((readp = __libdw_read_udata_addr (attr, IDX_debug_ranges,
+ DWARF_E_NO_DEBUG_RANGES,
+ &readendp)) == NULL)
return -1;
- if (d == NULL)
- goto no_ranges;
+ Dwarf_Word start_offset = (void *) readp - d->d_buf;
offset = start_offset;
assert ((Dwarf_Word) offset == start_offset);
@@ -172,17 +171,20 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
return -1;
}
}
- else if (offset < 0 || (size_t) offset >= d->d_size)
+ else
{
- __libdw_seterrno (DWARF_E_INVALID_OFFSET);
- return -1l;
- }
+ if (offset < 0 || (size_t) offset >= d->d_size)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+ return -1l;
+ }
- unsigned char *readp = d->d_buf + offset;
+ readp = d->d_buf + offset;
+ readendp = d->d_buf + d->d_size;
+ }
next:
- if ((unsigned char *) d->d_buf + d->d_size - readp
- < die->cu->address_size * 2)
+ if (readendp - readp < die->cu->address_size * 2)
goto invalid;
Dwarf_Addr begin;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index be0b99a8..16b19c6f 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -510,6 +510,11 @@ __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
Dwarf_Addr *basep)
internal_function;
+unsigned char *
+__libdw_read_udata_addr (Dwarf_Attribute *attr, int sec_index,
+ int err_nodata, unsigned char **endpp)
+ internal_function;
+
static inline int
__libdw_read_address (Dwarf *dbg,
int sec_index, const unsigned char *addr,