aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog15
-rw-r--r--bfd/elf-bfd.h5
-rw-r--r--bfd/elf32-arm.c70
-rw-r--r--bfd/elflink.c22
-rw-r--r--bfd/elfxx-target.h4
-rw-r--r--ld/ChangeLog5
-rw-r--r--ld/emultempl/armelf.em73
-rw-r--r--ld/testsuite/ChangeLog24
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp6
-rw-r--r--ld/testsuite/ld-arm/unwind-rel.d31
-rw-r--r--ld/testsuite/ld-arm/unwind-rel1.s9
-rw-r--r--ld/testsuite/ld-arm/unwind-rel2.s6
-rw-r--r--ld/testsuite/ld-arm/unwind-rel3.s9
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