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.
This commit is contained in:
Alan Modra 2014-04-23 14:26:19 +09:30
parent 1547d98f5a
commit cd0449ab05
3 changed files with 91 additions and 11 deletions

View File

@ -1,3 +1,16 @@
2014-04-23 Alan Modra <amodra@gmail.com>
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 <nickc@redhat.com> 2014-04-22 Nick Clifton <nickc@redhat.com>
PR ld/16821 PR ld/16821

View File

@ -156,6 +156,9 @@ struct dwarf2_debug
use. */ use. */
struct funcinfo *inliner_chain; 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. */ /* Number of sections whose VMA we must adjust. */
unsigned int adjusted_section_count; unsigned int adjusted_section_count;
@ -3031,7 +3034,9 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
bfd_size_type sz; bfd_size_type sz;
int is_debug_info; int is_debug_info;
if (sect->vma != 0) if ((sect->output_section != NULL
&& sect->output_section != sect)
|| sect->vma != 0)
continue; continue;
/* We need to adjust the VMAs of any .debug_info sections. /* We need to adjust the VMAs of any .debug_info sections.
@ -3053,6 +3058,8 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
i++; i++;
} }
if (i <= 1)
return TRUE;
amt = i * sizeof (struct adjusted_section); amt = i * sizeof (struct adjusted_section);
p = (struct adjusted_section *) bfd_alloc (abfd, amt); p = (struct adjusted_section *) bfd_alloc (abfd, amt);
@ -3067,7 +3074,9 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
bfd_size_type sz; bfd_size_type sz;
int is_debug_info; int is_debug_info;
if (sect->vma != 0) if ((sect->output_section != NULL
&& sect->output_section != sect)
|| sect->vma != 0)
continue; continue;
/* We need to adjust the VMAs of any .debug_info sections. /* 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); 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. /* Read debug information from DEBUG_BFD when DEBUG_BFD is specified.
If DEBUG_BFD is not specified, we read debug information from ABFD If DEBUG_BFD is not specified, we read debug information from ABFD
or its gnu_debuglink. The results will be stored in PINFO. 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; struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
if (stash != NULL) if (stash != NULL)
return TRUE; {
if (stash->syms == symbols
stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt); && section_vma_same (abfd, stash))
if (! stash) return TRUE;
return FALSE; _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->debug_sections = debug_sections;
stash->syms = symbols; stash->syms = symbols;
if (!save_section_vma (abfd, stash))
return FALSE;
*pinfo = stash; *pinfo = stash;
@ -3891,6 +3960,8 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
free (stash->alt_dwarf_str_buffer); free (stash->alt_dwarf_str_buffer);
if (stash->alt_dwarf_info_buffer) if (stash->alt_dwarf_info_buffer)
free (stash->alt_dwarf_info_buffer); free (stash->alt_dwarf_info_buffer);
if (stash->sec_vma)
free (stash->sec_vma);
if (stash->alt_bfd_ptr) if (stash->alt_bfd_ptr)
bfd_close (stash->alt_bfd_ptr); bfd_close (stash->alt_bfd_ptr);
} }

View File

@ -784,10 +784,6 @@ space consuming. For each target:
} }
} }
} }
else
{
reloc_entry->addend = 0;
}
/* FIXME: This overflow checking is incomplete, because the value /* FIXME: This overflow checking is incomplete, because the value
might have overflowed before we get here. For a correct check we might have overflowed before we get here. For a correct check we