summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2010-10-05 00:56:30 -0700
committerRoland McGrath <roland@redhat.com>2010-10-05 00:56:30 -0700
commit5f95e2b093cdeb4610cbb049dd5e7dac5dd7c3ef (patch)
tree1a542f7cd68bda4d2fbb01273483115fd71bb697
parent5659bdb5f8a20654ce34b39ea7162cba009f407d (diff)
downloadelfutils-5f95e2b093cdeb4610cbb049dd5e7dac5dd7c3ef.tar.gz
dwarf_getaranges: Avoid alloca to cope with huge .debug_aranges sections.
-rw-r--r--libdw/ChangeLog5
-rw-r--r--libdw/dwarf_getaranges.c52
2 files changed, 40 insertions, 17 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index da6ed056..57ab5880 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2010-10-05 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getaranges.c: Use malloc rather than alloca,
+ since the total number of elements can be quite huge.
+
2010-07-26 Roland McGrath <roland@redhat.com>
* dwarf_getlocation_implicit_pointer.c: New file.
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index cced9bf8..f18d63d0 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -67,9 +67,9 @@ struct arangelist
static int
compare_aranges (const void *a, const void *b)
{
- Dwarf_Arange *const *p1 = a, *const *p2 = b;
- Dwarf_Arange *l1 = *p1, *l2 = *p2;
- return l1->addr - l2->addr;
+ struct arangelist *const *p1 = a, *const *p2 = b;
+ struct arangelist *l1 = *p1, *l2 = *p2;
+ return l1->arange.addr - l2->arange.addr;
}
int
@@ -145,6 +145,13 @@ dwarf_getaranges (dbg, aranges, naranges)
{
invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
+ fail:
+ while (arangelist != NULL)
+ {
+ struct arangelist *next = arangelist->next;
+ free (arangelist);
+ arangelist = next;
+ }
return -1;
}
@@ -152,7 +159,7 @@ dwarf_getaranges (dbg, aranges, naranges)
if (__libdw_read_offset_inc (dbg,
IDX_debug_aranges, &readp,
length_bytes, &offset, IDX_debug_info, 4))
- return -1;
+ goto fail;
unsigned int address_size = *readp++;
if (address_size != 4 && address_size != 8)
@@ -173,7 +180,7 @@ dwarf_getaranges (dbg, aranges, naranges)
if (__libdw_read_address_inc (dbg, IDX_debug_aranges, &readp,
address_size, &range_address))
- return -1;
+ goto fail;
if (address_size == 4)
range_length = read_4ubyte_unaligned_inc (dbg, readp);
@@ -184,8 +191,14 @@ dwarf_getaranges (dbg, aranges, naranges)
if (range_address == 0 && range_length == 0)
break;
- struct arangelist *new_arange =
- (struct arangelist *) alloca (sizeof (struct arangelist));
+ /* We don't use alloca for these temporary structures because
+ the total number of them can be quite large. */
+ struct arangelist *new_arange = malloc (sizeof *new_arange);
+ if (unlikely (new_arange == NULL))
+ {
+ __libdw_seterrno (DWARF_E_NOMEM);
+ goto fail;
+ }
new_arange->arange.addr = range_address;
new_arange->arange.length = range_length;
@@ -202,19 +215,20 @@ dwarf_getaranges (dbg, aranges, naranges)
offset_size,
false);
- /* Sanity-check the data. */
- if (new_arange->arange.offset
- >= dbg->sectiondata[IDX_debug_info]->d_size)
- goto invalid;
-
new_arange->next = arangelist;
arangelist = new_arange;
++narangelist;
+
+ /* Sanity-check the data. */
+ if (unlikely (new_arange->arange.offset
+ >= dbg->sectiondata[IDX_debug_info]->d_size))
+ goto invalid;
}
}
if (narangelist == 0)
{
+ assert (arangelist == NULL);
if (naranges != NULL)
*naranges = 0;
*aranges = NULL;
@@ -230,9 +244,9 @@ dwarf_getaranges (dbg, aranges, naranges)
We'll write the pointers in the end of the buffer, and then
copy into the buffer from the beginning so the overlap works. */
assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
- Dwarf_Arange **sortaranges = (buf + sizeof (Dwarf_Aranges)
- + ((sizeof (Dwarf_Arange)
- - sizeof (Dwarf_Arange *)) * narangelist));
+ struct arangelist **sortaranges
+ = (buf + sizeof (Dwarf_Aranges)
+ + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
/* The list is in LIFO order and usually they come in clumps with
ascending addresses. So fill from the back to probably start with
@@ -240,7 +254,7 @@ dwarf_getaranges (dbg, aranges, naranges)
unsigned int i = narangelist;
while (i-- > 0)
{
- sortaranges[i] = &arangelist->arange;
+ sortaranges[i] = arangelist;
arangelist = arangelist->next;
}
assert (arangelist == NULL);
@@ -258,7 +272,11 @@ dwarf_getaranges (dbg, aranges, naranges)
if (naranges != NULL)
*naranges = narangelist;
for (i = 0; i < narangelist; ++i)
- (*aranges)->info[i] = *sortaranges[i];
+ {
+ struct arangelist *elt = sortaranges[i];
+ (*aranges)->info[i] = elt->arange;
+ free (elt);
+ }
return 0;
}