PR binutils/15994

* dwarf2.c (lookup_address_in_line_info_table): Change return type
	to be the range of addresses covered by the table.
	(comp_unit_find_nearest_line): Likewise.
	(find_line): Search all CUs.  Select the one that matches and
	covers the smallest address range.
This commit is contained in:
Nick Clifton 2013-10-25 09:32:43 +01:00 committed by Tom Tromey
parent 9993a35510
commit 240d6706c6
2 changed files with 76 additions and 28 deletions

View File

@ -1,3 +1,12 @@
2013-10-24 Nick Clifton <nickc@redhat.com>
PR binutils/15994
* dwarf2.c (lookup_address_in_line_info_table): Change return type
to be the range of addresses covered by the table.
(comp_unit_find_nearest_line): Likewise.
(find_line): Search all CUs. Select the one that matches and
covers the smallest address range.
2013-10-18 Hans-Peter Nilsson <hp@axis.com>
* elf32-cris.c (cris_elf_check_relocs): Don't assume

View File

@ -1909,11 +1909,13 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
return NULL;
}
/* If ADDR is within TABLE set the output parameters and return TRUE,
otherwise return FALSE. The output parameters, FILENAME_PTR and
LINENUMBER_PTR, are pointers to the objects to be filled in. */
/* If ADDR is within TABLE set the output parameters and return the
range of addresses covered by the entry used to fill them out.
Otherwise set * FILENAME_PTR to NULL and return 0.
The parameters FILENAME_PTR, LINENUMBER_PTR and DISCRIMINATOR_PTR
are pointers to the objects to be filled in. */
static bfd_boolean
static bfd_vma
lookup_address_in_line_info_table (struct line_info_table *table,
bfd_vma addr,
const char **filename_ptr,
@ -1955,12 +1957,12 @@ lookup_address_in_line_info_table (struct line_info_table *table,
*linenumber_ptr = each_line->line;
if (discriminator_ptr)
*discriminator_ptr = each_line->discriminator;
return TRUE;
return seq->last_line->address - seq->low_pc;
}
}
*filename_ptr = NULL;
return FALSE;
return 0;
}
/* Read in the .debug_ranges section for future reference. */
@ -1976,10 +1978,10 @@ read_debug_ranges (struct comp_unit *unit)
/* Function table functions. */
/* 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. */
/* If ADDR is within UNIT's function tables, 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 comp_unit *unit,
@ -2687,10 +2689,10 @@ comp_unit_contains_address (struct comp_unit *unit, bfd_vma addr)
FUNCTIONNAME_PTR, and LINENUMBER_PTR, are pointers to the objects
to be filled in.
Return TRUE if UNIT contains ADDR, and no errors were encountered;
FALSE otherwise. */
Returns the range of addresses covered by the entry that was used
to fill in *LINENUMBER_PTR or 0 if it was not filled in. */
static bfd_boolean
static bfd_vma
comp_unit_find_nearest_line (struct comp_unit *unit,
bfd_vma addr,
const char **filename_ptr,
@ -2699,7 +2701,6 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
unsigned int *discriminator_ptr,
struct dwarf2_debug *stash)
{
bfd_boolean line_p;
bfd_boolean func_p;
struct funcinfo *function;
@ -2735,11 +2736,11 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
&function, functionname_ptr);
if (func_p && (function->tag == DW_TAG_inlined_subroutine))
stash->inliner_chain = function;
line_p = lookup_address_in_line_info_table (unit->line_table, addr,
filename_ptr,
linenumber_ptr,
discriminator_ptr);
return line_p || func_p;
return lookup_address_in_line_info_table (unit->line_table, addr,
filename_ptr,
linenumber_ptr,
discriminator_ptr);
}
/* Check to see if line info is already decoded in a comp_unit.
@ -3470,7 +3471,7 @@ find_line (bfd *abfd,
/* What address are we looking for? */
bfd_vma addr;
struct comp_unit* each;
bfd_vma found = FALSE;
bfd_boolean found = FALSE;
bfd_boolean do_line;
*filename_ptr = NULL;
@ -3560,18 +3561,56 @@ find_line (bfd *abfd,
}
else
{
bfd_vma min_range = (bfd_vma) -1;
const char * local_filename = NULL;
const char * local_functionname = NULL;
unsigned int local_linenumber = 0;
unsigned int local_discriminator = 0;
for (each = stash->all_comp_units; each; each = each->next_unit)
{
bfd_vma range = (bfd_vma) -1;
found = ((each->arange.high == 0
|| comp_unit_contains_address (each, addr))
&& comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr,
discriminator_ptr,
stash));
&& (range = comp_unit_find_nearest_line (each, addr,
& local_filename,
& local_functionname,
& local_linenumber,
& local_discriminator,
stash)) != 0);
if (found)
goto done;
{
/* PRs 15935 15994: Bogus debug information may have provided us
with an erroneous match. We attempt to counter this by
selecting the match that has the smallest address range
associated with it. (We are assuming that corrupt debug info
will tend to result in extra large address ranges rather than
extra small ranges).
This does mean that we scan through all of the CUs associated
with the bfd each time this function is called. But this does
have the benefit of producing consistent results every time the
function is called. */
if (range <= min_range)
{
if (filename_ptr && local_filename)
* filename_ptr = local_filename;
if (functionname_ptr && local_functionname)
* functionname_ptr = local_functionname;
if (discriminator_ptr && local_discriminator)
* discriminator_ptr = local_discriminator;
if (local_linenumber)
* linenumber_ptr = local_linenumber;
min_range = range;
}
}
}
if (* linenumber_ptr)
{
found = TRUE;
goto done;
}
}
@ -3663,7 +3702,7 @@ find_line (bfd *abfd,
functionname_ptr,
linenumber_ptr,
discriminator_ptr,
stash));
stash)) > 0;
if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
== stash->sec->size)