diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index f0e9592d85dd6..0a52dfe6901bd 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -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 thinLTOObjectSuffixReplace; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index e8acdbefa32bb..c3b89a692081c 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -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) @@ -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 option = @@ -2831,9 +2845,12 @@ static void redirectSymbols(Ctx &ctx, ArrayRef 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; @@ -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) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5f6d2b6b647ee..5b65e33370dd6 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -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 @@ -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 data = sec.content(); auto err = [&](const uint8_t *place) -> ELFSyncStream { auto diag = Err(ctx); @@ -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 desc = note.getDesc(sec.addralign); const uint8_t *base = sec.content().data(); @@ -1066,9 +1078,9 @@ InputSectionBase *ObjFile::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 diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2531227cb99b7..4a503406915e4 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -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 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..f68fbddfa6026 --- /dev/null +++ b/lld/test/ELF/riscv-feature-zicfilp-func-sig.s @@ -0,0 +1,193 @@ +# REQUIRES: riscv +## Test the ZICFILP func-sig feature. +## To lift maintenance burden, most tests are conducted only with 64-bit RISC-V +## Naming convention: *-s.s files enables ZICFILP func-sig. +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f1-s.s -o rv32-f1-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f2-s.s -o rv32-f2-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f3-s.s -o rv32-f3-s.o + +# RUN: llvm-mc --filetype=obj --triple=riscv64 f1-s.s -o f1-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f2.s -o f2.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f2-s.s -o f2-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f3.s -o f3.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f3-s.s -o f3-s.o + +## ZICFILP-func-sig should be enabled when it's enabled in all inputs +# RUN: ld.lld rv32-f1-s.o rv32-f2-s.o rv32-f3-s.o -o out.rv32 --fatal-warnings +# RUN: llvm-readelf -n out.rv32 | FileCheck --check-prefix=ZICFILP %s +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -o out --fatal-warnings +# RUN: llvm-readelf -n out | FileCheck --check-prefix=ZICFILP %s +# RUN: ld.lld f1-s.o f3-s.o --shared -o out.so --fatal-warnings +# RUN: llvm-readelf -n out.so | FileCheck --check-prefix=ZICFILP %s +# ZICFILP: 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 f1-s.o f2.o f3-s.o -o out.no --fatal-warnings +# RUN: llvm-readelf -n out.no | count 0 +# RUN: ld.lld f2-s.o f3.o --shared -o out.no.so --fatal-warnings +# RUN: llvm-readelf -n out.no.so | count 0 + +## zicfilp-func-sig-report should report any input files that don't have the +## ZICFILP-func-sig property +# RUN: ld.lld f1-s.o f2.o f3-s.o -z zicfilp-func-sig-report=warning 2>&1 | FileCheck --check-prefix=REPORT-WARN %s +# RUN: not ld.lld f2-s.o f3.o --shared -z zicfilp-func-sig-report=error 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -z zicfilp-func-sig-report=warning 2>&1 | count 0 +# REPORT-WARN: warning: f2.o: -z zicfilp-func-sig-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG property +# REPORT-ERROR: error: f3.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 f2-s.o -z zicfilp-func-sig-report=x 2>&1 | FileCheck --check-prefix=INVALID %s +# INVALID: error: unknown -z zicfilp-func-sig-report= value: x + +#--- rv32-f1-s.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 f1,%function +f1: + call f2 + ret + +#--- f1-s.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 f1,%function +f1: + call f2 + ret + +#--- f2.s +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- rv32-f2-s.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 f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- f2-s.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 f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- f3.s +.text +.globl f3 +.type f3,@function +f3: + ret + +#--- rv32-f3-s.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 f3 +.type f3,@function +f3: + ret + +#--- f3-s.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 f3 +.type f3,@function +f3: + 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..0fcd8538d24a1 --- /dev/null +++ b/lld/test/ELF/riscv-feature-zicfilp-unlabeled.s @@ -0,0 +1,221 @@ +# REQUIRES: riscv +## Test the ZICFILP unlabeled feature. +## To lift maintenance burden, most tests are conducted only with 64-bit RISC-V +## Naming convention: *-s.s files enables ZICFILP unlabeled. +## Naming convention: *-c.s files enables both of the conflicting ZICFILP unlabeled and ZICFILP func-sig features. +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f1-s.s -o rv32-f1-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f2-s.s -o rv32-f2-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f3-s.s -o rv32-f3-s.o + +# RUN: llvm-mc --filetype=obj --triple=riscv64 f1-s.s -o f1-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f1-c.s -o f1-c.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f2.s -o f2.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f2-s.s -o f2-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f3.s -o f3.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f3-s.s -o f3-s.o + +## ZICFILP-unlabeled should be enabled when it's enabled in all inputs +# RUN: ld.lld rv32-f1-s.o rv32-f2-s.o rv32-f3-s.o -o out.rv32 --fatal-warnings +# RUN: llvm-readelf -n out.rv32 | FileCheck --check-prefix=ZICFILP %s +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -o out --fatal-warnings +# RUN: llvm-readelf -n out | FileCheck --check-prefix=ZICFILP %s +# RUN: ld.lld f1-s.o f3-s.o --shared -o out.so --fatal-warnings +# RUN: llvm-readelf -n out.so | FileCheck --check-prefix=ZICFILP %s +# ZICFILP: 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 f1-s.o f2.o f3-s.o -o out.no --fatal-warnings +# RUN: llvm-readelf -n out.no | count 0 +# RUN: ld.lld f2-s.o f3.o --shared -o out.no.so --fatal-warnings +# RUN: llvm-readelf -n out.no.so | count 0 + +## zicfilp-unlabeled-report should report any input files that don't have the +## ZICFILP-unlabeled property +# RUN: ld.lld f1-s.o f2.o f3-s.o -z zicfilp-unlabeled-report=warning 2>&1 | FileCheck --check-prefix=REPORT-WARN %s +# RUN: not ld.lld f2-s.o f3.o --shared -z zicfilp-unlabeled-report=error 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -z zicfilp-unlabeled-report=warning 2>&1 | count 0 +# REPORT-WARN: warning: f2.o: -z zicfilp-unlabeled-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED property +# REPORT-ERROR: error: f3.o: -z zicfilp-unlabeled-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED property + +## An invalid -z zicfilp-unlabeled-report option should give an error +# RUN: not ld.lld f2-s.o -z zicfilp-unlabeled-report=x 2>&1 | FileCheck --check-prefix=INVALID %s +# INVALID: error: unknown -z zicfilp-unlabeled-report= value: x + +## ZICFILP-unlabeled and ZICFILP-func-sig should conflict with each other +# RUN: not ld.lld f1-c.o 2>&1 | FileCheck --check-prefix=CONFLICT %s +# CONFLICT: error: f1-c.o: file has conflicting properties: GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED and GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG + +#--- rv32-f1-s.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 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED +.balign 4 +ndesc_end: + +.text +.globl _start +.type f1,%function +f1: + call f2 + ret + +#--- f1-s.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 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED +.balign 8 +ndesc_end: + +.text +.globl _start +.type f1,%function +f1: + call f2 + ret + +#--- f1-c.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 5 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED | GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG +.balign 8 +ndesc_end: + +.text +.globl _start +.type f1,%function +f1: + call f2 + ret + +#--- f2.s +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- rv32-f2-s.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 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED +.balign 4 +ndesc_end: + +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- f2-s.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 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED +.balign 8 +ndesc_end: + +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- f3.s +.text +.globl f3 +.type f3,@function +f3: + ret + +#--- rv32-f3-s.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 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED +.balign 4 +ndesc_end: + +.text +.globl f3 +.type f3,@function +f3: + ret + +#--- f3-s.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 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED +.balign 8 +ndesc_end: + +.text +.globl f3 +.type f3,@function +f3: + ret diff --git a/lld/test/ELF/riscv-feature-zicfiss.s b/lld/test/ELF/riscv-feature-zicfiss.s new file mode 100644 index 0000000000000..4623522f5ed79 --- /dev/null +++ b/lld/test/ELF/riscv-feature-zicfiss.s @@ -0,0 +1,193 @@ +# REQUIRES: riscv +## Test the ZICFISS feature. +## To lift maintenance burden, most tests are conducted only with 64-bit RISC-V +## Naming convention: *-s.s files enable ZICFISS. +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f1-s.s -o rv32-f1-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f2-s.s -o rv32-f2-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv32 rv32-f3-s.s -o rv32-f3-s.o + +# RUN: llvm-mc --filetype=obj --triple=riscv64 f1-s.s -o f1-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f2.s -o f2.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f2-s.s -o f2-s.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f3.s -o f3.o +# RUN: llvm-mc --filetype=obj --triple=riscv64 f3-s.s -o f3-s.o + +## ZICFISS should be enabled when it's enabled in all inputs +# RUN: ld.lld rv32-f1-s.o rv32-f2-s.o rv32-f3-s.o -o out.rv32 --fatal-warnings +# RUN: llvm-readelf -n out.rv32 | FileCheck --check-prefix=ZICFISS %s +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -o out --fatal-warnings +# RUN: llvm-readelf -n out | FileCheck --check-prefix=ZICFISS %s +# RUN: ld.lld f1-s.o f3-s.o --shared -o out.so --fatal-warnings +# RUN: llvm-readelf -n out.so | FileCheck --check-prefix=ZICFISS %s +# ZICFISS: Properties: RISC-V feature: ZICFISS + +## ZICFISS should not be enabled if it's not enabled in at least one input +# RUN: ld.lld f1-s.o f2.o f3-s.o -o out.no --fatal-warnings +# RUN: llvm-readelf -n out.no | count 0 +# RUN: ld.lld f2-s.o f3.o --shared -o out.no.so --fatal-warnings +# RUN: llvm-readelf -n out.no.so | count 0 + +## zicfiss-report should report any input files that don't have the zicfiss +## property +# RUN: ld.lld f1-s.o f2.o f3-s.o -z zicfiss-report=warning 2>&1 | FileCheck --check-prefix=REPORT-WARN %s +# RUN: not ld.lld f2-s.o f3.o --shared -z zicfiss-report=error 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -z zicfiss-report=warning 2>&1 | count 0 +# RUN: ld.lld f1-s.o f2-s.o f3-s.o -z zicfiss-report=error 2>&1 | count 0 +# REPORT-WARN: warning: f2.o: -z zicfiss-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS property +# REPORT-ERROR: error: f3.o: -z zicfiss-report: file does not have GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS property + +## An invalid -z zicfiss-report option should give an error +# RUN: not ld.lld f2-s.o f3-s.o -z zicfiss-report=x 2>&1 | FileCheck --check-prefix=INVALID %s +# INVALID: error: unknown -z zicfiss-report= value: x + +#--- rv32-f1-s.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 2 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS +.balign 4 +ndesc_end: + +.text +.globl _start +.type f1,%function +f1: + call f2 + ret + +#--- f1-s.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 2 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS +.balign 8 +ndesc_end: + +.text +.globl _start +.type f1,%function +f1: + call f2 + ret + +#--- f2.s +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- rv32-f2-s.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 2 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS +.balign 4 +ndesc_end: + +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- f2-s.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 2 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS +.balign 8 +ndesc_end: + +.text +.globl f2 +.type f2,@function +f2: + .globl f3 + .type f3, @function + call f3 + ret + +#--- f3.s +.text +.globl f3 +.type f3,@function +f3: + ret + +#--- rv32-f3-s.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 2 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS +.balign 4 +ndesc_end: + +.text +.globl f3 +.type f3,@function +f3: + ret + +#--- f3-s.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 2 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS +.balign 8 +ndesc_end: + +.text +.globl f3 +.type f3,@function +f3: + ret