This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: gc sections and .eh_frame
On Wed, Jun 22, 2005 at 12:46:21PM +0100, Jonathan Larmour wrote:
> I think Alan maybe didn't notice his name being mentioned :). Alan, do you
> have any guidance on the best approach?
None of the proposed solutions is right. If you take a look at a
typical .eh_frame, you'll see relocs pointing at text sections and
.gcc_except_table (or .rodata for broken ppc compilers). Changing
garbage collection to process .rela.eh_frame thus runs into the problem
of distinguishing the two types of reloc: You need to ignore the
former, and mark sections for the latter.
Try the following totally untested patch.
* elflink.c (_bfd_elf_gc_mark): Handle .eh_frame relocs specially..
(bfd_elf_gc_sections): ..rather than totally ignoring .eh_frame.
Don't recheck sections we have already marked.
--- bfd/elflink.c~ 2005-06-16 12:18:15.000000000 +0930
+++ bfd/elflink.c 2005-06-26 02:17:09.464213143 +0930
@@ -8733,6 +8733,7 @@
gc_mark_hook_fn gc_mark_hook)
{
bfd_boolean ret;
+ bfd_boolean is_eh;
asection *group_sec;
sec->gc_mark = 1;
@@ -8745,6 +8746,7 @@
/* Look through the section relocs. */
ret = TRUE;
+ is_eh = strcmp (sec->name, ".eh_frame") == 0;
if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
{
Elf_Internal_Rela *relstart, *rel, *relend;
@@ -8817,7 +8819,10 @@
rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
}
- if (rsec && !rsec->gc_mark)
+ if (rsec && !rsec->gc_mark
+ /* Don't mark code sections referenced by .eh_frame,
+ otherwise we'll mark all code sections in this file. */
+ && !(is_eh && (rsec->flags & SEC_CODE) != 0))
{
if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
rsec->gc_mark = 1;
@@ -9123,18 +9128,9 @@
continue;
for (o = sub->sections; o != NULL; o = o->next)
- {
- if (o->flags & SEC_KEEP)
- {
- /* _bfd_elf_discard_section_eh_frame knows how to discard
- orphaned FDEs so don't mark sections referenced by the
- EH frame section. */
- if (strcmp (o->name, ".eh_frame") == 0)
- o->gc_mark = 1;
- else if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
- return FALSE;
- }
- }
+ if ((o->flags & SEC_KEEP) != 0 && !o->gc_mark)
+ if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+ return FALSE;
}
/* ... and mark SEC_EXCLUDE for those that go. */
--
Alan Modra
IBM OzLabs - Linux Technology Centre