[lld] 2b4e605 - [lld] Add cet-report and bti-report flags

Daniel Kiss via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 16 07:26:31 PST 2021


Author: Daniel Kiss
Date: 2021-12-16T16:26:26+01:00
New Revision: 2b4e6052b3bfff7177d81a747e9f48b44da9eb1c

URL: https://github.com/llvm/llvm-project/commit/2b4e6052b3bfff7177d81a747e9f48b44da9eb1c
DIFF: https://github.com/llvm/llvm-project/commit/2b4e6052b3bfff7177d81a747e9f48b44da9eb1c.diff

LOG: [lld] Add cet-report and bti-report flags

Implement cet-report as supported in binutils.
bti-report has the same behaviour for AArch64-BTI.

Fixes https://github.com/llvm/llvm-project/issues/44828

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D113901

Added: 
    

Modified: 
    lld/ELF/Config.h
    lld/ELF/Driver.cpp
    lld/docs/ld.lld.1
    lld/test/ELF/aarch64-bti-pac-cli-error.s
    lld/test/ELF/aarch64-feature-bti.s
    lld/test/ELF/i386-feature-cet.s
    lld/test/ELF/x86-64-feature-cet.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f0f8eb86f44c4..0c8ce62c566a1 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -128,6 +128,8 @@ struct Configuration {
   llvm::StringRef thinLTOCacheDir;
   llvm::StringRef thinLTOIndexOnlyArg;
   llvm::StringRef whyExtract;
+  StringRef zBtiReport = "none";
+  StringRef zCetReport = "none";
   llvm::StringRef ltoBasicBlockSections;
   std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
   std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 4d6fec26bd3a8..d0007449a2b14 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -368,7 +368,13 @@ static void checkOptions() {
       error("-z pac-plt only supported on AArch64");
     if (config->zForceBti)
       error("-z force-bti only supported on AArch64");
+    if (config->zBtiReport != "none")
+      error("-z bti-report only supported on AArch64");
   }
+
+  if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
+      config->zCetReport != "none")
+    error("-z cet-report only supported on X86 and X86_64");
 }
 
 static const char *getReproduceOption(opt::InputArgList &args) {
@@ -455,6 +461,7 @@ static bool isKnownZFlag(StringRef s) {
          s == "rela" || s == "relro" || s == "retpolineplt" ||
          s == "rodynamic" || s == "shstk" || s == "text" || s == "undefs" ||
          s == "wxneeded" || s.startswith("common-page-size=") ||
+         s.startswith("bti-report=") || s.startswith("cet-report=") ||
          s.startswith("dead-reloc-in-nonalloc=") ||
          s.startswith("max-page-size=") || s.startswith("stack-size=") ||
          s.startswith("start-stop-visibility=");
@@ -970,6 +977,11 @@ static void parseClangOption(StringRef opt, const Twine &msg) {
   error(msg + ": " + StringRef(err).trim());
 }
 
+// Checks the parameter of the bti-report and cet-report options.
+static bool isValidReportString(StringRef arg) {
+  return arg == "none" || arg == "warning" || arg == "error";
+}
+
 // Initializes Config members by the command line options.
 static void readConfigs(opt::InputArgList &args) {
   errorHandler().verbose = args.hasArg(OPT_verbose);
@@ -1203,6 +1215,23 @@ static void readConfigs(opt::InputArgList &args) {
       error(errPrefix + toString(pat.takeError()));
   }
 
+  auto reports = {std::make_pair("bti-report", &config->zBtiReport),
+                  std::make_pair("cet-report", &config->zCetReport)};
+  for (opt::Arg *arg : args.filtered(OPT_z)) {
+    std::pair<StringRef, StringRef> option =
+        StringRef(arg->getValue()).split('=');
+    for (auto reportArg : reports) {
+      if (option.first != reportArg.first)
+        continue;
+      if (!isValidReportString(option.second)) {
+        error(Twine("-z ") + reportArg.first + "= parameter " + option.second +
+              " is not recognized");
+        continue;
+      }
+      *reportArg.second = option.second;
+    }
+  }
+
   for (opt::Arg *arg : args.filtered(OPT_z)) {
     std::pair<StringRef, StringRef> option =
         StringRef(arg->getValue()).split('=');
@@ -2103,6 +2132,16 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
     symtab->wrap(w.sym, w.real, w.wrap);
 }
 
+static void checkAndReportMissingFeature(StringRef config, uint32_t features,
+                                         uint32_t mask, const Twine &report) {
+  if (!(features & mask)) {
+    if (config == "error")
+      error(report);
+    else if (config == "warning")
+      warn(report);
+  }
+}
+
 // To enable CET (x86's hardware-assited control flow enforcement), each
 // source file must be compiled with -fcf-protection. Object files compiled
 // with the flag contain feature flags indicating that they are compatible
@@ -2119,14 +2158,32 @@ template <class ELFT> static uint32_t getAndFeatures() {
   uint32_t ret = -1;
   for (InputFile *f : objectFiles) {
     uint32_t features = cast<ObjFile<ELFT>>(f)->andFeatures;
+
+    checkAndReportMissingFeature(
+        config->zBtiReport, features, GNU_PROPERTY_AARCH64_FEATURE_1_BTI,
+        toString(f) + ": -z bti-report: file does not have "
+                      "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
+
+    checkAndReportMissingFeature(
+        config->zCetReport, features, GNU_PROPERTY_X86_FEATURE_1_IBT,
+        toString(f) + ": -z cet-report: file does not have "
+                      "GNU_PROPERTY_X86_FEATURE_1_IBT property");
+
+    checkAndReportMissingFeature(
+        config->zCetReport, features, GNU_PROPERTY_X86_FEATURE_1_SHSTK,
+        toString(f) + ": -z cet-report: file does not have "
+                      "GNU_PROPERTY_X86_FEATURE_1_SHSTK property");
+
     if (config->zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
-      warn(toString(f) + ": -z force-bti: file does not have "
-                         "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
       features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+      if (config->zBtiReport == "none")
+        warn(toString(f) + ": -z force-bti: file does not have "
+                           "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
     } else if (config->zForceIbt &&
                !(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
-      warn(toString(f) + ": -z force-ibt: file does not have "
-                         "GNU_PROPERTY_X86_FEATURE_1_IBT property");
+      if (config->zCetReport == "none")
+        warn(toString(f) + ": -z force-ibt: file does not have "
+                           "GNU_PROPERTY_X86_FEATURE_1_IBT property");
       features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
     }
     if (config->zPacPlt && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {

diff  --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 0422231d78b51..04f0982b4ced4 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -702,6 +702,16 @@ Stack permissions are recorded in the
 .Dv PT_GNU_STACK
 segment.
 .Pp
+.It Cm bti-report Ns = Ns Ar [none|warning|error]
+Specify how to report the missing GNU_PROPERTY_AARCH64_FEATURE_1_BTI property.
+.Cm none
+is the default, linker will not report the missing property otherwise will be reported as a warning or an error.
+.Pp
+.It Cm cet-report Ns = Ns Ar [none|warning|error]
+Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_IBT or GNU_PROPERTY_X86_FEATURE_1_SHSTK properties.
+.Cm none
+is the default, linker will not report the missing property otherwise will be reported as a warning or an error.
+.Pp
 .It Cm force-bti
 Force enable AArch64 BTI instruction in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property.
 .Pp

diff  --git a/lld/test/ELF/aarch64-bti-pac-cli-error.s b/lld/test/ELF/aarch64-bti-pac-cli-error.s
index 8155097674e76..b8ab1a28fa5a8 100644
--- a/lld/test/ELF/aarch64-bti-pac-cli-error.s
+++ b/lld/test/ELF/aarch64-bti-pac-cli-error.s
@@ -1,12 +1,18 @@
 # REQUIRES: x86
 # RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj -o %t.o %s
-# RUN: not ld.lld -z pac-plt -z force-bti %t.o -o /dev/null 2>&1 | FileCheck %s
+# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=error %t.o -o /dev/null 2>&1 | FileCheck %s
 #
-## Check that we error if -z pac-plt and -z force-bti are used when target is not
+## Check that we error if -z pac-plt, -z force-bti and -z bti-report=error are used when target is not
 ## aarch64
 
 # CHECK: error: -z pac-plt only supported on AArch64
 # CHECK-NEXT: error: -z force-bti only supported on AArch64
+# CHECK-NEXT: error: -z bti-report only supported on AArch64
+
+# RUN: not ld.lld -z bti-report=something %t.o -o /dev/null 2>&1 | \
+# RUN:     FileCheck --check-prefix=REPORT_INVALID %s
+# REPORT_INVALID: error: -z bti-report= parameter something is not recognized
+# REPORT_INVALID-EMPTY:
 
         .globl start
 start:  ret

diff  --git a/lld/test/ELF/aarch64-feature-bti.s b/lld/test/ELF/aarch64-feature-bti.s
index e9bbd9eaa38bc..7035c9e714a35 100644
--- a/lld/test/ELF/aarch64-feature-bti.s
+++ b/lld/test/ELF/aarch64-feature-bti.s
@@ -187,9 +187,11 @@
 ## from the file without the .note.gnu.property.
 
 # RUN: ld.lld %t.o %t2.o -z force-bti %t.so -o %tforcebti.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s
+# RUN: not ld.lld %t.o %t2.o -z force-bti -z bti-report=error %t.so -o %tfailifnotbti.exe 2>&1 | FileCheck --check-prefix=BTI_REPORT-ERROR %s
 
 # FORCE-WARN: aarch64-feature-bti.s.tmp2.o: -z force-bti: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property
-
+# BTI_REPORT-ERROR: aarch64-feature-bti.s.tmp2.o: -z bti-report: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property
+# BTI_REPORT-ERROR-EMPTY:
 
 # RUN: llvm-readelf -n %tforcebti.exe | FileCheck --check-prefix=BTIPROP %s
 # RUN: llvm-readelf --dynamic-table %tforcebti.exe | FileCheck --check-prefix BTIDYN %s

diff  --git a/lld/test/ELF/i386-feature-cet.s b/lld/test/ELF/i386-feature-cet.s
index 25a44ee6e52da..d748a98e997c7 100644
--- a/lld/test/ELF/i386-feature-cet.s
+++ b/lld/test/ELF/i386-feature-cet.s
@@ -23,6 +23,23 @@
 # RUN:   | FileCheck --check-prefix=WARN %s
 # WARN: {{.*}}.o: -z force-ibt: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
 
+# RUN: not ld.lld -e func1 %t.o %t3.o -o /dev/null -z cet-report=something 2>&1 \
+# RUN:   | FileCheck --check-prefix=REPORT_INVALID %s
+# REPORT_INVALID: error: -z cet-report= parameter something is not recognized
+# REPORT_INVALID-EMPTY:
+
+# RUN: ld.lld -e func1 %t.o %t3.o -o /dev/null -z cet-report=warning 2>&1 \
+# RUN:   | FileCheck --check-prefix=CET_REPORT_WARN %s
+# CET_REPORT_WARN: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
+# CET_REPORT_WARN: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property
+# CET_REPORT_WARN-EMPTY:
+
+# RUN: not ld.lld -e func1 %t.o %t3.o -o /dev/null -z cet-report=error 2>&1 \
+# RUN:   | FileCheck --check-prefix=CET_REPORT_ERROR %s
+# CET_REPORT_ERROR: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
+# CET_REPORT_ERROR: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property
+# CET_REPORT_ERROR-EMPTY:
+
 # RUN: ld.lld -e func1 %t.o %t4.o -o %t
 # RUN: llvm-readelf -n %t | FileCheck --check-prefix=NOSHSTK %s
 

diff  --git a/lld/test/ELF/x86-64-feature-cet.s b/lld/test/ELF/x86-64-feature-cet.s
index 7cd26696dc5ae..5322bbdf3f383 100644
--- a/lld/test/ELF/x86-64-feature-cet.s
+++ b/lld/test/ELF/x86-64-feature-cet.s
@@ -23,6 +23,29 @@
 # RUN:   | FileCheck --check-prefix=WARN %s
 # WARN: {{.*}}.o: -z force-ibt: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
 
+# RUN:not ld.lld -e func1 %t.o %t3.o -o /dev/null -z cet-report=something 2>&1 \
+# RUN:   | FileCheck --check-prefix=REPORT_INVALID %s
+# REPORT_INVALID: error: -z cet-report= parameter something is not recognized
+# REPORT_INVALID-EMPTY:
+
+# RUN: ld.lld -e func1 %t.o %t3.o -o /dev/null  -z force-ibt -z cet-report=warning 2>&1 \
+# RUN:   | FileCheck --check-prefix=REPORT_FORCE %s
+# REPORT_FORCE: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
+# REPORT_FORCE: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property
+# REPORT_FORCE-EMPTY:
+
+# RUN: ld.lld -e func1 %t.o %t3.o -o /dev/null -z cet-report=warning 2>&1 \
+# RUN:   | FileCheck --check-prefix=CET_REPORT_WARN %s
+# CET_REPORT_WARN: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
+# CET_REPORT_WARN: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property
+# CET_REPORT_WARN-EMPTY:
+
+# RUN: not ld.lld -e func1 %t.o %t3.o -o /dev/null -z cet-report=error 2>&1 \
+# RUN:   | FileCheck --check-prefix=CET_REPORT_ERROR %s
+# CET_REPORT_ERROR: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property
+# CET_REPORT_ERROR: {{.*}}.o: -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property
+# CET_REPORT_ERROR-EMPTY:
+
 # RUN: ld.lld -e func1 %t.o %t4.o -o %t
 # RUN: llvm-readelf -n %t | FileCheck --check-prefix=NOSHSTK %s
 


        


More information about the llvm-commits mailing list