[RFC][PATCH] Add DT_X86_64_PLT/DT_X86_64_PLTSZ/DT_X86_64_PLTENT

79 views
Skip to first unread message

H.J. Lu

unread,
Aug 18, 2023, 3:10:31 PM8/18/23
to x86-6...@googlegroups.com
Add DT_X86_64_PLT, DT_X86_64_PLTSZ and DT_X86_64_PLTENT, to the dynamic
linker to rewrite indirect branch in PLT entry to direct branch.
---
x86-64-ABI/dl.tex | 51 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)

diff --git a/x86-64-ABI/dl.tex b/x86-64-ABI/dl.tex
index 60f0196..f6b2908 100644
--- a/x86-64-ABI/dl.tex
+++ b/x86-64-ABI/dl.tex
@@ -88,6 +88,57 @@ Dynamic section entries give information to the dynamic linker. Some
of this information is processor-specific, including the interpretation
of some entries in the dynamic structure.

+The following optional \xARCH Dynamic Array Tags are defined:
+
+\begin{table}[H]
+\Hrule
+ \caption{Optional Dynamic Array Tags, d_tag}
+ \begin{center}
+ \begin{tabular}[t]{l|l|l}
+ \multicolumn{1}{c}{Name} & \multicolumn{1}{c}{Value} &
+ \multicolumn{1}{c}{d_un} \\
+ \hline
+ \texttt{DT_X86_64_PLT} & \texttt{DT_LOPROC + 0} & \texttt{d_ptr} \\
+ \texttt{DT_X86_64_PLTSZ} & \texttt{DT_LOPROC + 1} & \texttt{d_val} \\
+ \texttt{DT_X86_64_PLTENT} & \texttt{DT_LOPROC + 3} & \texttt{d_val} \\
+ \end{tabular}
+ \end{center}
+\Hrule
+\end{table}
+
+\begin{description}
+ \item[DT_X86_64_PLT]
+ The address of the procedure linkage table.
+ \item[DT_X86_64_PLTSZ]
+ The total size, in bytes, of the procedure linkage table.
+ \item[DT_X86_64_PLTENT]
+ The size, in bytes, of a procedure linkage table entry.
+\end{description}
+
+\texttt{DT_X86_64_PLT}, \texttt{DT_X86_64_PLTSZ} and
+\texttt{DT_X86_64_PLTENT} are provided only if
+
+\begin{itemize}
+ \item The procedure linkage table entries transfer control to external
+ functions via indirect branch over the corresponding entry in the global
+ offset table referenced by the \code{r_offset} field of
+ \texttt{R_X86_64_JUMP_SLOT} relocation and the \code{r_addend} field of
+ \texttt{R_X86_64_JUMP_SLOT} relocation stores the procedure linkage
+ table offset of indirect branch in the corresponding procedure linkage
+ table entry.
+ \item All such procedure linkage table entries have the same layout.
+ \item The only entry point of a procedure linkage table entry is the
+ first byte of the entry.
+ \item All entries have the same size and are aligned to the entry size.
+\end{itemize}
+
+If permitted, using \texttt{DT_X86_64_PLT}, \texttt{DT_X86_64_PLTSZ} and
+\texttt{DT_X86_64_PLTENT} together with the \code{r_offset} and
+\code{r_addend} fields of \texttt{R_X86_64_JUMP_SLOT} relocation, the
+dynamic linker may retrieve the indirect branch target address stored at
+the global offset table entry and rewrite indirect branch in the procedure
+linkage table entry to direct branch.
+
\subsubsection{Global Offset Table (GOT)}
\label{got}

--
2.41.0

Florian Weimer

unread,
Aug 20, 2023, 4:10:06 AM8/20/23
to H.J. Lu, x86-6...@googlegroups.com
* H. J. Lu:

> +If permitted, using \texttt{DT_X86_64_PLT}, \texttt{DT_X86_64_PLTSZ} and
> +\texttt{DT_X86_64_PLTENT} together with the \code{r_offset} and
> +\code{r_addend} fields of \texttt{R_X86_64_JUMP_SLOT} relocation, the
> +dynamic linker may retrieve the indirect branch target address stored at
> +the global offset table entry and rewrite indirect branch in the procedure
> +linkage table entry to direct branch.

What about the DWARF EH data? How can the dynamic linker ensure that
it stays compatible with the rewrite?

H.J. Lu

unread,
Aug 21, 2023, 11:19:28 AM8/21/23
to Florian Weimer, x86-6...@googlegroups.com
The PLT DWARF EH data for

0000000000001010 <foo@plt>:
1010: ff 25 ea 2f 00 00 jmp *0x2fea(%rip) # 4000 <foo>
1016: 68 00 00 00 00 push $0x0
101b: e9 e0 ff ff ff jmp 1000 <foo@plt-0x10>

is

Contents of the .eh_frame section:


00000000 0000000000000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_nop
DW_CFA_nop

00000018 0000000000000014 0000001c FDE cie=00000000
pc=0000000000001020..0000000000001025
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop

00000030 0000000000000020 00000034 FDE cie=00000000
pc=0000000000001000..0000000000001020
DW_CFA_def_cfa_offset: 16
DW_CFA_advance_loc: 6 to 0000000000001006
DW_CFA_def_cfa_offset: 24
DW_CFA_advance_loc: 10 to 0000000000001010
DW_CFA_def_cfa_expression (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip):
0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3;
DW_OP_shl; DW_OP_plus)

Since the PLT rewrite should be enabled only when lazy binding is
disabled,

1016: 68 00 00 00 00 push $0x0
101b: e9 e0 ff ff ff jmp 1000 <foo@plt-0x10>

will never be executed. The PLT rewrite will change the branch instruction
length such that

00000018 0000000000000014 0000001c FDE cie=00000000
pc=0000000000001020..0000000000001025
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop

is no longer the same. But GDB stack trace seems OK.

--
H.J.

Florian Weimer

unread,
Aug 21, 2023, 1:56:05 PM8/21/23
to H.J. Lu, x86-6...@googlegroups.com
* H. J. Lu:

> On Sun, Aug 20, 2023 at 1:10 AM Florian Weimer <f...@deneb.enyo.de> wrote:
>>
>> * H. J. Lu:
>>
>> > +If permitted, using \texttt{DT_X86_64_PLT}, \texttt{DT_X86_64_PLTSZ} and
>> > +\texttt{DT_X86_64_PLTENT} together with the \code{r_offset} and
>> > +\code{r_addend} fields of \texttt{R_X86_64_JUMP_SLOT} relocation, the
>> > +dynamic linker may retrieve the indirect branch target address stored at
>> > +the global offset table entry and rewrite indirect branch in the procedure
>> > +linkage table entry to direct branch.
>>
>> What about the DWARF EH data? How can the dynamic linker ensure that
>> it stays compatible with the rewrite?
>
> The PLT DWARF EH data for
>
> 0000000000001010 <foo@plt>:
> 1010: ff 25 ea 2f 00 00 jmp *0x2fea(%rip) # 4000 <foo>
> 1016: 68 00 00 00 00 push $0x0
> 101b: e9 e0 ff ff ff jmp 1000 <foo@plt-0x10>
>
> is
>
> Contents of the .eh_frame section:

[snip]

> 00000030 0000000000000020 00000034 FDE cie=00000000
> pc=0000000000001000..0000000000001020
> DW_CFA_def_cfa_offset: 16
> DW_CFA_advance_loc: 6 to 0000000000001006
> DW_CFA_def_cfa_offset: 24
> DW_CFA_advance_loc: 10 to 0000000000001010
> DW_CFA_def_cfa_expression (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip):
> 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3;
> DW_OP_shl; DW_OP_plus)

This computes the register contents based on the RIP value. It only
works if the stub layout does not diverge too much from the original.
In your example, this is the case, but I don't think it's possible in
general. So far, the format is agnostic regarding what precisely goes
on in the PLT stub (e.g., whether there's an ENDBR64 or not, or the
old bounds stuff for MPX). Retpolines in PLT stubs have seen some
deployment, I believe, and would be incompatible with the rewrite (but
maybe they do not have correct EH data anyway …). So I think this
needs further discussion in the psABI supplement.

H.J. Lu

unread,
Aug 22, 2023, 12:44:07 PM8/22/23
to Florian Weimer, x86-6...@googlegroups.com
We can require PLT layouts specified in the psABI.

--
H.J.

Florian Weimer

unread,
Aug 22, 2023, 3:21:19 PM8/22/23
to H.J. Lu, x86-6...@googlegroups.com
* H. J. Lu:

> We can require PLT layouts specified in the psABI.

That would be conservative, yes. Thanks.

H.J. Lu

unread,
Aug 22, 2023, 4:12:51 PM8/22/23
to Florian Weimer, x86-6...@googlegroups.com
Something like this?

\item All such procedure linkage table entries have the same layout
which contains an indirect branch similar to the \code{.PLT1} entry
in figure~\ref{small_med_plt}. There should be no functional side
effect when the indirect branch is replaced by a direct branch.

--
H.J.

Florian Weimer

unread,
Aug 23, 2023, 3:32:24 AM8/23/23
to H.J. Lu, x86-6...@googlegroups.com
* H. J. Lu:
Well, except that example lacks endbr64 instructions that we nowadays
expect.

I think the key question is that if the DT_* tags are present, does the
linker have to validate existing PLT stub code sequences before doing
the rewrite? I think the answer is yes. For the 64-bit rewrite, it
also has to know that bytes after the jmp instruction are unused.
That's why I think we may need more information.

H.J. Lu

unread,
Aug 23, 2023, 12:09:48 PM8/23/23
to Florian Weimer, x86-6...@googlegroups.com
On Wed, Aug 23, 2023 at 12:32 AM Florian Weimer <fwe...@redhat.com> wrote:
>
> * H. J. Lu:
>
> > On Tue, Aug 22, 2023 at 12:21 PM Florian Weimer <f...@deneb.enyo.de> wrote:
> >>
> >> * H. J. Lu:
> >>
> >> > We can require PLT layouts specified in the psABI.
> >>
> >> That would be conservative, yes. Thanks.
> >
> > Something like this?
> >
> > \item All such procedure linkage table entries have the same layout
> > which contains an indirect branch similar to the \code{.PLT1} entry
> > in figure~\ref{small_med_plt}. There should be no functional side
> > effect when the indirect branch is replaced by a direct branch.
>
> Well, except that example lacks endbr64 instructions that we nowadays
> expect.

I will add CET bits to psABI after this merge request is approved:

https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/13

> I think the key question is that if the DT_* tags are present, does the
> linker have to validate existing PLT stub code sequences before doing
> the rewrite? I think the answer is yes. For the 64-bit rewrite, it
> also has to know that bytes after the jmp instruction are unused.
> That's why I think we may need more information.
>

I think

All such procedure linkage table entries have the same layout.

The only entry point of a procedure linkage table entry is the
first byte of the entry.

All entries have the same size and are aligned to the entry size.

There should be no functional side effect when the indirect
branch is replaced by a direct branch.

should cover PLT rewrite. We can assume that when these dynamic
tags are provided, all conditions are satisfied.

Dynamic linker should check if the PLT entry size is big
enough for 64-bit direct branch.

--
H.J.

H.J. Lu

unread,
Aug 28, 2023, 12:01:24 PM8/28/23
to x86-6...@googlegroups.com
V2 changes:

All such procedure linkage table entries have the same layout
which starts with an indirect branch over the global offset table
entry and ENDBR64 instruction is optional before the indirect
branch. There should be no functional side effect when the indirect
branch is replaced by a direct branch.


H.J.
---
Add DT_X86_64_PLT, DT_X86_64_PLTSZ and DT_X86_64_PLTENT to help dynamic
linker rewrite indirect branch in PLT entries to direct branch.
---
x86-64-ABI/dl.tex | 55 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)

diff --git a/x86-64-ABI/dl.tex b/x86-64-ABI/dl.tex
index 60f0196..9f3500e 100644
--- a/x86-64-ABI/dl.tex
+++ b/x86-64-ABI/dl.tex
@@ -88,6 +88,61 @@ Dynamic section entries give information to the dynamic linker. Some
+ which starts with an indirect branch over the global offset table
+ entry and \code{ENDBR64} instruction is optional before the indirect
+ branch. There should be no functional side effect when the indirect
+ branch is replaced by a direct branch.

H.J. Lu

unread,
Sep 14, 2023, 12:44:58 PM9/14/23
to x86-6...@googlegroups.com
On Mon, Aug 28, 2023 at 9:01 AM H.J. Lu <hjl....@gmail.com> wrote:
>
> V2 changes:
>
> All such procedure linkage table entries have the same layout
> which starts with an indirect branch over the global offset table
> entry and ENDBR64 instruction is optional before the indirect
> branch. There should be no functional side effect when the indirect
> branch is replaced by a direct branch.
>
>

Here is the merge request:

https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/50

--
H.J.

Michael Matz

unread,
Sep 15, 2023, 9:29:49 AM9/15/23
to x86-6...@googlegroups.com
Hello,
Any more comments from the mailing list members here? I'm fine with the
change and will approve it after the weekend when no further comments flow
in.


Ciao,
Michael.

H.J. Lu

unread,
Sep 20, 2023, 11:15:37 AM9/20/23
to Michael Matz, x86-6...@googlegroups.com
Does it look OK to everyone?

Thanks.

--
H.J.
Reply all
Reply to author
Forward
0 new messages