This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
-gc-sections and ARM unwinding tables
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 15 Feb 2007 20:22:58 +0000
- Subject: -gc-sections and ARM unwinding tables
The ARM EABI includes its own unwinding table format, including a special
section type (SHT_ARM_EXIDX) to contain these tables. These sections are not
referenced directly, so -gc-sections thinks they are unused and incorrectly
removes them. BFD already contains code to avoid discarding GNU .eh_frame
sections when the corresponding code section is required.
The attached patch adds an ELF linker backend hook and uses it to implement
something similar for ARM unwinding tables.
Tested on arm-linux-gnueabi.
Ok?
Paul
2007-02-15 Paul Brook <paul@codesourcery.com>
bfd/
* elflink.c (gc_mark_hook_fn): Remove.
(_bfd_elf_gc_mark): Rename gc_mark_hook_fn to elf_gc_mark_hook_fn.
(bfd_elf_gc_sections): Ditto. Call gc_mark_extra_sections.
* elf-bfd.h (elf_gc_mark_hook_fn): Define.
(elf_backend_data): Add gc_mark_extra_sections.
* elfxx-target.h (elf_backend_gc_mark_extra_sections): Provide default
definition.
(elfNN_bed): Add elf_backend_gc_mark_extra_sections.
* elf32-arm.c (elf32_arm_gc_mark_extra_sections): New function.
(elf_backend_gc_mark_extra_sections): Define.
ld/testsuite/
* ld-arm/arm-elf.exp (armelftests): Add gc-unwind.h.
* ld-arm/gc-unwind.s: New file.
* ld-arm/gc-unwind.d: New file.
Index: bfd/elf-bfd.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf-bfd.h,v
retrieving revision 1.226
diff -u -p -r1.226 elf-bfd.h
--- bfd/elf-bfd.h 5 Feb 2007 19:50:12 -0000 1.226
+++ bfd/elf-bfd.h 15 Feb 2007 19:59:43 -0000
@@ -538,6 +538,10 @@ enum action_discarded
PRETEND = 2
};
+typedef asection * (*elf_gc_mark_hook_fn)
+ (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *);
+
struct elf_backend_data
{
/* The architecture for this backend. */
@@ -843,9 +847,12 @@ struct elf_backend_data
/* This function is called during section gc to discover the section a
particular relocation refers to. */
- asection * (*gc_mark_hook)
- (asection *sec, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *h, Elf_Internal_Sym *);
+ elf_gc_mark_hook_fn gc_mark_hook;
+
+ /* This function, if defined, is called after the first gc marking pass
+ to allow the backend to mark additional sections. */
+ bfd_boolean (*gc_mark_extra_sections)
+ (struct bfd_link_info *info, elf_gc_mark_hook_fn gc_mark_hook);
/* This function, if defined, is called during the sweep phase of gc
in order that a backend might update any data structures it might
Index: bfd/elf32-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
retrieving revision 1.104
diff -u -p -r1.104 elf32-arm.c
--- bfd/elf32-arm.c 29 Jan 2007 16:29:21 -0000 1.104
+++ bfd/elf32-arm.c 15 Feb 2007 19:59:43 -0000
@@ -8150,6 +8150,50 @@ elf32_arm_check_relocs (bfd *abfd, struc
return TRUE;
}
+/* Unwinding tables are not referenced directly. This pass marks them as
+ required if the corresponding code section is marked. */
+
+static bfd_boolean
+elf32_arm_gc_mark_extra_sections(struct bfd_link_info *info,
+ elf_gc_mark_hook_fn gc_mark_hook)
+{
+ bfd *sub;
+ Elf_Internal_Shdr **elf_shdrp;
+ bfd_boolean again;
+
+ /* Marking EH data may cause additional code sections to be marked,
+ requiring multiple passes. */
+ again = TRUE;
+ while (again)
+ {
+ again = FALSE;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *o;
+
+ if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
+ continue;
+
+ elf_shdrp = elf_elfsections (sub);
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ Elf_Internal_Shdr *hdr;
+ hdr = &elf_section_data (o)->this_hdr;
+ if (hdr->sh_type == SHT_ARM_EXIDX && hdr->sh_link
+ && !o->gc_mark
+ && elf_shdrp[hdr->sh_link]->bfd_section->gc_mark)
+ {
+ again = TRUE;
+ if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
/* Treat mapping symbols as special target symbols. */
static bfd_boolean
@@ -10532,6 +10576,7 @@ const struct elf_size_info elf32_arm_siz
#define elf_backend_get_symbol_type elf32_arm_get_symbol_type
#define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook
+#define elf_backend_gc_mark_extra_sections elf32_arm_gc_mark_extra_sections
#define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook
#define elf_backend_check_relocs elf32_arm_check_relocs
#define elf_backend_relocate_section elf32_arm_relocate_section
Index: bfd/elflink.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elflink.c,v
retrieving revision 1.250
diff -u -p -r1.250 elflink.c
--- bfd/elflink.c 14 Feb 2007 14:15:52 -0000 1.250
+++ bfd/elflink.c 15 Feb 2007 20:00:55 -0000
@@ -10088,10 +10088,6 @@ bfd_elf_final_link (bfd *abfd, struct bf
/* Garbage collect unused sections. */
-typedef asection * (*gc_mark_hook_fn)
- (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *);
-
/* Default gc_mark_hook. */
asection *
@@ -10129,7 +10125,7 @@ _bfd_elf_gc_mark_hook (asection *sec,
bfd_boolean
_bfd_elf_gc_mark (struct bfd_link_info *info,
asection *sec,
- gc_mark_hook_fn gc_mark_hook)
+ elf_gc_mark_hook_fn gc_mark_hook)
{
bfd_boolean ret;
bfd_boolean is_eh;
@@ -10498,9 +10494,7 @@ bfd_elf_gc_sections (bfd *abfd, struct b
{
bfd_boolean ok = TRUE;
bfd *sub;
- asection * (*gc_mark_hook)
- (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *h, Elf_Internal_Sym *);
+ elf_gc_mark_hook_fn gc_mark_hook;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (!bed->can_gc_sections
@@ -10547,6 +10541,10 @@ bfd_elf_gc_sections (bfd *abfd, struct b
return FALSE;
}
+ /* Allow the backend to mark additional target specific sections. */
+ if (bed->gc_mark_extra_sections)
+ bed->gc_mark_extra_sections(info, gc_mark_hook);
+
/* ... again for sections marked from eh_frame. */
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
{
Index: bfd/elfxx-target.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elfxx-target.h,v
retrieving revision 1.102
diff -u -p -r1.102 elfxx-target.h
--- bfd/elfxx-target.h 1 Feb 2007 05:35:58 -0000 1.102
+++ bfd/elfxx-target.h 15 Feb 2007 19:59:43 -0000
@@ -133,6 +133,9 @@
#ifndef elf_backend_gc_mark_hook
#define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook
#endif
+#ifndef elf_backend_gc_mark_extra_sections
+#define elf_backend_gc_mark_extra_sections NULL
+#endif
#ifndef elf_backend_gc_sweep_hook
#define elf_backend_gc_sweep_hook NULL
#endif
@@ -624,6 +627,7 @@ static struct elf_backend_data elfNN_bed
elf_backend_modify_program_headers,
elf_backend_gc_mark_dynamic_ref,
elf_backend_gc_mark_hook,
+ elf_backend_gc_mark_extra_sections,
elf_backend_gc_sweep_hook,
elf_backend_post_process_headers,
elf_backend_print_symbol_all,
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.19
diff -u -p -r1.19 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 29 Jan 2007 16:27:34 -0000 1.19
+++ ld/testsuite/ld-arm/arm-elf.exp 15 Feb 2007 20:04:59 -0000
@@ -156,6 +156,9 @@ set armelftests {
"-EL --vfp11-denorm-fix=scalar" "-EL" {vfp11-fix-none.s}
{{objdump -dr vfp11-fix-none.d}}
"vfp11-fix-none"}
+ {"Unwinding and -gc-sections" "-gc-sections" "" {gc-unwind.s}
+ {{objdump -sj.data gc-unwind.d}}
+ "gc-unwind"}
}
Index: ld/testsuite/ld-arm/gc-unwind.d
===================================================================
RCS file: ld/testsuite/ld-arm/gc-unwind.d
diff -N ld/testsuite/ld-arm/gc-unwind.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/gc-unwind.d 15 Feb 2007 19:59:43 -0000
@@ -0,0 +1,5 @@
+
+.*: file format.*
+
+Contents of section .data:
+ [^ ]* 22222222 .*
Index: ld/testsuite/ld-arm/gc-unwind.s
===================================================================
RCS file: ld/testsuite/ld-arm/gc-unwind.s
diff -N ld/testsuite/ld-arm/gc-unwind.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/gc-unwind.s 15 Feb 2007 19:59:43 -0000
@@ -0,0 +1,38 @@
+@ Test -gc-sections and unwinding tables. .data.eh should be pulled in
+@ via the EH tables, .data.foo should not.
+.text
+.global _start
+.fnstart
+_start:
+bx lr
+.personality my_pr
+.handlerdata
+.word 0
+.fnend
+
+.section .data.foo
+my_foo:
+.word 0x11111111
+
+.section .text.foo
+.fnstart
+foo:
+bx lr
+.personality my_pr
+.handlerdata
+.word my_foo
+.fnend
+
+.section .data.eh
+my_eh:
+.word 0x22222222
+
+.section .text.eh
+.fnstart
+my_pr:
+bx lr
+.personality my_pr
+.handlerdata
+.word my_eh
+.fnend
+