diff options
Diffstat (limited to 'bfd/dwarf2.c')
-rw-r--r-- | bfd/dwarf2.c | 218 |
1 files changed, 83 insertions, 135 deletions
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index e7077a1..7a9e5b0 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -1,5 +1,5 @@ /* DWARF 2 support. - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions @@ -245,8 +245,6 @@ static bfd_boolean lookup_address_in_line_info_table static bfd_boolean lookup_address_in_function_table PARAMS ((struct funcinfo *, bfd_vma, struct funcinfo **, const char **)); static bfd_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 bfd_boolean comp_unit_contains_address @@ -546,13 +544,11 @@ read_abbrevs (abfd, offset, stash) } stash->dwarf_abbrev_size = msec->_raw_size; - stash->dwarf_abbrev_buffer = (char*) bfd_alloc (abfd, msec->_raw_size); + stash->dwarf_abbrev_buffer + = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, + stash->syms); if (! stash->dwarf_abbrev_buffer) return 0; - - if (! bfd_get_section_contents (abfd, msec, stash->dwarf_abbrev_buffer, - (bfd_vma) 0, msec->_raw_size)) - return 0; } if (offset >= stash->dwarf_abbrev_size) @@ -654,7 +650,7 @@ read_attribute_value (attr, form, unit, info_ptr) switch (form) { case DW_FORM_addr: - /* FIXME: DWARF3 draft sais DW_FORM_ref_addr is offset_size. */ + /* FIXME: DWARF3 draft says DW_FORM_ref_addr is offset_size. */ case DW_FORM_ref_addr: DW_ADDR (attr) = read_address (unit, info_ptr); info_ptr += unit->addr_size; @@ -821,11 +817,11 @@ struct funcinfo bfd_vma high; }; -/* add_line_info: adds a new entry to the line_info list in the - line_info_table, ensuring that the list is sorted. Note that the - line_info list is sorted from highest to lowest VMA (with possible - duplicates); that is, line_info->prev_line always accesses an equal - or smaller VMA. */ +/* Adds a new entry to the line_info list in the line_info_table, ensuring + that the list is sorted. Note that the line_info list is sorted from + highest to lowest VMA (with possible duplicates); that is, + line_info->prev_line always accesses an equal or smaller VMA. */ + static void add_line_info (table, address, filename, line, column, end_sequence) struct line_info_table* table; @@ -905,12 +901,25 @@ add_line_info (table, address, filename, line, column, end_sequence) /* Set member data of 'info'. */ info->address = address; - info->filename = filename; info->line = line; info->column = column; info->end_sequence = end_sequence; + + amt = strlen (filename); + if (amt) + { + info->filename = bfd_alloc (table->abfd, amt + 1); + if (info->filename) + strcpy (info->filename, filename); + } + else + info->filename = NULL; } +/* Extract a fully qualified filename from a line info table. + The returned string has been malloc'ed and it is the caller's + responsibility to free it. */ + static char * concat_filename (table, file) struct line_info_table* table; @@ -922,25 +931,32 @@ concat_filename (table, file) { (*_bfd_error_handler) (_("Dwarf Error: mangled line number section (bad file number).")); - return "<unknown>"; + return strdup ("<unknown>"); } filename = table->files[file - 1].name; - if (IS_ABSOLUTE_PATH(filename)) - return filename; - else + + if (! IS_ABSOLUTE_PATH (filename)) { char* dirname = (table->files[file - 1].dir ? table->dirs[table->files[file - 1].dir - 1] : table->comp_dir); - /* Not all tools set DW_AT_comp_dir, so dirname may be unknown. The - best we can do is return the filename part. */ - if (dirname == NULL) - return filename; - else - return (char*) concat (dirname, "/", filename, NULL); + /* Not all tools set DW_AT_comp_dir, so dirname may be unknown. + The best we can do is return the filename part. */ + if (dirname != NULL) + { + unsigned int len = strlen (dirname) + strlen (filename) + 2; + char * name; + + name = bfd_malloc (len); + if (name) + sprintf (name, "%s/%s", dirname, filename); + return name; + } } + + return strdup (filename); } static void @@ -1019,21 +1035,15 @@ decode_line_info (unit, stash) } stash->dwarf_line_size = msec->_raw_size; - stash->dwarf_line_buffer = (char *) bfd_alloc (abfd, msec->_raw_size); + stash->dwarf_line_buffer + = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, + stash->syms); if (! stash->dwarf_line_buffer) return 0; - - if (! bfd_get_section_contents (abfd, msec, stash->dwarf_line_buffer, - (bfd_vma) 0, msec->_raw_size)) - return 0; - - /* FIXME: We ought to apply the relocs against this section before - we process it... */ } - /* Since we are using un-relocated data, it is possible to get a bad value - for the line_offset. Validate it here so that we won't get a segfault - below. */ + /* It is possible to get a bad value for the line_offset. Validate + it here so that we won't get a segfault below. */ if (unit->line_offset >= stash->dwarf_line_size) { (*_bfd_error_handler) (_("Dwarf Error: Line offset (%lu) greater than or equal to .debug_line size (%lu)."), @@ -1272,6 +1282,8 @@ decode_line_info (unit, stash) based, the references are 1 based. */ file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; + if (filename) + free (filename); filename = concat_filename (table, file); break; } @@ -1296,6 +1308,7 @@ decode_line_info (unit, stash) default: { int i; + /* Unknown standard opcode, ignore it. */ for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++) { @@ -1305,6 +1318,9 @@ decode_line_info (unit, stash) } } } + + if (filename) + free (filename); } return table; @@ -1521,60 +1537,6 @@ scan_unit_for_functions (unit) 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 ((bfd_size_type) 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 @@ -1602,7 +1564,6 @@ parse_comp_unit (abfd, stash, unit_length, offset_size) char *info_ptr = stash->info_ptr; char *end_ptr = info_ptr + unit_length; bfd_size_type amt; - bfd_size_type off; version = read_2_bytes (abfd, info_ptr); info_ptr += 2; @@ -1611,12 +1572,6 @@ parse_comp_unit (abfd, stash, unit_length, offset_size) abbrev_offset = read_4_bytes (abfd, info_ptr); else 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. */ - off = info_ptr - stash->sec_info_ptr; - abbrev_offset += find_rela_addend (abfd, stash->sec, off, stash->syms); info_ptr += offset_size; addr_size = read_1_byte (abfd, info_ptr); info_ptr += 1; @@ -1939,8 +1894,8 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, start = stash->info_ptr_end - stash->info_ptr; - if (! bfd_get_section_contents (abfd, msec, stash->info_ptr + start, - (bfd_vma) 0, size)) + if ((bfd_simple_get_relocated_section_contents + (abfd, msec, stash->info_ptr + start, symbols)) == NULL) continue; stash->info_ptr_end = stash->info_ptr + start + size; @@ -1953,21 +1908,6 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, stash->syms = symbols; } - /* 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). */ if (! stash->info_ptr) @@ -1987,26 +1927,34 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, bfd_boolean found; unsigned int offset_size = addr_size; - if (addr_size == 4) + length = read_4_bytes (abfd, stash->info_ptr); + /* A 0xffffff length is the DWARF3 way of indicating we use + 64-bit offsets, instead of 32-bit offsets. */ + if (length == 0xffffffff) { - length = read_4_bytes (abfd, stash->info_ptr); - if (length == 0xffffffff) - { - offset_size = 8; - length = read_8_bytes (abfd, stash->info_ptr + 4); - stash->info_ptr += 8; - } - else if (length == 0) - { - /* Handle (non-standard) 64-bit DWARF2 formats. */ - offset_size = 8; - length = read_4_bytes (abfd, stash->info_ptr + 4); - stash->info_ptr += 4; - } + offset_size = 8; + length = read_8_bytes (abfd, stash->info_ptr + 4); + stash->info_ptr += 12; + } + /* A zero length is the IRIX way of indicating 64-bit offsets, + mostly because the 64-bit length will generally fit in 32 + bits, and the endianness helps. */ + else if (length == 0) + { + offset_size = 8; + length = read_4_bytes (abfd, stash->info_ptr + 4); + stash->info_ptr += 8; + } + /* In the absence of the hints above, we assume addr_size-sized + offsets, for backward-compatibility with pre-DWARF3 64-bit + platforms. */ + else if (addr_size == 8) + { + length = read_8_bytes (abfd, stash->info_ptr); + stash->info_ptr += 8; } else - length = read_8_bytes (abfd, stash->info_ptr); - stash->info_ptr += addr_size; + stash->info_ptr += 4; if (length > 0) { @@ -2034,10 +1982,10 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, { if (comp_unit_contains_address (each, addr)) return comp_unit_find_nearest_line (each, addr, - filename_ptr, - functionname_ptr, - linenumber_ptr, - stash); + filename_ptr, + functionname_ptr, + linenumber_ptr, + stash); } else { |