Find all sections containing debug information and include them in the stash.
This commit is contained in:
parent
7450026cd9
commit
a092b08432
@ -1,3 +1,10 @@
|
||||
2000-09-02 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* dwarf2.c (find_debug_info): New function: Locate a section
|
||||
containing dwarf2 debug information.
|
||||
(bfd_dwarf2_find_nearest_line): Find all sections containing
|
||||
debug information and include them in the stash.
|
||||
|
||||
2000-09-01 Niibe Yutaka <gniibe@m17n.org>, Kaz Kojima <kkojima@rr.iij4u.or.jp>, Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* elf32-sh.c (R_SH_GOT32, R_SH_PLT32, R_SH_COPY, R_SH_GLOB_DAT,
|
||||
|
405
bfd/dwarf2.c
405
bfd/dwarf2.c
@ -36,36 +36,38 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "elf/dwarf2.h"
|
||||
|
||||
/* The data in the .debug_line statement prologue looks like this. */
|
||||
|
||||
struct line_head
|
||||
{
|
||||
unsigned int total_length;
|
||||
unsigned short version;
|
||||
unsigned int prologue_length;
|
||||
unsigned char minimum_instruction_length;
|
||||
unsigned char default_is_stmt;
|
||||
int line_base;
|
||||
unsigned char line_range;
|
||||
unsigned char opcode_base;
|
||||
unsigned char *standard_opcode_lengths;
|
||||
};
|
||||
{
|
||||
unsigned int total_length;
|
||||
unsigned short version;
|
||||
unsigned int prologue_length;
|
||||
unsigned char minimum_instruction_length;
|
||||
unsigned char default_is_stmt;
|
||||
int line_base;
|
||||
unsigned char line_range;
|
||||
unsigned char opcode_base;
|
||||
unsigned char *standard_opcode_lengths;
|
||||
};
|
||||
|
||||
/* Attributes have a name and a value. */
|
||||
|
||||
/* Attributes have a name and a value */
|
||||
struct attribute
|
||||
{
|
||||
enum dwarf_attribute name;
|
||||
enum dwarf_form form;
|
||||
union
|
||||
{
|
||||
enum dwarf_attribute name;
|
||||
enum dwarf_form form;
|
||||
union
|
||||
{
|
||||
char *str;
|
||||
struct dwarf_block *blk;
|
||||
unsigned int unsnd;
|
||||
int snd;
|
||||
bfd_vma addr;
|
||||
}
|
||||
u;
|
||||
};
|
||||
char *str;
|
||||
struct dwarf_block *blk;
|
||||
unsigned int unsnd;
|
||||
int snd;
|
||||
bfd_vma addr;
|
||||
}
|
||||
u;
|
||||
};
|
||||
|
||||
/* Get at parts of an attribute structure */
|
||||
/* Get at parts of an attribute structure. */
|
||||
|
||||
#define DW_STRING(attr) ((attr)->u.str)
|
||||
#define DW_UNSND(attr) ((attr)->u.unsnd)
|
||||
@ -75,29 +77,28 @@ struct attribute
|
||||
|
||||
/* Blocks are a bunch of untyped bytes. */
|
||||
struct dwarf_block
|
||||
{
|
||||
unsigned int size;
|
||||
char *data;
|
||||
};
|
||||
{
|
||||
unsigned int size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
|
||||
struct dwarf2_debug {
|
||||
|
||||
/* A list of all previously read comp_units. */
|
||||
struct dwarf2_debug
|
||||
{
|
||||
/* A list of all previously read comp_units. */
|
||||
struct comp_unit* all_comp_units;
|
||||
|
||||
/* The next unread compilation unit within the .debug_info section.
|
||||
Zero indicates that the .debug_info section has not been loaded
|
||||
into a buffer yet.*/
|
||||
into a buffer yet. */
|
||||
char* info_ptr;
|
||||
|
||||
/* Pointer to the end of the .debug_info section memory buffer. */
|
||||
/* Pointer to the end of the .debug_info section memory buffer. */
|
||||
char* info_ptr_end;
|
||||
|
||||
/* Pointer to the .debug_abbrev section loaded into memory. */
|
||||
/* Pointer to the .debug_abbrev section loaded into memory. */
|
||||
char* dwarf_abbrev_buffer;
|
||||
|
||||
/* Length of the loaded .debug_abbrev section. */
|
||||
/* Length of the loaded .debug_abbrev section. */
|
||||
unsigned long dwarf_abbrev_size;
|
||||
|
||||
/* Buffer for decode_line_info. */
|
||||
@ -107,69 +108,67 @@ struct dwarf2_debug {
|
||||
unsigned long dwarf_line_size;
|
||||
};
|
||||
|
||||
struct arange {
|
||||
struct arange
|
||||
{
|
||||
struct arange *next;
|
||||
bfd_vma low;
|
||||
bfd_vma high;
|
||||
};
|
||||
|
||||
|
||||
/* A minimal decoding of DWARF2 compilation units. We only decode
|
||||
what's needed to get to the line number information. */
|
||||
what's needed to get to the line number information. */
|
||||
|
||||
struct comp_unit {
|
||||
|
||||
/* Chain the previously read compilation units. */
|
||||
struct comp_unit
|
||||
{
|
||||
/* Chain the previously read compilation units. */
|
||||
struct comp_unit* next_unit;
|
||||
|
||||
/* Keep the bdf convenient (for memory allocation). */
|
||||
/* Keep the bdf convenient (for memory allocation). */
|
||||
bfd* abfd;
|
||||
|
||||
/* The lowest and higest addresses contained in this compilation
|
||||
unit as specified in the compilation unit header. */
|
||||
unit as specified in the compilation unit header. */
|
||||
struct arange arange;
|
||||
|
||||
/* The DW_AT_name attribute (for error messages). */
|
||||
/* The DW_AT_name attribute (for error messages). */
|
||||
char* name;
|
||||
|
||||
/* The abbrev hash table. */
|
||||
/* The abbrev hash table. */
|
||||
struct abbrev_info** abbrevs;
|
||||
|
||||
/* Note that an error was found by comp_unit_find_nearest_line. */
|
||||
/* Note that an error was found by comp_unit_find_nearest_line. */
|
||||
int error;
|
||||
|
||||
/* The DW_AT_comp_dir attribute */
|
||||
/* The DW_AT_comp_dir attribute. */
|
||||
char* comp_dir;
|
||||
|
||||
/* True if there is a line number table associated with this comp. unit. */
|
||||
/* True if there is a line number table associated with this comp. unit. */
|
||||
int stmtlist;
|
||||
|
||||
/* The offset into .debug_line of the line number table. */
|
||||
/* The offset into .debug_line of the line number table. */
|
||||
unsigned long line_offset;
|
||||
|
||||
/* Pointer to the first child die for the comp unit. */
|
||||
/* Pointer to the first child die for the comp unit. */
|
||||
char *first_child_die_ptr;
|
||||
|
||||
/* The end of the comp unit. */
|
||||
/* The end of the comp unit. */
|
||||
char *end_ptr;
|
||||
|
||||
/* The decoded line number, NULL if not yet decoded. */
|
||||
/* The decoded line number, NULL if not yet decoded. */
|
||||
struct line_info_table* line_table;
|
||||
|
||||
/* A list of the functions found in this comp. unit. */
|
||||
/* A list of the functions found in this comp. unit. */
|
||||
struct funcinfo* function_table;
|
||||
|
||||
/* Address size for this unit - from unit header */
|
||||
/* Address size for this unit - from unit header. */
|
||||
unsigned char addr_size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* VERBATIM
|
||||
The following function up to the END VERBATIM mark are
|
||||
copied directly from dwarf2read.c. */
|
||||
copied directly from dwarf2read.c. */
|
||||
|
||||
/* read dwarf information from a buffer */
|
||||
/* Read dwarf information from a buffer. */
|
||||
|
||||
static unsigned int
|
||||
read_1_byte (abfd, buf)
|
||||
@ -195,9 +194,7 @@ read_2_bytes (abfd, buf)
|
||||
return bfd_get_16 (abfd, (bfd_byte *) buf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* This is not used. */
|
||||
#if 0 /* This is not used. */
|
||||
|
||||
static int
|
||||
read_2_signed_bytes (abfd, buf)
|
||||
@ -217,9 +214,7 @@ read_4_bytes (abfd, buf)
|
||||
return bfd_get_32 (abfd, (bfd_byte *) buf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* This is not used. */
|
||||
#if 0 /* This is not used. */
|
||||
|
||||
static int
|
||||
read_4_signed_bytes (abfd, buf)
|
||||
@ -265,6 +260,7 @@ read_string (abfd, buf, bytes_read_ptr)
|
||||
*bytes_read_ptr = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*bytes_read_ptr = strlen (buf) + 1;
|
||||
return buf;
|
||||
}
|
||||
@ -352,26 +348,22 @@ read_address (unit, buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* This data structure holds the information of an abbrev. */
|
||||
struct abbrev_info
|
||||
{
|
||||
unsigned int number; /* number identifying abbrev */
|
||||
enum dwarf_tag tag; /* dwarf tag */
|
||||
int has_children; /* boolean */
|
||||
unsigned int num_attrs; /* number of attributes */
|
||||
struct attr_abbrev *attrs; /* an array of attribute descriptions */
|
||||
struct abbrev_info *next; /* next in chain */
|
||||
};
|
||||
{
|
||||
unsigned int number; /* Number identifying abbrev. */
|
||||
enum dwarf_tag tag; /* DWARF tag. */
|
||||
int has_children; /* Boolean. */
|
||||
unsigned int num_attrs; /* Number of attributes. */
|
||||
struct attr_abbrev *attrs; /* An array of attribute descriptions. */
|
||||
struct abbrev_info *next; /* Next in chain. */
|
||||
};
|
||||
|
||||
struct attr_abbrev
|
||||
{
|
||||
enum dwarf_attribute name;
|
||||
enum dwarf_form form;
|
||||
};
|
||||
{
|
||||
enum dwarf_attribute name;
|
||||
enum dwarf_form form;
|
||||
};
|
||||
|
||||
#ifndef ABBREV_HASH_SIZE
|
||||
#define ABBREV_HASH_SIZE 121
|
||||
@ -400,6 +392,7 @@ lookup_abbrev (number,abbrevs)
|
||||
else
|
||||
abbrev = abbrev->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -459,23 +452,24 @@ read_abbrevs (abfd, offset)
|
||||
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_ptr += bytes_read;
|
||||
|
||||
/* loop until we reach an abbrev number of 0 */
|
||||
/* Loop until we reach an abbrev number of 0. */
|
||||
while (abbrev_number)
|
||||
{
|
||||
cur_abbrev = (struct abbrev_info*)bfd_zalloc (abfd, sizeof (struct abbrev_info));
|
||||
|
||||
/* read in abbrev header */
|
||||
/* Read in abbrev header. */
|
||||
cur_abbrev->number = abbrev_number;
|
||||
cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_ptr += bytes_read;
|
||||
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
|
||||
abbrev_ptr += 1;
|
||||
|
||||
/* now read in declarations */
|
||||
/* Now read in declarations. */
|
||||
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_ptr += bytes_read;
|
||||
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_ptr += bytes_read;
|
||||
|
||||
while (abbrev_name)
|
||||
{
|
||||
if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
|
||||
@ -487,6 +481,7 @@ read_abbrevs (abfd, offset)
|
||||
if (! cur_abbrev->attrs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
|
||||
cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
|
||||
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
@ -533,6 +528,7 @@ read_attribute (attr, abbrev, unit, info_ptr)
|
||||
|
||||
attr->name = abbrev->name;
|
||||
attr->form = abbrev->form;
|
||||
|
||||
switch (abbrev->form)
|
||||
{
|
||||
case DW_FORM_addr:
|
||||
@ -634,35 +630,34 @@ read_attribute (attr, abbrev, unit, info_ptr)
|
||||
return info_ptr;
|
||||
}
|
||||
|
||||
|
||||
/* Source line information table routines. */
|
||||
/* Source line information table routines. */
|
||||
|
||||
#define FILE_ALLOC_CHUNK 5
|
||||
#define DIR_ALLOC_CHUNK 5
|
||||
|
||||
struct line_info {
|
||||
struct line_info
|
||||
{
|
||||
struct line_info* prev_line;
|
||||
|
||||
bfd_vma address;
|
||||
char* filename;
|
||||
unsigned int line;
|
||||
unsigned int column;
|
||||
int end_sequence; /* end of (sequential) code sequence */
|
||||
int end_sequence; /* End of (sequential) code sequence. */
|
||||
};
|
||||
|
||||
struct fileinfo {
|
||||
struct fileinfo
|
||||
{
|
||||
char *name;
|
||||
unsigned int dir;
|
||||
unsigned int time;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct line_info_table {
|
||||
struct line_info_table
|
||||
{
|
||||
bfd* abfd;
|
||||
|
||||
unsigned int num_files;
|
||||
unsigned int num_dirs;
|
||||
|
||||
char* comp_dir;
|
||||
char** dirs;
|
||||
struct fileinfo* files;
|
||||
@ -691,7 +686,7 @@ add_line_info (table, address, filename, line, column, end_sequence)
|
||||
info->end_sequence = end_sequence;
|
||||
}
|
||||
|
||||
static char*
|
||||
static char *
|
||||
concat_filename (table, file)
|
||||
struct line_info_table* table;
|
||||
unsigned int file;
|
||||
@ -726,8 +721,9 @@ arange_add (unit, low_pc, high_pc)
|
||||
{
|
||||
struct arange *arange;
|
||||
|
||||
/* first see if we can cheaply extend an existing range: */
|
||||
/* First see if we can cheaply extend an existing range. */
|
||||
arange = &unit->arange;
|
||||
|
||||
do
|
||||
{
|
||||
if (low_pc == arange->high)
|
||||
@ -746,14 +742,14 @@ arange_add (unit, low_pc, high_pc)
|
||||
|
||||
if (unit->arange.high == 0)
|
||||
{
|
||||
/* this is the first address range: store it in unit->arange: */
|
||||
/* 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: */
|
||||
/* Need to allocate a new arange and insert it into the arange list. */
|
||||
arange = bfd_zalloc (unit->abfd, sizeof (*arange));
|
||||
arange->low = low_pc;
|
||||
arange->high = high_pc;
|
||||
@ -762,18 +758,15 @@ arange_add (unit, low_pc, high_pc)
|
||||
unit->arange.next = arange;
|
||||
}
|
||||
|
||||
/* Decode the line number information for UNIT. */
|
||||
/* Decode the line number information for UNIT. */
|
||||
|
||||
static struct line_info_table*
|
||||
decode_line_info (unit)
|
||||
struct comp_unit *unit;
|
||||
{
|
||||
bfd *abfd = unit->abfd;
|
||||
|
||||
struct dwarf2_debug *stash;
|
||||
|
||||
struct line_info_table* table;
|
||||
|
||||
char *line_ptr;
|
||||
char *line_end;
|
||||
struct line_head lh;
|
||||
@ -806,7 +799,7 @@ decode_line_info (unit)
|
||||
return 0;
|
||||
|
||||
/* FIXME: We ought to apply the relocs against this section before
|
||||
we process it.... */
|
||||
we process it... */
|
||||
}
|
||||
|
||||
/* Since we are using un-relocated data, it is possible to get a bad value
|
||||
@ -836,7 +829,7 @@ decode_line_info (unit)
|
||||
|
||||
line_ptr = stash->dwarf_line_buffer + unit->line_offset;
|
||||
|
||||
/* read in the prologue */
|
||||
/* Read in the prologue. */
|
||||
lh.total_length = read_4_bytes (abfd, line_ptr);
|
||||
line_ptr += 4;
|
||||
line_end = line_ptr + lh.total_length;
|
||||
@ -858,16 +851,18 @@ decode_line_info (unit)
|
||||
bfd_alloc (abfd, lh.opcode_base * sizeof (unsigned char));
|
||||
|
||||
lh.standard_opcode_lengths[0] = 1;
|
||||
|
||||
for (i = 1; i < lh.opcode_base; ++i)
|
||||
{
|
||||
lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
}
|
||||
|
||||
/* Read directory table */
|
||||
/* Read directory table. */
|
||||
while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
{
|
||||
line_ptr += bytes_read;
|
||||
|
||||
if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)
|
||||
{
|
||||
table->dirs = (char **)
|
||||
@ -876,14 +871,17 @@ decode_line_info (unit)
|
||||
if (! table->dirs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
table->dirs[table->num_dirs++] = cur_dir;
|
||||
}
|
||||
|
||||
line_ptr += bytes_read;
|
||||
|
||||
/* Read file name table */
|
||||
/* Read file name table. */
|
||||
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
{
|
||||
line_ptr += bytes_read;
|
||||
|
||||
if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
|
||||
{
|
||||
table->files = (struct fileinfo *)
|
||||
@ -893,6 +891,7 @@ decode_line_info (unit)
|
||||
if (! table->files)
|
||||
return 0;
|
||||
}
|
||||
|
||||
table->files[table->num_files].name = cur_file;
|
||||
table->files[table->num_files].dir =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
@ -905,12 +904,13 @@ decode_line_info (unit)
|
||||
line_ptr += bytes_read;
|
||||
table->num_files++;
|
||||
}
|
||||
|
||||
line_ptr += bytes_read;
|
||||
|
||||
/* Read the statement sequences until there's nothing left. */
|
||||
while (line_ptr < line_end)
|
||||
{
|
||||
/* state machine registers */
|
||||
/* State machine registers. */
|
||||
bfd_vma address = 0;
|
||||
char* filename = concat_filename (table, 1);
|
||||
unsigned int line = 1;
|
||||
@ -920,15 +920,16 @@ decode_line_info (unit)
|
||||
int end_sequence = 0, need_low_pc = 1;
|
||||
bfd_vma low_pc = 0;
|
||||
|
||||
/* Decode the table. */
|
||||
/* Decode the table. */
|
||||
while (! end_sequence)
|
||||
{
|
||||
op_code = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
|
||||
switch (op_code)
|
||||
{
|
||||
case DW_LNS_extended_op:
|
||||
line_ptr += 1; /* ignore length */
|
||||
line_ptr += 1; /* Ignore length. */
|
||||
extended_op = read_1_byte (abfd, line_ptr);
|
||||
line_ptr += 1;
|
||||
switch (extended_op)
|
||||
@ -1025,12 +1026,12 @@ decode_line_info (unit)
|
||||
address += read_2_bytes (abfd, line_ptr);
|
||||
line_ptr += 2;
|
||||
break;
|
||||
default: /* special operand */
|
||||
default: /* Special operand. */
|
||||
adj_opcode = op_code - lh.opcode_base;
|
||||
address += (adj_opcode / lh.line_range)
|
||||
* lh.minimum_instruction_length;
|
||||
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, 0);
|
||||
basic_block = 1;
|
||||
if (need_low_pc)
|
||||
@ -1045,10 +1046,9 @@ decode_line_info (unit)
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
LINENUMBER_PTR, are pointers to the objects to be filled in. */
|
||||
|
||||
static boolean
|
||||
lookup_address_in_line_info_table (table,
|
||||
@ -1084,20 +1084,16 @@ lookup_address_in_line_info_table (table,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Function table functions. */
|
||||
|
||||
|
||||
|
||||
/* Function table functions. */
|
||||
|
||||
struct funcinfo {
|
||||
struct funcinfo
|
||||
{
|
||||
struct funcinfo *prev_func;
|
||||
|
||||
char* name;
|
||||
bfd_vma low;
|
||||
bfd_vma high;
|
||||
};
|
||||
|
||||
|
||||
/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true. */
|
||||
|
||||
static boolean
|
||||
@ -1124,14 +1120,10 @@ lookup_address_in_function_table (table,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* DWARF2 Compilation unit functions. */
|
||||
|
||||
/* DWARF2 Compilation unit functions. */
|
||||
|
||||
/* Scan over each die in a comp. unit looking for functions to add
|
||||
to the function table. */
|
||||
to the function table. */
|
||||
|
||||
static boolean
|
||||
scan_unit_for_functions (unit)
|
||||
@ -1230,11 +1222,6 @@ scan_unit_for_functions (unit)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Parse a DWARF2 compilation unit starting at INFO_PTR. This
|
||||
includes the compilation unit header that proceeds the DIE's, but
|
||||
does not include the length field that preceeds each compilation
|
||||
@ -1299,7 +1286,7 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the abbrevs for this compilation unit into a table */
|
||||
/* Read the abbrevs for this compilation unit into a table. */
|
||||
abbrevs = read_abbrevs (abfd, abbrev_offset);
|
||||
if (! abbrevs)
|
||||
return 0;
|
||||
@ -1379,11 +1366,7 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
|
||||
return unit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Return true if UNIT contains the address given by ADDR. */
|
||||
/* Return true if UNIT contains the address given by ADDR. */
|
||||
|
||||
static boolean
|
||||
comp_unit_contains_address (unit, addr)
|
||||
@ -1403,10 +1386,10 @@ comp_unit_contains_address (unit, addr)
|
||||
arange = arange->next;
|
||||
}
|
||||
while (arange);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* If UNIT contains ADDR, set the output parameters to the values for
|
||||
the line containing ADDR. The output parameters, FILENAME_PTR,
|
||||
FUNCTIONNAME_PTR, and LINENUMBER_PTR, are pointers to the objects
|
||||
@ -1463,6 +1446,43 @@ comp_unit_find_nearest_line (unit, addr,
|
||||
return line_p || func_p;
|
||||
}
|
||||
|
||||
/* Locate a section in a BFD containing debugging info. The search starts from the
|
||||
section after AFTER_SEC, or from the first section in the BFD if AFTER_SEC is
|
||||
NULL. The search works by examining the names of the sections. There are two
|
||||
permissiable names. The first is .debug_info. This is the standard DWARF2 name.
|
||||
The second is a prefix .gnu.linkonce.wi. This is a variation on the .debug_info
|
||||
section which has a checksum describing the contents appended onto the name. This
|
||||
allows the linker to identify and discard duplicate debugging sections for
|
||||
different compilation units. */
|
||||
#define DWARF2_DEBUG_INFO ".debug_info"
|
||||
#define GNU_LINKONCE_INFO ".gnu.linkonce.wi."
|
||||
|
||||
static asection *
|
||||
find_debug_info (abfd, after_sec)
|
||||
bfd * abfd;
|
||||
asection * after_sec;
|
||||
{
|
||||
asection * msec;
|
||||
|
||||
if (after_sec)
|
||||
msec = after_sec->next;
|
||||
else
|
||||
msec = abfd->sections;
|
||||
|
||||
while (msec)
|
||||
{
|
||||
if (strcmp (msec->name, DWARF2_DEBUG_INFO) == 0)
|
||||
return msec;
|
||||
|
||||
if (strncmp (msec->name, GNU_LINKONCE_INFO, strlen (GNU_LINKONCE_INFO)) == 0)
|
||||
return msec;
|
||||
|
||||
msec = msec->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The DWARF2 version of find_nearest line. Return true if the line
|
||||
is found without error. ADDR_SIZE is the number of bytes in the
|
||||
initial .debug_info length field and in the abbreviation offset.
|
||||
@ -1490,12 +1510,10 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
||||
|
||||
We keep a list of all the previously read compilation units, and
|
||||
a pointer to the next un-read compilation unit. Check the
|
||||
previously read units before reading more.
|
||||
*/
|
||||
|
||||
previously read units before reading more. */
|
||||
struct dwarf2_debug *stash = elf_tdata (abfd)->dwarf2_find_line_info;
|
||||
|
||||
/* What address are we looking for? */
|
||||
/* What address are we looking for? */
|
||||
bfd_vma addr = offset + section->vma;
|
||||
|
||||
struct comp_unit* each;
|
||||
@ -1513,71 +1531,84 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
||||
|
||||
if (! stash)
|
||||
{
|
||||
unsigned long total_size;
|
||||
asection *msec;
|
||||
unsigned long size;
|
||||
|
||||
|
||||
stash = elf_tdata (abfd)->dwarf2_find_line_info =
|
||||
(struct dwarf2_debug*) bfd_zalloc (abfd, sizeof (struct dwarf2_debug));
|
||||
|
||||
if (! stash)
|
||||
return false;
|
||||
|
||||
msec = bfd_get_section_by_name (abfd, ".debug_info");
|
||||
|
||||
msec = find_debug_info (abfd, NULL);
|
||||
if (! msec)
|
||||
{
|
||||
/* No dwarf2 info. Note that at this point the stash
|
||||
has been allocated, but contains zeros, this lets
|
||||
future calls to this function fail quicker. */
|
||||
return false;
|
||||
}
|
||||
|
||||
size = msec->_raw_size;
|
||||
if (size == 0)
|
||||
return false;
|
||||
|
||||
stash->info_ptr = (char *) bfd_alloc (abfd, size);
|
||||
|
||||
if (! stash->info_ptr)
|
||||
/* No dwarf2 info. Note that at this point the stash
|
||||
has been allocated, but contains zeros, this lets
|
||||
future calls to this function fail quicker. */
|
||||
return false;
|
||||
|
||||
if (! bfd_get_section_contents (abfd, msec, stash->info_ptr, 0, size))
|
||||
/* There can be more than one DWARF2 info section in a BFD these days.
|
||||
Read them all in and produce one large stash. We do this in two
|
||||
passes - in the first pass we just accumulate the section sizes.
|
||||
In the second pass we read in the section's contents. The allows
|
||||
us to avoid reallocing the data as we add sections to the stash. */
|
||||
for (total_size = 0; msec; msec = find_debug_info (abfd, msec))
|
||||
total_size += msec->_raw_size;
|
||||
|
||||
stash->info_ptr = (char *) bfd_alloc (abfd, total_size);
|
||||
if (stash->info_ptr == NULL)
|
||||
return false;
|
||||
|
||||
stash->info_ptr_end = stash->info_ptr;
|
||||
|
||||
for (msec = find_debug_info (abfd, NULL);
|
||||
msec;
|
||||
msec = find_debug_info (abfd, msec))
|
||||
{
|
||||
stash->info_ptr = 0;
|
||||
return false;
|
||||
unsigned long size;
|
||||
unsigned long start;
|
||||
|
||||
size = msec->_raw_size;
|
||||
if (size == 0)
|
||||
continue;
|
||||
|
||||
start = stash->info_ptr_end - stash->info_ptr;
|
||||
|
||||
if (! bfd_get_section_contents (abfd, msec, stash->info_ptr + start, 0, size))
|
||||
continue;
|
||||
|
||||
stash->info_ptr_end = stash->info_ptr + start + size;
|
||||
}
|
||||
|
||||
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 (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...
|
||||
|
||||
For now, this means that disassembling object files (as
|
||||
opposed to fully executables) does not always work as well as
|
||||
we would like. */
|
||||
BFD_ASSERT (stash->info_ptr_end = stash->info_ptr + total_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 (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...
|
||||
|
||||
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
|
||||
(or that an error occured while setting up the stash). */
|
||||
|
||||
(or that an error occured while setting up the stash). */
|
||||
if (! stash->info_ptr)
|
||||
return false;
|
||||
|
||||
/* 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)
|
||||
if (comp_unit_contains_address (each, addr))
|
||||
return comp_unit_find_nearest_line (each, addr, filename_ptr,
|
||||
functionname_ptr, linenumber_ptr);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct comp_unit* each;
|
||||
@ -1606,7 +1637,7 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
||||
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. */
|
||||
address. */
|
||||
if (each->arange.high > 0)
|
||||
{
|
||||
if (comp_unit_contains_address (each, addr))
|
||||
@ -1630,5 +1661,3 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* end of file */
|
||||
|
Loading…
x
Reference in New Issue
Block a user