Skip to content

[PAC][lld][ELF] Use PAC instructions in PLT header with -z pac-plt #116334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions lld/ELF/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1039,13 +1039,23 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {

void AArch64BtiPac::writePltHeader(uint8_t *buf) const {
const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
const uint8_t signLR[] = {0x7f, 0x23, 0x03, 0xd5}; // pacibsp
const uint8_t pltData[] = {
0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.got.plt[2]))
0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.got.plt[2]))]
0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.got.plt[2]))
0x20, 0x02, 0x1f, 0xd6, // br x17
0x1f, 0x20, 0x03, 0xd5, // nop
};
const uint8_t pacHintBr[] = {
0x9f, 0x21, 0x03, 0xd5, // autia1716
0x20, 0x02, 0x1f, 0xd6 // br x17
};
const uint8_t pacBr[] = {
0x30, 0x0a, 0x1f, 0xd7, // braa x17, x16
0x1f, 0x20, 0x03, 0xd5 // nop
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need extra nop here? And below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@asl The plt header size was aligned to 16, and this patch preserves this invariant. We can delete nops from pacBr and stdBr, but in this case we'll need to add them manually later. So, current variant should probably be OK

};
const uint8_t stdBr[] = {
0x20, 0x02, 0x1f, 0xd6, // br x17
0x1f, 0x20, 0x03, 0xd5 // nop
};
const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
Expand All @@ -1060,15 +1070,30 @@ void AArch64BtiPac::writePltHeader(uint8_t *buf) const {
buf += sizeof(btiData);
plt += sizeof(btiData);
}
if (pacEntryKind != PEK_NoAuth) {
memcpy(buf, signLR, sizeof(signLR));
buf += sizeof(signLR);
plt += sizeof(signLR);
}
memcpy(buf, pltData, sizeof(pltData));

relocateNoSym(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
getAArch64Page(got + 16) - getAArch64Page(plt + 4));
relocateNoSym(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
relocateNoSym(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);

if (pacEntryKind != PEK_NoAuth)
memcpy(buf + sizeof(pltData),
(pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr),
sizeof(pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr));
else
memcpy(buf + sizeof(pltData), stdBr, sizeof(stdBr));
if (!btiHeader)
// We didn't add the BTI c instruction so round out size with NOP.
memcpy(buf + sizeof(pltData), nopData, sizeof(nopData));
memcpy(buf + sizeof(pltData) + sizeof(stdBr), nopData, sizeof(nopData));
if (pacEntryKind == PEK_NoAuth)
// We didn't add the PACIBSP instruction so round out size with NOP.
memcpy(buf + sizeof(pltData) + sizeof(stdBr), nopData, sizeof(nopData));
}

void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
Expand Down
4 changes: 2 additions & 2 deletions lld/test/ELF/aarch64-feature-btipac.s
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,13 @@ func1:
# BTIPACEX2: Disassembly of section .plt:
# BTIPACEX2: 0000000000210380 <.plt>:
# BTIPACEX2-NEXT: 210380: bti c
# BTIPACEX2-NEXT: pacibsp
# BTIPACEX2-NEXT: stp x16, x30, [sp, #-16]!
# BTIPACEX2-NEXT: adrp x16, 0x230000
# BTIPACEX2-NEXT: ldr x17, [x16, #1208]
# BTIPACEX2-NEXT: add x16, x16, #1208
# BTIPACEX2-NEXT: autia1716
# BTIPACEX2-NEXT: br x17
# BTIPACEX2-NEXT: nop
# BTIPACEX2-NEXT: nop
# BTIPACEX2: 00000000002103a0 <func2@plt>:
# BTIPACEX2-NEXT: 2103a0: adrp x16, 0x230000
# BTIPACEX2-NEXT: ldr x17, [x16, #1216]
Expand Down
6 changes: 3 additions & 3 deletions lld/test/ELF/aarch64-feature-pac.s
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@
# PACPLT-NEXT: 210378: ret
# PACPLT: Disassembly of section .plt:
# PACPLT: 0000000000210380 <.plt>:
# PACPLT-NEXT: 210380: stp x16, x30, [sp, #-16]!
# PACPLT-NEXT: 210380: pacibsp
# PACPLT-NEXT: stp x16, x30, [sp, #-16]!
# PACPLT-NEXT: adrp x16, 0x230000
# PACPLT-NEXT: ldr x17, [x16, #1192]
# PACPLT-NEXT: add x16, x16, #1192
# PACPLT-NEXT: autia1716
# PACPLT-NEXT: br x17
# PACPLT-NEXT: nop
# PACPLT-NEXT: nop
# PACPLT-NEXT: nop
# PACPLT: 00000000002103a0 <func2@plt>:
# PACPLT-NEXT: 2103a0: adrp x16, 0x230000
# PACPLT-NEXT: ldr x17, [x16, #1200]
Expand Down
8 changes: 5 additions & 3 deletions lld/test/ELF/aarch64-feature-pauth.s
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@
# PACPLT-NEXT: ret
# PACPLT: Disassembly of section .plt:
# PACPLT: <.plt>:
# PACPLT-NEXT: pacibsp
# PACPLT-NEXT: stp x16, x30, [sp, #-0x10]!
# PACPLT-NEXT: adrp x16, 0x30000 <func3+0x30000>
# PACPLT-NEXT: ldr x17, [x16, #0x[[B]]]
# PACPLT-NEXT: add x16, x16, #0x[[B]]
# PACPLT-NEXT: br x17
# PACPLT-NEXT: nop
# PACPLT-NEXT: nop
# NOHINT-NEXT: braa x17, x16
# NOHINT-NEXT: nop
# HINT-NEXT: autia1716
# HINT-NEXT: br x17
# PACPLT-NEXT: nop
# PACPLT: <func3@plt>:
# PACPLT-NEXT: adrp x16, 0x30000 <func3+0x30000>
Expand Down
Loading