diff options
-rw-r--r-- | bfd/ChangeLog | 23 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 2 | ||||
-rw-r--r-- | bfd/dwarf2.c | 114 | ||||
-rw-r--r-- | bfd/elfxx-ia64.c | 15 | ||||
-rw-r--r-- | bfd/simple.c | 92 |
5 files changed, 130 insertions, 116 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 13f14d4..007d400 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,26 @@ +2003-03-31 Andreas Schwab <schwab@suse.de> + Daniel Jacobowitz <drow@mvista.com> + + * simple.c (bfd_simple_get_relocated_section_contents): Add + parameter symbol_table. Optionally use it instead of the symbol + table from the bfd. Save and restore output offsets and output + sections around bfd_get_relocated_section_contents. Fix a memory + leak. + (simple_save_output_info, simple_restore_output_info): New + functions. + * bfd-in2.h: Regenerate. + * dwarf2.c (read_abbrevs): Use + bfd_simple_get_relocated_section_contents instead of + bfd_get_section_contents. + (decode_line_info): Likewise. + (_bfd_dwarf2_find_nearest_line): Likewise. Don't call + find_rela_addend. + (find_rela_addend): Remove. + * elfxx-ia64.c (elfNN_ia64_reloc): Weaken sanity check for + debugging sections. + (elfNN_ia64_hash_table_create): Create the hash table with malloc, + not bfd_zalloc. + 2003-03-31 David Heine <dlheine@suif.stanford.edu> * aoutx.h (aout_link_hash_table_create): Use bfd_malloc instead of diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8960f66..51e2a21 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -4385,7 +4385,7 @@ bfd_link_split_section PARAMS ((bfd *abfd, asection *sec)); /* Extracted from simple.c. */ bfd_byte * -bfd_simple_get_relocated_section_contents PARAMS ((bfd *abfd, asection *sec, bfd_byte *outbuf)); +bfd_simple_get_relocated_section_contents PARAMS ((bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table)); #ifdef __cplusplus } diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 521bb71..0bc94b6 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -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) @@ -1023,21 +1019,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)."), @@ -1529,60 +1519,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 @@ -1610,7 +1546,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; @@ -1619,12 +1554,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; @@ -1947,8 +1876,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; @@ -1961,21 +1890,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) @@ -2042,10 +1956,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 { diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index c423057..3c8ec9e 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -357,6 +357,10 @@ elfNN_ia64_reloc (abfd, reloc, sym, data, input_section, reloc->address += input_section->output_offset; return bfd_reloc_ok; } + + if (input_section->flags & SEC_DEBUGGING) + return bfd_reloc_continue; + *error_message = "Unsupported call to elfNN_ia64_reloc"; return bfd_reloc_notsupported; } @@ -1788,19 +1792,24 @@ elfNN_ia64_hash_table_create (abfd) { struct elfNN_ia64_link_hash_table *ret; - ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret)); + ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret)); if (!ret) return 0; + if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, elfNN_ia64_new_elf_hash_entry)) { - bfd_release (abfd, ret); + free (ret); return 0; } if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd, elfNN_ia64_new_loc_hash_entry)) - return 0; + { + free (ret); + return 0; + } + return &ret->root.root; } diff --git a/bfd/simple.c b/bfd/simple.c index 30f9be0..a91d118 100644 --- a/bfd/simple.c +++ b/bfd/simple.c @@ -42,8 +42,14 @@ static bfd_boolean simple_dummy_reloc_dangerous static bfd_boolean simple_dummy_unattached_reloc PARAMS ((struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma)); +static void simple_save_output_info + PARAMS ((bfd *, asection *, PTR)); + +static void simple_restore_output_info + PARAMS ((bfd *, asection *, PTR)); + bfd_byte * bfd_simple_get_relocated_section_contents - PARAMS ((bfd *, asection *, bfd_byte *)); + PARAMS ((bfd *, asection *, bfd_byte *, asymbol **)); static bfd_boolean simple_dummy_warning (link_info, warning, symbol, abfd, section, address) @@ -105,17 +111,48 @@ simple_dummy_unattached_reloc (link_info, name, abfd, section, address) return TRUE; } +struct saved_output_info +{ + bfd_vma offset; + asection *section; +}; + +static void +simple_save_output_info (abfd, section, ptr) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section; + PTR ptr; +{ + struct saved_output_info *output_info = (struct saved_output_info *) ptr; + output_info[section->index].offset = section->output_offset; + output_info[section->index].section = section->output_section; + section->output_offset = 0; + section->output_section = section; +} + +static void +simple_restore_output_info (abfd, section, ptr) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section; + PTR ptr; +{ + struct saved_output_info *output_info = (struct saved_output_info *) ptr; + section->output_offset = output_info[section->index].offset; + section->output_section = output_info[section->index].section; +} + /* FUNCTION bfd_simple_relocate_secton SYNOPSIS - bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf); + bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); DESCRIPTION - Returns the relocated contents of section @var{sec}. Only symbols - from @var{abfd} and the output offsets assigned to sections in - @var{abfd} are used. The result will be stored at @var{outbuf} + Returns the relocated contents of section @var{sec}. The symbols in + @var{symbol_table} will be used, or the symbols from @var{abfd} if + @var{symbol_table} is NULL. The output offsets for all sections will + be temporarily reset to 0. The result will be stored at @var{outbuf} or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}. Generally all sections in @var{abfd} should have their @@ -126,17 +163,18 @@ DESCRIPTION */ bfd_byte * -bfd_simple_get_relocated_section_contents (abfd, sec, outbuf) +bfd_simple_get_relocated_section_contents (abfd, sec, outbuf, symbol_table) bfd *abfd; asection *sec; bfd_byte *outbuf; + asymbol **symbol_table; { struct bfd_link_info link_info; struct bfd_link_order link_order; struct bfd_link_callbacks callbacks; bfd_byte *contents, *data; int storage_needed; - asymbol **symbol_table; + PTR saved_offsets; if (! (sec->flags & SEC_RELOC)) { @@ -183,11 +221,36 @@ bfd_simple_get_relocated_section_contents (abfd, sec, outbuf) return NULL; outbuf = data; } - bfd_link_add_symbols (abfd, &link_info); - storage_needed = bfd_get_symtab_upper_bound (abfd); - symbol_table = (asymbol **) bfd_malloc (storage_needed); - bfd_canonicalize_symtab (abfd, symbol_table); + /* The sections in ABFD may already have output sections and offsets set. + Because this function is primarily for debug sections, and GCC uses the + knowledge that debug sections will generally have VMA 0 when emiting + relocations between DWARF-2 sections (which are supposed to be + section-relative offsets anyway), we need to reset the output offsets + to zero. We also need to arrange for section->output_section->vma plus + section->output_offset to equal section->vma, which we do by setting + section->output_section to point back to section. Save the original + output offset and output section to restore later. */ + saved_offsets = malloc (sizeof (struct saved_output_info) + * abfd->section_count); + if (saved_offsets == NULL) + { + if (data) + free (data); + return NULL; + } + bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets); + + if (symbol_table == NULL) + { + bfd_link_add_symbols (abfd, &link_info); + + storage_needed = bfd_get_symtab_upper_bound (abfd); + symbol_table = (asymbol **) bfd_malloc (storage_needed); + bfd_canonicalize_symtab (abfd, symbol_table); + } + else + storage_needed = 0; contents = bfd_get_relocated_section_contents (abfd, &link_info, @@ -198,6 +261,12 @@ bfd_simple_get_relocated_section_contents (abfd, sec, outbuf) if (contents == NULL && data != NULL) free (data); + if (storage_needed != 0) + free (symbol_table); + + bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets); + free (saved_offsets); + /* Foul hack to prevent bfd_section_size aborts. This flag only controls that macro (and the related size macros), selecting between _raw_size and _cooked_size. Debug sections won't change size while we're only @@ -208,6 +277,5 @@ bfd_simple_get_relocated_section_contents (abfd, sec, outbuf) bfd_link_hash_table_free (abfd, link_info.hash); - free (symbol_table); return contents; } |