mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
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:
@ -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>>
|
1999-06-02 Mark Mitchell <Mark Mitchell <mark@codesourcery.com>>
|
||||||
|
|
||||||
* elf32-mips.c (elf_mips_howto_table): Add R_MIPS_JALR.
|
* elf32-mips.c (elf_mips_howto_table): Add R_MIPS_JALR.
|
||||||
|
120
bfd/dwarf2.c
120
bfd/dwarf2.c
@ -631,6 +631,7 @@ struct line_info {
|
|||||||
char* filename;
|
char* filename;
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
unsigned int column;
|
unsigned int column;
|
||||||
|
int end_sequence; /* end of (sequential) code sequence */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fileinfo {
|
struct fileinfo {
|
||||||
@ -653,12 +654,13 @@ struct line_info_table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
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;
|
struct line_info_table* table;
|
||||||
bfd_vma address;
|
bfd_vma address;
|
||||||
char* filename;
|
char* filename;
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
unsigned int column;
|
unsigned int column;
|
||||||
|
int end_sequence;
|
||||||
{
|
{
|
||||||
struct line_info* info = (struct line_info*)
|
struct line_info* info = (struct line_info*)
|
||||||
bfd_alloc (table->abfd, sizeof (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->filename = filename;
|
||||||
info->line = line;
|
info->line = line;
|
||||||
info->column = column;
|
info->column = column;
|
||||||
|
info->end_sequence = end_sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
@ -677,7 +680,16 @@ concat_filename (table, file)
|
|||||||
struct line_info_table* table;
|
struct line_info_table* table;
|
||||||
unsigned int file;
|
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 == '/')
|
if (*filename == '/')
|
||||||
return filename;
|
return filename;
|
||||||
|
|
||||||
@ -708,6 +720,12 @@ decode_line_info (unit)
|
|||||||
unsigned int i, bytes_read;
|
unsigned int i, bytes_read;
|
||||||
char *cur_file, *cur_dir;
|
char *cur_file, *cur_dir;
|
||||||
unsigned char op_code, extended_op, adj_opcode;
|
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)
|
if (! dwarf_line_buffer)
|
||||||
{
|
{
|
||||||
@ -747,6 +765,9 @@ decode_line_info (unit)
|
|||||||
table->num_dirs = 0;
|
table->num_dirs = 0;
|
||||||
table->dirs = NULL;
|
table->dirs = NULL;
|
||||||
|
|
||||||
|
table->files = NULL;
|
||||||
|
table->last_line = NULL;
|
||||||
|
|
||||||
line_ptr = dwarf_line_buffer + unit->line_offset;
|
line_ptr = dwarf_line_buffer + unit->line_offset;
|
||||||
|
|
||||||
/* read in the prologue */
|
/* read in the prologue */
|
||||||
@ -831,6 +852,7 @@ decode_line_info (unit)
|
|||||||
int is_stmt = lh.default_is_stmt;
|
int is_stmt = lh.default_is_stmt;
|
||||||
int basic_block = 0;
|
int basic_block = 0;
|
||||||
int end_sequence = 0;
|
int end_sequence = 0;
|
||||||
|
boolean first_time = true;
|
||||||
|
|
||||||
/* Decode the table. */
|
/* Decode the table. */
|
||||||
while (! end_sequence)
|
while (! end_sequence)
|
||||||
@ -847,7 +869,7 @@ decode_line_info (unit)
|
|||||||
{
|
{
|
||||||
case DW_LNE_end_sequence:
|
case DW_LNE_end_sequence:
|
||||||
end_sequence = 1;
|
end_sequence = 1;
|
||||||
add_line_info (table, address, filename, line, column);
|
add_line_info (table, address, filename, line, column, end_sequence);
|
||||||
break;
|
break;
|
||||||
case DW_LNE_set_address:
|
case DW_LNE_set_address:
|
||||||
address = read_address (unit, line_ptr);
|
address = read_address (unit, line_ptr);
|
||||||
@ -884,7 +906,7 @@ decode_line_info (unit)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DW_LNS_copy:
|
case DW_LNS_copy:
|
||||||
add_line_info (table, address, filename, line, column);
|
add_line_info (table, address, filename, line, column, 0);
|
||||||
basic_block = 0;
|
basic_block = 0;
|
||||||
break;
|
break;
|
||||||
case DW_LNS_advance_pc:
|
case DW_LNS_advance_pc:
|
||||||
@ -918,7 +940,8 @@ decode_line_info (unit)
|
|||||||
basic_block = 1;
|
basic_block = 1;
|
||||||
break;
|
break;
|
||||||
case DW_LNS_const_add_pc:
|
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;
|
break;
|
||||||
case DW_LNS_fixed_advance_pc:
|
case DW_LNS_fixed_advance_pc:
|
||||||
address += read_2_bytes (abfd, line_ptr);
|
address += read_2_bytes (abfd, line_ptr);
|
||||||
@ -930,11 +953,27 @@ decode_line_info (unit)
|
|||||||
* lh.minimum_instruction_length;
|
* lh.minimum_instruction_length;
|
||||||
line += lh.line_base + (adj_opcode % lh.line_range);
|
line += lh.line_base + (adj_opcode % lh.line_range);
|
||||||
/* append row to matrix using current values */
|
/* 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;
|
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;
|
return table;
|
||||||
}
|
}
|
||||||
@ -954,21 +993,25 @@ lookup_address_in_line_info_table (table,
|
|||||||
const char **filename_ptr;
|
const char **filename_ptr;
|
||||||
unsigned int *linenumber_ptr;
|
unsigned int *linenumber_ptr;
|
||||||
{
|
{
|
||||||
|
struct line_info* next_line = table->last_line;
|
||||||
struct line_info* each_line;
|
struct line_info* each_line;
|
||||||
struct line_info* next_line;
|
|
||||||
|
|
||||||
for (next_line = 0, each_line = table->last_line;
|
if (!next_line)
|
||||||
each_line;
|
return false;
|
||||||
next_line = each_line, each_line = each_line->prev_line)
|
|
||||||
|
each_line = next_line->prev_line;
|
||||||
|
|
||||||
|
while (each_line && next_line)
|
||||||
{
|
{
|
||||||
if (addr >= each_line->address
|
if (!each_line->end_sequence
|
||||||
&& (next_line == 0
|
&& addr >= each_line->address && addr < next_line->address)
|
||||||
|| addr < next_line->address))
|
|
||||||
{
|
{
|
||||||
*filename_ptr = each_line->filename;
|
*filename_ptr = each_line->filename;
|
||||||
*linenumber_ptr = each_line->line;
|
*linenumber_ptr = each_line->line;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
next_line = each_line;
|
||||||
|
each_line = each_line->prev_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -1363,6 +1406,8 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
|||||||
|
|
||||||
struct comp_unit* each;
|
struct comp_unit* each;
|
||||||
|
|
||||||
|
boolean found;
|
||||||
|
|
||||||
*filename_ptr = NULL;
|
*filename_ptr = NULL;
|
||||||
*functionname_ptr = NULL;
|
*functionname_ptr = NULL;
|
||||||
*linenumber_ptr = 0;
|
*linenumber_ptr = 0;
|
||||||
@ -1404,14 +1449,20 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
|||||||
|
|
||||||
stash->info_ptr_end = stash->info_ptr + size;
|
stash->info_ptr_end = stash->info_ptr + size;
|
||||||
|
|
||||||
/* FIXME: There is a problem with the contents of the .debug_info section.
|
/* FIXME: There is a problem with the contents of the
|
||||||
The 'low' and 'high' addresses of the comp_units are computed by relocs
|
.debug_info section. The 'low' and 'high' addresses of the
|
||||||
against symbols in the .text segment. We need these addresses in
|
comp_units are computed by relocs against symbols in the
|
||||||
order to determine the nearest line number, and so we have to resolve
|
.text segment. We need these addresses in order to determine
|
||||||
the relocs. There is a similar problem when the .debug_line section is
|
the nearest line number, and so we have to resolve the
|
||||||
processed as well.
|
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
|
/* A null info_ptr indicates that there is no dwarf2 info
|
||||||
@ -1423,6 +1474,8 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
|||||||
/* Check the previously read comp. units first. */
|
/* Check the previously read comp. units first. */
|
||||||
|
|
||||||
for (each = stash->all_comp_units; each; each = each->next_unit)
|
for (each = stash->all_comp_units; each; each = each->next_unit)
|
||||||
|
{
|
||||||
|
if (each->high > 0)
|
||||||
{
|
{
|
||||||
if (comp_unit_contains_address (each, addr))
|
if (comp_unit_contains_address (each, addr))
|
||||||
return comp_unit_find_nearest_line (each, addr,
|
return comp_unit_find_nearest_line (each, addr,
|
||||||
@ -1430,6 +1483,16 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
|||||||
functionname_ptr,
|
functionname_ptr,
|
||||||
linenumber_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. */
|
/* Read each remaining comp. units checking each as they are read. */
|
||||||
while (stash->info_ptr < stash->info_ptr_end)
|
while (stash->info_ptr < stash->info_ptr_end)
|
||||||
@ -1451,12 +1514,29 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
|||||||
each->next_unit = stash->all_comp_units;
|
each->next_unit = stash->all_comp_units;
|
||||||
stash->all_comp_units = each;
|
stash->all_comp_units = each;
|
||||||
|
|
||||||
|
/* 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))
|
if (comp_unit_contains_address (each, addr))
|
||||||
return comp_unit_find_nearest_line (each, addr,
|
return comp_unit_find_nearest_line (each, addr,
|
||||||
filename_ptr,
|
filename_ptr,
|
||||||
functionname_ptr,
|
functionname_ptr,
|
||||||
linenumber_ptr);
|
linenumber_ptr);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = comp_unit_find_nearest_line (each, addr,
|
||||||
|
filename_ptr,
|
||||||
|
functionname_ptr,
|
||||||
|
linenumber_ptr);
|
||||||
|
if (found)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user