diff options
author | Yury Usishchev <y.usishchev@samsung.com> | 2015-12-22 15:50:13 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-12-22 15:50:13 +0000 |
commit | 491d01d3da18fb61fa6c7c61c091b4cb8c5773f7 (patch) | |
tree | 4f325fdc33925c18aa4db39125a2f91ef8d39e7c /bfd/elf32-arm.c | |
parent | 4abd5ed2221c826bcb843794286777452de5c50b (diff) | |
download | gdb-491d01d3da18fb61fa6c7c61c091b4cb8c5773f7.zip gdb-491d01d3da18fb61fa6c7c61c091b4cb8c5773f7.tar.gz gdb-491d01d3da18fb61fa6c7c61c091b4cb8c5773f7.tar.bz2 |
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.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r-- | bfd/elf32-arm.c | 70 |
1 files changed, 68 insertions, 2 deletions
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 |