diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2022-11-01 11:36:04 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2023-09-29 07:58:53 -0700 |
commit | 832ca732b8a96ff9a3e7c4abf24098bf2a59a96d (patch) | |
tree | 5ee140bdc26d1d37696b865c80becee32ecde8c6 /ld | |
parent | a78c3c9717e8fa98b11482f948e71c6d1d9d0e44 (diff) | |
download | gdb-832ca732b8a96ff9a3e7c4abf24098bf2a59a96d.zip gdb-832ca732b8a96ff9a3e7c4abf24098bf2a59a96d.tar.gz gdb-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 'ld')
-rw-r--r-- | ld/emulparams/elf32_x86_64.sh | 1 | ||||
-rw-r--r-- | ld/emulparams/elf_x86_64.sh | 1 | ||||
-rw-r--r-- | ld/emulparams/x86-64-plt.sh | 14 | ||||
-rw-r--r-- | ld/ld.texi | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1.s | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1a-x32.d | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1a.d | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1b-x32.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1b.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1c-x32.d | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1c.d | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1d-x32.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/mark-plt-1d.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/x86-64.exp | 8 |
14 files changed, 154 insertions, 0 deletions
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh index 4bff412..f6c6de9 100644 --- a/ld/emulparams/elf32_x86_64.sh +++ b/ld/emulparams/elf32_x86_64.sh @@ -6,6 +6,7 @@ source_sh ${srcdir}/emulparams/call_nop.sh source_sh ${srcdir}/emulparams/cet.sh source_sh ${srcdir}/emulparams/x86-report-relative.sh source_sh ${srcdir}/emulparams/x86-64-level.sh +source_sh ${srcdir}/emulparams/x86-64-plt.sh source_sh ${srcdir}/emulparams/static.sh source_sh ${srcdir}/emulparams/dt-relr.sh SCRIPT_NAME=elf diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh index a689a7b..466da2c 100644 --- a/ld/emulparams/elf_x86_64.sh +++ b/ld/emulparams/elf_x86_64.sh @@ -7,6 +7,7 @@ source_sh ${srcdir}/emulparams/cet.sh source_sh ${srcdir}/emulparams/x86-report-relative.sh source_sh ${srcdir}/emulparams/x86-64-level.sh source_sh ${srcdir}/emulparams/x86-64-lam.sh +source_sh ${srcdir}/emulparams/x86-64-plt.sh source_sh ${srcdir}/emulparams/static.sh source_sh ${srcdir}/emulparams/dt-relr.sh SCRIPT_NAME=elf diff --git a/ld/emulparams/x86-64-plt.sh b/ld/emulparams/x86-64-plt.sh new file mode 100644 index 0000000..9273240 --- /dev/null +++ b/ld/emulparams/x86-64-plt.sh @@ -0,0 +1,14 @@ +PARSE_AND_LIST_OPTIONS_X86_64_PLT=' + fprintf (file, _("\ + -z mark-plt Mark PLT with dynamic tags\n\ + -z nomark-plt Do not mark PLT with dynamic tags (default)\n")); +' +PARSE_AND_LIST_ARGS_CASE_Z_X86_64_PLT=' + else if (strcmp (optarg, "mark-plt") == 0) + params.mark_plt = 1; + else if (strcmp (optarg, "nomark-plt") == 0) + params.mark_plt = 0; +' + +PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_X86_64_PLT" +PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_X86_64_PLT" @@ -1475,6 +1475,17 @@ Specify that the object's filters be processed immediately at runtime. @item max-page-size=@var{value} Set the maximum memory page size supported to @var{value}. +@item mark-plt +@itemx nomark-plt +Mark PLT entries with dynamic tags, DT_X86_64_PLT, DT_X86_64_PLTSZ and +DT_X86_64_PLTENT. Since this option stores a non-zero value in the +r_addend field of R_X86_64_JUMP_SLOT relocations, the resulting +executables and shared libraries are incompatible with dynamic linkers, +such as those in older versions of glibc without the change to ignore +r_addend in R_X86_64_GLOB_DAT and R_X86_64_JUMP_SLOT relocations, which +don't ignore the r_addend field of R_X86_64_JUMP_SLOT relocations. +Supported for x86_64. + @item muldefs Allow multiple definitions. diff --git a/ld/testsuite/ld-x86-64/mark-plt-1.s b/ld/testsuite/ld-x86-64/mark-plt-1.s new file mode 100644 index 0000000..e3f03c8 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1.s @@ -0,0 +1,7 @@ + .text + .globl foo + .type foo, @function +foo: + call bar@PLT + ret + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/mark-plt-1a-x32.d b/ld/testsuite/ld-x86-64/mark-plt-1a-x32.d new file mode 100644 index 0000000..2051356 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1a-x32.d @@ -0,0 +1,12 @@ +#source: mark-plt-1.s +#as: --x32 +#ld: -melf32_x86_64 -shared -z mark-plt +#readelf: -drW + +#... + 0x70000000 \(DT_X86_64_PLT\) 0x1000 + 0x70000001 \(DT_X86_64_PLTSZ\) 0x20 + 0x70000003 \(DT_X86_64_PLTENT\) 0x10 +#... +[0-9a-f ]+R_X86_64_JUMP_SLOT +0+ +bar \+ 1010 +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1a.d b/ld/testsuite/ld-x86-64/mark-plt-1a.d new file mode 100644 index 0000000..a252e95 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1a.d @@ -0,0 +1,12 @@ +#source: mark-plt-1.s +#as: --64 +#ld: -melf_x86_64 -shared -z mark-plt +#readelf: -drW + +#... + 0x0000000070000000 \(DT_X86_64_PLT\) 0x1000 + 0x0000000070000001 \(DT_X86_64_PLTSZ\) 0x20 + 0x0000000070000003 \(DT_X86_64_PLTENT\) 0x10 +#... +[0-9a-f ]+R_X86_64_JUMP_SLOT +0+ +bar \+ 1010 +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1b-x32.d b/ld/testsuite/ld-x86-64/mark-plt-1b-x32.d new file mode 100644 index 0000000..74306a0 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1b-x32.d @@ -0,0 +1,16 @@ +#source: mark-plt-1.s +#as: --x32 +#ld: -melf32_x86_64 -shared -z mark-plt +#objdump: -dw + +#... +0+1010 <bar@plt>: + +1010: ff 25 9a 10 00 00 jmp \*0x109a\(%rip\) # 20b0 <bar> + +1016: 68 00 00 00 00 push \$0x0 + +101b: e9 e0 ff ff ff jmp 1000 <bar@plt-0x10> + +Disassembly of section .text: + +0+1020 <foo>: + +1020: e8 eb ff ff ff call 1010 <bar@plt> +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1b.d b/ld/testsuite/ld-x86-64/mark-plt-1b.d new file mode 100644 index 0000000..dc046c0 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1b.d @@ -0,0 +1,16 @@ +#source: mark-plt-1.s +#as: --64 +#ld: -melf_x86_64 -shared -z mark-plt +#objdump: -dw + +#... +0+1010 <bar@plt>: + +1010: ff 25 32 11 00 00 jmp \*0x1132\(%rip\) # 2148 <bar> + +1016: 68 00 00 00 00 push \$0x0 + +101b: e9 e0 ff ff ff jmp 1000 <bar@plt-0x10> + +Disassembly of section .text: + +0+1020 <foo>: + +1020: e8 eb ff ff ff call 1010 <bar@plt> +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1c-x32.d b/ld/testsuite/ld-x86-64/mark-plt-1c-x32.d new file mode 100644 index 0000000..6354dc3 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1c-x32.d @@ -0,0 +1,12 @@ +#source: mark-plt-1.s +#as: --x32 +#ld: -melf32_x86_64 -shared -z mark-plt -z ibtplt +#readelf: -drW + +#... + 0x70000000 \(DT_X86_64_PLT\) 0x1020 + 0x70000001 \(DT_X86_64_PLTSZ\) 0x10 + 0x70000003 \(DT_X86_64_PLTENT\) 0x10 +#... +[0-9a-f ]+R_X86_64_JUMP_SLOT +0+ +bar \+ 1024 +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1c.d b/ld/testsuite/ld-x86-64/mark-plt-1c.d new file mode 100644 index 0000000..e11e0b7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1c.d @@ -0,0 +1,12 @@ +#source: mark-plt-1.s +#as: --64 +#ld: -melf_x86_64 -shared -z mark-plt -z ibtplt +#readelf: -drW + +#... + 0x0000000070000000 \(DT_X86_64_PLT\) 0x1020 + 0x0000000070000001 \(DT_X86_64_PLTSZ\) 0x10 + 0x0000000070000003 \(DT_X86_64_PLTENT\) 0x10 +#... +[0-9a-f ]+R_X86_64_JUMP_SLOT +0+ +bar \+ 1024 +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1d-x32.d b/ld/testsuite/ld-x86-64/mark-plt-1d-x32.d new file mode 100644 index 0000000..318ca1f --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1d-x32.d @@ -0,0 +1,16 @@ +#source: mark-plt-1.s +#as: --x32 +#ld: -melf32_x86_64 -shared -z mark-plt -z ibtplt +#objdump: -dw + +#... +0+1020 <bar@plt>: + +1020: f3 0f 1e fa endbr64 + +1024: ff 25 86 10 00 00 jmp \*0x1086\(%rip\) # 20b0 <bar> + +102a: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+1030 <foo>: + +1030: e8 eb ff ff ff call 1020 <bar@plt> +#pass diff --git a/ld/testsuite/ld-x86-64/mark-plt-1d.d b/ld/testsuite/ld-x86-64/mark-plt-1d.d new file mode 100644 index 0000000..2dd63bc --- /dev/null +++ b/ld/testsuite/ld-x86-64/mark-plt-1d.d @@ -0,0 +1,16 @@ +#source: mark-plt-1.s +#as: --64 +#ld: -melf_x86_64 -shared -z mark-plt -z ibtplt +#objdump: -dw + +#... +0+1020 <bar@plt>: + +1020: f3 0f 1e fa endbr64 + +1024: ff 25 1e 11 00 00 jmp \*0x111e\(%rip\) # 2148 <bar> + +102a: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+1030 <foo>: + +1030: e8 eb ff ff ff call 1020 <bar@plt> +#pass diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index f94284b..3dc8cb4 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -2228,5 +2228,13 @@ run_dump_test "ibt-plt-3a-x32" run_dump_test "ibt-plt-3b-x32" run_dump_test "ibt-plt-3c-x32" run_dump_test "ibt-plt-3d-x32" +run_dump_test "mark-plt-1a" +run_dump_test "mark-plt-1b" +run_dump_test "mark-plt-1c" +run_dump_test "mark-plt-1d" +run_dump_test "mark-plt-1a-x32" +run_dump_test "mark-plt-1b-x32" +run_dump_test "mark-plt-1c-x32" +run_dump_test "mark-plt-1d-x32" set ASFLAGS "$saved_ASFLAGS" |