Update to correctly decode (non-standard DWARF2) out-of-order address sequences.

This commit is contained in:
Nick Clifton
2002-09-23 16:13:52 +00:00
parent 1b67de929e
commit e2f6d27741
2 changed files with 67 additions and 63 deletions

View File

@ -1,3 +1,9 @@
2002-09-23 Nathan Tallent <eraxxon@alumni.rice.edu>
* dwarf2.c (decode_line_info): Update to correctly decode
the (non-standard DWARF2) out-of-order address sequences
generated by the Intel C++ 6.0 compiler for ia64-Linux.
2002-09-23 Mark Elbrecht <snowball3@softhome.net> 2002-09-23 Mark Elbrecht <snowball3@softhome.net>
* config.bfd: For DJGPP targets, match with any cpu and any machine. * config.bfd: For DJGPP targets, match with any cpu and any machine.

View File

@ -13,21 +13,21 @@
based on Fred Fish's (Cygnus Support) implementation of DWARF 1 based on Fred Fish's (Cygnus Support) implementation of DWARF 1
support in dwarfread.c support in dwarfread.c
This file is part of BFD. This file is part of BFD.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at the Free Software Foundation; either version 2 of the License, or (at
your option) any later version. your option) any later version.
This program is distributed in the hope that it will be useful, but This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h" #include "bfd.h"
#include "sysdep.h" #include "sysdep.h"
@ -1084,13 +1084,19 @@ decode_line_info (unit, stash)
{ {
/* State machine registers. */ /* State machine registers. */
bfd_vma address = 0; bfd_vma address = 0;
char* filename = concat_filename (table, 1); char * filename = concat_filename (table, 1);
unsigned int line = 1; unsigned int line = 1;
unsigned int column = 0; unsigned int column = 0;
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, need_low_pc = 1; int end_sequence = 0;
bfd_vma low_pc = 0; /* eraxxon@alumni.rice.edu: Against the DWARF2 specs, some
compilers generate address sequences that are wildly out of
order using DW_LNE_set_address (e.g. Intel C++ 6.0 compiler
for ia64-Linux). Thus, to determine the low and high
address, we must compare on every DW_LNS_copy, etc. */
bfd_vma low_pc = 0;
bfd_vma high_pc = 0;
/* Decode the table. */ /* Decode the table. */
while (! end_sequence) while (! end_sequence)
@ -1099,7 +1105,8 @@ decode_line_info (unit, stash)
line_ptr += 1; line_ptr += 1;
if (op_code >= lh.opcode_base) if (op_code >= lh.opcode_base)
{ /* Special operand. */ {
/* Special operand. */
adj_opcode = op_code - lh.opcode_base; adj_opcode = op_code - lh.opcode_base;
address += (adj_opcode / lh.line_range) address += (adj_opcode / lh.line_range)
* lh.minimum_instruction_length; * lh.minimum_instruction_length;
@ -1107,29 +1114,30 @@ decode_line_info (unit, stash)
/* Append row to matrix using current values. */ /* Append row to matrix using current values. */
add_line_info (table, address, filename, line, column, 0); add_line_info (table, address, filename, line, column, 0);
basic_block = 1; basic_block = 1;
if (need_low_pc) if (low_pc == 0 || address < low_pc)
{ low_pc = address;
need_low_pc = 0; if (address > high_pc)
low_pc = address; high_pc = address;
}
} }
else switch (op_code) else switch (op_code)
{ {
case DW_LNS_extended_op: case DW_LNS_extended_op:
line_ptr += 1; /* Ignore length. */ /* Ignore length. */
line_ptr += 1;
extended_op = read_1_byte (abfd, line_ptr); extended_op = read_1_byte (abfd, line_ptr);
line_ptr += 1; line_ptr += 1;
switch (extended_op) switch (extended_op)
{ {
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); end_sequence);
if (need_low_pc) arange_add (unit, low_pc, high_pc);
{ if (low_pc == 0 || address < low_pc)
need_low_pc = 0; low_pc = address;
low_pc = address; if (address > high_pc)
} high_pc = address;
arange_add (unit, low_pc, address); arange_add (unit, low_pc, address);
break; break;
case DW_LNE_set_address: case DW_LNE_set_address:
@ -1169,11 +1177,10 @@ decode_line_info (unit, stash)
case DW_LNS_copy: case DW_LNS_copy:
add_line_info (table, address, filename, line, column, 0); add_line_info (table, address, filename, line, column, 0);
basic_block = 0; basic_block = 0;
if (need_low_pc) if (low_pc == 0 || address < low_pc)
{ low_pc = address;
need_low_pc = 0; if (address > high_pc)
low_pc = address; high_pc = address;
}
break; break;
case DW_LNS_advance_pc: case DW_LNS_advance_pc:
address += lh.minimum_instruction_length address += lh.minimum_instruction_length
@ -1188,8 +1195,8 @@ decode_line_info (unit, stash)
{ {
unsigned int file; unsigned int file;
/* The file and directory tables are 0 based, the references /* The file and directory tables are 0
are 1 based. */ based, the references are 1 based. */
file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read; line_ptr += bytes_read;
filename = concat_filename (table, file); filename = concat_filename (table, file);
@ -1214,8 +1221,9 @@ decode_line_info (unit, stash)
line_ptr += 2; line_ptr += 2;
break; break;
default: default:
{ /* Unknown standard opcode, ignore it. */ {
int i; int i;
/* Unknown standard opcode, ignore it. */
for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++) for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
{ {
(void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
@ -1234,10 +1242,7 @@ decode_line_info (unit, stash)
LINENUMBER_PTR, are pointers to the objects to be filled in. */ LINENUMBER_PTR, are pointers to the objects to be filled in. */
static boolean static boolean
lookup_address_in_line_info_table (table, lookup_address_in_line_info_table (table, addr, function, filename_ptr,
addr,
function,
filename_ptr,
linenumber_ptr) linenumber_ptr)
struct line_info_table* table; struct line_info_table* table;
bfd_vma addr; bfd_vma addr;
@ -1298,9 +1303,7 @@ lookup_address_in_line_info_table (table,
/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true. */ /* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true. */
static boolean static boolean
lookup_address_in_function_table (table, lookup_address_in_function_table (table, addr, function_ptr,
addr,
function_ptr,
functionname_ptr) functionname_ptr)
struct funcinfo* table; struct funcinfo* table;
bfd_vma addr; bfd_vma addr;
@ -1666,9 +1669,8 @@ comp_unit_contains_address (unit, addr)
false otherwise. */ false otherwise. */
static boolean static boolean
comp_unit_find_nearest_line (unit, addr, comp_unit_find_nearest_line (unit, addr, filename_ptr, functionname_ptr,
filename_ptr, functionname_ptr, linenumber_ptr, linenumber_ptr, stash)
stash)
struct comp_unit* unit; struct comp_unit* unit;
bfd_vma addr; bfd_vma addr;
const char **filename_ptr; const char **filename_ptr;
@ -1708,26 +1710,23 @@ comp_unit_find_nearest_line (unit, addr,
} }
function = NULL; function = NULL;
func_p = lookup_address_in_function_table (unit->function_table, func_p = lookup_address_in_function_table (unit->function_table, addr,
addr, &function, functionname_ptr);
&function, line_p = lookup_address_in_line_info_table (unit->line_table, addr,
functionname_ptr); function, filename_ptr,
line_p = lookup_address_in_line_info_table (unit->line_table,
addr,
function,
filename_ptr,
linenumber_ptr); linenumber_ptr);
return line_p || func_p; return line_p || func_p;
} }
/* Locate a section in a BFD containing debugging info. The search starts from the /* Locate a section in a BFD containing debugging info. The search starts
section after AFTER_SEC, or from the first section in the BFD if AFTER_SEC is from the section after AFTER_SEC, or from the first section in the BFD if
NULL. The search works by examining the names of the sections. There are two AFTER_SEC is NULL. The search works by examining the names of the
permissiable names. The first is .debug_info. This is the standard DWARF2 name. sections. There are two permissiable names. The first is .debug_info.
The second is a prefix .gnu.linkonce.wi. This is a variation on the .debug_info This is the standard DWARF2 name. The second is a prefix .gnu.linkonce.wi.
section which has a checksum describing the contents appended onto the name. This This is a variation on the .debug_info section which has a checksum
allows the linker to identify and discard duplicate debugging sections for describing the contents appended onto the name. This allows the linker to
different compilation units. */ identify and discard duplicate debugging sections for different
compilation units. */
#define DWARF2_DEBUG_INFO ".debug_info" #define DWARF2_DEBUG_INFO ".debug_info"
#define GNU_LINKONCE_INFO ".gnu.linkonce.wi." #define GNU_LINKONCE_INFO ".gnu.linkonce.wi."
@ -1766,8 +1765,7 @@ find_debug_info (abfd, after_sec)
boolean boolean
_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
filename_ptr, functionname_ptr, filename_ptr, functionname_ptr,
linenumber_ptr, linenumber_ptr, addr_size, pinfo)
addr_size, pinfo)
bfd *abfd; bfd *abfd;
asection *section; asection *section;
asymbol **symbols; asymbol **symbols;