This is the mail archive of the binutils-cvs@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]

[binutils-gdb] ARM: Fix exidx coverage for relocatable builds.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=491d01d3da18fb61fa6c7c61c091b4cb8c5773f7

commit 491d01d3da18fb61fa6c7c61c091b4cb8c5773f7
Author: Yury Usishchev <y.usishchev@samsung.com>
Date:   Tue Dec 22 15:50:13 2015 +0000

    ARM: Fix exidx coverage for relocatable builds.
    
    bfd  * elf-bfd.h: Add callback to count additional relocations.
         * elf32-arm.c (_arm_elf_section_data): Add new counter.
         (insert_cantunwind_after): Increment relocations counter.
         (elf32_arm_fix_exidx_coverage): Remove exidx entries and add
         terminating CANTUNWIND entry only in final builds.
         (elf32_arm_add_relocation): New function.
         (elf32_arm_write_section): Add relocations in relocatable builds.
         (elf32_arm_count_additional_relocs): New function.
         (elf_backend_count_additional_relocs): New define.
         * bfd/elflink.c (bfd_elf_final_link): Use callback and adjust size of
         .rel section.
         * bfd/elfxx-target.h (elf_backend_count_additional_relocs): New define.
    
    ld   * emultempl/armelf.em (gld${EMULATION_NAME}_after_allocation): Call
         elf32_arm_fix_exidx_coverage for relocatable builds.
    
    ld/testsuite
         * ld-arm/arm-elf.exp: New test.
         * ld-arm/unwind-rel.d: New file.
         * ld-arm/unwind-rel1.s: New file.
         * ld-arm/unwind-rel2.s: New file.
         * ld-arm/unwind-rel3.s: New file.

Diff:
---
 bfd/ChangeLog                     | 15 ++++++++
 bfd/elf-bfd.h                     |  5 +++
 bfd/elf32-arm.c                   | 70 +++++++++++++++++++++++++++++++++++--
 bfd/elflink.c                     | 22 ++++++++++--
 bfd/elfxx-target.h                |  4 +++
 ld/ChangeLog                      |  5 +++
 ld/emultempl/armelf.em            | 73 +++++++++++++++++++--------------------
 ld/testsuite/ChangeLog            | 24 ++++++++-----
 ld/testsuite/ld-arm/arm-elf.exp   |  6 ++++
 ld/testsuite/ld-arm/unwind-rel.d  | 31 +++++++++++++++++
 ld/testsuite/ld-arm/unwind-rel1.s |  9 +++++
 ld/testsuite/ld-arm/unwind-rel2.s |  6 ++++
 ld/testsuite/ld-arm/unwind-rel3.s |  9 +++++
 13 files changed, 228 insertions(+), 51 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 49baaa1..e5bedae 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,18 @@
+2015-12-22 Yury Usishchev <y.usishchev@samsung.com>
+
+	* elf-bfd.h: Add callback to count additional relocations.
+	* elf32-arm.c (_arm_elf_section_data): Add new counter.
+	(insert_cantunwind_after): Increment relocations counter.
+	(elf32_arm_fix_exidx_coverage): Remove exidx entries and add
+	terminating CANTUNWIND entry only in final builds.
+	(elf32_arm_add_relocation): New function.
+	(elf32_arm_write_section): Add relocations in relocatable builds.
+	(elf32_arm_count_additional_relocs): New function.
+	(elf_backend_count_additional_relocs): New define.
+	* elflink.c (bfd_elf_final_link): Use callback and adjust size of
+	.rel section.
+	* elfxx-target.h (elf_backend_count_additional_relocs): New define.
+
 2015-12-22  Yoshinori Sato <ysato@users.sourceforge.jp>
 
 	* archures.c: Add bfd_mach_rx_v2.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 70e3327..129aa64 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1170,6 +1170,11 @@ struct elf_backend_data
   unsigned int (*elf_backend_count_relocs)
     (struct bfd_link_info *, asection *);
 
+  /* Count additionals relocations.  Called for relocatable links if
+     additional relocations needs to be created.  */
+  unsigned int (*elf_backend_count_additional_relocs)
+    (asection *);
+
   /* Say whether to sort relocs output by ld -r and ld --emit-relocs,
      by r_offset.  If NULL, default to true.  */
   bfd_boolean (*sort_relocs_p)
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 5d31ef2..583db4d 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2802,6 +2802,7 @@ typedef struct _arm_elf_section_data
   elf32_vfp11_erratum_list *erratumlist;
   unsigned int stm32l4xx_erratumcount;
   elf32_stm32l4xx_erratum_list *stm32l4xx_erratumlist;
+  unsigned int additional_reloc_count;
   /* Information about unwind tables.  */
   union
   {
@@ -11619,6 +11620,8 @@ insert_cantunwind_after(asection *text_sec, asection *exidx_sec)
     &exidx_arm_data->u.exidx.unwind_edit_tail,
     INSERT_EXIDX_CANTUNWIND_AT_END, text_sec, UINT_MAX);
 
+  exidx_arm_data->additional_reloc_count++;
+
   adjust_exidx_size(exidx_sec, 8);
 }
 
@@ -11761,7 +11764,7 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
 	  else
 	    unwind_type = 2;
 
-	  if (elide)
+	  if (elide && !bfd_link_relocatable (info))
 	    {
 	      add_unwind_table_edit (&unwind_edit_head, &unwind_edit_tail,
 				     DELETE_EXIDX_ENTRY, NULL, j / 8);
@@ -11788,7 +11791,8 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
     }
 
   /* Add terminating CANTUNWIND entry.  */
-  if (last_exidx_sec && last_unwind_type != 0)
+  if (!bfd_link_relocatable (info) && last_exidx_sec
+      && last_unwind_type != 0)
     insert_cantunwind_after(last_text_sec, last_exidx_sec);
 
   return TRUE;
@@ -16984,6 +16988,39 @@ stm32l4xx_create_replacing_stub (struct elf32_arm_link_hash_table * htab,
 /* End of stm32l4xx work-around.  */
 
 
+static void
+elf32_arm_add_relocation (bfd *output_bfd, struct bfd_link_info *info,
+			  asection *output_sec, Elf_Internal_Rela *rel)
+{
+  BFD_ASSERT (output_sec && rel);
+  struct bfd_elf_section_reloc_data *output_reldata;
+  struct elf32_arm_link_hash_table *htab;
+  struct bfd_elf_section_data *oesd = elf_section_data (output_sec);
+  Elf_Internal_Shdr *rel_hdr;
+
+
+  if (oesd->rel.hdr)
+    {
+      rel_hdr = oesd->rel.hdr;
+      output_reldata = &(oesd->rel);
+    }
+  else if (oesd->rela.hdr)
+    {
+      rel_hdr = oesd->rela.hdr;
+      output_reldata = &(oesd->rela);
+    }
+  else
+    {
+      abort ();
+    }
+
+  bfd_byte *erel = rel_hdr->contents;
+  erel += output_reldata->count * rel_hdr->sh_entsize;
+  htab = elf32_arm_hash_table (info);
+  SWAP_RELOC_OUT (htab) (output_bfd, rel, erel);
+  output_reldata->count++;
+}
+
 /* Do code byteswapping.  Return FALSE afterwards so that the section is
    written out as normal.  */
 
@@ -17228,6 +17265,26 @@ elf32_arm_write_section (bfd *output_bfd,
 			   usual BFD method.  */
 			prel31_offset = (text_offset - exidx_offset)
 					& 0x7ffffffful;
+			if (bfd_link_relocatable (link_info))
+			  {
+			    /* Here relocation for new EXIDX_CANTUNWIND is
+			       created, so there is no need to
+			       adjust offset by hand.  */
+			    prel31_offset = text_sec->output_offset
+					    + text_sec->size;
+
+			    /* New relocation entity.  */
+			    asection *text_out = text_sec->output_section;
+			    Elf_Internal_Rela rel;
+			    rel.r_addend = 0;
+			    rel.r_offset = exidx_offset;
+			    rel.r_info = ELF32_R_INFO (text_out->target_index,
+						       R_ARM_PREL31);
+
+			    elf32_arm_add_relocation (output_bfd, link_info,
+						      sec->output_section,
+						      &rel);
+			  }
 
 			/* First address we can't unwind.  */
 			bfd_put_32 (output_bfd, prel31_offset,
@@ -17742,6 +17799,14 @@ elf32_arm_lookup_section_flags (char *flag_name)
   return SEC_NO_FLAGS;
 }
 
+static unsigned int
+elf32_arm_count_additional_relocs (asection *sec)
+{
+  struct _arm_elf_section_data *arm_data;
+  arm_data = get_arm_elf_section_data (sec);
+  return arm_data->additional_reloc_count;
+}
+
 #define ELF_ARCH			bfd_arch_arm
 #define ELF_TARGET_ID			ARM_ELF_DATA
 #define ELF_MACHINE_CODE		EM_ARM
@@ -17796,6 +17861,7 @@ elf32_arm_lookup_section_flags (char *flag_name)
 #define elf_backend_output_arch_local_syms      elf32_arm_output_arch_local_syms
 #define elf_backend_begin_write_processing      elf32_arm_begin_write_processing
 #define elf_backend_add_symbol_hook		elf32_arm_add_symbol_hook
+#define elf_backend_count_additional_relocs	elf32_arm_count_additional_relocs
 
 #define elf_backend_can_refcount       1
 #define elf_backend_can_gc_sections    1
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1b41c79..2eeada2 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10988,6 +10988,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       for (p = o->map_head.link_order; p != NULL; p = p->next)
 	{
 	  unsigned int reloc_count = 0;
+	  unsigned int additional_reloc_count = 0;
 	  struct bfd_elf_section_data *esdi = NULL;
 
 	  if (p->type == bfd_section_reloc_link_order
@@ -11016,7 +11017,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 		   reloc sections themselves can't have relocations.  */
 		reloc_count = 0;
 	      else if (emit_relocs)
-		reloc_count = sec->reloc_count;
+		{
+		  reloc_count = sec->reloc_count;
+		  if (bed->elf_backend_count_additional_relocs)
+		    {
+		      int c;
+		      c = (*bed->elf_backend_count_additional_relocs) (sec);
+		      additional_reloc_count += c;
+		    }
+		}
 	      else if (bed->elf_backend_count_relocs)
 		reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
 
@@ -11065,14 +11074,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	  if (reloc_count == 0)
 	    continue;
 
+	  reloc_count += additional_reloc_count;
 	  o->reloc_count += reloc_count;
 
 	  if (p->type == bfd_indirect_link_order && emit_relocs)
 	    {
 	      if (esdi->rel.hdr)
-		esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr);
+		{
+		  esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr);
+		  esdo->rel.count += additional_reloc_count;
+		}
 	      if (esdi->rela.hdr)
-		esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr);
+		{
+		  esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr);
+		  esdo->rela.count += additional_reloc_count;
+		}
 	    }
 	  else
 	    {
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 0acecaf..c5bd7de 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -538,6 +538,9 @@
 #ifndef elf_backend_count_relocs
 #define elf_backend_count_relocs		NULL
 #endif
+#ifndef elf_backend_count_additional_relocs
+#define elf_backend_count_additional_relocs	NULL
+#endif
 #ifndef elf_backend_sort_relocs_p
 #define elf_backend_sort_relocs_p		NULL
 #endif
@@ -755,6 +758,7 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_ignore_undef_symbol,
   elf_backend_emit_relocs,
   elf_backend_count_relocs,
+  elf_backend_count_additional_relocs,
   elf_backend_sort_relocs_p,
   elf_backend_grok_prstatus,
   elf_backend_grok_psinfo,
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 576e3dc..a7014d5 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-22 Yury Usishchev <y.usishchev@samsung.com>
+
+	* emultempl/armelf.em (gld${EMULATION_NAME}_after_allocation): Call
+	elf32_arm_fix_exidx_coverage for relocatable builds.
+
 2015-12-10  Kwok Cheung Yeung  <kcy@codesourcery.com>
 
 	PR ld/18199
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 2931a49..aae45d1 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -293,55 +293,52 @@ gld${EMULATION_NAME}_after_allocation (void)
 {
   int ret;
 
-  if (!bfd_link_relocatable (&link_info))
+  /* Build a sorted list of input text sections, then use that to process
+     the unwind table index.  */
+  unsigned int list_size = 10;
+  asection **sec_list = (asection **)
+      xmalloc (list_size * sizeof (asection *));
+  unsigned int sec_count = 0;
+
+  LANG_FOR_EACH_INPUT_STATEMENT (is)
     {
-      /* Build a sorted list of input text sections, then use that to process
-	 the unwind table index.  */
-      unsigned int list_size = 10;
-      asection **sec_list = (asection **)
-          xmalloc (list_size * sizeof (asection *));
-      unsigned int sec_count = 0;
+      bfd *abfd = is->the_bfd;
+      asection *sec;
 
-      LANG_FOR_EACH_INPUT_STATEMENT (is)
-	{
-	  bfd *abfd = is->the_bfd;
-	  asection *sec;
+      if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+	continue;
 
-	  if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
-	    continue;
-
-	  for (sec = abfd->sections; sec != NULL; sec = sec->next)
+      for (sec = abfd->sections; sec != NULL; sec = sec->next)
+	{
+	  asection *out_sec = sec->output_section;
+
+	  if (out_sec
+	      && elf_section_data (sec)
+	      && elf_section_type (sec) == SHT_PROGBITS
+	      && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
+	      && (sec->flags & SEC_EXCLUDE) == 0
+	      && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
+	      && out_sec != bfd_abs_section_ptr)
 	    {
-	      asection *out_sec = sec->output_section;
-
-	      if (out_sec
-		  && elf_section_data (sec)
-		  && elf_section_type (sec) == SHT_PROGBITS
-		  && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
-		  && (sec->flags & SEC_EXCLUDE) == 0
-		  && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
-		  && out_sec != bfd_abs_section_ptr)
+	      if (sec_count == list_size)
 		{
-		  if (sec_count == list_size)
-		    {
-		      list_size *= 2;
-		      sec_list = (asection **)
-                          xrealloc (sec_list, list_size * sizeof (asection *));
-		    }
-
-		  sec_list[sec_count++] = sec;
+		  list_size *= 2;
+		  sec_list = (asection **)
+		      xrealloc (sec_list, list_size * sizeof (asection *));
 		}
+
+	      sec_list[sec_count++] = sec;
 	    }
 	}
+    }
 
-      qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
+  qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
 
-      if (elf32_arm_fix_exidx_coverage (sec_list, sec_count, &link_info,
-					   merge_exidx_entries))
-	need_laying_out = 1;
+  if (elf32_arm_fix_exidx_coverage (sec_list, sec_count, &link_info,
+				    merge_exidx_entries))
+    need_laying_out = 1;
 
-      free (sec_list);
-    }
+  free (sec_list);
 
   /* bfd_elf32_discard_info just plays with debugging sections,
      ie. doesn't affect any code, so we can delay resizing the
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index d5982b9..d8b2d3c 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,14 +1,22 @@
+2015-12-21 Yury Usishchev <y.usishchev@samsung.com>
+
+	* ld-arm/arm-elf.exp: New test.
+	* ld-arm/unwind-rel.d: New file.
+	* ld-arm/unwind-rel1.s: New file.
+	* ld-arm/unwind-rel2.s: New file.
+	* ld-arm/unwind-rel3.s: New file.
+
 2015-12-22 Mickael Guene <mickael.guene@st.com>
 
 	* ld-arm/arm-elf.exp: New tests.
-	* ld-arm/thumb1-input-section-flag-match.d: New
-	* ld-arm/thumb1-input-section-flag-match.s: New
-	* ld-arm/thumb1-noread-not-present-mixing-two-section.d: New
-	* ld-arm/thumb1-noread-not-present-mixing-two-section.s: New
-	* ld-arm/thumb1-noread-present-one-section.d: New
-	* ld-arm/thumb1-noread-present-one-section.s: New
-	* ld-arm/thumb1-noread-present-two-section.d: New
-	* ld-arm/thumb1-noread-present-two-section.s: New
+	* ld-arm/thumb1-input-section-flag-match.d: New.
+	* ld-arm/thumb1-input-section-flag-match.s: New.
+	* ld-arm/thumb1-noread-not-present-mixing-two-section.d: New.
+	* ld-arm/thumb1-noread-not-present-mixing-two-section.s: New.
+	* ld-arm/thumb1-noread-present-one-section.d: New.
+	* ld-arm/thumb1-noread-present-one-section.s: New.
+	* ld-arm/thumb1-noread-present-two-section.d: New.
+	* ld-arm/thumb1-noread-present-two-section.s: New.
 
 2015-12-16  Mickael Guene <mickael.guene@st.com>
 
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index a970dba..ac2abf1 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -941,3 +941,9 @@ run_dump_test "gc-hidden-1"
 run_dump_test "protected-data"
 run_dump_test "stm32l4xx-cannot-fix-it-block"
 run_dump_test "stm32l4xx-cannot-fix-far-ldm"
+set arm_unwind_tests {
+    {"unwind-rel" "-r -Tarm.ld" "" "" {unwind-rel1.s unwind-rel2.s unwind-rel3.s}
+     {{readelf -ur unwind-rel.d}}
+     "unwind-rel"}
+}
+run_ld_link_tests $arm_unwind_tests
diff --git a/ld/testsuite/ld-arm/unwind-rel.d b/ld/testsuite/ld-arm/unwind-rel.d
new file mode 100644
index 0000000..b2aa6e2
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-rel.d
@@ -0,0 +1,31 @@
+
+Relocation section '\.rel\.text' at offset .* contains 3 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+00000000  00000028 R_ARM_V4BX       
+00000004  00000028 R_ARM_V4BX       
+00000008  00000028 R_ARM_V4BX       
+
+Relocation section '\.rel\.ARM\.exidx' at offset .* contains 5 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+00000000  0000012a R_ARM_PREL31      00000000   \.text
+00000000  00000e00 R_ARM_NONE        00000000   __aeabi_unwind_cpp_pr0
+00000008  0000012a R_ARM_PREL31      00000000   \.text
+00000010  0000012a R_ARM_PREL31      00000000   \.text
+00000010  00000e00 R_ARM_NONE        00000000   __aeabi_unwind_cpp_pr0
+
+Unwind table index '\.ARM\.exidx' at offset .* contains 3 entries:
+
+0x0: 0x80a8b0b0
+  Compact model index: 0
+  0xa8      pop {r4, r14}
+  0xb0      finish
+  0xb0      finish
+
+0x4 <test>: 0x1 \[cantunwind\]
+
+0x8 <end>: 0x80a8b0b0
+  Compact model index: 0
+  0xa8      pop {r4, r14}
+  0xb0      finish
+  0xb0      finish
+
diff --git a/ld/testsuite/ld-arm/unwind-rel1.s b/ld/testsuite/ld-arm/unwind-rel1.s
new file mode 100644
index 0000000..9efb78b
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-rel1.s
@@ -0,0 +1,9 @@
+	.syntax unified
+	.text
+	.global _start
+	.type _start, %function
+_start:
+	.fnstart
+	.save {r4, lr}
+	bx lr
+	.fnend
diff --git a/ld/testsuite/ld-arm/unwind-rel2.s b/ld/testsuite/ld-arm/unwind-rel2.s
new file mode 100644
index 0000000..1001743
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-rel2.s
@@ -0,0 +1,6 @@
+	.syntax unified
+	.text
+	.global test
+	.type test, %function
+test:
+	bx lr
diff --git a/ld/testsuite/ld-arm/unwind-rel3.s b/ld/testsuite/ld-arm/unwind-rel3.s
new file mode 100644
index 0000000..8511339
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-rel3.s
@@ -0,0 +1,9 @@
+	.syntax unified
+	.text
+	.global end
+	.type end, %function
+end:
+	.fnstart
+	.save {r4, lr}
+	bx lr
+	.fnend


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