From cd0449ab05e9045682a81bf521bd0c8732c98feb Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 23 Apr 2014 14:26:19 +0930 Subject: [PATCH] PR ld/16787, stale dwarf2 stash Throw away the dwarf2 stash if it becomes invalid due to section VMAs changing. It would be nice to reclaim all the bfd_alloc memory here when we throw away the stash, perhaps by putting everything we alloc on a private dwarf2 objalloc, but I haven't done that with this patch. I've also fixed a problem with bfd_perform_relocation losing reloc addends, which meant a second or subsequent look at debug info sections did not properly relocate the sections. I can't see why bfd_perform_relocation should need to change addends except for ld -r, and the history (985fca12, e98e6ec1) doesn't help much. Finally, the patch tweaks place_sections to avoid unnecessary work. If we've mapped input to output sections, then input section VMA isn't used so there's not much point in adjusting it. Incidentally, this also means place_sections isn't effective in all cases. PR ld/16787 * dwarf2.c (struct dwarf2_debug): Add sec_vma field. (place_sections): Do not modify VMA of sections when called from linker after sections have been placed in output sections. Short circuit single section case. (save_section_vma, section_vma_same): New functions. (_bfd_dwarf2_slurp_debug_info): Throw away stash if section VMAs change. * reloc.c (bfd_perform_relocation): Do not modify reloc addend when non-relocatable. --- bfd/ChangeLog | 13 ++++++++ bfd/dwarf2.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++----- bfd/reloc.c | 4 --- 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f76f7cd527a..89c496f8879 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2014-04-23 Alan Modra + + PR ld/16787 + * dwarf2.c (struct dwarf2_debug): Add sec_vma field. + (place_sections): Do not modify VMA of sections when called from + linker after sections have been placed in output sections. Short + circuit single section case. + (save_section_vma, section_vma_same): New functions. + (_bfd_dwarf2_slurp_debug_info): Throw away stash if section VMAs + change. + * reloc.c (bfd_perform_relocation): Do not modify reloc addend + when non-relocatable. + 2014-04-22 Nick Clifton PR ld/16821 diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 592e3255757..6a4f4fd3141 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -156,6 +156,9 @@ struct dwarf2_debug use. */ struct funcinfo *inliner_chain; + /* Section VMAs at the time the stash was built. */ + bfd_vma *sec_vma; + /* Number of sections whose VMA we must adjust. */ unsigned int adjusted_section_count; @@ -3031,7 +3034,9 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) bfd_size_type sz; int is_debug_info; - if (sect->vma != 0) + if ((sect->output_section != NULL + && sect->output_section != sect) + || sect->vma != 0) continue; /* We need to adjust the VMAs of any .debug_info sections. @@ -3053,6 +3058,8 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) i++; } + if (i <= 1) + return TRUE; amt = i * sizeof (struct adjusted_section); p = (struct adjusted_section *) bfd_alloc (abfd, amt); @@ -3067,7 +3074,9 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) bfd_size_type sz; int is_debug_info; - if (sect->vma != 0) + if ((sect->output_section != NULL + && sect->output_section != sect) + || sect->vma != 0) continue; /* We need to adjust the VMAs of any .debug_info sections. @@ -3341,6 +3350,56 @@ stash_find_line_fast (struct dwarf2_debug *stash, filename_ptr, linenumber_ptr); } +/* Save current section VMAs. */ + +static bfd_boolean +save_section_vma (const bfd *abfd, struct dwarf2_debug *stash) +{ + asection *s; + unsigned int i; + + if (abfd->section_count == 0) + return TRUE; + stash->sec_vma = bfd_malloc (sizeof (*stash->sec_vma) * abfd->section_count); + if (stash->sec_vma == NULL) + return FALSE; + for (i = 0, s = abfd->sections; i < abfd->section_count; i++, s = s->next) + { + if (s->output_section != NULL) + stash->sec_vma[i] = s->output_section->vma + s->output_offset; + else + stash->sec_vma[i] = s->vma; + } + return TRUE; +} + +/* Compare current section VMAs against those at the time the stash + was created. If find_nearest_line is used in linker warnings or + errors early in the link process, the debug info stash will be + invalid for later calls. This is because we relocate debug info + sections, so the stashed section contents depend on symbol values, + which in turn depend on section VMAs. */ + +static bfd_boolean +section_vma_same (const bfd *abfd, const struct dwarf2_debug *stash) +{ + asection *s; + unsigned int i; + + for (i = 0, s = abfd->sections; i < abfd->section_count; i++, s = s->next) + { + bfd_vma vma; + + if (s->output_section != NULL) + vma = s->output_section->vma + s->output_offset; + else + vma = s->vma; + if (vma != stash->sec_vma[i]) + return FALSE; + } + return TRUE; +} + /* Read debug information from DEBUG_BFD when DEBUG_BFD is specified. If DEBUG_BFD is not specified, we read debug information from ABFD or its gnu_debuglink. The results will be stored in PINFO. @@ -3358,13 +3417,23 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo; if (stash != NULL) - return TRUE; - - stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt); - if (! stash) - return FALSE; + { + if (stash->syms == symbols + && section_vma_same (abfd, stash)) + return TRUE; + _bfd_dwarf2_cleanup_debug_info (abfd, pinfo); + memset (stash, 0, amt); + } + else + { + stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt); + if (! stash) + return FALSE; + } stash->debug_sections = debug_sections; stash->syms = symbols; + if (!save_section_vma (abfd, stash)) + return FALSE; *pinfo = stash; @@ -3891,6 +3960,8 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo) free (stash->alt_dwarf_str_buffer); if (stash->alt_dwarf_info_buffer) free (stash->alt_dwarf_info_buffer); + if (stash->sec_vma) + free (stash->sec_vma); if (stash->alt_bfd_ptr) bfd_close (stash->alt_bfd_ptr); } diff --git a/bfd/reloc.c b/bfd/reloc.c index bc6b393904b..7f46c587e20 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -784,10 +784,6 @@ space consuming. For each target: } } } - else - { - reloc_entry->addend = 0; - } /* FIXME: This overflow checking is incomplete, because the value might have overflowed before we get here. For a correct check we -- 2.30.2