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.
This commit is contained in:
Yury Usishchev
2015-12-22 15:50:13 +00:00
committed by Nick Clifton
parent 4abd5ed222
commit 491d01d3da
13 changed files with 229 additions and 52 deletions

View File

@ -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> 2015-12-22 Yoshinori Sato <ysato@users.sourceforge.jp>
* archures.c: Add bfd_mach_rx_v2. * archures.c: Add bfd_mach_rx_v2.

View File

@ -1170,6 +1170,11 @@ struct elf_backend_data
unsigned int (*elf_backend_count_relocs) unsigned int (*elf_backend_count_relocs)
(struct bfd_link_info *, asection *); (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, /* Say whether to sort relocs output by ld -r and ld --emit-relocs,
by r_offset. If NULL, default to true. */ by r_offset. If NULL, default to true. */
bfd_boolean (*sort_relocs_p) bfd_boolean (*sort_relocs_p)

View File

@ -2802,6 +2802,7 @@ typedef struct _arm_elf_section_data
elf32_vfp11_erratum_list *erratumlist; elf32_vfp11_erratum_list *erratumlist;
unsigned int stm32l4xx_erratumcount; unsigned int stm32l4xx_erratumcount;
elf32_stm32l4xx_erratum_list *stm32l4xx_erratumlist; elf32_stm32l4xx_erratum_list *stm32l4xx_erratumlist;
unsigned int additional_reloc_count;
/* Information about unwind tables. */ /* Information about unwind tables. */
union union
{ {
@ -11619,6 +11620,8 @@ insert_cantunwind_after(asection *text_sec, asection *exidx_sec)
&exidx_arm_data->u.exidx.unwind_edit_tail, &exidx_arm_data->u.exidx.unwind_edit_tail,
INSERT_EXIDX_CANTUNWIND_AT_END, text_sec, UINT_MAX); INSERT_EXIDX_CANTUNWIND_AT_END, text_sec, UINT_MAX);
exidx_arm_data->additional_reloc_count++;
adjust_exidx_size(exidx_sec, 8); adjust_exidx_size(exidx_sec, 8);
} }
@ -11761,7 +11764,7 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
else else
unwind_type = 2; unwind_type = 2;
if (elide) if (elide && !bfd_link_relocatable (info))
{ {
add_unwind_table_edit (&unwind_edit_head, &unwind_edit_tail, add_unwind_table_edit (&unwind_edit_head, &unwind_edit_tail,
DELETE_EXIDX_ENTRY, NULL, j / 8); DELETE_EXIDX_ENTRY, NULL, j / 8);
@ -11788,7 +11791,8 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
} }
/* Add terminating CANTUNWIND entry. */ /* 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); insert_cantunwind_after(last_text_sec, last_exidx_sec);
return TRUE; return TRUE;
@ -16984,6 +16988,39 @@ stm32l4xx_create_replacing_stub (struct elf32_arm_link_hash_table * htab,
/* End of stm32l4xx work-around. */ /* 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 /* Do code byteswapping. Return FALSE afterwards so that the section is
written out as normal. */ written out as normal. */
@ -17228,6 +17265,26 @@ elf32_arm_write_section (bfd *output_bfd,
usual BFD method. */ usual BFD method. */
prel31_offset = (text_offset - exidx_offset) prel31_offset = (text_offset - exidx_offset)
& 0x7ffffffful; & 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. */ /* First address we can't unwind. */
bfd_put_32 (output_bfd, prel31_offset, bfd_put_32 (output_bfd, prel31_offset,
@ -17742,6 +17799,14 @@ elf32_arm_lookup_section_flags (char *flag_name)
return SEC_NO_FLAGS; 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_ARCH bfd_arch_arm
#define ELF_TARGET_ID ARM_ELF_DATA #define ELF_TARGET_ID ARM_ELF_DATA
#define ELF_MACHINE_CODE EM_ARM #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_output_arch_local_syms elf32_arm_output_arch_local_syms
#define elf_backend_begin_write_processing elf32_arm_begin_write_processing #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_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_refcount 1
#define elf_backend_can_gc_sections 1 #define elf_backend_can_gc_sections 1

View File

@ -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) for (p = o->map_head.link_order; p != NULL; p = p->next)
{ {
unsigned int reloc_count = 0; unsigned int reloc_count = 0;
unsigned int additional_reloc_count = 0;
struct bfd_elf_section_data *esdi = NULL; struct bfd_elf_section_data *esdi = NULL;
if (p->type == bfd_section_reloc_link_order 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 sections themselves can't have relocations. */
reloc_count = 0; reloc_count = 0;
else if (emit_relocs) 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) else if (bed->elf_backend_count_relocs)
reloc_count = (*bed->elf_backend_count_relocs) (info, sec); 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) if (reloc_count == 0)
continue; continue;
reloc_count += additional_reloc_count;
o->reloc_count += reloc_count; o->reloc_count += reloc_count;
if (p->type == bfd_indirect_link_order && emit_relocs) if (p->type == bfd_indirect_link_order && emit_relocs)
{ {
if (esdi->rel.hdr) 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) 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 else
{ {

View File

@ -538,6 +538,9 @@
#ifndef elf_backend_count_relocs #ifndef elf_backend_count_relocs
#define elf_backend_count_relocs NULL #define elf_backend_count_relocs NULL
#endif #endif
#ifndef elf_backend_count_additional_relocs
#define elf_backend_count_additional_relocs NULL
#endif
#ifndef elf_backend_sort_relocs_p #ifndef elf_backend_sort_relocs_p
#define elf_backend_sort_relocs_p NULL #define elf_backend_sort_relocs_p NULL
#endif #endif
@ -755,6 +758,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_ignore_undef_symbol, elf_backend_ignore_undef_symbol,
elf_backend_emit_relocs, elf_backend_emit_relocs,
elf_backend_count_relocs, elf_backend_count_relocs,
elf_backend_count_additional_relocs,
elf_backend_sort_relocs_p, elf_backend_sort_relocs_p,
elf_backend_grok_prstatus, elf_backend_grok_prstatus,
elf_backend_grok_psinfo, elf_backend_grok_psinfo,

View File

@ -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> 2015-12-10 Kwok Cheung Yeung <kcy@codesourcery.com>
PR ld/18199 PR ld/18199

View File

@ -293,56 +293,53 @@ gld${EMULATION_NAME}_after_allocation (void)
{ {
int ret; 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 bfd *abfd = is->the_bfd;
the unwind table index. */ asection *sec;
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) if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
continue;
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{ {
bfd *abfd = is->the_bfd; asection *out_sec = sec->output_section;
asection *sec;
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) if (out_sec
continue; && elf_section_data (sec)
&& elf_section_type (sec) == SHT_PROGBITS
for (sec = abfd->sections; sec != NULL; sec = sec->next) && (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 (sec_count == list_size)
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) list_size *= 2;
{ sec_list = (asection **)
list_size *= 2; xrealloc (sec_list, list_size * sizeof (asection *));
sec_list = (asection **)
xrealloc (sec_list, list_size * sizeof (asection *));
}
sec_list[sec_count++] = sec;
} }
sec_list[sec_count++] = sec;
} }
} }
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;
free (sec_list);
} }
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;
free (sec_list);
/* bfd_elf32_discard_info just plays with debugging sections, /* bfd_elf32_discard_info just plays with debugging sections,
ie. doesn't affect any code, so we can delay resizing the ie. doesn't affect any code, so we can delay resizing the
sections. It's likely we'll resize everything in the process of sections. It's likely we'll resize everything in the process of

View File

@ -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> 2015-12-22 Mickael Guene <mickael.guene@st.com>
* ld-arm/arm-elf.exp: New tests. * ld-arm/arm-elf.exp: New tests.
* ld-arm/thumb1-input-section-flag-match.d: New * ld-arm/thumb1-input-section-flag-match.d: New.
* ld-arm/thumb1-input-section-flag-match.s: 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.d: New.
* ld-arm/thumb1-noread-not-present-mixing-two-section.s: 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.d: New.
* ld-arm/thumb1-noread-present-one-section.s: 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.d: New.
* ld-arm/thumb1-noread-present-two-section.s: New * ld-arm/thumb1-noread-present-two-section.s: New.
2015-12-16 Mickael Guene <mickael.guene@st.com> 2015-12-16 Mickael Guene <mickael.guene@st.com>

View File

@ -941,3 +941,9 @@ run_dump_test "gc-hidden-1"
run_dump_test "protected-data" run_dump_test "protected-data"
run_dump_test "stm32l4xx-cannot-fix-it-block" run_dump_test "stm32l4xx-cannot-fix-it-block"
run_dump_test "stm32l4xx-cannot-fix-far-ldm" 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

View File

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

View File

@ -0,0 +1,9 @@
.syntax unified
.text
.global _start
.type _start, %function
_start:
.fnstart
.save {r4, lr}
bx lr
.fnend

View File

@ -0,0 +1,6 @@
.syntax unified
.text
.global test
.type test, %function
test:
bx lr

View File

@ -0,0 +1,9 @@
.syntax unified
.text
.global end
.type end, %function
end:
.fnstart
.save {r4, lr}
bx lr
.fnend