This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
gc sections and .eh_frame
- From: Jonathan Larmour <jifl at eCosCentric dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 07 Jun 2005 18:49:00 +0100
- Subject: gc sections and .eh_frame
After an update to binutils 2.16 from 2.15 I have found that sections
referenced by .eh_frame with relocs do not get pulled in if linking
(statically) with --gc-sections. Initially I just put a
KEEP(*(.gcc_except_table)) in my ldscript to work round this.
But now I'm using the powerpc architecture where the stuff usually in
.gcc_except_table is placed in .rodata instead. If the object file has
nothing else in .rodata, then that section is also being GC'd in the final
link. And Bad Things Happen.
I believe I have tracked this down to a change enclosed in full at the end
of this mail, made by Eric Botcazou on 2004-04-21. I've looked at the
mailing list archives, and not found any posting or discussion of the
patch, or its rationale. Is that right?
Anyway, the most relevant bit in elflink.c:bfd_elf_gc_sections() is:
for (o = sub->sections; o != NULL; o = o->next)
{
if (o->flags & SEC_KEEP)
- if (!elf_gc_mark (info, o, gc_mark_hook))
- return FALSE;
+ {
+ /* _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 (!elf_gc_mark (info, o, gc_mark_hook))
+ return FALSE;
+ }
}
}
This change doesn't make sense to me. _bfd_elf_discard_section_eh_frame
does not set gc_mark on any section. So as a result, I would assume none
of the reloc dependencies of .eh_frame would ever get marked and that's
how those sections get GC'd. Am I missing something?
There seems to have been some effort at the time to allow GC of sections
in dynamically linked programs (I think). Perhaps this was a change which
is only relevant for dynamic, not static linking? Certainly from my view,
the correct thing to do is simply revert this part of the change.
Jifl
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/bfd/ChangeLog,v
retrieving revision 1.2501
retrieving revision 1.2502
diff -u -5 -p -r1.2501 -r1.2502
--- ChangeLog 20 Apr 2004 12:17:12 -0000 1.2501
+++ ChangeLog 21 Apr 2004 07:14:15 -0000 1.2502
@@ -1,5 +1,14 @@
+2004-04-21 Eric Botcazou <ebotcazou@act-europe.fr>
+
+ * elflink.c (elf_gc_mark_dynamic_ref_symbol): New function.
+ (bfd_elf_gc_sections): Fail if a shared object is being created.
+ Do not fail if dynamic sections have been created. Instead call
+ elf_gc_mark_dynamic_ref_symbol to mark sections that contain
+ dynamically referenced symbols. Do not mark the whole graph
+ rooted at .eh_frame, only the section proper.
+
2004-04-20 DJ Delorie <dj@redhat.com>
* reloc.c: Add BFD_RELOC_32_SECREL.
* bfd-in2.h: Regenerate.
* libbfd.h: Likewise.
Index: elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -5 -p -r1.65 -r1.66
--- elflink.c 15 Apr 2004 02:55:20 -0000 1.65
+++ elflink.c 21 Apr 2004 07:14:15 -0000 1.66
@@ -8410,10 +8410,28 @@ elf_gc_smash_unused_vtentry_relocs (stru
}
return TRUE;
}
+/* Mark sections containing dynamically referenced symbols. This is called
+ through elf_link_hash_traverse. */
+
+static bfd_boolean
+elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h,
+ void *okp ATTRIBUTE_UNUSED)
+{
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC))
+ h->root.u.def.section->flags |= SEC_KEEP;
+
+ return TRUE;
+}
+
/* Do mark and sweep of unused sections. */
bfd_boolean
bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
{
@@ -8424,12 +8442,12 @@ bfd_elf_gc_sections (bfd *abfd, struct b
struct elf_link_hash_entry *h, Elf_Internal_Sym *);
if (!get_elf_backend_data (abfd)->can_gc_sections
|| info->relocatable
|| info->emitrelocations
- || !is_elf_hash_table (info->hash)
- || elf_hash_table (info)->dynamic_sections_created)
+ || info->shared
+ || !is_elf_hash_table (info->hash))
{
(*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
return TRUE;
}
@@ -8445,12 +8463,19 @@ bfd_elf_gc_sections (bfd *abfd, struct b
elf_gc_smash_unused_vtentry_relocs,
&ok);
if (!ok)
return FALSE;
- /* Grovel through relocs to find out who stays ... */
+ /* Mark dynamically referenced symbols. */
+ if (elf_hash_table (info)->dynamic_sections_created)
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_gc_mark_dynamic_ref_symbol,
+ &ok);
+ if (!ok)
+ return FALSE;
+ /* Grovel through relocs to find out who stays ... */
gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
{
asection *o;
@@ -8458,12 +8483,19 @@ bfd_elf_gc_sections (bfd *abfd, struct b
continue;
for (o = sub->sections; o != NULL; o = o->next)
{
if (o->flags & SEC_KEEP)
- if (!elf_gc_mark (info, o, gc_mark_hook))
- return FALSE;
+ {
+ /* _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 (!elf_gc_mark (info, o, gc_mark_hook))
+ return FALSE;
+ }
}
}
/* ... and mark SEC_EXCLUDE for those that go. */
if (!elf_gc_sweep (info, get_elf_backend_data (abfd)->gc_sweep_hook))
--
eCosCentric http://www.eCosCentric.com/ The eCos and RedBoot experts
--["No sense being pessimistic, it wouldn't work anyway"]-- Opinions==mine