-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[PAC][lld] Use braa instr in PAC PLT sequence with valid PAuth core info #113945
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -999,7 +999,11 @@ class AArch64BtiPac final : public AArch64 { | |
|
||
private: | ||
bool btiHeader; // bti instruction needed in PLT Header and Entry | ||
bool pacEntry; // autia1716 instruction needed in PLT Entry | ||
enum { | ||
PEK_NoAuth, | ||
PEK_AuthHint, // use autia1716 instr for authenticated branch in PLT entry | ||
PEK_Auth, // use braa instr for authenticated branch in PLT entry | ||
} pacEntryKind; | ||
}; | ||
} // namespace | ||
|
||
|
@@ -1014,9 +1018,21 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) { | |
// relocations. | ||
// The PAC PLT entries require dynamic loader support and this isn't known | ||
// from properties in the objects, so we use the command line flag. | ||
pacEntry = ctx.arg.zPacPlt; | ||
// By default we only use hint-space instructions, but if we detect the | ||
// PAuthABI, which requires v8.3-A, we can use the non-hint space | ||
// instructions. | ||
|
||
if (ctx.arg.zPacPlt) { | ||
if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo, | ||
[](uint8_t c) { return c != 0; })) | ||
pacEntryKind = PEK_Auth; | ||
else | ||
pacEntryKind = PEK_AuthHint; | ||
} else { | ||
pacEntryKind = PEK_NoAuth; | ||
} | ||
|
||
if (btiHeader || pacEntry) { | ||
if (btiHeader || (pacEntryKind != PEK_NoAuth)) { | ||
pltEntrySize = 24; | ||
ipltEntrySize = 24; | ||
} | ||
|
@@ -1066,9 +1082,13 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym, | |
0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.got.plt[n]))] | ||
0x10, 0x02, 0x00, 0x91 // add x16, x16, Offset(&(.got.plt[n])) | ||
}; | ||
const uint8_t pacHintBr[] = { | ||
0x9f, 0x21, 0x03, 0xd5, // autia1716 | ||
0x20, 0x02, 0x1f, 0xd6 // br x17 | ||
}; | ||
const uint8_t pacBr[] = { | ||
0x9f, 0x21, 0x03, 0xd5, // autia1716 | ||
0x20, 0x02, 0x1f, 0xd6 // br x17 | ||
0x30, 0x0a, 0x1f, 0xd7, // braa x17, x16 | ||
0x1f, 0x20, 0x03, 0xd5 // nop | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe UDF instruction is a safer choice instead of NOP. also may not have any significance. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's a nice suggestion, but I'll apply it in a separate PR not to mix different changes - |
||
}; | ||
const uint8_t stdBr[] = { | ||
0x20, 0x02, 0x1f, 0xd6, // br x17 | ||
|
@@ -1096,8 +1116,10 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym, | |
relocateNoSym(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr); | ||
relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); | ||
|
||
if (pacEntry) | ||
memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr)); | ||
if (pacEntryKind != PEK_NoAuth) | ||
memcpy(buf + sizeof(addrInst), | ||
pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could be a possibility to make pacHintBr and pacBr into an array indexed by pacEntryKind.
Not sure if it is worth the trouble though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for suggestion. I think I'll leave this "as is" w/o changes - it looks like that a pretty small decrease in code length here will require increase in complexity by introducing invariants on enum values and increase in code length somewhere else. |
||
sizeof(pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr)); | ||
else | ||
memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr)); | ||
if (!hasBti) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be worth adding to the comment here. Something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added, thanks, see b189f51