This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

-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
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]