/* Return list address ranges.
Copyright (C) 2000, 2001, 2002, 2004 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <libdwP.h>
struct arangelist
{
Dwarf_Arange arange;
struct arangelist *next;
};
int
dwarf_getaranges (dbg, aranges, naranges)
Dwarf *dbg;
Dwarf_Aranges **aranges;
size_t *naranges;
{
if (dbg == NULL)
return -1;
if (dbg->aranges != NULL)
{
*aranges = dbg->aranges;
if (naranges != NULL)
*naranges = dbg->aranges->naranges;
return 0;
}
if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
return -1;
struct arangelist *arangelist = NULL;
unsigned int narangelist = 0;
const char *readp
= (const char *) dbg->sectiondata[IDX_debug_aranges]->d_buf;
const char *readendp = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
while (readp < readendp)
{
const char *hdrstart = readp;
/* Each entry starts with a header:
1. A 4-byte or 12-byte length containing the length of the
set of entries for this compilation unit, not including the
length field itself. [...]
2. A 2-byte version identifier containing the value 2 for
DWARF Version 2.1.
3. A 4-byte or 8-byte offset into the .debug_info section. [...]
4. A 1-byte unsigned integer containing the size in bytes of
an address (or the offset portion of an address for segmented
addressing) on the target system.
5. A 1-byte unsigned integer containing the size in bytes of
a segment descriptor on the target system. */
Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
unsigned int length_bytes = 4;
if (length == 0xffffffff)
{
length = read_8ubyte_unaligned_inc (dbg, readp);
length_bytes = 8;
}
unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
if (version != 2)
{
invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return -1;
}
Dwarf_Word offset;
if (length_bytes == 4)
offset = read_4ubyte_unaligned_inc (dbg, readp);
else
offset = read_8ubyte_unaligned_inc (dbg, readp);
unsigned int address_size = *readp++;
if (address_size != 4 && address_size != 8)
goto invalid;
/* Ignore the segment size value. */
// XXX Really?
(void) *readp++;
/* Round the address to the next multiple of 2*address_size. */
readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
% (2 * address_size));
//arange_info->offset = offset;
while (1)
{
Dwarf_Word range_address;
Dwarf_Word range_length;
if (address_size == 4)
{
range_address = read_4ubyte_unaligned_inc (dbg, readp);
range_length = read_4ubyte_unaligned_inc (dbg, readp);
}
else
{
range_address = read_8ubyte_unaligned_inc (dbg, readp);
range_length = read_8ubyte_unaligned_inc (dbg, readp);
}
/* Two zero values mark the end. */
if (range_address == 0 && range_length == 0)
break;
struct arangelist *new_arange =
(struct arangelist *) alloca (sizeof (struct arangelist));
new_arange->arange.addr = range_address;
new_arange->arange.length = range_length;
/* We store the actual CU DIE offset, not the CU header offset. */
const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf
+ offset);
unsigned int offset_size;
if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
offset_size = 8;
else
offset_size = 4;
new_arange->arange.offset = offset + 3 * offset_size - 4 + 3;
new_arange->next = arangelist;
arangelist = new_arange;
++narangelist;
}
}
if (narangelist == 0)
{
if (naranges != NULL)
*naranges = 0;
*aranges = NULL;
return 0;
}
/* Allocate the array for the result. */
if (naranges != NULL)
*naranges = narangelist;
*aranges = libdw_alloc (dbg, Dwarf_Aranges,
sizeof (Dwarf_Aranges)
+ narangelist * sizeof (Dwarf_Arange), 1);
(*aranges)->dbg = dbg;
(*aranges)->naranges = narangelist;
while (narangelist-- > 0)
{
(*aranges)->info[narangelist] = arangelist->arange;
arangelist = arangelist->next;
}
dbg->aranges = *aranges;
return 0;
}