aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2022-11-01 11:36:04 -0700
committerH.J. Lu <hjl.tools@gmail.com>2023-09-29 07:58:53 -0700
commit832ca732b8a96ff9a3e7c4abf24098bf2a59a96d (patch)
tree5ee140bdc26d1d37696b865c80becee32ecde8c6 /bfd
parenta78c3c9717e8fa98b11482f948e71c6d1d9d0e44 (diff)
downloadbinutils-832ca732b8a96ff9a3e7c4abf24098bf2a59a96d.zip
binutils-832ca732b8a96ff9a3e7c4abf24098bf2a59a96d.tar.gz
binutils-832ca732b8a96ff9a3e7c4abf24098bf2a59a96d.tar.bz2
x86-64: Add -z mark-plt and -z nomark-plt
The PLT entry in executables and shared libraries contains an indirect branch, like jmp *foo@GOTPCREL(%rip) push $index_foo jmp .PLT0 or endbr64 jmp *foo@GOTPCREL(%rip) NOP padding which is used to branch to the function, foo, defined in another object. Each R_X86_64_JUMP_SLOT relocation has a corresponding PLT entry. The dynamic tags have been added to the x86-64 psABI to mark such PLT entries: https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/6d824a52a42d173eb838b879616c1be5870b593e Add an x86-64 linker option, -z mark-plt, to mark PLT entries with #define DT_X86_64_PLT (DT_LOPROC + 0) #define DT_X86_64_PLTSZ (DT_LOPROC + 1) #define DT_X86_64_PLTENT (DT_LOPROC + 3) 1. DT_X86_64_PLT: The address of the procedure linkage table. 2. DT_X86_64_PLTSZ: The total size, in bytes, of the procedure linkage table. 3. DT_X86_64_PLTENT: The size, in bytes, of a procedure linkage table entry. and set the r_addend field of the R_X86_64_JUMP_SLOT relocation to the memory offset of the indirect branch instruction. The dynamic linker can use these tags to update the PLT section to direct branch. bfd/ * elf-linker-x86.h (elf_linker_x86_params): Add mark_plt. * elf64-x86-64.c (elf_x86_64_finish_dynamic_symbol): Set the r_addend of R_X86_64_JUMP_SLOT to the indirect branch offset in PLT entry for -z mark-plt. * elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Add DT_X86_64_PLT, DT_X86_64_PLTSZ and DT_X86_64_PLTENT for -z mark-plt. (_bfd_x86_elf_finish_dynamic_sections): Set DT_X86_64_PLT, DT_X86_64_PLTSZ and DT_X86_64_PLTENT. (_bfd_x86_elf_get_synthetic_symtab): Ignore addend for JUMP_SLOT relocation. (_bfd_x86_elf_link_setup_gnu_properties): Set plt_indirect_branch_offset. * elfxx-x86.h (elf_x86_plt_layout): Add plt_indirect_branch_offset. binutils/ * readelf.c (get_x86_64_dynamic_type): New function. (get_dynamic_type): Call get_x86_64_dynamic_type. include/ * elf/x86-64.h (DT_X86_64_PLT): New. (DT_X86_64_PLTSZ): Likewise. (DT_X86_64_PLTENT): Likewise. ld/ * ld.texi: Document -z mark-plt and -z nomark-plt. * emulparams/elf32_x86_64.sh: Source x86-64-plt.sh. * emulparams/elf_x86_64.sh: Likewise. * emulparams/x86-64-plt.sh: New file. * testsuite/ld-x86-64/mark-plt-1.s: Likewise. * testsuite/ld-x86-64/mark-plt-1a-x32.d: Likewise. * testsuite/ld-x86-64/mark-plt-1a.d: Likewise. * testsuite/ld-x86-64/mark-plt-1b-x32.d: Likewise. * testsuite/ld-x86-64/mark-plt-1b.d: Likewise. * testsuite/ld-x86-64/mark-plt-1c-x32.d: Likewise. * testsuite/ld-x86-64/mark-plt-1c.d: Likewise. * testsuite/ld-x86-64/mark-plt-1d-x32.d: Likewise. * testsuite/ld-x86-64/mark-plt-1d.d: Likewise. * testsuite/ld-x86-64/x86-64.exp: Run -z mark-plt tests.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/elf-linker-x86.h3
-rw-r--r--bfd/elf64-x86-64.c7
-rw-r--r--bfd/elfxx-x86.c47
-rw-r--r--bfd/elfxx-x86.h3
4 files changed, 58 insertions, 2 deletions
diff --git a/bfd/elf-linker-x86.h b/bfd/elf-linker-x86.h
index e39dbf2..1e6ecb1 100644
--- a/bfd/elf-linker-x86.h
+++ b/bfd/elf-linker-x86.h
@@ -61,6 +61,9 @@ struct elf_linker_x86_params
/* Report relative relocations. */
unsigned int report_relative_reloc : 1;
+ /* Mark PLT with dynamic tags. */
+ unsigned int mark_plt : 1;
+
/* X86-64 ISA level needed. */
unsigned int isa_level;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index e7a0a91..3b7a8ae 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -4455,7 +4455,12 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
else
{
rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT);
- rela.r_addend = 0;
+ if (htab->params->mark_plt)
+ rela.r_addend = (resolved_plt->output_section->vma
+ + plt_offset
+ + htab->plt.plt_indirect_branch_offset);
+ else
+ rela.r_addend = 0;
plt_index = htab->next_jump_slot_index++;
}
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 103559d..58bd76d 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -2525,6 +2525,19 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
}
}
+ asection *resolved_plt = NULL;
+
+ if (htab->params->mark_plt && htab->elf.dynamic_sections_created)
+ {
+ if (htab->plt_second != NULL)
+ resolved_plt = htab->plt_second;
+ else
+ resolved_plt = htab->elf.splt;
+
+ if (resolved_plt != NULL && resolved_plt->size == 0)
+ resolved_plt = NULL;
+ }
+
/* We now have determined the sizes of the various dynamic sections.
Allocate memory for them. */
relocs = false;
@@ -2673,6 +2686,12 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
_bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_SEC);
}
+ if (resolved_plt != NULL
+ && (!_bfd_elf_add_dynamic_entry (info, DT_X86_64_PLT, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_X86_64_PLTSZ, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_X86_64_PLTENT, 0)))
+ return false;
+
return _bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info,
relocs);
}
@@ -2747,6 +2766,12 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
if (sdyn == NULL || htab->elf.sgot == NULL)
abort ();
+ asection *resolved_plt;
+ if (htab->plt_second != NULL)
+ resolved_plt = htab->plt_second;
+ else
+ resolved_plt = htab->elf.splt;
+
sizeof_dyn = bed->s->sizeof_dyn;
dyncon = sdyn->contents;
dynconend = sdyn->contents + sdyn->size;
@@ -2791,6 +2816,19 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+ htab->elf.tlsdesc_got;
break;
+
+ case DT_X86_64_PLT:
+ s = resolved_plt->output_section;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+ break;
+
+ case DT_X86_64_PLTSZ:
+ dyn.d_un.d_val = resolved_plt->size;
+ break;
+
+ case DT_X86_64_PLTENT:
+ dyn.d_un.d_ptr = htab->plt.plt_entry_size;
+ break;
}
(*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
@@ -3561,6 +3599,7 @@ _bfd_x86_elf_get_synthetic_symtab (bfd *abfd,
bfd_vma (*get_plt_got_vma) (struct elf_x86_plt *, bfd_vma, bfd_vma,
bfd_vma);
bool (*valid_plt_reloc_p) (unsigned int);
+ unsigned int jump_slot_reloc;
dynrelbuf = NULL;
if (count == 0)
@@ -3601,11 +3640,13 @@ _bfd_x86_elf_get_synthetic_symtab (bfd *abfd,
{
get_plt_got_vma = elf_x86_64_get_plt_got_vma;
valid_plt_reloc_p = elf_x86_64_valid_plt_reloc_p;
+ jump_slot_reloc = R_X86_64_JUMP_SLOT;
}
else
{
get_plt_got_vma = elf_i386_get_plt_got_vma;
valid_plt_reloc_p = elf_i386_valid_plt_reloc_p;
+ jump_slot_reloc = R_386_JUMP_SLOT;
if (got_addr)
{
/* Check .got.plt and then .got to get the _GLOBAL_OFFSET_TABLE_
@@ -3710,7 +3751,9 @@ _bfd_x86_elf_get_synthetic_symtab (bfd *abfd,
len = strlen ((*p->sym_ptr_ptr)->name);
memcpy (names, (*p->sym_ptr_ptr)->name, len);
names += len;
- if (p->addend != 0)
+ /* There may be JUMP_SLOT and IRELATIVE relocations.
+ JUMP_SLOT r_addend should be ignored. */
+ if (p->addend != 0 && p->howto->type != jump_slot_reloc)
{
char buf[30], *a;
@@ -4275,6 +4318,7 @@ _bfd_x86_elf_link_setup_gnu_properties
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */
htab->plt.has_plt0 = 1;
+ htab->plt.plt_indirect_branch_offset = 0;
normal_target = htab->elf.target_os == is_normal;
if (normal_target)
@@ -4283,6 +4327,7 @@ _bfd_x86_elf_link_setup_gnu_properties
{
htab->lazy_plt = init_table->lazy_ibt_plt;
htab->non_lazy_plt = init_table->non_lazy_ibt_plt;
+ htab->plt.plt_indirect_branch_offset = 4;
}
else
{
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 3b4644c..0bc966b 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -502,6 +502,9 @@ struct elf_x86_plt_layout
/* 1 has PLT0. */
unsigned int has_plt0;
+ /* Offset of indirect branch in plt_entry. */
+ unsigned int plt_indirect_branch_offset;
+
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */