David Mosberger <davidm@hpl.hp.com>

* dwarf2.c (struct line_info): Add member END_SEQUENCE to keep
        track of end_sequence markers.
        (add_line_info): Add END_SEQUENCE arg.
        (decode_line_info): Don't try to infer lo_pc and hi_pc from the
        debug-line info---it doesn't work right if a compilation unit
        consists of multiple discontiguous code-sequences.  It would be
        worthwhile to optimize for the common case where a compilation
        unit results in a contiguous set of code sequences, but this is
        quite tricky to get right for arbitrary DWARF2 files.
        (lookup_address_in_line_info_table): Don't use the last line entry
        for a compilation unit for anything with an address higher than
        this line entry.  Also, check for end_sequence markers to
        correctly handle discontinuities.
        (_bfd_dwarf2_find_nearest_line): When checking previously loaded
        compilation units, check all compilation units with each->high==0
        just like when reading compilation units.
        * dwarf2.c (decode_line_info): Initialize table->files and
        table->last_line to NULL to avoid segfaults due to random
        values in these members.
        (concat_filename): Check for out-of-range file number before
        indexing filename table.  Segfaults suck.
        * dwarf2.c (decode_line_info): Don't truncate address to least
        significant 32 bits (breaks 64 bit targets).
        (lookup_address_in_function_table): Ditto.
        (comp_unit_contains_address): Ditto.
This commit is contained in:
Richard Henderson 1999-06-03 02:46:47 +00:00
parent 49309057b4
commit 159002ff69
2 changed files with 140 additions and 30 deletions

View File

@ -1,3 +1,33 @@
1999-06-03 David Mosberger <davidm@hpl.hp.com>
* dwarf2.c (struct line_info): Add member END_SEQUENCE to keep
track of end_sequence markers.
(add_line_info): Add END_SEQUENCE arg.
(decode_line_info): Don't try to infer lo_pc and hi_pc from the
debug-line info---it doesn't work right if a compilation unit
consists of multiple discontiguous code-sequences. It would be
worthwhile to optimize for the common case where a compilation
unit results in a contiguous set of code sequences, but this is
quite tricky to get right for arbitrary DWARF2 files.
(lookup_address_in_line_info_table): Don't use the last line entry
for a compilation unit for anything with an address higher than
this line entry. Also, check for end_sequence markers to
correctly handle discontinuities.
(_bfd_dwarf2_find_nearest_line): When checking previously loaded
compilation units, check all compilation units with each->high==0
just like when reading compilation units.
* dwarf2.c (decode_line_info): Initialize table->files and
table->last_line to NULL to avoid segfaults due to random
values in these members.
(concat_filename): Check for out-of-range file number before
indexing filename table. Segfaults suck.
* dwarf2.c (decode_line_info): Don't truncate address to least
significant 32 bits (breaks 64 bit targets).
(lookup_address_in_function_table): Ditto.
(comp_unit_contains_address): Ditto.
1999-06-02 Mark Mitchell <Mark Mitchell <mark@codesourcery.com>>
* elf32-mips.c (elf_mips_howto_table): Add R_MIPS_JALR.

View File

@ -631,6 +631,7 @@ struct line_info {
char* filename;
unsigned int line;
unsigned int column;
int end_sequence; /* end of (sequential) code sequence */
};
struct fileinfo {
@ -653,12 +654,13 @@ struct line_info_table {
};
static void
add_line_info (table, address, filename, line, column)
add_line_info (table, address, filename, line, column, end_sequence)
struct line_info_table* table;
bfd_vma address;
char* filename;
unsigned int line;
unsigned int column;
int end_sequence;
{
struct line_info* info = (struct line_info*)
bfd_alloc (table->abfd, sizeof (struct line_info));
@ -670,6 +672,7 @@ add_line_info (table, address, filename, line, column)
info->filename = filename;
info->line = line;
info->column = column;
info->end_sequence = end_sequence;
}
static char*
@ -677,7 +680,16 @@ concat_filename (table, file)
struct line_info_table* table;
unsigned int file;
{
char* filename = table->files[file - 1].name;
char* filename;
if (file - 1 >= table->num_files)
{
(*_bfd_error_handler) (_("Dwarf Error: mangled line number "
"section (bad file number)."));
return "<unknown>";
}
filename = table->files[file - 1].name;
if (*filename == '/')
return filename;
@ -708,6 +720,12 @@ decode_line_info (unit)
unsigned int i, bytes_read;
char *cur_file, *cur_dir;
unsigned char op_code, extended_op, adj_opcode;
#if 0
/* This optimization unfortunately does not work well on programs
that have multiple sections containing text (such as Linux which
uses .text, and .text.init, for example. */
bfd_vma hi_pc = 0, lo_pc = ~ (bfd_vma) 0;
#endif
if (! dwarf_line_buffer)
{
@ -747,6 +765,9 @@ decode_line_info (unit)
table->num_dirs = 0;
table->dirs = NULL;
table->files = NULL;
table->last_line = NULL;
line_ptr = dwarf_line_buffer + unit->line_offset;
/* read in the prologue */
@ -831,6 +852,7 @@ decode_line_info (unit)
int is_stmt = lh.default_is_stmt;
int basic_block = 0;
int end_sequence = 0;
boolean first_time = true;
/* Decode the table. */
while (! end_sequence)
@ -847,7 +869,7 @@ decode_line_info (unit)
{
case DW_LNE_end_sequence:
end_sequence = 1;
add_line_info (table, address, filename, line, column);
add_line_info (table, address, filename, line, column, end_sequence);
break;
case DW_LNE_set_address:
address = read_address (unit, line_ptr);
@ -884,7 +906,7 @@ decode_line_info (unit)
}
break;
case DW_LNS_copy:
add_line_info (table, address, filename, line, column);
add_line_info (table, address, filename, line, column, 0);
basic_block = 0;
break;
case DW_LNS_advance_pc:
@ -918,7 +940,8 @@ decode_line_info (unit)
basic_block = 1;
break;
case DW_LNS_const_add_pc:
address += (255 - lh.opcode_base) / lh.line_range;
address += lh.minimum_instruction_length
* ((255 - lh.opcode_base) / lh.line_range);
break;
case DW_LNS_fixed_advance_pc:
address += read_2_bytes (abfd, line_ptr);
@ -930,11 +953,27 @@ decode_line_info (unit)
* lh.minimum_instruction_length;
line += lh.line_base + (adj_opcode % lh.line_range);
/* append row to matrix using current values */
add_line_info (table, address, filename, line, column);
add_line_info (table, address, filename, line, column, 0);
basic_block = 1;
}
#if 0
if (unit->high == 0)
{
if (address > hi_pc)
hi_pc = address;
if (address < lo_pc)
lo_pc = address;
}
#endif
}
}
#if 0
if (unit->high == 0 && hi_pc != 0)
{
unit->high = hi_pc;
unit->low = lo_pc;
}
#endif
return table;
}
@ -954,21 +993,25 @@ lookup_address_in_line_info_table (table,
const char **filename_ptr;
unsigned int *linenumber_ptr;
{
struct line_info* next_line = table->last_line;
struct line_info* each_line;
struct line_info* next_line;
for (next_line = 0, each_line = table->last_line;
each_line;
next_line = each_line, each_line = each_line->prev_line)
if (!next_line)
return false;
each_line = next_line->prev_line;
while (each_line && next_line)
{
if (addr >= each_line->address
&& (next_line == 0
|| addr < next_line->address))
if (!each_line->end_sequence
&& addr >= each_line->address && addr < next_line->address)
{
*filename_ptr = each_line->filename;
*linenumber_ptr = each_line->line;
return true;
}
next_line = each_line;
each_line = each_line->prev_line;
}
return false;
@ -1363,6 +1406,8 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
struct comp_unit* each;
boolean found;
*filename_ptr = NULL;
*functionname_ptr = NULL;
*linenumber_ptr = 0;
@ -1404,14 +1449,20 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
stash->info_ptr_end = stash->info_ptr + size;
/* FIXME: There is a problem with the contents of the .debug_info section.
The 'low' and 'high' addresses of the comp_units are computed by relocs
against symbols in the .text segment. We need these addresses in
order to determine the nearest line number, and so we have to resolve
the relocs. There is a similar problem when the .debug_line section is
processed as well.
/* FIXME: There is a problem with the contents of the
.debug_info section. The 'low' and 'high' addresses of the
comp_units are computed by relocs against symbols in the
.text segment. We need these addresses in order to determine
the nearest line number, and so we have to resolve the
relocs. There is a similar problem when the .debug_line
section is processed as well (e.g., there may be relocs
against the operand of the DW_LNE_set_address operator).
Unfortunately getting hold of the reloc information is hard... */
Unfortunately getting hold of the reloc information is hard...
For now, this means that disassembling object files (as
opposed to fully executables) does not always work as well as
we would like. */
}
/* A null info_ptr indicates that there is no dwarf2 info
@ -1424,11 +1475,23 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
for (each = stash->all_comp_units; each; each = each->next_unit)
{
if (comp_unit_contains_address (each, addr))
return comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
if (each->high > 0)
{
if (comp_unit_contains_address (each, addr))
return comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
}
else
{
found = comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
if (found)
return true;
}
}
/* Read each remaining comp. units checking each as they are read. */
@ -1451,11 +1514,28 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
each->next_unit = stash->all_comp_units;
stash->all_comp_units = each;
if (comp_unit_contains_address (each, addr))
return comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
/* DW_AT_low_pc and DW_AT_high_pc are optional for
compilation units. If we don't have them (i.e.,
unit->high == 0), we need to consult the line info
table to see if a compilation unit contains the given
address. */
if (each->high > 0)
{
if (comp_unit_contains_address (each, addr))
return comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
}
else
{
found = comp_unit_find_nearest_line (each, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
if (found)
return true;
}
}
}
}