Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 3 additions & 2 deletions lld/ELF/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,8 +1044,9 @@ 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.has_value() &&
(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform != 0 ||
ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion != 0))
pacEntryKind = PEK_Auth;
else
pacEntryKind = PEK_AuthHint;
Expand Down
8 changes: 7 additions & 1 deletion lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "llvm/Support/GlobPattern.h"
#include "llvm/Support/TarWriter.h"
#include <atomic>
#include <cstdint>
#include <memory>
#include <mutex>
#include <optional>
Expand Down Expand Up @@ -139,6 +140,11 @@ enum class GcsPolicy { Implicit, Never, Always };
// For some options that resemble -z bti-report={none,warning,error}
enum class ReportPolicy { None, Warning, Error };

struct AArch64PauthAbiCoreInfo {
uint64_t aarch64PauthAbiPlatform;
uint64_t aarch64PauthAbiVersion;
};

struct SymbolVersion {
llvm::StringRef name;
bool isExternCpp;
Expand Down Expand Up @@ -695,7 +701,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
Expand Down
33 changes: 24 additions & 9 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2841,15 +2841,17 @@ 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.has_value() &&
(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform != 0 ||
ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion != 0);

auto report = [&](ReportPolicy policy) -> ELFSyncStream {
return {ctx, toDiagLevel(policy)};
Expand Down Expand Up @@ -2909,10 +2911,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 "
Expand All @@ -2921,12 +2923,25 @@ static void readSecurityNotes(Ctx &ctx) {
continue;
}

if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo)
Err(ctx) << "incompatible values of AArch64 PAuth core info found\n>>> "
if (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform !=
f->aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform)
Err(ctx) << "incompatible AArch64 PAuth Platform Values\n>>> "
<< referenceFileName << ": 0x"
<< toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true)
<< toHex(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform,
/*LowerCase=*/true)
<< "\n>>> " << f << ": 0x"
<< toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true);
<< toHex(f->aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform,
/*LowerCase=*/true);

if (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion !=
f->aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion)
Err(ctx) << "incompatible AArch64 PAuth Version Values\n>>> "
<< referenceFileName << ": 0x"
<< toHex(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion,
/*LowerCase=*/true)
<< "\n>>> " << f << ": 0x"
<< toHex(f->aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion,
/*LowerCase=*/true);
}

// Force enable Shadow Stack.
Expand Down
8 changes: 6 additions & 2 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,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 "
Expand All @@ -961,7 +961,11 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
"is invalid: expected 16 bytes, but got "
<< size);
}
f.aarch64PauthAbiCoreInfo = desc;
f.aarch64PauthAbiCoreInfo.emplace();
f.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform =
support::endian::read64<ELFT::Endianness>(&desc[0]);
f.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion =
support::endian::read64<ELFT::Endianness>(&desc[8]);
}

// Padding is present in the note descriptor, if necessary.
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/InputFiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class ELFFileBase : public InputFile {
StringRef sourceFile;
uint32_t andFeatures = 0;
bool hasCommonSyms = false;
ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;
};

// .o file.
Expand Down
16 changes: 9 additions & 7 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,20 +344,22 @@ 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, sizeof(uint64_t) * 2);
write64(ctx, buf + offset + 8,
ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform);
write64(ctx, buf + offset + 16,
ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion);
}
}

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 + sizeof(uint64_t) * 2;
assert(contentSize != 0);
return contentSize + 16;
}
Expand Down Expand Up @@ -4959,7 +4961,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);
}
Expand Down
6 changes: 3 additions & 3 deletions lld/test/ELF/aarch64-feature-pauth.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o
# 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: error: incompatible AArch64 PAuth Version Values
# 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
Expand Down
Loading