-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[LLD][ELF][RISCV][Zicfilp] Handle .note.gnu.property sections for Zicfilp/Zicfiss features #127193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: Ming-Yi Lai (mylai-mtk) ChangesRISC-V Zicfilp/Zicfiss features indicate their adoptions as bits in the These feature bits are encoded as a mask in each input ELF files and intended to be "and"-ed together to check that all input files support a particular feature. For RISC-V Zicfilp features, there are 2 conflicting bits allocated: GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and For RISC-V Zicfiss feature, there's only one bit allocated: GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS. This bit indicates that the ELF file supports Zicfiss-based shadow stack. This patch adds the Patch is 32.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/127193.diff 7 Files Affected:
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f132b11b20c63..e452d27828779 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -229,6 +229,9 @@ struct Config {
StringRef zCetReport = "none";
StringRef zPauthReport = "none";
StringRef zGcsReport = "none";
+ StringRef zZicfilpUnlabeledReport = "none";
+ StringRef zZicfilpFuncSigReport = "none";
+ StringRef zZicfissReport = "none";
bool ltoBBAddrMap;
llvm::StringRef ltoBasicBlockSections;
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7d14180a49926..2500f58df55cc 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -414,8 +414,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 != "none")
+ ErrAlways(ctx) << "-z zicfilip-unlabeled-report is only supported on "
+ "RISC-V targets";
+ if (ctx.arg.zZicfilpFuncSigReport != "none")
+ ErrAlways(ctx) << "-z zicfilip-func-sig-report is only supported on "
+ "RISC-V targets";
+ if (ctx.arg.zZicfissReport != "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 != "none")
@@ -1623,7 +1633,12 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
auto reports = {std::make_pair("bti-report", &ctx.arg.zBtiReport),
std::make_pair("cet-report", &ctx.arg.zCetReport),
std::make_pair("gcs-report", &ctx.arg.zGcsReport),
- 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)};
for (opt::Arg *arg : args.filtered(OPT_z)) {
std::pair<StringRef, StringRef> option =
StringRef(arg->getValue()).split('=');
@@ -2796,7 +2811,7 @@ static void redirectSymbols(Ctx &ctx, ArrayRef<WrappedSymbol> wrapped) {
// ones can be allowed (see -z pauth-report).
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;
@@ -2852,6 +2867,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 == "none")
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index d43de8ce6dfef..060ea38112fd0 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -920,7 +920,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
// 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>
@@ -929,6 +929,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);
@@ -949,10 +965,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);
while (!desc.empty()) {
@@ -1050,9 +1062,10 @@ 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.
+ // Read a bitmap containing the 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
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b03c4282ab1aa..a63368597238e 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -325,15 +325,29 @@ 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:
+ Err(ctx) << "(e_machine) " << ctx.arg.emachine
+ << ": e_machine does not support .note.gnu.property section";
+ return;
+ }
+
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
diff --git a/lld/test/ELF/riscv-feature-zicfilp-func-sig.s b/lld/test/ELF/riscv-feature-zicfilp-func-sig.s
new file mode 100644
index 0000000000000..21cd348b3403e
--- /dev/null
+++ b/lld/test/ELF/riscv-feature-zicfilp-func-sig.s
@@ -0,0 +1,201 @@
+# REQUIRES: riscv
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func1-zicfilp.s -o rv32-func1-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu func2.s -o rv32-func2.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func2-zicfilp.s -o rv32-func2-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu func3.s -o rv32-func3.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func3-zicfilp.s -o rv32-func3-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func1-zicfilp.s -o rv64-func1-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu func2.s -o rv64-func2.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func2-zicfilp.s -o rv64-func2-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu func3.s -o rv64-func3.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func3-zicfilp.s -o rv64-func3-zicfilp.o
+
+## ZICFILP-func-sig should be enabled when it's enabled in all inputs
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-FUNC-SIG %s
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func3-zicfilp.o --shared -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-FUNC-SIG %s
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2-zicfilp.o rv64-func3-zicfilp.o -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-FUNC-SIG %s
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func3-zicfilp.o --shared -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-FUNC-SIG %s
+# ZICFILP-FUNC-SIG: Properties: RISC-V feature: ZICFILP-func-sig
+
+## ZICFILP-func-sig should not be enabled if it's not enabled in at least one input.
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2.o rv32-func3-zicfilp.o -o - | llvm-readelf -n - | count 0
+# RUN: ld.lld rv32-func2-zicfilp.o rv32-func3.o --shared -o - | llvm-readelf -n - | count 0
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2.o rv64-func3-zicfilp.o -o - | llvm-readelf -n - | count 0
+# RUN: ld.lld rv64-func2-zicfilp.o rv64-func3.o --shared -o - | llvm-readelf -n - | count 0
+
+## zicfilp-func-sig-report should report any input files that don't have the zicfilp-func-sig property.
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2.o rv32-func3-zicfilp.o -o /dev/null -z zicfilp-func-sig-report=warning 2>&1 | FileCheck --check-prefix=MISS-LP-WARN %s
+# RUN: not ld.lld rv32-func2-zicfilp.o rv32-func3.o --shared -o /dev/null -z zicfilp-func-sig-report=error 2>&1 | FileCheck --check-prefix=MISS-LP-ERROR %s
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o /dev/null -z zicfilp-func-sig-report=warning 2>&1 | count 0
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o /dev/null -z zicfilp-func-sig-report=error 2>&1 | count 0
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2.o rv64-func3-zicfilp.o -o /dev/null -z zicfilp-func-sig-report=warning 2>&1 | FileCheck --check-prefix=MISS-LP-WARN %s
+# RUN: not ld.lld rv64-func2-zicfilp.o rv64-func3.o --shared -o /dev/null -z zicfilp-func-sig-report=error 2>&1 | FileCheck --check-prefix=MISS-LP-ERROR %s
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2-zicfilp.o rv64-func3-zicfilp.o -o /dev/null -z zicfilp-func-sig-report=warning 2>&1 | count 0
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2-zicfilp.o rv64-func3-zicfilp.o -o /dev/null -z zicfilp-func-sig-report=error 2>&1 | count 0
+# MISS-LP-WARN: warning: rv{{32|64}}-func2.o: -z zicfilp-func-sig-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG property
+# MISS-LP-ERROR: error: rv{{32|64}}-func3.o: -z zicfilp-func-sig-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG property
+
+## An invalid -z zicfilp-func-sig-report option should give an error
+# RUN: not ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -z zicfilp-func-sig-report=nonsense 2>&1 | FileCheck --check-prefix=INVALID-REPORT %s
+# RUN: not ld.lld rv64-func1-zicfilp.o rv64-func2-zicfilp.o rv64-func3-zicfilp.o -z zicfilp-func-sig-report=nonsense 2>&1 | FileCheck --check-prefix=INVALID-REPORT %s
+# INVALID-REPORT: error: -z zicfilp-func-sig-report= parameter nonsense is not recognized
+
+#--- rv32-func1-zicfilp.s
+
+.section ".note.gnu.property", "a"
+.balign 4
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 4
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 4 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+.balign 4
+ndesc_end:
+
+.text
+.globl _start
+.type func1,%function
+func1:
+ call func2
+ ret
+
+#--- rv64-func1-zicfilp.s
+
+.section ".note.gnu.property", "a"
+.balign 8
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 8
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 4 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+.balign 8
+ndesc_end:
+
+.text
+.globl _start
+.type func1,%function
+func1:
+ call func2
+ ret
+
+#--- func2.s
+
+.text
+.globl func2
+.type func2,@function
+func2:
+ .globl func3
+ .type func3, @function
+ call func3
+ ret
+
+#--- rv32-func2-zicfilp.s
+
+.section ".note.gnu.property", "a"
+.balign 4
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 4
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 4 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+.balign 4
+ndesc_end:
+
+.text
+.globl func2
+.type func2,@function
+func2:
+ .globl func3
+ .type func3, @function
+ call func3
+ ret
+
+#--- rv64-func2-zicfilp.s
+
+.section ".note.gnu.property", "a"
+.balign 8
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 8
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 4 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+.balign 8
+ndesc_end:
+
+.text
+.globl func2
+.type func2,@function
+func2:
+ .globl func3
+ .type func3, @function
+ call func3
+ ret
+
+#--- func3.s
+
+.text
+.globl func3
+.type func3,@function
+func3:
+ ret
+
+#--- rv32-func3-zicfilp.s
+
+.section ".note.gnu.property", "a"
+.balign 4
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 4
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 4 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+.balign 4
+ndesc_end:
+
+.text
+.globl func3
+.type func3,@function
+func3:
+ ret
+
+#--- rv64-func3-zicfilp.s
+
+.section ".note.gnu.property", "a"
+.balign 8
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 8
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 4 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+.balign 8
+ndesc_end:
+
+.text
+.globl func3
+.type func3,@function
+func3:
+ ret
diff --git a/lld/test/ELF/riscv-feature-zicfilp-unlabeled.s b/lld/test/ELF/riscv-feature-zicfilp-unlabeled.s
new file mode 100644
index 0000000000000..5c244e8e44500
--- /dev/null
+++ b/lld/test/ELF/riscv-feature-zicfilp-unlabeled.s
@@ -0,0 +1,254 @@
+# REQUIRES: riscv
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func1-zicfilp.s -o rv32-func1-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func1-zicfilp-conflict.s -o rv32-func1-zicfilp-conflict.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu func2.s -o rv32-func2.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func2-zicfilp.s -o rv32-func2-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu func3.s -o rv32-func3.o
+# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func3-zicfilp.s -o rv32-func3-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func1-zicfilp.s -o rv64-func1-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func1-zicfilp-conflict.s -o rv64-func1-zicfilp-conflict.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu func2.s -o rv64-func2.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func2-zicfilp.s -o rv64-func2-zicfilp.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu func3.s -o rv64-func3.o
+# RUN: llvm-mc --filetype=obj --triple=riscv64-unknown-linux-gnu rv64-func3-zicfilp.s -o rv64-func3-zicfilp.o
+
+## ZICFILP-unlabeled should be enabled when it's enabled in all inputs
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-UNLABELED %s
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func3-zicfilp.o --shared -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-UNLABELED %s
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2-zicfilp.o rv64-func3-zicfilp.o -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-UNLABELED %s
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func3-zicfilp.o --shared -o - | llvm-readelf -n - | FileCheck --check-prefix ZICFILP-UNLABELED %s
+# ZICFILP-UNLABELED: Properties: RISC-V feature: ZICFILP-unlabeled
+
+## ZICFILP-unlabeled should not be enabled if it's not enabled in at least one input.
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2.o rv32-func3-zicfilp.o -o - | llvm-readelf -n - | count 0
+# RUN: ld.lld rv32-func2-zicfilp.o rv32-func3.o --shared -o - | llvm-readelf -n - | count 0
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2.o rv64-func3-zicfilp.o -o - | llvm-readelf -n - | count 0
+# RUN: ld.lld rv64-func2-zicfilp.o rv64-func3.o --shared -o - | llvm-readelf -n - | count 0
+
+## ZICFILP-unlabeled and ZICFILP-func-sig should conflict with each other
+# RUN: not ld.lld rv32-func1-zicfilp-conflict.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o /dev/null 2>&1 | FileCheck --check-prefix UNLABELED-FUNC-SIG-CONFLICT %s
+# RUN: not ld.lld rv64-func1-zicfilp-conflict.o rv64-func2-zicfilp.o rv64-func3-zicfilp.o -o /dev/null 2>&1 | FileCheck --check-prefix UNLABELED-FUNC-SIG-CONFLICT %s
+# UNLABELED-FUNC-SIG-CONFLICT: rv{{32|64}}-func1-zicfilp-conflict.o: file has conflicting properties: GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
+
+## zicfilp-unlabeled-report should report any input files that don't have the zicfilp-unlabeled property.
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2.o rv32-func3-zicfilp.o -o /dev/null -z zicfilp-unlabeled-report=warning 2>&1 | FileCheck --check-prefix=MISS-LP-WARN %s
+# RUN: not ld.lld rv32-func2-zicfilp.o rv32-func3.o --shared -o /dev/null -z zicfilp-unlabeled-report=error 2>&1 | FileCheck --check-prefix=MISS-LP-ERROR %s
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o /dev/null -z zicfilp-unlabeled-report=warning 2>&1 | count 0
+# RUN: ld.lld rv32-func1-zicfilp.o rv32-func2-zicfilp.o rv32-func3-zicfilp.o -o /dev/null -z zicfilp-unlabeled-report=error 2>&1 | count 0
+# RUN: ld.lld rv64-func1-zicfilp.o rv64-func2.o rv64-func3-zicfilp.o -o /dev/null -z zicfilp-unlabeled-report=warning 2>&1 | FileCheck --check-p...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The review comments on #90732 could be useful. Have you checked them?
lld/ELF/SyntheticSections.cpp
Outdated
featureAndType = GNU_PROPERTY_RISCV_FEATURE_1_AND; | ||
break; | ||
default: | ||
Err(ctx) << "(e_machine) " << ctx.arg.emachine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
llvm_unreachable (if this is indeed unreachable)
@@ -0,0 +1,201 @@ | |||
# REQUIRES: riscv | |||
# RUN: rm -rf %t && split-file %s %t && cd %t | |||
# RUN: llvm-mc --filetype=obj --triple=riscv32-unknown-linux-gnu rv32-func1-zicfilp.s -o rv32-func1-zicfilp.o |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-triple=riscv32
(make it clear that this is a generic ELF feature and make the triple shorter)
Hi MaskRay, thanks for the comments. I've gone through the comments in #90732 and applied those related to coding style to this patch. There are some other comments around the (force) GCS flag. Since this patch does not include an equivalent of the force flag, I'd just ignore them for now, but with this chance I would like to take this toolchain convention issue to a stakeholder @kito-cheng : Should we follow the "force" style (-z force-zicfilp=, -z force-zicfiss), or use the "feature" style (-z zicfilp=, -z zicfiss) for the force flag? Thanks! Updates: Address comments, beautify tests |
Update: Address comments |
I would prefer use
|
I can see that your proposal squashes together the conventional CFI flags of "reporting on something wrong" and "forcing the feature to be on/off", which is good as they are usually mutually exclusive. Though I have a few opinions:
|
Oh, wait, I should read the PR description clearly before I leave comment, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but please make sure @MaskRay is also good with that before merge :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Request changes in case this lands before I reviewed. This patch is on the 2nd page of my "Involved PR list. It may take some time.
Can you change the description to link to the psABI change?
Q: what is GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG?
Sure. The description has a new paragraph to indicate the involved psABI PRs.
A: The (p.s. The Updated: Update PR description |
@MaskRay ping |
Some AArch64 changes have updated similar BTI options. You'll need a rebase |
…iss features RISC-V Zicfilp/Zicfiss features indicate their adoptions as bits in the `.note.gnu.property` section of ELF files. This patch enables LLD to process the information correctly by parsing, checking and merging the bits from all input ELF files and writing the merged result to the output ELF file. These feature bits are encoded as a mask in each input ELF files and intended to be "and"-ed together to check that all input files support a particular feature. For RISC-V Zicfilp features, there are 2 conflicting bits allocated: GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG. They represent the adoption of the forward edge protection of control-flow integrity with the "unlabeled" or "func-sig" policy. Since these 2 policies conflicts with each other, these 2 bits also conflicts with each other. This patch adds the `-z zicfilp-unlabeled-report=none|warning|error` and `-z zicfilp-func-sig-report=none|warning|error` commandline options to make LLD report files that do not have the expected bits toggled on. For RISC-V Zicfiss feature, there's only one bit allocated: GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS. This bit indicates that the ELF file supports Zicfiss-based shadow stack. This patch adds the `-z zicfiss-report=none|warning|error` commandline option to make LLD report files that do not have the expected bit toggled on.
9b2713a
to
54dfada
Compare
Update: Rebase to |
The first three paragraphs are dense but probably not so clear. Can you replace that with:
|
Your words explains the expected behavior of LLD, but does not explain the intention/meaning of that behavior, so I adapted it to be included in the PR message (the to-be commit msg) and chose to also keep my old msgs. Hope you like it. Note that the force flags. e.g. Update: Address comments. |
Update: Address comment |
.note.gnu.property
section (withNT_GNU_PROPERTY_TYPE_0
notes) which contains aGNU_PROPERTY_RISCV_FEATURE_1_AND
property in which theGNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
/GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG
/GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_SS
bit is set:.note.gnu.property
section with the bit setPT_GNU_PROPERTY
program header is created to encompass the.note.gnu.property
section-z zicfilp-unlabeled-report=[warning|error]
/-z zicfilp-func-sig-report=[warning|error]
/-z zicfiss-report=[warning|error]
is specified, the linker will report a warning or error for any relocatable file lacking the feature bitRISC-V Zicfilp/Zicfiss features indicate their adoptions as bits in the
.note.gnu.property
section of ELF files. This patch enables LLD to process the information correctly by parsing, checking and merging the bits from all input ELF files and writing the merged result to the output ELF file.These feature bits are encoded as a mask in each input ELF files and intended to be "and"-ed together to check that all input files support a particular feature.
For RISC-V Zicfilp features, there are 2 conflicting bits allocated: GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and
GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG. They represent the adoption of the forward edge protection of control-flow integrity with the "unlabeled" or "func-sig" policy. Since these 2 policies conflicts with each other, these 2 bits also conflict with each other. This patch adds the
-z zicfilp-unlabeled-report=[none|warning|error]
and-z zicfilp-func-sig-report=[none|warning|error]
commandline options to make LLD report files that do not have the expected bits toggled on.For RISC-V Zicfiss feature, there's only one bit allocated: GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS. This bit indicates that the ELF file supports Zicfiss-based shadow stack. This patch adds the
-z zicfiss-report=[none|warning|error]
commandline option to make LLD report files that do not have the expected bit toggled on.The adoption of the
.note.gnu.property
section for RISC-V targets can be found in the psABI PR riscv-non-isa/riscv-elf-psabi-doc#417 (CFI_LP_UNLABELED
andCFI_SS
) and PR riscv-non-isa/riscv-elf-psabi-doc#434 (CFI_LP_FUNC_SIG
).