[LLD] [ELF] Make {bti,gcs}-report=none silence warnings from force-bti/gcs=always (#186343)

Previously, the implicit warnings from force-bti (or gcs=always) weren't
possible to silence.

The force-ibt/cet-report flags could also be handled the same way, but I
haven't checked with GNU ld how they behave. And there, the force-ibt
flag only produces warnings if the IBT bit is missing, while cet-report
warns if either IBT or SHSTK are missing - but force-ibt probably
shouldn't implicitly start warning for missing SHSTK.

This addresses a discrepancy to GNU ld that was noted in #186173.
This commit is contained in:
Martin Storsjö 2026-03-22 14:17:52 +02:00 committed by GitHub
parent b4084bd213
commit 4c4925f1a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 23 additions and 15 deletions

View File

@ -250,9 +250,11 @@ struct Config {
llvm::StringRef cmseInputLib;
llvm::StringRef cmseOutputLib;
ReportPolicy zBtiReport = ReportPolicy::None;
llvm::StringRef zBtiReportSource;
ReportPolicy zCetReport = ReportPolicy::None;
ReportPolicy zPauthReport = ReportPolicy::None;
ReportPolicy zGcsReport = ReportPolicy::None;
llvm::StringRef zGcsReportSource;
ReportPolicy zGcsReportDynamic = ReportPolicy::None;
ReportPolicy zExecuteOnlyReport = ReportPolicy::None;
ReportPolicy zZicfilpUnlabeledReport = ReportPolicy::None;

View File

@ -1706,6 +1706,15 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
ErrAlways(ctx) << errPrefix << pat.takeError() << ": " << kv.first;
}
if (ctx.arg.zForceBti) {
ctx.arg.zBtiReport = ReportPolicy::Warning;
ctx.arg.zBtiReportSource = "-z force-bti";
}
if (ctx.arg.zGcs == GcsPolicy::Always) {
ctx.arg.zGcsReport = ReportPolicy::Warning;
ctx.arg.zGcsReportSource = "-z gcs";
}
auto reports = {
std::make_pair("bti-report", &ctx.arg.zBtiReport),
std::make_pair("cet-report", &ctx.arg.zCetReport),
@ -1737,6 +1746,10 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
continue;
}
hasGcsReportDynamic |= option.first == "gcs-report-dynamic";
if (option.first == "bti-report")
ctx.arg.zBtiReportSource = "-z bti-report";
else if (option.first == "gcs-report")
ctx.arg.zGcsReportSource = "-z gcs-report";
}
}
@ -2946,14 +2959,14 @@ static void readSecurityNotes(Ctx &ctx) {
reportUnless(ctx.arg.zBtiReport,
features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
<< f
<< ": -z bti-report: file does not have "
<< f << ": " << ctx.arg.zBtiReportSource
<< ": file does not have "
"GNU_PROPERTY_AARCH64_FEATURE_1_BTI property";
reportUnless(ctx.arg.zGcsReport,
features & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
<< f
<< ": -z gcs-report: file does not have "
<< f << ": " << ctx.arg.zGcsReportSource
<< ": file does not have "
"GNU_PROPERTY_AARCH64_FEATURE_1_GCS property";
reportUnless(ctx.arg.zCetReport, features & GNU_PROPERTY_X86_FEATURE_1_IBT)
@ -3008,10 +3021,6 @@ static void readSecurityNotes(Ctx &ctx) {
if (ctx.arg.zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
if (ctx.arg.zBtiReport == ReportPolicy::None)
Warn(ctx) << f
<< ": -z force-bti: file does not have "
"GNU_PROPERTY_AARCH64_FEATURE_1_BTI property";
} else if (ctx.arg.zForceIbt &&
!(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
if (ctx.arg.zCetReport == ReportPolicy::None)
@ -3020,13 +3029,6 @@ static void readSecurityNotes(Ctx &ctx) {
"GNU_PROPERTY_X86_FEATURE_1_IBT property";
features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
}
if (ctx.arg.zGcs == GcsPolicy::Always &&
!(features & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)) {
if (ctx.arg.zGcsReport == ReportPolicy::None)
Warn(ctx) << f
<< ": -z gcs: file does not have "
"GNU_PROPERTY_AARCH64_FEATURE_1_GCS property";
}
if (ctx.arg.zPacPlt && !(hasValidPauthAbiCoreInfo ||
(features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC))) {
Warn(ctx) << f

View File

@ -230,6 +230,9 @@
# 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:
## Ensure that warnings from force-bti can be silenced with bti-report=none.
# RUN: ld.lld %t.o %t2.o -z force-bti -z bti-report=none %t.so -o %t.so 2>&1 | count 0
# RUN: llvm-readelf -n %tforcebti.exe | FileCheck --check-prefix=BTIPROP %s
# RUN: llvm-readelf --dynamic-table %tforcebti.exe | FileCheck --check-prefix BTIDYN %s
# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+bti --no-show-raw-insn %tforcebti.exe | FileCheck --check-prefix=FORCE %s

View File

@ -44,6 +44,7 @@
# RUN: ld.lld f1-s.o f2.o f3-s.o -z gcs-report=warning 2>&1 | FileCheck --check-prefix=REPORT-WARN %s
# RUN: ld.lld f1-s.o f2.o f3-s.o -z gcs-report=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN %s
# RUN: ld.lld f1-s.o f2.o f3-s.o -z gcs-report=warning -z gcs=never 2>&1 | FileCheck --check-prefix=REPORT-WARN %s
# RUN: ld.lld f1-s.o f2.o f3-s.o -z gcs-report=none -z gcs=always 2>&1 | count 0
# RUN: not ld.lld f2-s.o f3.o --shared -z gcs-report=error 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s
# RUN: ld.lld f1-s.o f2-s.o f3-s.o -z gcs-report=warning -z gcs=always 2>&1 | count 0