aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2022-01-02 21:14:46 -0800
committerH.J. Lu <hjl.tools@gmail.com>2022-01-12 06:04:51 -0800
commit5af6f000d88622107e7382d337af2884fd211da2 (patch)
treefebc80d4b1e88ca1d383dfda5c4e72e7f6685e19 /bfd/elf64-x86-64.c
parentf2e37a5c7f8c8f761d2d86f2a69efe07503dc640 (diff)
downloadfsf-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.c83
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)