[lld] [llvm] [RISCV] Support .note.gnu.property for enable Zicfiss and Zicfilp extension (PR #77414)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 14 01:11:16 PDT 2024
https://github.com/SuHo-llrr updated https://github.com/llvm/llvm-project/pull/77414
>From 61aaf8df2fbd0abfa4dfcd807f3366ce67f5603d Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 14:36:43 +0800
Subject: [PATCH 1/5] [RISCV][ELF] Add RISCV GNU property label
---
llvm/include/llvm/BinaryFormat/ELF.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index f296acc2ca4bb..c8da286fc9588 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1737,6 +1737,7 @@ enum : unsigned {
GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000,
GNU_PROPERTY_AARCH64_FEATURE_PAUTH = 0xc0000001,
GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002,
+ GNU_PROPERTY_RISCV_FEATURE_1_AND = 0xc0000000,
GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000,
GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1,
@@ -1796,6 +1797,12 @@ enum : unsigned {
GNU_PROPERTY_X86_ISA_1_V4 = 1 << 3,
};
+// riscv processor feature bits.
+enum : unsigned {
+ GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE = 1 << 0,
+ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS = 1 << 1,
+};
+
// FreeBSD note types.
enum {
NT_FREEBSD_ABI_TAG = 1,
>From 601815aafb3c9f06766a326914c1d710ffbbb2a1 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 14:38:34 +0800
Subject: [PATCH 2/5] [RISCV][ELF] Emit .note.gnu.property for
Zicfiss/Zicfilip(CFI extension)
---
.../MCTargetDesc/RISCVTargetStreamer.cpp | 53 ++++++++++++++++++-
.../RISCV/MCTargetDesc/RISCVTargetStreamer.h | 7 +++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
index 0f92e9ed6a64d..c374eb6cf0453 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
@@ -13,7 +13,10 @@
#include "RISCVTargetStreamer.h"
#include "RISCVBaseInfo.h"
#include "RISCVMCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/RISCVAttributes.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
@@ -22,7 +25,11 @@ using namespace llvm;
RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
-void RISCVTargetStreamer::finish() { finishAttributeSection(); }
+void RISCVTargetStreamer::finish() {
+ finishAttributeSection();
+ emitGNUProgramProperties();
+}
+
void RISCVTargetStreamer::reset() {}
void RISCVTargetStreamer::emitDirectiveOptionPush() {}
@@ -52,6 +59,9 @@ void RISCVTargetStreamer::setFlagsFromFeatures(const MCSubtargetInfo &STI) {
HasRVC = STI.hasFeature(RISCV::FeatureStdExtC) ||
STI.hasFeature(RISCV::FeatureStdExtZca);
HasTSO = STI.hasFeature(RISCV::FeatureStdExtZtso);
+ HasZicfilp = STI.hasFeature(RISCV::FeatureStdExtZicfilp);
+ HasZicfiss = STI.hasFeature(RISCV::FeatureStdExtZicfiss);
+ IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
}
void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI,
@@ -77,6 +87,47 @@ void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI,
}
}
+void RISCVTargetStreamer::emitGNUProgramProperties() {
+ unsigned FeatureAndFlags = 0;
+ // Check Zicfilp or Zicfiss with features
+ // TODO should we check with codegen enable
+ // ex. -mllvm -riscv-hardware-shadow-stack=true ?
+ if (hasZicfilp())
+ FeatureAndFlags |= ELF::GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE;
+
+ if (hasZicfiss())
+ FeatureAndFlags |= ELF::GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS;
+
+ if (FeatureAndFlags == 0)
+ return;
+
+ MCStreamer &OutStreamer = getStreamer();
+ MCContext &Context = OutStreamer.getContext();
+ MCSectionELF *Nt = Context.getELFSection(".note.gnu.property", ELF::SHT_NOTE,
+ ELF::SHF_ALLOC);
+ MCSection *Cur = OutStreamer.getCurrentSectionOnly();
+ OutStreamer.switchSection(Nt);
+
+ // Emit the note header.
+ uint64_t DataSize = isRV64() ? 4 : 3;
+ OutStreamer.emitValueToAlignment(isRV64() ? Align(8) : Align(4));
+ OutStreamer.emitIntValue(4, 4); // data size for note name
+ OutStreamer.emitIntValue(4 * DataSize, 4); // data size
+ OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4); // note type
+ OutStreamer.emitBytes(StringRef("GNU", 4)); // note name
+
+ // Emit the CFI(Zicfilp/Zicfiss) properties.
+ OutStreamer.emitIntValue(ELF::GNU_PROPERTY_RISCV_FEATURE_1_AND,
+ 4); // and property
+ OutStreamer.emitIntValue(4, 4); // data size
+ OutStreamer.emitIntValue(FeatureAndFlags, 4); // data
+ if (isRV64())
+ OutStreamer.emitIntValue(0, 4); // Padding
+
+ OutStreamer.endSection(Nt);
+ OutStreamer.switchSection(Cur);
+}
+
// This part is for ascii assembly output
RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS)
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
index cb8bc21cb6355..0f3a3e501cfe2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
@@ -35,6 +35,9 @@ class RISCVTargetStreamer : public MCTargetStreamer {
RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
bool HasRVC = false;
bool HasTSO = false;
+ bool HasZicfilp = false;
+ bool HasZicfiss = false;
+ bool IsRV64 = false;
public:
RISCVTargetStreamer(MCStreamer &S);
@@ -58,11 +61,15 @@ class RISCVTargetStreamer : public MCTargetStreamer {
StringRef StringValue);
void emitTargetAttributes(const MCSubtargetInfo &STI, bool EmitStackAlign);
+ void emitGNUProgramProperties();
void setTargetABI(RISCVABI::ABI ABI);
RISCVABI::ABI getTargetABI() const { return TargetABI; }
void setFlagsFromFeatures(const MCSubtargetInfo &STI);
bool hasRVC() const { return HasRVC; }
bool hasTSO() const { return HasTSO; }
+ bool hasZicfilp() const { return HasZicfilp; }
+ bool hasZicfiss() const { return HasZicfiss; }
+ bool isRV64() const { return IsRV64; }
};
// This part is for ascii assembly output
>From 1e4142ed9cfcc9258aab9549ec4c5cd8e3a08a93 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 18:21:01 +0800
Subject: [PATCH 3/5] [llvm-readobj] Parse .note.gnu.property in RISCV for
Zicfiss/Zicfilip(CFI extension)
---
.../ELF/RISCV/riscv-cfi-property.s | 78 +++++++++++++++++++
llvm/tools/llvm-readobj/ELFDumper.cpp | 51 ++++++++----
2 files changed, 114 insertions(+), 15 deletions(-)
create mode 100644 llvm/test/tools/llvm-readobj/ELF/RISCV/riscv-cfi-property.s
diff --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/riscv-cfi-property.s b/llvm/test/tools/llvm-readobj/ELF/RISCV/riscv-cfi-property.s
new file mode 100644
index 0000000000000..865532196c4d0
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/riscv-cfi-property.s
@@ -0,0 +1,78 @@
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+#--- gnu-property-riscv32.s
+// RUN: llvm-mc -triple riscv32 -filetype obj gnu-property-riscv32.s -o gnu-property-riscv32.o
+// RUN: llvm-readobj -n gnu-property-riscv32.o | FileCheck -check-prefix=LLVM gnu-property-riscv32.s
+// RUN: llvm-readobj -n --elf-output-style=GNU gnu-property-riscv32.o | FileCheck -check-prefix=GNU gnu-property-riscv32.s
+
+
+// LLVM: Notes [
+// LLVM-NEXT: NoteSection {
+// LLVM-NEXT: Name: .note.gnu.property
+// LLVM-NEXT: Offset: 0x34
+// LLVM-NEXT: Size: 0x1C
+// LLVM-NEXT: Note {
+// LLVM-NEXT: Owner: GNU
+// LLVM-NEXT: Data size: 0xC
+// LLVM-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
+// LLVM-NEXT: Property [
+// LLVM-NEXT: riscv feature: Zicfilp, Zicfiss
+// LLVM-NEXT: ]
+// LLVM-NEXT: }
+// LLVM-NEXT: }
+// LLVM-NEXT: ]
+
+// GNU: Displaying notes found in: .note.gnu.property
+// GNU-NEXT: Owner Data size Description
+// GNU-NEXT: GNU 0x0000000c NT_GNU_PROPERTY_TYPE_0 (property note)
+// GNU-NEXT: Properties: riscv feature: Zicfilp, Zicfiss
+
+// GNU Note Section Example
+.section .note.gnu.property, "a"
+ .p2align 2
+ .long 4
+ .long 12;
+ .long 5
+ .asciz "GNU"
+ .long 0xc0000000
+ .long 4
+ .long 3
+
+#--- gnu-property-riscv64.s
+// RUN: llvm-mc -triple riscv64 -filetype obj gnu-property-riscv64.s -o gnu-property-riscv64.o
+// RUN: llvm-readobj -n gnu-property-riscv64.o | FileCheck -check-prefix=LLVM64 gnu-property-riscv64.s
+// RUN: llvm-readobj -n --elf-output-style=GNU gnu-property-riscv64.o | FileCheck -check-prefix=GNU64 gnu-property-riscv64.s
+
+
+// LLVM64: Notes [
+// LLVM64-NEXT: NoteSection {
+// LLVM64-NEXT: Name: .note.gnu.property
+// LLVM64-NEXT: Offset: 0x40
+// LLVM64-NEXT: Size: 0x20
+// LLVM64-NEXT: Note {
+// LLVM64-NEXT: Owner: GNU
+// LLVM64-NEXT: Data size: 0x10
+// LLVM64-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
+// LLVM64-NEXT: Property [
+// LLVM64-NEXT: riscv feature: Zicfilp, Zicfiss
+// LLVM64-NEXT: ]
+// LLVM64-NEXT: }
+// LLVM64-NEXT: }
+// LLVM64-NEXT: ]
+
+// GNU64: Displaying notes found in: .note.gnu.property
+// GNU64-NEXT: Owner Data size Description
+// GNU64-NEXT: GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 (property note)
+// GNU64-NEXT: Properties: riscv feature: Zicfilp, Zicfiss
+
+// GNU Note Section Example
+.section .note.gnu.property, "a"
+ .p2align 2
+ .long 4
+ .long 16;
+ .long 5
+ .asciz "GNU"
+ .long 0xc0000000
+ .long 4
+ .long 3
+ .long 0
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index a752cc4015293..096fdf58bacac 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5239,7 +5239,7 @@ static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,
template <typename ELFT>
static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
- ArrayRef<uint8_t> Data) {
+ ArrayRef<uint8_t> Data, unsigned EMachine) {
std::string str;
raw_string_ostream OS(str);
uint32_t PrData;
@@ -5272,8 +5272,19 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
return OS.str();
case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
case GNU_PROPERTY_X86_FEATURE_1_AND:
- OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "
- : "x86 feature: ");
+ if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
+ static_assert(
+ GNU_PROPERTY_AARCH64_FEATURE_1_AND ==
+ GNU_PROPERTY_RISCV_FEATURE_1_AND,
+ "AARCH64 and RISCV have different FEATURE_1_AND property type");
+ if (EMachine == ELF::EM_RISCV)
+ OS << "riscv feature: ";
+ else
+ OS << "aarch64 feature: ";
+ } else {
+ OS << "x86 feature: ";
+ }
+
if (DataSize != 4) {
OS << format("<corrupt length: 0x%x>", DataSize);
return OS.str();
@@ -5283,14 +5294,21 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
OS << "<None>";
return OS.str();
}
+
if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
- DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
- DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
- DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
+ if (EMachine == ELF::EM_RISCV) {
+ DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE, "Zicfilp");
+ DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS, "Zicfiss");
+ } else {
+ DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
+ DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
+ DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
+ }
} else {
DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
}
+
if (PrData)
OS << format("<unknown flags: 0x%x>", PrData);
return OS.str();
@@ -5347,7 +5365,8 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
}
template <typename ELFT>
-static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
+static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr,
+ unsigned EMachine) {
using Elf_Word = typename ELFT::Word;
SmallVector<std::string, 4> Properties;
@@ -5365,8 +5384,8 @@ static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
Properties.push_back(OS.str());
break;
}
- Properties.push_back(
- getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
+ Properties.push_back(getGNUProperty<ELFT>(
+ Type, DataSize, Arr.take_front(PaddedSize), EMachine));
Arr = Arr.drop_front(PaddedSize);
}
@@ -5418,7 +5437,7 @@ static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) {
template <typename ELFT>
static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
- ArrayRef<uint8_t> Desc) {
+ ArrayRef<uint8_t> Desc, unsigned EMachine) {
// Return true if we were able to pretty-print the note, false otherwise.
switch (NoteType) {
default:
@@ -5440,7 +5459,7 @@ static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
break;
case ELF::NT_GNU_PROPERTY_TYPE_0:
OS << " Properties:";
- for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
+ for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
OS << " " << Property << "\n";
break;
}
@@ -6130,7 +6149,8 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
// Print the description, or fallback to printing raw bytes for unknown
// owners/if we fail to pretty-print the contents.
if (Name == "GNU") {
- if (printGNUNote<ELFT>(OS, Type, Descriptor))
+ if (printGNUNote<ELFT>(OS, Type, Descriptor,
+ this->Obj.getHeader().e_machine))
return Error::success();
} else if (Name == "FreeBSD") {
if (std::optional<FreeBSDNote> N =
@@ -7746,7 +7766,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
template <typename ELFT>
static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
- ScopedPrinter &W) {
+ ScopedPrinter &W, unsigned EMachine) {
// Return true if we were able to pretty-print the note, false otherwise.
switch (NoteType) {
default:
@@ -7771,7 +7791,7 @@ static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
break;
case ELF::NT_GNU_PROPERTY_TYPE_0:
ListScope D(W, "Property");
- for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
+ for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
W.printString(Property);
break;
}
@@ -7887,7 +7907,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
// Print the description, or fallback to printing raw bytes for unknown
// owners/if we fail to pretty-print the contents.
if (Name == "GNU") {
- if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
+ if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W,
+ this->Obj.getHeader().e_machine))
return Error::success();
} else if (Name == "FreeBSD") {
if (std::optional<FreeBSDNote> N =
>From 1db55d65b85ca07662bdb5b4d736bb4fcc4f18b2 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 16:37:08 +0800
Subject: [PATCH 4/5] [LLD] Emit .note.gnu.property in RISCV for
Zicfiss/Zicfilip(CFI extension)
---
lld/ELF/Driver.cpp | 2 +-
lld/ELF/InputFiles.cpp | 17 ++++++++++++++---
lld/ELF/SyntheticSections.cpp | 15 ++++++++++++---
3 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index b29e1e1a67f13..8456491da77ca 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2651,7 +2651,7 @@ static void checkAndReportMissingFeature(StringRef config, uint32_t features,
// ones can be allowed (see -z pauth-report).
static void readSecurityNotes() {
if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
- config->emachine != EM_AARCH64)
+ config->emachine != EM_AARCH64 && config->emachine != EM_RISCV)
return;
config->andFeatures = -1;
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 1f496026d3ae2..e80e11714a694 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -954,9 +954,20 @@ void readGnuProperty(const InputSection &sec, ObjFile<ELFT> &f) {
continue;
}
- uint32_t featureAndType = config->emachine == EM_AARCH64
- ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
- : GNU_PROPERTY_X86_FEATURE_1_AND;
+ uint32_t featureAndType = 0;
+ switch (config->emachine) {
+ 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("unknow EMachine for GNU_PROPERTY AND");
+ }
// Read a body of a NOTE record, which consists of type-length-value fields.
ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 7b9ada40c0f67..bd6f3a3f2bb07 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -323,9 +323,18 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
memcpy(buf + 12, "GNU", 4); // Name string
- uint32_t featureAndType = config->emachine == EM_AARCH64
- ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
- : GNU_PROPERTY_X86_FEATURE_1_AND;
+ uint32_t featureAndType = 0;
+ switch (config->emachine) {
+ default:
+ 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;
+ }
unsigned offset = 16;
if (config->andFeatures != 0) {
>From 9363ff1319114e6a74e39a6a033cd9bc0a058edd Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 19:04:26 +0800
Subject: [PATCH 5/5] [LLD] Add force enable Zicfiss/Zicfilip(CFI extension)
option
---
lld/ELF/Config.h | 4 +++
lld/ELF/Driver.cpp | 42 ++++++++++++++++++++++++-
lld/test/ELF/riscv-force-cfi-property.s | 36 +++++++++++++++++++++
3 files changed, 81 insertions(+), 1 deletion(-)
create mode 100644 lld/test/ELF/riscv-force-cfi-property.s
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index c55b547a733c7..6c43d3aadbdbe 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -188,6 +188,8 @@ struct Config {
StringRef zBtiReport = "none";
StringRef zCetReport = "none";
StringRef zPauthReport = "none";
+ StringRef zZicfilpReport = "none";
+ StringRef zZicfissReport = "none";
bool ltoBBAddrMap;
llvm::StringRef ltoBasicBlockSections;
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
@@ -331,6 +333,8 @@ struct Config {
bool zText;
bool zRetpolineplt;
bool zWxneeded;
+ bool zForceZicfilp;
+ bool zForceZicfiss;
DiscardPolicy discard;
GnuStackKind zGnustack;
ICFLevel icf;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 8456491da77ca..54b6dc40c33a5 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -468,6 +468,13 @@ static void checkOptions() {
error("-z pauth-report only supported on AArch64");
}
+ if (config->emachine != EM_RISCV) {
+ if (config->zZicfilpReport != "none")
+ error("-z zicfilip-report only supported on RISC-V");
+ if (config->zZicfissReport != "none")
+ error("-z zicfiss-report only supported on RISC-V");
+ }
+
if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
config->zCetReport != "none")
error("-z cet-report only supported on X86 and X86_64");
@@ -1465,6 +1472,8 @@ static void readConfigs(opt::InputArgList &args) {
config->zWxneeded = hasZOption(args, "wxneeded");
setUnresolvedSymbolPolicy(args);
config->power10Stubs = args.getLastArgValue(OPT_power10_stubs_eq) != "no";
+ config->zForceZicfilp = hasZOption(args, "force-zicfilp");
+ config->zForceZicfiss = hasZOption(args, "force-zicfiss");
if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
if (arg->getOption().matches(OPT_eb))
@@ -1508,7 +1517,9 @@ static void readConfigs(opt::InputArgList &args) {
auto reports = {std::make_pair("bti-report", &config->zBtiReport),
std::make_pair("cet-report", &config->zCetReport),
- std::make_pair("pauth-report", &config->zPauthReport)};
+ std::make_pair("pauth-report", &config->zPauthReport),
+ std::make_pair("zicfilp-report", &config->zZicfilpReport),
+ std::make_pair("zicfiss-report", &config->zZicfissReport)};
for (opt::Arg *arg : args.filtered(OPT_z)) {
std::pair<StringRef, StringRef> option =
StringRef(arg->getValue()).split('=');
@@ -2685,6 +2696,17 @@ static void readSecurityNotes() {
toString(f) + ": -z cet-report: file does not have "
"GNU_PROPERTY_X86_FEATURE_1_SHSTK property");
+ checkAndReportMissingFeature(
+ config->zZicfilpReport, features,
+ GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE,
+ toString(f) + ": -z zicfilp-report: file does not have "
+ "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE property");
+
+ checkAndReportMissingFeature(
+ config->zZicfissReport, features, GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS,
+ toString(f) + ": -z zicfiss-report: file does not have "
+ "GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS property");
+
if (config->zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
if (config->zBtiReport == "none")
@@ -2697,6 +2719,24 @@ static void readSecurityNotes() {
"GNU_PROPERTY_X86_FEATURE_1_IBT property");
features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
}
+
+ if (config->zForceZicfilp &&
+ !(features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE)) {
+ features |= GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE;
+ if (config->zZicfilpReport == "none")
+ warn(toString(f) +
+ ": -z force-zicfilp: file does not have "
+ "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SIMPLE property");
+ }
+
+ if (config->zForceZicfiss &&
+ !(features & GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS)) {
+ features |= GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS;
+ if (config->zZicfissReport == "none")
+ warn(toString(f) + ": -z force-zicfiss: file does not have "
+ "GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS property");
+ }
+
if (config->zPacPlt && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {
warn(toString(f) + ": -z pac-plt: file does not have "
"GNU_PROPERTY_AARCH64_FEATURE_1_PAC property");
diff --git a/lld/test/ELF/riscv-force-cfi-property.s b/lld/test/ELF/riscv-force-cfi-property.s
new file mode 100644
index 0000000000000..1fcc84a0d5912
--- /dev/null
+++ b/lld/test/ELF/riscv-force-cfi-property.s
@@ -0,0 +1,36 @@
+# REQUIRES: riscv
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf %s -o %t.rv32_lp.o
+# RUN: ld.lld %t.rv32_lp.o -zforce-zicfilp -o %t.rv32_lp | count 0
+# RUN: llvm-readobj -n %t.rv32_lp | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf %s -o %t.rv64_lp.o
+# RUN: ld.lld %t.rv64_lp.o -zforce-zicfilp -o %t.rv64_lp | count 0
+# RUN: llvm-readobj -n %t.rv64_lp | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf %s -o %t.rv32_ss.o
+# RUN: ld.lld %t.rv32_ss.o -zforce-zicfiss -o %t.rv32_ss | count 0
+# RUN: llvm-readobj -n %t.rv32_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFISS %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf %s -o %t.rv64_ss.o
+# RUN: ld.lld %t.rv64_ss.o -zforce-zicfiss -o %t.rv64_ss | count 0
+# RUN: llvm-readobj -n %t.rv64_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFISS %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf %s -o %t.rv32_lp_ss.o
+# RUN: ld.lld %t.rv32_lp_ss.o -zforce-zicfilp -zforce-zicfiss -o %t.rv32_lp_ss | count 0
+# RUN: llvm-readobj -n %t.rv32_lp_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP_ZICFISS %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf %s -o %t.rv64_lp_ss.o
+# RUN: ld.lld %t.rv64_lp_ss.o -zforce-zicfilp -zforce-zicfiss -o %t.rv64_lp_ss | count 0
+# RUN: llvm-readobj -n %t.rv64_lp_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP_ZICFISS %s
+
+
+
+// CHECK: Name: .note.gnu.property
+// CHECK: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
+// CHECK: Property [
+// CHECK_ZICFISS: riscv feature: Zicfiss
+// CHECK_ZICFILP: riscv feature: Zicfilp
+// CHECK_ZICFILP_ZICFISS: riscv feature: Zicfilp, Zicfiss
+// CHECK: ]
+
More information about the llvm-commits
mailing list