forked from Imagelibrary/binutils-gdb
gdb/
* dwarf2read.c (dwarf2_get_pc_bounds): Moved the `DW_AT_ranges' parsing code with its variables OBJFILE, CU_HEADER and OBFD into ... (dwarf2_ranges_read): ... a new function. (read_partial_die): Implemented the parsing of `DW_AT_ranges'. gdb/testsuite/ * gdb.dwarf2/dw2-ranges.S, gdb.dwarf2/dw2-ranges.exp: New files.
This commit is contained in:
227
gdb/dwarf2read.c
227
gdb/dwarf2read.c
@@ -3077,6 +3077,124 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
|
||||
local_symbols = new->locals;
|
||||
}
|
||||
|
||||
/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
|
||||
Return 1 if the attributes are present and valid, otherwise, return 0. */
|
||||
|
||||
static int
|
||||
dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
|
||||
CORE_ADDR *high_return, struct dwarf2_cu *cu)
|
||||
{
|
||||
struct objfile *objfile = cu->objfile;
|
||||
struct comp_unit_head *cu_header = &cu->header;
|
||||
bfd *obfd = objfile->obfd;
|
||||
unsigned int addr_size = cu_header->addr_size;
|
||||
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
|
||||
/* Base address selection entry. */
|
||||
CORE_ADDR base;
|
||||
int found_base;
|
||||
unsigned int dummy;
|
||||
gdb_byte *buffer;
|
||||
CORE_ADDR marker;
|
||||
int low_set;
|
||||
CORE_ADDR low = 0;
|
||||
CORE_ADDR high = 0;
|
||||
|
||||
found_base = cu_header->base_known;
|
||||
base = cu_header->base_address;
|
||||
|
||||
if (offset >= dwarf2_per_objfile->ranges_size)
|
||||
{
|
||||
complaint (&symfile_complaints,
|
||||
_("Offset %d out of bounds for DW_AT_ranges attribute"),
|
||||
offset);
|
||||
return 0;
|
||||
}
|
||||
buffer = dwarf2_per_objfile->ranges_buffer + offset;
|
||||
|
||||
/* Read in the largest possible address. */
|
||||
marker = read_address (obfd, buffer, cu, &dummy);
|
||||
if ((marker & mask) == mask)
|
||||
{
|
||||
/* If we found the largest possible address, then
|
||||
read the base address. */
|
||||
base = read_address (obfd, buffer + addr_size, cu, &dummy);
|
||||
buffer += 2 * addr_size;
|
||||
offset += 2 * addr_size;
|
||||
found_base = 1;
|
||||
}
|
||||
|
||||
low_set = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
CORE_ADDR range_beginning, range_end;
|
||||
|
||||
range_beginning = read_address (obfd, buffer, cu, &dummy);
|
||||
buffer += addr_size;
|
||||
range_end = read_address (obfd, buffer, cu, &dummy);
|
||||
buffer += addr_size;
|
||||
offset += 2 * addr_size;
|
||||
|
||||
/* An end of list marker is a pair of zero addresses. */
|
||||
if (range_beginning == 0 && range_end == 0)
|
||||
/* Found the end of list entry. */
|
||||
break;
|
||||
|
||||
/* Each base address selection entry is a pair of 2 values.
|
||||
The first is the largest possible address, the second is
|
||||
the base address. Check for a base address here. */
|
||||
if ((range_beginning & mask) == mask)
|
||||
{
|
||||
/* If we found the largest possible address, then
|
||||
read the base address. */
|
||||
base = read_address (obfd, buffer + addr_size, cu, &dummy);
|
||||
found_base = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!found_base)
|
||||
{
|
||||
/* We have no valid base address for the ranges
|
||||
data. */
|
||||
complaint (&symfile_complaints,
|
||||
_("Invalid .debug_ranges data (no base address)"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
range_beginning += base;
|
||||
range_end += base;
|
||||
|
||||
/* FIXME: This is recording everything as a low-high
|
||||
segment of consecutive addresses. We should have a
|
||||
data structure for discontiguous block ranges
|
||||
instead. */
|
||||
if (! low_set)
|
||||
{
|
||||
low = range_beginning;
|
||||
high = range_end;
|
||||
low_set = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (range_beginning < low)
|
||||
low = range_beginning;
|
||||
if (range_end > high)
|
||||
high = range_end;
|
||||
}
|
||||
}
|
||||
|
||||
if (! low_set)
|
||||
/* If the first entry is an end-of-list marker, the range
|
||||
describes an empty scope, i.e. no instructions. */
|
||||
return 0;
|
||||
|
||||
if (low_return)
|
||||
*low_return = low;
|
||||
if (high_return)
|
||||
*high_return = high;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get low and high pc attributes from a die. Return 1 if the attributes
|
||||
are present and valid, otherwise, return 0. Return -1 if the range is
|
||||
discontinuous, i.e. derived from DW_AT_ranges information. */
|
||||
@@ -3084,10 +3202,7 @@ static int
|
||||
dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
|
||||
CORE_ADDR *highpc, struct dwarf2_cu *cu)
|
||||
{
|
||||
struct objfile *objfile = cu->objfile;
|
||||
struct comp_unit_head *cu_header = &cu->header;
|
||||
struct attribute *attr;
|
||||
bfd *obfd = objfile->obfd;
|
||||
CORE_ADDR low = 0;
|
||||
CORE_ADDR high = 0;
|
||||
int ret = 0;
|
||||
@@ -3111,108 +3226,11 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
|
||||
attr = dwarf2_attr (die, DW_AT_ranges, cu);
|
||||
if (attr != NULL)
|
||||
{
|
||||
unsigned int addr_size = cu_header->addr_size;
|
||||
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
|
||||
/* Value of the DW_AT_ranges attribute is the offset in the
|
||||
.debug_ranges section. */
|
||||
unsigned int offset = DW_UNSND (attr);
|
||||
/* Base address selection entry. */
|
||||
CORE_ADDR base;
|
||||
int found_base;
|
||||
unsigned int dummy;
|
||||
gdb_byte *buffer;
|
||||
CORE_ADDR marker;
|
||||
int low_set;
|
||||
|
||||
found_base = cu_header->base_known;
|
||||
base = cu_header->base_address;
|
||||
|
||||
if (offset >= dwarf2_per_objfile->ranges_size)
|
||||
{
|
||||
complaint (&symfile_complaints,
|
||||
_("Offset %d out of bounds for DW_AT_ranges attribute"),
|
||||
offset);
|
||||
return 0;
|
||||
}
|
||||
buffer = dwarf2_per_objfile->ranges_buffer + offset;
|
||||
|
||||
/* Read in the largest possible address. */
|
||||
marker = read_address (obfd, buffer, cu, &dummy);
|
||||
if ((marker & mask) == mask)
|
||||
{
|
||||
/* If we found the largest possible address, then
|
||||
read the base address. */
|
||||
base = read_address (obfd, buffer + addr_size, cu, &dummy);
|
||||
buffer += 2 * addr_size;
|
||||
offset += 2 * addr_size;
|
||||
found_base = 1;
|
||||
}
|
||||
|
||||
low_set = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
CORE_ADDR range_beginning, range_end;
|
||||
|
||||
range_beginning = read_address (obfd, buffer, cu, &dummy);
|
||||
buffer += addr_size;
|
||||
range_end = read_address (obfd, buffer, cu, &dummy);
|
||||
buffer += addr_size;
|
||||
offset += 2 * addr_size;
|
||||
|
||||
/* An end of list marker is a pair of zero addresses. */
|
||||
if (range_beginning == 0 && range_end == 0)
|
||||
/* Found the end of list entry. */
|
||||
break;
|
||||
|
||||
/* Each base address selection entry is a pair of 2 values.
|
||||
The first is the largest possible address, the second is
|
||||
the base address. Check for a base address here. */
|
||||
if ((range_beginning & mask) == mask)
|
||||
{
|
||||
/* If we found the largest possible address, then
|
||||
read the base address. */
|
||||
base = read_address (obfd, buffer + addr_size, cu, &dummy);
|
||||
found_base = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!found_base)
|
||||
{
|
||||
/* We have no valid base address for the ranges
|
||||
data. */
|
||||
complaint (&symfile_complaints,
|
||||
_("Invalid .debug_ranges data (no base address)"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
range_beginning += base;
|
||||
range_end += base;
|
||||
|
||||
/* FIXME: This is recording everything as a low-high
|
||||
segment of consecutive addresses. We should have a
|
||||
data structure for discontiguous block ranges
|
||||
instead. */
|
||||
if (! low_set)
|
||||
{
|
||||
low = range_beginning;
|
||||
high = range_end;
|
||||
low_set = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (range_beginning < low)
|
||||
low = range_beginning;
|
||||
if (range_end > high)
|
||||
high = range_end;
|
||||
}
|
||||
}
|
||||
|
||||
if (! low_set)
|
||||
/* If the first entry is an end-of-list marker, the range
|
||||
describes an empty scope, i.e. no instructions. */
|
||||
if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu))
|
||||
return 0;
|
||||
|
||||
/* Found discontinuous range of addresses. */
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
@@ -5569,6 +5587,11 @@ read_partial_die (struct partial_die_info *part_die,
|
||||
has_high_pc_attr = 1;
|
||||
part_die->highpc = DW_ADDR (&attr);
|
||||
break;
|
||||
case DW_AT_ranges:
|
||||
if (dwarf2_ranges_read (DW_UNSND (&attr), &part_die->lowpc,
|
||||
&part_die->highpc, cu))
|
||||
has_low_pc_attr = has_high_pc_attr = 1;
|
||||
break;
|
||||
case DW_AT_location:
|
||||
/* Support the .debug_loc offsets */
|
||||
if (attr_form_is_block (&attr))
|
||||
|
||||
Reference in New Issue
Block a user