Skip to content
Open
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
44 changes: 20 additions & 24 deletions lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,8 +704,10 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
uint64_t offsetInSec, Symbol &sym, int64_t addend,
RelExpr expr, RelType type) {
Partition &part = isec.getPartition(ctx);
bool isAArch64Auth =
ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64;

if (sym.isTagged()) {
if (sym.isTagged() && !isAArch64Auth) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've preserved the fact that sym.isTagged() is ignored for R_AARCH64_AUTH_ABS64, but suspect that the ptrauth and memtag ABIs are currently mutually-exclusive? If so I can drop this diff from this and later PRs.

Copy link
Contributor

Choose a reason for hiding this comment

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

but suspect that the ptrauth and memtag ABIs are currently mutually-exclusive?

@smithp35 Could you please clarify what is the correct answer for the question above? I was only working on ptrauth and do not feel confident enough to reason about memtag with ptrauth combination :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

The TL;DR is that in theory they could be combined. In practice no-one has tried combining or expressed an interest in combining them. One opinion is that it could be removed for now, and when someone does try it, they'll need to put something similar back. Perhaps leave a comment.

From a user group perspective the PAuthABI and the MemtagABI communities are separate. As I understand the PAuthABI is an ABI break for the group using Memtag and the group intending to use PAuthABI is targeting hardware that doesn't have MTE so can't use the Memtag ABI anyway.

Re-reading the specifications I don't think that there's anything fundamental at the specification level that would prevent the two being used together. The PAuthABI adds new relocations, the MemtagABI alters the behaviour of existing non PAuth ABI relocations. This means that global signed pointers can't be tagged, but as tagging does not have to be complete, anything that isn't signed could be tagged.

I expect that the memtag ABI could be extended to cover signed pointers. It would need to encode the tag offset for relative relocations for R_AARCH64_AUTH_RELATIVE in a compatible way to the signing schema.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@fmayer is I think the lead for the Memtag ABI. Tagging him here just in case there are any plans for combining hte Memtag ABI with PAuthABI.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

With PAuth2 XORing rather than replacing the upper bits you might even be able to do both for a given pointer? I haven’t properly thought it through and it may be a terrible idea, but on the surface it seemed plausible to me.

Copy link
Collaborator

Choose a reason for hiding this comment

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

When both MTE and PAC are enabled the amount of bits avaible to PAC is reduced so they don't overlap with the bits used for MTE. They can be used together, although fewer bits available to PAC makes it statistically weaker.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, MTE and PAuth ABI are not mutually exclusive, as they can use different bits.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is the existing implementation that uses .relr.auth.dyn and/or no offset to the start of the symbol for AUTH_RELATIVE relocations against tagged symbols correct? I am assuming not, and that it should be doing the "obvious" composition of the two. Which would also simplify this patch.

part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
offsetInSec, sym, addend, type, expr);
// With MTE globals, we always want to derive the address tag by `ldg`-ing
Expand All @@ -727,13 +729,22 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
// relrDyn sections don't support odd offsets. Also, relrDyn sections
// don't store the addend values, so we must write it to the relocated
// address.
if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
part.relrDyn->addRelativeReloc<shard>(isec, offsetInSec, sym, addend, type,
expr);
//
// When symbol values are determined in finalizeAddressDependentContent,
// some .relr.auth.dyn relocations may be moved to .rela.dyn.
RelrBaseSection *relrDyn = part.relrDyn.get();
if (isAArch64Auth)
relrDyn = part.relrAuthDyn.get();
if (relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
relrDyn->addRelativeReloc<shard>(isec, offsetInSec, sym, addend, type,
expr);
return;
}
part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
offsetInSec, sym, addend, type, expr);
RelType relativeType = ctx.target->relativeRel;
if (isAArch64Auth)
relativeType = R_AARCH64_AUTH_RELATIVE;
part.relaDyn->addRelativeReloc<shard>(relativeType, isec, offsetInSec, sym,
addend, type, expr);
}

template <class PltSection, class GotPltSection>
Expand Down Expand Up @@ -992,7 +1003,9 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
if (canWrite) {
RelType rel = ctx.target->getDynRel(type);
if (oneof<R_GOT, RE_LOONGARCH_GOT>(expr) ||
(rel == ctx.target->symbolicRel && !sym.isPreemptible)) {
((rel == ctx.target->symbolicRel ||
(ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64)) &&
!sym.isPreemptible)) {
addRelativeReloc<true>(ctx, *sec, offset, sym, addend, expr, type);
return;
}
Expand All @@ -1001,23 +1014,6 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
rel = ctx.target->relativeRel;
std::lock_guard<std::mutex> lock(ctx.relocMutex);
Partition &part = sec->getPartition(ctx);
// For a preemptible symbol, we can't use a relative relocation. For an
// undefined symbol, we can't compute offset at link-time and use a
// relative relocation. Use a symbolic relocation instead.
if (ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64 &&
!sym.isPreemptible) {
if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0) {
// When symbol values are determined in
// finalizeAddressDependentContent, some .relr.auth.dyn relocations
// may be moved to .rela.dyn.
part.relrAuthDyn->addRelativeReloc(*sec, offset, sym, addend, type,
expr);
} else {
part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, false,
sym, addend, R_ABS});
}
return;
}
if (LLVM_UNLIKELY(type == ctx.target->iRelSymbolicRel)) {
if (sym.isPreemptible) {
auto diag = Err(ctx);
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.