[lld] Refactor storage of PAuth ABI core info (#141920)
Previously, the AArch64 PAuth ABI core values were stored as an ArrayRef<uint8_t>, introducing unnecessary indirection. This patch replaces the ArrayRef with two explicit uint64_t fields: aarch64PauthAbiPlatform and aarch64PauthAbiVersion. This simplifies the representation and improves readability. No functional change intended, aside from improved error messages.
This commit is contained in:
@@ -1043,8 +1043,7 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
|
||||
// instructions.
|
||||
|
||||
if (ctx.arg.zPacPlt) {
|
||||
if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,
|
||||
[](uint8_t c) { return c != 0; }))
|
||||
if (ctx.aarch64PauthAbiCoreInfo && ctx.aarch64PauthAbiCoreInfo->isValid())
|
||||
pacEntryKind = PEK_Auth;
|
||||
else
|
||||
pacEntryKind = PEK_AuthHint;
|
||||
|
||||
@@ -139,6 +139,23 @@ enum class GcsPolicy { Implicit, Never, Always };
|
||||
// For some options that resemble -z bti-report={none,warning,error}
|
||||
enum class ReportPolicy { None, Warning, Error };
|
||||
|
||||
// Describes the signing schema for a file using the PAuth ABI extension.
|
||||
// Two files are considered compatible when both `platform` and `version` match.
|
||||
// The pair (0, 0) is reserved to indicate incompatibility with the PAuth ABI.
|
||||
struct AArch64PauthAbiCoreInfo {
|
||||
uint64_t platform;
|
||||
uint64_t version;
|
||||
// Returns true if the core info is not the reserved (0, 0) value.
|
||||
bool isValid() const { return platform || version; }
|
||||
static constexpr size_t size() { return sizeof(platform) + sizeof(version); }
|
||||
bool operator==(const AArch64PauthAbiCoreInfo &other) const {
|
||||
return platform == other.platform && version == other.version;
|
||||
}
|
||||
bool operator!=(const AArch64PauthAbiCoreInfo &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct SymbolVersion {
|
||||
llvm::StringRef name;
|
||||
bool isExternCpp;
|
||||
@@ -699,7 +716,7 @@ struct Ctx : CommonLinkerContext {
|
||||
|
||||
llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &);
|
||||
|
||||
ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
|
||||
std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;
|
||||
};
|
||||
|
||||
// The first two elements of versionDefinitions represent VER_NDX_LOCAL and
|
||||
|
||||
@@ -2857,15 +2857,15 @@ static void readSecurityNotes(Ctx &ctx) {
|
||||
StringRef referenceFileName;
|
||||
if (ctx.arg.emachine == EM_AARCH64) {
|
||||
auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) {
|
||||
return !f->aarch64PauthAbiCoreInfo.empty();
|
||||
return f->aarch64PauthAbiCoreInfo.has_value();
|
||||
});
|
||||
if (it != ctx.objectFiles.end()) {
|
||||
ctx.aarch64PauthAbiCoreInfo = (*it)->aarch64PauthAbiCoreInfo;
|
||||
referenceFileName = (*it)->getName();
|
||||
}
|
||||
}
|
||||
bool hasValidPauthAbiCoreInfo = llvm::any_of(
|
||||
ctx.aarch64PauthAbiCoreInfo, [](uint8_t c) { return c != 0; });
|
||||
bool hasValidPauthAbiCoreInfo =
|
||||
ctx.aarch64PauthAbiCoreInfo && ctx.aarch64PauthAbiCoreInfo->isValid();
|
||||
|
||||
auto report = [&](ReportPolicy policy) -> ELFSyncStream {
|
||||
return {ctx, toDiagLevel(policy)};
|
||||
@@ -2952,10 +2952,10 @@ static void readSecurityNotes(Ctx &ctx) {
|
||||
}
|
||||
ctx.arg.andFeatures &= features;
|
||||
|
||||
if (ctx.aarch64PauthAbiCoreInfo.empty())
|
||||
if (!ctx.aarch64PauthAbiCoreInfo)
|
||||
continue;
|
||||
|
||||
if (f->aarch64PauthAbiCoreInfo.empty()) {
|
||||
if (!f->aarch64PauthAbiCoreInfo) {
|
||||
report(ctx.arg.zPauthReport)
|
||||
<< f
|
||||
<< ": -z pauth-report: file does not have AArch64 "
|
||||
@@ -2965,11 +2965,18 @@ static void readSecurityNotes(Ctx &ctx) {
|
||||
}
|
||||
|
||||
if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo)
|
||||
Err(ctx) << "incompatible values of AArch64 PAuth core info found\n>>> "
|
||||
<< referenceFileName << ": 0x"
|
||||
<< toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true)
|
||||
<< "\n>>> " << f << ": 0x"
|
||||
<< toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true);
|
||||
Err(ctx)
|
||||
<< "incompatible values of AArch64 PAuth core info found\n"
|
||||
<< "platform:\n"
|
||||
<< ">>> " << referenceFileName << ": 0x"
|
||||
<< toHex(ctx.aarch64PauthAbiCoreInfo->platform, /*LowerCase=*/true)
|
||||
<< "\n>>> " << f << ": 0x"
|
||||
<< toHex(f->aarch64PauthAbiCoreInfo->platform, /*LowerCase=*/true)
|
||||
<< "\nversion:\n"
|
||||
<< ">>> " << referenceFileName << ": 0x"
|
||||
<< toHex(ctx.aarch64PauthAbiCoreInfo->version, /*LowerCase=*/true)
|
||||
<< "\n>>> " << f << ": 0x"
|
||||
<< toHex(f->aarch64PauthAbiCoreInfo->version, /*LowerCase=*/true);
|
||||
}
|
||||
|
||||
// Force enable Shadow Stack.
|
||||
|
||||
@@ -948,7 +948,7 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
|
||||
} else if (ctx.arg.emachine == EM_AARCH64 &&
|
||||
type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
|
||||
ArrayRef<uint8_t> contents = data ? *data : desc;
|
||||
if (!f.aarch64PauthAbiCoreInfo.empty()) {
|
||||
if (f.aarch64PauthAbiCoreInfo) {
|
||||
return void(
|
||||
err(contents.data())
|
||||
<< "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are "
|
||||
@@ -959,7 +959,9 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
|
||||
"is invalid: expected 16 bytes, but got "
|
||||
<< size);
|
||||
}
|
||||
f.aarch64PauthAbiCoreInfo = desc;
|
||||
f.aarch64PauthAbiCoreInfo = {
|
||||
support::endian::read64<ELFT::Endianness>(&desc[0]),
|
||||
support::endian::read64<ELFT::Endianness>(&desc[8])};
|
||||
}
|
||||
|
||||
// Padding is present in the note descriptor, if necessary.
|
||||
|
||||
@@ -241,7 +241,7 @@ public:
|
||||
StringRef sourceFile;
|
||||
uint32_t andFeatures = 0;
|
||||
bool hasCommonSyms = false;
|
||||
ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
|
||||
std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;
|
||||
};
|
||||
|
||||
// .o file.
|
||||
|
||||
@@ -354,11 +354,11 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
if (!ctx.aarch64PauthAbiCoreInfo.empty()) {
|
||||
if (ctx.aarch64PauthAbiCoreInfo) {
|
||||
write32(ctx, buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
|
||||
write32(ctx, buf + offset + 4, ctx.aarch64PauthAbiCoreInfo.size());
|
||||
memcpy(buf + offset + 8, ctx.aarch64PauthAbiCoreInfo.data(),
|
||||
ctx.aarch64PauthAbiCoreInfo.size());
|
||||
write32(ctx, buf + offset + 4, AArch64PauthAbiCoreInfo::size());
|
||||
write64(ctx, buf + offset + 8, ctx.aarch64PauthAbiCoreInfo->platform);
|
||||
write64(ctx, buf + offset + 16, ctx.aarch64PauthAbiCoreInfo->version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,8 +366,8 @@ size_t GnuPropertySection::getSize() const {
|
||||
uint32_t contentSize = 0;
|
||||
if (ctx.arg.andFeatures != 0)
|
||||
contentSize += ctx.arg.is64 ? 16 : 12;
|
||||
if (!ctx.aarch64PauthAbiCoreInfo.empty())
|
||||
contentSize += 4 + 4 + ctx.aarch64PauthAbiCoreInfo.size();
|
||||
if (ctx.aarch64PauthAbiCoreInfo)
|
||||
contentSize += 4 + 4 + AArch64PauthAbiCoreInfo::size();
|
||||
assert(contentSize != 0);
|
||||
return contentSize + 16;
|
||||
}
|
||||
@@ -4967,7 +4967,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
|
||||
ctx.in.iplt = std::make_unique<IpltSection>(ctx);
|
||||
add(*ctx.in.iplt);
|
||||
|
||||
if (ctx.arg.andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty()) {
|
||||
if (ctx.arg.andFeatures || ctx.aarch64PauthAbiCoreInfo) {
|
||||
ctx.in.gnuProperty = std::make_unique<GnuPropertySection>(ctx);
|
||||
add(*ctx.in.gnuProperty);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,12 @@
|
||||
# RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
|
||||
|
||||
# ERR1: error: incompatible values of AArch64 PAuth core info found
|
||||
# ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000
|
||||
# ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000
|
||||
# ERR1-NEXT: platform:
|
||||
# ERR1-NEXT: >>> tag1.o: 0x2a
|
||||
# ERR1-NEXT: >>> tag2.o: 0x2a
|
||||
# ERR1-NEXT: version:
|
||||
# ERR1-NEXT: >>> tag1.o: 0x01
|
||||
# ERR1-NEXT: >>> tag2.o: 0x02
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o
|
||||
# RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s
|
||||
|
||||
Reference in New Issue
Block a user