aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-i386.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/elf32-i386.c
parentf2e37a5c7f8c8f761d2d86f2a69efe07503dc640 (diff)
downloadgdb-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.c68
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)