Apply patch for binutils bug 806, approved by nickc@redhat.com.
2005-04-03 Fred Fish <fnf@specifixinc.com> * dwarf2.c (struct dwarf2_debug): Add dwarf_ranges_buffer and dwarf_ranges_size members. (struct comp_unit): Add base_address member. (struct funcinfo): Replace low/high members with an arange. (arange_add): Replace incoming "unit" parameter with "abfd" and "first_arange" pointers. Reorganize/rewrite function body. (decode_line_info): Change arange_add call to pass bfd and arange pointers. (lookup_address_in_line_info_table): Use arange list instead of individual low/high members. Walk function's arange list to find lowest PC in list, to test for overlapping functions. (read_debug_ranges): New function, reads the debug_ranges section. (lookup_address_in_function_table): Use arange list instead of individual low/high members. Rewrite to find smallest range that matches. (read_rangelist): Read a given rangelist from debug_ranges. (scan_unit_for_functions): Use arange list instead of individual low/high members. Handle a DW_AT_ranges attribute. (parse_comp_unit): Use arange list instead of individual low/high members. Save comp unit base address. Handle a DW_AT_ranges attribute.
This commit is contained in:
parent
14a88c496b
commit
a13afe8eb5
@ -1,3 +1,27 @@
|
||||
2005-04-03 Fred Fish <fnf@specifixinc.com>
|
||||
|
||||
* dwarf2.c (struct dwarf2_debug): Add dwarf_ranges_buffer and
|
||||
dwarf_ranges_size members.
|
||||
(struct comp_unit): Add base_address member.
|
||||
(struct funcinfo): Replace low/high members with an arange.
|
||||
(arange_add): Replace incoming "unit" parameter with "abfd" and
|
||||
"first_arange" pointers. Reorganize/rewrite function body.
|
||||
(decode_line_info): Change arange_add call to pass bfd and arange
|
||||
pointers.
|
||||
(lookup_address_in_line_info_table): Use arange list instead of
|
||||
individual low/high members. Walk function's arange list to find
|
||||
lowest PC in list, to test for overlapping functions.
|
||||
(read_debug_ranges): New function, reads the debug_ranges section.
|
||||
(lookup_address_in_function_table): Use arange list instead of
|
||||
individual low/high members. Rewrite to find smallest range that
|
||||
matches.
|
||||
(read_rangelist): Read a given rangelist from debug_ranges.
|
||||
(scan_unit_for_functions): Use arange list instead of individual
|
||||
low/high members. Handle a DW_AT_ranges attribute.
|
||||
(parse_comp_unit): Use arange list instead of individual low/high
|
||||
members. Save comp unit base address. Handle a DW_AT_ranges
|
||||
attribute.
|
||||
|
||||
2005-04-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf.c (assign_section_numbers): Really use the kept section.
|
||||
|
220
bfd/dwarf2.c
220
bfd/dwarf2.c
@ -112,6 +112,12 @@ struct dwarf2_debug
|
||||
|
||||
/* Length of the loaded .debug_str section. */
|
||||
unsigned long dwarf_str_size;
|
||||
|
||||
/* Pointer to the .debug_ranges section loaded into memory. */
|
||||
bfd_byte *dwarf_ranges_buffer;
|
||||
|
||||
/* Length of the loaded .debug_ranges section. */
|
||||
unsigned long dwarf_ranges_size;
|
||||
};
|
||||
|
||||
struct arange
|
||||
@ -178,6 +184,10 @@ struct comp_unit
|
||||
|
||||
/* Offset size for this unit - from unit header. */
|
||||
unsigned char offset_size;
|
||||
|
||||
/* Base address for this unit - from DW_AT_low_pc attribute of
|
||||
DW_TAG_compile_unit DIE */
|
||||
bfd_vma base_address;
|
||||
};
|
||||
|
||||
/* This data structure holds the information of an abbrev. */
|
||||
@ -657,8 +667,7 @@ struct funcinfo
|
||||
{
|
||||
struct funcinfo *prev_func;
|
||||
char *name;
|
||||
bfd_vma low;
|
||||
bfd_vma high;
|
||||
struct arange arange;
|
||||
};
|
||||
|
||||
/* Adds a new entry to the line_info list in the line_info_table, ensuring
|
||||
@ -800,13 +809,20 @@ concat_filename (struct line_info_table *table, unsigned int file)
|
||||
}
|
||||
|
||||
static void
|
||||
arange_add (struct comp_unit *unit, bfd_vma low_pc, bfd_vma high_pc)
|
||||
arange_add (bfd *abfd, struct arange *first_arange, bfd_vma low_pc, bfd_vma high_pc)
|
||||
{
|
||||
struct arange *arange;
|
||||
|
||||
/* First see if we can cheaply extend an existing range. */
|
||||
arange = &unit->arange;
|
||||
/* If the first arange is empty, use it. */
|
||||
if (first_arange->high == 0)
|
||||
{
|
||||
first_arange->low = low_pc;
|
||||
first_arange->high = high_pc;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Next see if we can cheaply extend an existing range. */
|
||||
arange = first_arange;
|
||||
do
|
||||
{
|
||||
if (low_pc == arange->high)
|
||||
@ -823,22 +839,13 @@ arange_add (struct comp_unit *unit, bfd_vma low_pc, bfd_vma high_pc)
|
||||
}
|
||||
while (arange);
|
||||
|
||||
if (unit->arange.high == 0)
|
||||
{
|
||||
/* This is the first address range: store it in unit->arange. */
|
||||
unit->arange.next = 0;
|
||||
unit->arange.low = low_pc;
|
||||
unit->arange.high = high_pc;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Need to allocate a new arange and insert it into the arange list. */
|
||||
arange = bfd_zalloc (unit->abfd, sizeof (*arange));
|
||||
/* Need to allocate a new arange and insert it into the arange list.
|
||||
Order isn't significant, so just insert after the first arange. */
|
||||
arange = bfd_zalloc (abfd, sizeof (*arange));
|
||||
arange->low = low_pc;
|
||||
arange->high = high_pc;
|
||||
|
||||
arange->next = unit->arange.next;
|
||||
unit->arange.next = arange;
|
||||
arange->next = first_arange->next;
|
||||
first_arange->next = arange;
|
||||
}
|
||||
|
||||
/* Decode the line number information for UNIT. */
|
||||
@ -1055,7 +1062,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
low_pc = address;
|
||||
if (address > high_pc)
|
||||
high_pc = address;
|
||||
arange_add (unit, low_pc, high_pc);
|
||||
arange_add (unit->abfd, &unit->arange, low_pc, high_pc);
|
||||
break;
|
||||
case DW_LNE_set_address:
|
||||
address = read_address (unit, line_ptr);
|
||||
@ -1191,7 +1198,7 @@ lookup_address_in_line_info_table (struct line_info_table *table,
|
||||
to return as good as results as possible for strange debugging
|
||||
info. */
|
||||
bfd_boolean addr_match = FALSE;
|
||||
if (each_line->address <= addr && addr <= next_line->address)
|
||||
if (each_line->address <= addr && addr < next_line->address)
|
||||
{
|
||||
addr_match = TRUE;
|
||||
|
||||
@ -1199,17 +1206,34 @@ lookup_address_in_line_info_table (struct line_info_table *table,
|
||||
later function, return the first line of that function instead
|
||||
of the last line of the earlier one. This check is for GCC
|
||||
2.95, which emits the first line number for a function late. */
|
||||
if (function != NULL
|
||||
&& each_line->address < function->low
|
||||
&& next_line->address > function->low)
|
||||
|
||||
if (function != NULL)
|
||||
{
|
||||
*filename_ptr = next_line->filename;
|
||||
*linenumber_ptr = next_line->line;
|
||||
}
|
||||
else
|
||||
{
|
||||
*filename_ptr = each_line->filename;
|
||||
*linenumber_ptr = each_line->line;
|
||||
bfd_vma lowest_pc;
|
||||
struct arange *arange;
|
||||
|
||||
/* Find the lowest address in the function's range list */
|
||||
lowest_pc = function->arange.low;
|
||||
for (arange = &function->arange;
|
||||
arange;
|
||||
arange = arange->next)
|
||||
{
|
||||
if (function->arange.low < lowest_pc)
|
||||
lowest_pc = function->arange.low;
|
||||
}
|
||||
/* Check for spanning function and set outgoing line info */
|
||||
if (addr >= lowest_pc
|
||||
&& each_line->address < lowest_pc
|
||||
&& next_line->address > lowest_pc)
|
||||
{
|
||||
*filename_ptr = next_line->filename;
|
||||
*linenumber_ptr = next_line->line;
|
||||
}
|
||||
else
|
||||
{
|
||||
*filename_ptr = each_line->filename;
|
||||
*linenumber_ptr = each_line->line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1236,9 +1260,41 @@ lookup_address_in_line_info_table (struct line_info_table *table,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read in the .debug_ranges section for future reference */
|
||||
|
||||
static bfd_boolean
|
||||
read_debug_ranges (struct comp_unit *unit)
|
||||
{
|
||||
struct dwarf2_debug *stash = unit->stash;
|
||||
if (! stash->dwarf_ranges_buffer)
|
||||
{
|
||||
bfd *abfd = unit->abfd;
|
||||
asection *msec;
|
||||
|
||||
msec = bfd_get_section_by_name (abfd, ".debug_ranges");
|
||||
if (! msec)
|
||||
{
|
||||
(*_bfd_error_handler) (_("Dwarf Error: Can't find .debug_ranges section."));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
stash->dwarf_ranges_size = msec->size;
|
||||
stash->dwarf_ranges_buffer
|
||||
= bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
|
||||
stash->syms);
|
||||
if (! stash->dwarf_ranges_buffer)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Function table functions. */
|
||||
|
||||
/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return TRUE. */
|
||||
/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return TRUE.
|
||||
Note that we need to find the function that has the smallest
|
||||
range that contains ADDR, to handle inlined functions without
|
||||
depending upon them being ordered in TABLE by increasing range. */
|
||||
|
||||
static bfd_boolean
|
||||
lookup_address_in_function_table (struct funcinfo *table,
|
||||
@ -1247,20 +1303,36 @@ lookup_address_in_function_table (struct funcinfo *table,
|
||||
const char **functionname_ptr)
|
||||
{
|
||||
struct funcinfo* each_func;
|
||||
struct funcinfo* best_fit = NULL;
|
||||
struct arange *arange;
|
||||
|
||||
for (each_func = table;
|
||||
each_func;
|
||||
each_func = each_func->prev_func)
|
||||
{
|
||||
if (addr >= each_func->low && addr < each_func->high)
|
||||
for (arange = &each_func->arange;
|
||||
arange;
|
||||
arange = arange->next)
|
||||
{
|
||||
*functionname_ptr = each_func->name;
|
||||
*function_ptr = each_func;
|
||||
return TRUE;
|
||||
if (addr >= arange->low && addr < arange->high)
|
||||
{
|
||||
if (!best_fit ||
|
||||
((arange->high - arange->low) < (best_fit->arange.high - best_fit->arange.low)))
|
||||
best_fit = each_func;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
if (best_fit)
|
||||
{
|
||||
*functionname_ptr = best_fit->name;
|
||||
*function_ptr = best_fit;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -1308,6 +1380,47 @@ find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
|
||||
return (name);
|
||||
}
|
||||
|
||||
static void
|
||||
read_rangelist (struct comp_unit *unit, struct arange *arange, bfd_uint64_t offset)
|
||||
{
|
||||
bfd_byte *ranges_ptr;
|
||||
bfd_vma base_address = unit->base_address;
|
||||
|
||||
if (! unit->stash->dwarf_ranges_buffer)
|
||||
{
|
||||
if (! read_debug_ranges (unit))
|
||||
return;
|
||||
}
|
||||
ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bfd_vma low_pc;
|
||||
bfd_vma high_pc;
|
||||
|
||||
if (unit->offset_size == 4)
|
||||
{
|
||||
low_pc = read_4_bytes (unit->abfd, ranges_ptr);
|
||||
ranges_ptr += 4;
|
||||
high_pc = read_4_bytes (unit->abfd, ranges_ptr);
|
||||
ranges_ptr += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
low_pc = read_8_bytes (unit->abfd, ranges_ptr);
|
||||
ranges_ptr += 8;
|
||||
high_pc = read_8_bytes (unit->abfd, ranges_ptr);
|
||||
ranges_ptr += 8;
|
||||
}
|
||||
if (low_pc == 0 && high_pc == 0)
|
||||
break;
|
||||
if (low_pc == -1UL && high_pc != -1UL)
|
||||
base_address = high_pc;
|
||||
else
|
||||
arange_add (unit->abfd, arange, base_address + low_pc, base_address + high_pc);
|
||||
}
|
||||
}
|
||||
|
||||
/* DWARF2 Compilation unit functions. */
|
||||
|
||||
/* Scan over each die in a comp. unit looking for functions to add
|
||||
@ -1326,6 +1439,8 @@ scan_unit_for_functions (struct comp_unit *unit)
|
||||
struct abbrev_info *abbrev;
|
||||
struct attribute attr;
|
||||
struct funcinfo *func;
|
||||
bfd_vma low_pc = 0;
|
||||
bfd_vma high_pc = 0;
|
||||
|
||||
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
@ -1379,11 +1494,15 @@ scan_unit_for_functions (struct comp_unit *unit)
|
||||
break;
|
||||
|
||||
case DW_AT_low_pc:
|
||||
func->low = attr.u.val;
|
||||
low_pc = attr.u.val;
|
||||
break;
|
||||
|
||||
case DW_AT_high_pc:
|
||||
func->high = attr.u.val;
|
||||
high_pc = attr.u.val;
|
||||
break;
|
||||
|
||||
case DW_AT_ranges:
|
||||
read_rangelist (unit, &func->arange, attr.u.val);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1392,6 +1511,11 @@ scan_unit_for_functions (struct comp_unit *unit)
|
||||
}
|
||||
}
|
||||
|
||||
if (func && high_pc != 0)
|
||||
{
|
||||
arange_add (unit->abfd, &func->arange, low_pc, high_pc);
|
||||
}
|
||||
|
||||
if (abbrev->has_children)
|
||||
nesting_level++;
|
||||
}
|
||||
@ -1426,6 +1550,8 @@ parse_comp_unit (bfd *abfd,
|
||||
bfd_byte *info_ptr = stash->info_ptr;
|
||||
bfd_byte *end_ptr = info_ptr + unit_length;
|
||||
bfd_size_type amt;
|
||||
bfd_vma low_pc = 0;
|
||||
bfd_vma high_pc = 0;
|
||||
|
||||
version = read_2_bytes (abfd, info_ptr);
|
||||
info_ptr += 2;
|
||||
@ -1513,11 +1639,19 @@ parse_comp_unit (bfd *abfd,
|
||||
break;
|
||||
|
||||
case DW_AT_low_pc:
|
||||
unit->arange.low = attr.u.val;
|
||||
low_pc = attr.u.val;
|
||||
/* If the compilation unit DIE has a DW_AT_low_pc attribute,
|
||||
this is the base address to use when reading location
|
||||
lists or range lists. */
|
||||
unit->base_address = low_pc;
|
||||
break;
|
||||
|
||||
case DW_AT_high_pc:
|
||||
unit->arange.high = attr.u.val;
|
||||
high_pc = attr.u.val;
|
||||
break;
|
||||
|
||||
case DW_AT_ranges:
|
||||
read_rangelist (unit, &unit->arange, attr.u.val);
|
||||
break;
|
||||
|
||||
case DW_AT_comp_dir:
|
||||
@ -1540,6 +1674,10 @@ parse_comp_unit (bfd *abfd,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (high_pc != 0)
|
||||
{
|
||||
arange_add (unit->abfd, &unit->arange, low_pc, high_pc);
|
||||
}
|
||||
|
||||
unit->first_child_die_ptr = info_ptr;
|
||||
return unit;
|
||||
|
Loading…
Reference in New Issue
Block a user