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/elf64-x86-64.c | |
parent | f2e37a5c7f8c8f761d2d86f2a69efe07503dc640 (diff) | |
download | fsf-binutils-gdb-5af6f000d88622107e7382d337af2884fd211da2.zip fsf-binutils-gdb-5af6f000d88622107e7382d337af2884fd211da2.tar.gz fsf-binutils-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/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 83 |
1 files changed, 55 insertions, 28 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index ad885f8..02ca552 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2867,7 +2867,10 @@ elf_x86_64_relocate_section (bfd *output_bfd, as -1 | 1 still is -1. */ 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)) { /* If this symbol isn't dynamic in PIC, generate R_X86_64_RELATIVE here. */ @@ -2899,8 +2902,11 @@ elf_x86_64_relocate_section (bfd *output_bfd, /* NB: GOTPCREL relocations against local absolute symbol store relocation value in the GOT slot - without relative relocation. */ - if (bfd_link_pic (info) + without relative relocation. Don't generate + relative relocation here if it has been generated + by DT_RELR. */ + if (!info->enable_dt_relr + && bfd_link_pic (info) && !(sym->st_shndx == SHN_ABS && (r_type == R_X86_64_GOTPCREL || r_type == R_X86_64_GOTPCRELX @@ -3215,6 +3221,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, { Elf_Internal_Rela outrel; bool skip, relocate; + bool generate_dynamic_reloc = true; asection *sreloc; const char *relative_reloc_name = NULL; @@ -3253,9 +3260,17 @@ elf_x86_64_relocate_section (bfd *output_bfd, && htab->params->no_reloc_overflow_check)) { relocate = true; - outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); - outrel.r_addend = relocation + rel->r_addend; - relative_reloc_name = "R_X86_64_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 = + htab->r_info (0, R_X86_64_RELATIVE); + outrel.r_addend = relocation + rel->r_addend; + relative_reloc_name = "R_X86_64_RELATIVE"; + } } else if (r_type == R_X86_64_64 && !ABI_64_P (output_bfd)) @@ -3323,21 +3338,24 @@ elf_x86_64_relocate_section (bfd *output_bfd, } } - 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; - if (relative_reloc_name - && htab->params->report_relative_reloc) - _bfd_x86_elf_link_report_relative_reloc - (info, input_section, h, sym, relative_reloc_name, - &outrel); + if (sreloc == NULL || sreloc->contents == NULL) + { + r = bfd_reloc_notsupported; + goto check_relocation_error; + } - elf_append_rela (output_bfd, sreloc, &outrel); + if (relative_reloc_name + && htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, + relative_reloc_name, &outrel); + + elf_append_rela (output_bfd, sreloc, &outrel); + } /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we @@ -4424,6 +4442,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Rela rela; 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. */ @@ -4506,11 +4525,16 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, if (!SYMBOL_DEFINED_NON_SHARED_P (h)) return false; BFD_ASSERT((h->got.offset & 1) != 0); - rela.r_info = htab->r_info (0, R_X86_64_RELATIVE); - rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - relative_reloc_name = "R_X86_64_RELATIVE"; + if (info->enable_dt_relr) + generate_dynamic_reloc = false; + else + { + rela.r_info = htab->r_info (0, R_X86_64_RELATIVE); + rela.r_addend = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + relative_reloc_name = "R_X86_64_RELATIVE"; + } } else { @@ -4522,12 +4546,15 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, rela.r_addend = 0; } - if (relative_reloc_name != NULL - && htab->params->report_relative_reloc) - _bfd_x86_elf_link_report_relative_reloc - (info, relgot, h, sym, relative_reloc_name, &rela); + 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, &rela); - elf_append_rela (output_bfd, relgot, &rela); + elf_append_rela (output_bfd, relgot, &rela); + } } if (h->needs_copy) |