diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2022-01-02 21:14:46 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2022-01-12 06:04:51 -0800 |
commit | 5af6f000d88622107e7382d337af2884fd211da2 (patch) | |
tree | febc80d4b1e88ca1d383dfda5c4e72e7f6685e19 /bfd/elf32-i386.c | |
parent | f2e37a5c7f8c8f761d2d86f2a69efe07503dc640 (diff) | |
download | gdb-5af6f000d88622107e7382d337af2884fd211da2.zip gdb-5af6f000d88622107e7382d337af2884fd211da2.tar.gz gdb-5af6f000d88622107e7382d337af2884fd211da2.tar.bz2 |
x86: Add DT_RELR support
DT_RELR is implemented with linker relaxation:
1. During linker relaxation, we scan input relocations with the same
logic in relocate_section to determine if a relative relocation should
be generated and save the relative relocation candidate information for
sizing the DT_RELR section later after all symbols addresses can be
determined. For these relative relocations which can't be placed in
the DT_RELR section, they will be placed in the rela.dyn/rel.dyn
section.
2. When DT_RELR is enabled, _bfd_elf_map_sections_to_segments calls a
backend function to size the DT_RELR section which will compute the
DT_RELR section size and tell ldelf_map_segments to layout sections
again when the DT_RELR section size has been increased.
3. After regular symbol processing is finished, bfd_elf_final_link calls
a backend function to finish the DT_RELR section.
* elf32-i386.c (elf_i386_relocate_section): Don't generate
relative relocation when DT_RELR is enabled.
(elf_i386_finish_dynamic_symbol): Likewise.
* elf64-x86-64.c (elf_x86_64_relocate_section): Don't generate
relative relocation when DT_RELR is enabled.
(elf_x86_64_finish_dynamic_symbol): Likewise.
* elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Initialize
relative_r_type, relative_r_name, elf_append_reloc,
elf_write_addend and elf_write_addend_in_got.
(elf_x86_relative_reloc_record_add): New function.
(_bfd_x86_elf_link_relax_section): Likewise.
(elf64_dt_relr_bitmap_add): Likewise.
(elf32_dt_relr_bitmap_add): Likewise.
(_bfd_elf32_write_addend): Likewise.
(_bfd_elf64_write_addend): Likewise.
(elf_x86_size_or_finish_relative_reloc): Likewise.
(elf_x86_compute_dl_relr_bitmap): Likewise.
(elf_x86_write_dl_relr_bitmap): Likewise.
(elf_x86_relative_reloc_compare ): Likewise.
(_bfd_elf_x86_size_relative_relocs): Likewise.
(_bfd_elf_x86_finish_relative_relocs): Likewise.
(_bfd_x86_elf_size_dynamic_sections): Skip the .relr.dyn section.
(_bfd_x86_elf_finish_dynamic_sections): Convert 3 spare dynamic
tags to DT_RELR, DT_RELRSZ and for compact relative relocation.
* elfxx-x86.h (X86_64_GOT_TYPE_P): New.
(I386_GOT_TYPE_P): Likewise.
(X86_GOT_TYPE_P): Likewise.
(X86_64_RELATIVE_RELOC_TYPE_P): Likewise.
(I386_RELATIVE_RELOC_TYPE_P): Likewise.
(X86_RELATIVE_RELOC_TYPE_P): Likewise.
(X86_LOCAL_GOT_RELATIVE_RELOC_P): Likewise.
(I386_PCREL_TYPE_P): Likewise.
(X86_64_PCREL_TYPE_P): Likewise.
(X86_64_NEED_DYNAMIC_RELOC_TYPE_P): Rewrite.
(I386_NEED_DYNAMIC_RELOC_TYPE_P): Likewise.
(GENERATE_DYNAMIC_RELOCATION_P): Also check rel_from_abs.
(elf_x86_link_hash_entry): Add got_relative_reloc_done.
(elf_x86_relative_reloc_record): New.
(elf_x86_relative_reloc_data): Likewise.
(elf_dt_relr_bitmap): Likewise.
(elf_x86_link_hash_table): Add dt_relr_bitmap, relative_reloc,
unaligned_relative_reloc, relative_r_type, relative_r_name,
elf_append_reloc, elf_write_addend, elf_write_addend_in_got and
relative_reloc_done.
(elf_x86_relative_reloc_done): New.
(relative_reloc_packed): Likewise.
(_bfd_x86_elf_link_relax_section): Likewise.
(_bfd_elf_x86_size_relative_relocs): Likewise.
(_bfd_elf_x86_finish_relative_relocs): Likewise.
(_bfd_elf32_write_addend): Likewise.
(_bfd_elf64_write_addend): Likewise.
(bfd_elf32_bfd_relax_section): Likewise.
(bfd_elf64_bfd_relax_section): Likewise.
(elf_backend_size_relative_relocs): Likewise.
(elf_backend_finish_relative_relocs): Likewise.
(elf_x86_allocate_local_got_info): Also allocate
relative_reloc_done.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index d1f61be..25977cc 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -2473,8 +2473,10 @@ elf_i386_relocate_section (bfd *output_bfd, bfd_put_32 (output_bfd, relocation, htab->elf.sgot->contents + off); h->got.offset |= 1; - - if (GENERATE_RELATIVE_RELOC_P (info, h)) + /* NB: Don't generate relative relocation here if + it has been generated by DT_RELR. */ + if (!info->enable_dt_relr + && GENERATE_RELATIVE_RELOC_P (info, h)) { /* PR ld/21402: If this symbol isn't dynamic in PIC, generate R_386_RELATIVE here. */ @@ -2504,7 +2506,9 @@ elf_i386_relocate_section (bfd *output_bfd, htab->elf.sgot->contents + off); local_got_offsets[r_symndx] |= 1; - if (bfd_link_pic (info)) + /* NB: Don't generate relative relocation here if it + has been generated by DT_RELR. */ + if (!info->enable_dt_relr && bfd_link_pic (info)) relative_reloc = true; } } @@ -2707,6 +2711,7 @@ elf_i386_relocate_section (bfd *output_bfd, { Elf_Internal_Rela outrel; bool skip, relocate; + bool generate_dynamic_reloc = true; asection *sreloc; /* When generating a shared object, these relocations @@ -2734,23 +2739,33 @@ elf_i386_relocate_section (bfd *output_bfd, { /* This symbol is local, or marked to become local. */ relocate = true; - outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + /* NB: Don't generate relative relocation here if it + has been generated by DT_RELR. */ + if (info->enable_dt_relr) + generate_dynamic_reloc = false; + else + { + outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); - if (htab->params->report_relative_reloc) - _bfd_x86_elf_link_report_relative_reloc - (info, input_section, h, sym, "R_386_RELATIVE", - &outrel); + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, "R_386_RELATIVE", + &outrel); + } } - sreloc = elf_section_data (input_section)->sreloc; - - if (sreloc == NULL || sreloc->contents == NULL) + if (generate_dynamic_reloc) { - r = bfd_reloc_notsupported; - goto check_relocation_error; - } + sreloc = elf_section_data (input_section)->sreloc; - elf_append_rel (output_bfd, sreloc, &outrel); + if (sreloc == NULL || sreloc->contents == NULL) + { + r = bfd_reloc_notsupported; + goto check_relocation_error; + } + + elf_append_rel (output_bfd, sreloc, &outrel); + } /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we @@ -3776,6 +3791,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Rela rel; asection *relgot = htab->elf.srelgot; const char *relative_reloc_name = NULL; + bool generate_dynamic_reloc = true; /* This symbol has an entry in the global offset table. Set it up. */ @@ -3858,8 +3874,13 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, && SYMBOL_REFERENCES_LOCAL_P (info, h)) { BFD_ASSERT((h->got.offset & 1) != 0); - rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); - relative_reloc_name = "R_386_RELATIVE"; + if (info->enable_dt_relr) + generate_dynamic_reloc = false; + else + { + rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + relative_reloc_name = "R_386_RELATIVE"; + } } else { @@ -3870,12 +3891,15 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); } - if (relative_reloc_name != NULL - && htab->params->report_relative_reloc) - _bfd_x86_elf_link_report_relative_reloc - (info, relgot, h, sym, relative_reloc_name, &rel); + if (generate_dynamic_reloc) + { + if (relative_reloc_name != NULL + && htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, relgot, h, sym, relative_reloc_name, &rel); - elf_append_rel (output_bfd, relgot, &rel); + elf_append_rel (output_bfd, relgot, &rel); + } } if (h->needs_copy) |