summaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2021-12-27 10:13:06 -0800
committerH.J. Lu <hjl.tools@gmail.com>2022-01-07 17:58:20 -0800
commit3747999c6bd40a7ac905ef306a82214b336067b6 (patch)
treeb05f73242942f28863f14a2a26929104b1d5ee86 /bfd/elf64-x86-64.c
parentce230579c65b9e04c830f35cb78ff33206e65db1 (diff)
downloadbinutils-gdb-3747999c6bd40a7ac905ef306a82214b336067b6.tar.gz
ld: Extract _bfd_elf_link_iterate_on_relocs
DT_RELR encodes consecutive R_*_RELATIVE relocations in GOT (the global offset table) and data sections in a compact format: https://groups.google.com/g/generic-abi/c/bX460iggiKg On some targets, R_*_RELATIVE relocations are counted and the GOT offsets are allocated when setting the dynamic section sizes after seeing all relocations. R_*_RELATIVE relocations are generated while relocating sections after section layout has been finalized. To prepare for DT_RELR implementation on these targets, extract _bfd_elf_link_iterate_on_relocs from _bfd_elf_link_check_relocs so that a backend can scan relocations in elf_backend_always_size_sections For x86 targets, the old check_relocs is renamed to scan_relocs and a new check_relocs is added to chek input sections and create dynamic relocation sections so that they will be mapped to output sections. scan_relocs is now called from elf_backend_always_size_sections. Since relocations are scanned after __start, __stop, .startof. and .sizeof. symbols have been finalized on x86, __[start|stop]_SECNAME for --gc-sections -z start-stop-gc are now zero when all SECNAME sections been garbage collected. This is no need for elf_x86_start_stop_gc_p. bfd/ * elf-bfd.h (_bfd_elf_link_iterate_on_relocs): New. * elf32-i386.c (elf_i386_convert_load_reloc): Don't call elf_x86_start_stop_gc_p. (elf_i386_check_relocs): Renamed to ... (elf_i386_scan_relocs): This. Don't call _bfd_elf_make_dynamic_reloc_section. (elf_i386_always_size_sections): New. (elf_backend_check_relocs): Removed. (elf_backend_always_size_sections): New. * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Don't call elf_x86_start_stop_gc_p. (elf_x86_64_check_relocs): Renamed to ... (elf_x86_64_scan_relocs): This. Don't call _bfd_elf_make_dynamic_reloc_section. (elf_x86_64_always_size_sections): New. (elf_backend_check_relocs): Removed. (elf_backend_always_size_sections): New. * elflink.c (elf_link_check_or_scan_relocs): New. Extracted from _bfd_elf_link_check_relocs. (_bfd_elf_link_check_relocs): Call elf_link_check_or_scan_relocs. * elfxx-x86.c (_bfd_x86_elf_check_relocs): New. * elfxx-x86.h (X86_64_NEED_DYNAMIC_RELOC_TYPE_P): New. (I386_NEED_DYNAMIC_RELOC_TYPE_P): Likewise. (X86_NEED_DYNAMIC_RELOC_TYPE_P): Likewise. (_bfd_x86_elf_check_relocs): Likewise. (elf_backend_check_relocs): Likewise. (elf_backend_always_size_sections): Removed. (elf_x86_start_stop_gc_p): Likewise. ld/ * testsuite/ld-i386/pr27491-1a.d: Updated. * testsuite/ld-x86-64/pr27491-1a.d: Likewise.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c55
1 files changed, 26 insertions, 29 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 22aa3ee3b68..ad885f89e11 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1309,7 +1309,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
}
/* We checked the transition before when we were called from
- elf_x86_64_check_relocs. We only want to check the new
+ elf_x86_64_scan_relocs. We only want to check the new
transition which hasn't been checked before. */
check = new_to_type != to_type && from_type == to_type;
to_type = new_to_type;
@@ -1628,11 +1628,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section == bfd_und_section_ptr))))
{
- /* Skip __start_SECNAME/__stop_SECNAME when --gc-sections
- -z start-stop-gc are used. */
- if (elf_x86_start_stop_gc_p (link_info, h))
- return true;
-
/* Skip since R_X86_64_32/R_X86_64_32S may overflow. */
if (no_overflow)
return true;
@@ -1823,20 +1818,19 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
}
/* Look through the relocs for a section during the first phase, and
- calculate needed space in the global offset table, procedure
- linkage table, and dynamic reloc sections. */
+ calculate needed space in the global offset table, and procedure
+ linkage table. */
static bool
-elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
+elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
+ asection *sec,
+ const Elf_Internal_Rela *relocs)
{
struct elf_x86_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
- asection *sreloc;
bfd_byte *contents;
bool converted;
@@ -1866,8 +1860,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
converted = false;
- sreloc = NULL;
-
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
@@ -2263,19 +2255,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
- /* We must copy these reloc types into the output file.
- Create a reloc section in dynobj and make room for
- this reloc. */
- if (sreloc == NULL)
- {
- sreloc = _bfd_elf_make_dynamic_reloc_section
- (sec, htab->elf.dynobj, ABI_64_P (abfd) ? 3 : 2,
- abfd, /*rela?*/ true);
-
- if (sreloc == NULL)
- goto error_return;
- }
-
/* If this is a global symbol, we count the number of
relocations we need for this symbol. */
if (h != NULL)
@@ -2371,6 +2350,24 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
return false;
}
+static bool
+elf_x86_64_always_size_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ bfd *abfd;
+
+ /* Scan relocations after rel_from_abs has been set on __ehdr_start. */
+ for (abfd = info->input_bfds;
+ abfd != (bfd *) NULL;
+ abfd = abfd->link.next)
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && !_bfd_elf_link_iterate_on_relocs (abfd, info,
+ elf_x86_64_scan_relocs))
+ return false;
+
+ return _bfd_x86_elf_always_size_sections (output_bfd, info);
+}
+
/* Return the relocation value for @tpoff relocation
if STT_TLS virtual address is ADDRESS. */
@@ -2413,7 +2410,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
unsigned int plt_entry_size;
bool status;
- /* Skip if check_relocs failed. */
+ /* Skip if check_relocs or scan_relocs failed. */
if (input_section->check_relocs_failed)
return false;
@@ -5238,7 +5235,7 @@ elf_x86_64_special_sections[]=
elf_x86_64_reloc_name_lookup
#define elf_backend_relocs_compatible elf_x86_64_relocs_compatible
-#define elf_backend_check_relocs elf_x86_64_check_relocs
+#define elf_backend_always_size_sections elf_x86_64_always_size_sections
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
#define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_x86_64_finish_dynamic_symbol