summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Driver.cpp')
-rw-r--r--lld/ELF/Driver.cpp87
1 files changed, 65 insertions, 22 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index b43da7727e22..86cc09621a91 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -46,6 +46,7 @@
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "lld/Common/Version.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -461,6 +462,8 @@ static void checkOptions() {
error("-z force-bti only supported on AArch64");
if (config->zBtiReport != "none")
error("-z bti-report only supported on AArch64");
+ if (config->zPauthReport != "none")
+ error("-z pauth-report only supported on AArch64");
}
if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
@@ -1501,7 +1504,8 @@ 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("cet-report", &config->zCetReport),
+ std::make_pair("pauth-report", &config->zPauthReport)};
for (opt::Arg *arg : args.filtered(OPT_z)) {
std::pair<StringRef, StringRef> option =
StringRef(arg->getValue()).split('=');
@@ -2599,14 +2603,17 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
symtab.wrap(w.sym, w.real, w.wrap);
}
+static void reportMissingFeature(StringRef config, const Twine &report) {
+ if (config == "error")
+ error(report);
+ else if (config == "warning")
+ warn(report);
+}
+
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);
- }
+ if (!(features & mask))
+ reportMissingFeature(config, report);
}
// To enable CET (x86's hardware-assisted control flow enforcement), each
@@ -2617,12 +2624,28 @@ static void checkAndReportMissingFeature(StringRef config, uint32_t features,
//
// This is also the case with AARCH64's BTI and PAC which use the similar
// GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
-static uint32_t getAndFeatures() {
+//
+// 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).
+static void readSecurityNotes() {
if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
config->emachine != EM_AARCH64)
- return 0;
+ return;
+
+ config->andFeatures = -1;
+
+ StringRef referenceFileName;
+ if (config->emachine == EM_AARCH64) {
+ auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) {
+ return !f->aarch64PauthAbiCoreInfo.empty();
+ });
+ if (it != ctx.objectFiles.end()) {
+ ctx.aarch64PauthAbiCoreInfo = (*it)->aarch64PauthAbiCoreInfo;
+ referenceFileName = (*it)->getName();
+ }
+ }
- uint32_t ret = -1;
for (ELFFileBase *f : ctx.objectFiles) {
uint32_t features = f->andFeatures;
@@ -2658,14 +2681,31 @@ static uint32_t getAndFeatures() {
"GNU_PROPERTY_AARCH64_FEATURE_1_PAC property");
features |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
}
- ret &= features;
+ config->andFeatures &= features;
+
+ if (ctx.aarch64PauthAbiCoreInfo.empty())
+ continue;
+
+ if (f->aarch64PauthAbiCoreInfo.empty()) {
+ reportMissingFeature(config->zPauthReport,
+ toString(f) +
+ ": -z pauth-report: file does not have AArch64 "
+ "PAuth core info while '" +
+ referenceFileName + "' has one");
+ continue;
+ }
+
+ if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo)
+ errorOrWarn("incompatible values of AArch64 PAuth core info found\n>>> " +
+ referenceFileName + ": 0x" +
+ toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true) +
+ "\n>>> " + toString(f) + ": 0x" +
+ toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true));
}
// Force enable Shadow Stack.
if (config->zShstk)
- ret |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
-
- return ret;
+ config->andFeatures |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
}
static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) {
@@ -2727,13 +2767,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
// Create dynamic sections for dynamic linking and static PIE.
config->hasDynSymTab = !ctx.sharedFiles.empty() || config->isPic;
- script->addScriptReferencedSymbolsToSymTable();
-
- // Prevent LTO from removing any definition referenced by -u.
- for (StringRef name : config->undefined)
- if (Defined *sym = dyn_cast_or_null<Defined>(symtab.find(name)))
- sym->isUsedInRegularObj = true;
-
// If an entry symbol is in a static archive, pull out that file now.
if (Symbol *sym = symtab.find(config->entry))
handleUndefined(sym, "--entry");
@@ -2742,6 +2775,16 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
for (StringRef pat : args::getStrings(args, OPT_undefined_glob))
handleUndefinedGlob(pat);
+ // After potential archive member extraction involving ENTRY and
+ // -u/--undefined-glob, check whether PROVIDE symbols should be defined (the
+ // RHS may refer to definitions in just extracted object files).
+ script->addScriptReferencedSymbolsToSymTable();
+
+ // Prevent LTO from removing any definition referenced by -u.
+ for (StringRef name : config->undefined)
+ if (Defined *sym = dyn_cast_or_null<Defined>(symtab.find(name)))
+ sym->isUsedInRegularObj = true;
+
// Mark -init and -fini symbols so that the LTO doesn't eliminate them.
if (Symbol *sym = dyn_cast_or_null<Defined>(symtab.find(config->init)))
sym->isUsedInRegularObj = true;
@@ -2944,7 +2987,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
// Read .note.gnu.property sections from input object files which
// contain a hint to tweak linker's and loader's behaviors.
- config->andFeatures = getAndFeatures();
+ readSecurityNotes();
// The Target instance handles target-specific stuff, such as applying
// relocations or writing a PLT section. It also contains target-dependent