/* Pointer to the end of the .debug_info section memory buffer. */
char* info_ptr_end;
+ /* Pointer to the section and address of the beginning of the
+ section. */
+ asection* sec;
+ char* sec_info_ptr;
+
+ /* Pointer to the symbol table. */
+ asymbol** syms;
+
/* Pointer to the .debug_abbrev section loaded into memory. */
char* dwarf_abbrev_buffer;
unsigned char addr_size;
};
+/* 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. */
+};
+
+struct attr_abbrev
+{
+ enum dwarf_attribute name;
+ enum dwarf_form form;
+};
+
+#ifndef ABBREV_HASH_SIZE
+#define ABBREV_HASH_SIZE 121
+#endif
+#ifndef ATTR_ALLOC_CHUNK
+#define ATTR_ALLOC_CHUNK 4
+#endif
+
+static unsigned int read_1_byte PARAMS ((bfd *, char *));
+static int read_1_signed_byte PARAMS ((bfd *, char *));
+static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+static unsigned int read_unsigned_leb128
+ PARAMS ((bfd *, char *, unsigned int *));
+static int read_signed_leb128
+ PARAMS ((bfd *, char *, unsigned int *));
+static bfd_vma read_address PARAMS ((struct comp_unit *, char *));
+static struct abbrev_info *lookup_abbrev
+ PARAMS ((unsigned int, struct abbrev_info **));
+static struct abbrev_info **read_abbrevs
+ PARAMS ((bfd *, unsigned int, struct dwarf2_debug *));
+static char *read_attribute
+ PARAMS ((struct attribute *, struct attr_abbrev *,
+ struct comp_unit *, char *));
+static void add_line_info
+ PARAMS ((struct line_info_table *, bfd_vma, char *,
+ unsigned int, unsigned int, int));
+static char *concat_filename PARAMS ((struct line_info_table *, unsigned int));
+static void arange_add PARAMS ((struct comp_unit *, bfd_vma, bfd_vma));
+static struct line_info_table *decode_line_info
+ PARAMS ((struct comp_unit *, struct dwarf2_debug *));
+static boolean lookup_address_in_line_info_table
+ PARAMS ((struct line_info_table *, bfd_vma, const char **, unsigned int *));
+static boolean lookup_address_in_function_table
+ PARAMS ((struct funcinfo *, bfd_vma, const char **));
+static boolean scan_unit_for_functions PARAMS ((struct comp_unit *));
+static bfd_vma find_rela_addend
+ PARAMS ((bfd *, asection *, bfd_size_type, asymbol**));
+static struct comp_unit *parse_comp_unit
+ PARAMS ((bfd *, struct dwarf2_debug *, bfd_vma, unsigned int));
+static boolean comp_unit_contains_address
+ PARAMS ((struct comp_unit *, bfd_vma));
+static boolean comp_unit_find_nearest_line
+ PARAMS ((struct comp_unit *, bfd_vma, const char **, const char **,
+ unsigned int *, struct dwarf2_debug *));
+static asection *find_debug_info PARAMS ((bfd *, asection *));
+
/* VERBATIM
The following function up to the END VERBATIM mark are
copied directly from dwarf2read.c. */
}
}
-/* 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. */
-};
-
-struct attr_abbrev
-{
- enum dwarf_attribute name;
- enum dwarf_form form;
-};
-
-#ifndef ABBREV_HASH_SIZE
-#define ABBREV_HASH_SIZE 121
-#endif
-#ifndef ATTR_ALLOC_CHUNK
-#define ATTR_ALLOC_CHUNK 4
-#endif
-
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info *
return 0;
}
- if (offset > stash->dwarf_abbrev_size)
+ if (offset >= stash->dwarf_abbrev_size)
{
- (*_bfd_error_handler) (_("Dwarf Error: Abbrev offset (%u) bigger than abbrev size (%u)."),
+ (*_bfd_error_handler) (_("Dwarf Error: Abbrev offset (%u) greater than or equal to abbrev size (%u)."),
offset, stash->dwarf_abbrev_size );
bfd_set_error (bfd_error_bad_value);
return 0;
below. */
if (unit->line_offset >= stash->dwarf_line_size)
{
- (*_bfd_error_handler) (_("Dwarf Error: Line offset (%u) bigger than line size (%u)."),
+ (*_bfd_error_handler) (_("Dwarf Error: Line offset (%u) greater than or equal to line size (%u)."),
unit->line_offset, stash->dwarf_line_size);
bfd_set_error (bfd_error_bad_value);
return 0;
return true;
}
+/* Look for a RELA relocation to be applied on OFFSET of section SEC,
+ and return the addend if such a relocation is found. Since this is
+ only used to find relocations referring to the .debug_abbrev
+ section, we make sure the relocation refers to this section, but
+ this is not strictly necessary, and it can probably be safely
+ removed if needed. However, it is important to note that this
+ function only returns the addend, it doesn't serve the purpose of
+ applying a generic relocation.
+
+ If no suitable relocation is found, or if it is not a real RELA
+ relocation, this function returns 0. */
+
+static bfd_vma
+find_rela_addend (abfd, sec, offset, syms)
+ bfd* abfd;
+ asection* sec;
+ bfd_size_type offset;
+ asymbol** syms;
+{
+ long reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
+ arelent **relocs = NULL;
+ long reloc_count, relc;
+
+ if (reloc_size <= 0)
+ return 0;
+
+ relocs = (arelent **) bfd_malloc ((size_t) reloc_size);
+ if (relocs == NULL)
+ return 0;
+
+ reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, syms);
+
+ if (reloc_count <= 0)
+ {
+ free (relocs);
+ return 0;
+ }
+
+ for (relc = 0; relc < reloc_count; relc++)
+ if (relocs[relc]->address == offset
+ && (*relocs[relc]->sym_ptr_ptr)->flags & BSF_SECTION_SYM
+ && strcmp ((*relocs[relc]->sym_ptr_ptr)->name,
+ ".debug_abbrev") == 0)
+ {
+ bfd_vma addend = (relocs[relc]->howto->partial_inplace
+ ? 0 : relocs[relc]->addend);
+ free (relocs);
+ return addend;
+ }
+
+ free (relocs);
+ return 0;
+}
+
/* 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
abbrev_offset = read_4_bytes (abfd, info_ptr);
else if (abbrev_length == 8)
abbrev_offset = read_8_bytes (abfd, info_ptr);
+ /* The abbrev offset is generally a relocation pointing to
+ .debug_abbrev+offset. On RELA targets, we have to find the
+ relocation and extract the addend to obtain the actual
+ abbrev_offset, so do it here. */
+ abbrev_offset += find_rela_addend (abfd, stash->sec,
+ info_ptr - stash->sec_info_ptr,
+ stash->syms);
info_ptr += abbrev_length;
addr_size = read_1_byte (abfd, info_ptr);
info_ptr += 1;
addr_size, pinfo)
bfd *abfd;
asection *section;
- asymbol **symbols ATTRIBUTE_UNUSED;
+ asymbol **symbols;
bfd_vma offset;
const char **filename_ptr;
const char **functionname_ptr;
stash->info_ptr_end = stash->info_ptr + start + size;
}
- BFD_ASSERT (stash->info_ptr_end = stash->info_ptr + total_size);
+ BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
+
+ stash->sec = find_debug_info (abfd, NULL);
+ stash->sec_info_ptr = stash->info_ptr;
+ stash->syms = symbols;
}
/* FIXME: There is a problem with the contents of the
each = parse_comp_unit (abfd, stash, length, addr_size);
stash->info_ptr += length;
+ if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
+ == stash->sec->_raw_size)
+ {
+ stash->sec = find_debug_info (abfd, stash->sec);
+ stash->sec_info_ptr = stash->info_ptr;
+ }
+
if (each)
{
each->next_unit = stash->all_comp_units;