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
3 changes: 3 additions & 0 deletions lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ struct Config {
ReportPolicy zGcsReport = ReportPolicy::None;
ReportPolicy zGcsReportDynamic = ReportPolicy::None;
ReportPolicy zExecuteOnlyReport = ReportPolicy::None;
ReportPolicy zZicfilpUnlabeledReport = ReportPolicy::None;
ReportPolicy zZicfilpFuncSigReport = ReportPolicy::None;
ReportPolicy zZicfissReport = ReportPolicy::None;
bool ltoBBAddrMap;
llvm::StringRef ltoBasicBlockSections;
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
Expand Down
52 changes: 48 additions & 4 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,18 @@ static void checkOptions(Ctx &ctx) {
<< "--pcrel-optimize is only supported on PowerPC64 targets";
}

if (ctx.arg.relaxGP && ctx.arg.emachine != EM_RISCV)
ErrAlways(ctx) << "--relax-gp is only supported on RISC-V targets";
if (ctx.arg.emachine != EM_RISCV) {
if (ctx.arg.relaxGP)
ErrAlways(ctx) << "--relax-gp is only supported on RISC-V targets";
if (ctx.arg.zZicfilpUnlabeledReport != ReportPolicy::None)
ErrAlways(ctx) << "-z zicfilip-unlabeled-report is only supported on "
"RISC-V targets";
if (ctx.arg.zZicfilpFuncSigReport != ReportPolicy::None)
ErrAlways(ctx) << "-z zicfilip-func-sig-report is only supported on "
"RISC-V targets";
if (ctx.arg.zZicfissReport != ReportPolicy::None)
ErrAlways(ctx) << "-z zicfiss-report is only supported on RISC-V targets";
}

if (ctx.arg.emachine != EM_386 && ctx.arg.emachine != EM_X86_64 &&
ctx.arg.zCetReport != ReportPolicy::None)
Expand Down Expand Up @@ -1637,7 +1647,11 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
std::make_pair("execute-only-report", &ctx.arg.zExecuteOnlyReport),
std::make_pair("gcs-report", &ctx.arg.zGcsReport),
std::make_pair("gcs-report-dynamic", &ctx.arg.zGcsReportDynamic),
std::make_pair("pauth-report", &ctx.arg.zPauthReport)};
std::make_pair("pauth-report", &ctx.arg.zPauthReport),
std::make_pair("zicfilp-unlabeled-report",
&ctx.arg.zZicfilpUnlabeledReport),
std::make_pair("zicfilp-func-sig-report", &ctx.arg.zZicfilpFuncSigReport),
std::make_pair("zicfiss-report", &ctx.arg.zZicfissReport)};
bool hasGcsReportDynamic = false;
for (opt::Arg *arg : args.filtered(OPT_z)) {
std::pair<StringRef, StringRef> option =
Expand Down Expand Up @@ -2831,9 +2845,12 @@ static void redirectSymbols(Ctx &ctx, ArrayRef<WrappedSymbol> wrapped) {
// For AArch64 PAuth-enabled object files, the core info of all of them must
// match. Missing info for some object files with matching info for remaining
// ones can be allowed (see -z pauth-report).
//
// RISC-V Zicfilp/Zicfiss extension also use the same mechanism to record
// enabled features in the GNU_PROPERTY_RISCV_FEATURE_1_AND bit mask.
static void readSecurityNotes(Ctx &ctx) {
if (ctx.arg.emachine != EM_386 && ctx.arg.emachine != EM_X86_64 &&
ctx.arg.emachine != EM_AARCH64)
ctx.arg.emachine != EM_AARCH64 && ctx.arg.emachine != EM_RISCV)
return;

ctx.arg.andFeatures = -1;
Expand Down Expand Up @@ -2885,6 +2902,33 @@ static void readSecurityNotes(Ctx &ctx) {
<< ": -z cet-report: file does not have "
"GNU_PROPERTY_X86_FEATURE_1_SHSTK property";

if (ctx.arg.emachine == EM_RISCV) {
reportUnless(ctx.arg.zZicfilpUnlabeledReport,
features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED)
<< f
<< ": -z zicfilp-unlabeled-report: file does not have "
"GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED property";

reportUnless(ctx.arg.zZicfilpFuncSigReport,
features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG)
<< f
<< ": -z zicfilp-func-sig-report: file does not have "
"GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG property";

if ((features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED) &&
(features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG))
Err(ctx) << f
<< ": file has conflicting properties: "
"GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and "
"GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG";

reportUnless(ctx.arg.zZicfissReport,
features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS)
<< f
<< ": -z zicfiss-report: file does not have "
"GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS property";
}

if (ctx.arg.zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
if (ctx.arg.zBtiReport == ReportPolicy::None)
Expand Down
28 changes: 20 additions & 8 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
}
// Read the following info from the .note.gnu.property section and write it to
// the corresponding fields in `ObjFile`:
// - Feature flags (32 bits) representing x86 or AArch64 features for
// - Feature flags (32 bits) representing x86, AArch64 or RISC-V features for
// hardware-assisted call flow control;
// - AArch64 PAuth ABI core info (16 bytes).
template <class ELFT>
Expand All @@ -979,6 +979,22 @@ static void readGnuProperty(Ctx &ctx, const InputSection &sec,
using Elf_Nhdr = typename ELFT::Nhdr;
using Elf_Note = typename ELFT::Note;

uint32_t featureAndType;
switch (ctx.arg.emachine) {
case EM_386:
case EM_X86_64:
featureAndType = GNU_PROPERTY_X86_FEATURE_1_AND;
break;
case EM_AARCH64:
featureAndType = GNU_PROPERTY_AARCH64_FEATURE_1_AND;
break;
case EM_RISCV:
featureAndType = GNU_PROPERTY_RISCV_FEATURE_1_AND;
break;
default:
return;
}

ArrayRef<uint8_t> data = sec.content();
auto err = [&](const uint8_t *place) -> ELFSyncStream {
auto diag = Err(ctx);
Expand All @@ -999,10 +1015,6 @@ static void readGnuProperty(Ctx &ctx, const InputSection &sec,
continue;
}

uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64
? GNU_PROPERTY_AARCH64_FEATURE_1_AND
: GNU_PROPERTY_X86_FEATURE_1_AND;

// Read a body of a NOTE record, which consists of type-length-value fields.
ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
const uint8_t *base = sec.content().data();
Expand Down Expand Up @@ -1066,9 +1078,9 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
}

// Object files that use processor features such as Intel Control-Flow
// Enforcement (CET) or AArch64 Branch Target Identification BTI, use a
// .note.gnu.property section containing a bitfield of feature bits like the
// GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag.
// Enforcement (CET), AArch64 Branch Target Identification BTI or RISC-V
// Zicfilp/Zicfiss extensions, use a .note.gnu.property section containing
// a bitfield of feature bits like the GNU_PROPERTY_X86_FEATURE_1_IBT flag.
//
// Since we merge bitmaps from multiple object files to create a new
// .note.gnu.property containing a single AND'ed bitmap, we discard an input
Expand Down
21 changes: 17 additions & 4 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,28 @@ GnuPropertySection::GnuPropertySection(Ctx &ctx)
ctx.arg.wordsize) {}

void GnuPropertySection::writeTo(uint8_t *buf) {
uint32_t featureAndType;
switch (ctx.arg.emachine) {
case EM_386:
case EM_X86_64:
featureAndType = GNU_PROPERTY_X86_FEATURE_1_AND;
break;
case EM_AARCH64:
featureAndType = GNU_PROPERTY_AARCH64_FEATURE_1_AND;
break;
case EM_RISCV:
featureAndType = GNU_PROPERTY_RISCV_FEATURE_1_AND;
break;
default:
llvm_unreachable(
"target machine does not support .note.gnu.property section");
}

write32(ctx, buf, 4); // Name size
write32(ctx, buf + 4, getSize() - 16); // Content size
write32(ctx, buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
memcpy(buf + 12, "GNU", 4); // Name string

uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64
? GNU_PROPERTY_AARCH64_FEATURE_1_AND
: GNU_PROPERTY_X86_FEATURE_1_AND;

unsigned offset = 16;
if (ctx.arg.andFeatures != 0) {
write32(ctx, buf + offset + 0, featureAndType); // Feature type
Expand Down
Loading