[lld] [ELF] Add context-aware diagnostic functions (PR #112319)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 15 21:57:55 PDT 2024
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/112319
>From 0735048976b738c0b03d34050542c48654979d85 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 14 Oct 2024 23:30:38 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.6-beta.1
---
lld/Common/ErrorHandler.cpp | 18 ++++++++++++++++++
lld/ELF/Config.h | 21 +++++++++++++++++++++
lld/ELF/Driver.cpp | 17 ++++++++++++++---
lld/ELF/InputFiles.cpp | 6 ++++++
lld/ELF/InputFiles.h | 2 ++
lld/ELF/Target.cpp | 9 +++++++++
lld/ELF/Target.h | 2 ++
lld/include/lld/Common/ErrorHandler.h | 15 ++++++++++++++-
8 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/lld/Common/ErrorHandler.cpp b/lld/Common/ErrorHandler.cpp
index 4e3a1bc31ade50..21755481665961 100644
--- a/lld/Common/ErrorHandler.cpp
+++ b/lld/Common/ErrorHandler.cpp
@@ -335,3 +335,21 @@ void ErrorHandler::fatal(const Twine &msg) {
error(msg);
exitLld(1);
}
+
+SyncStream::~SyncStream() {
+ os.flush();
+ switch (level) {
+ case DiagLevel::Log:
+ e.log(buf);
+ break;
+ case DiagLevel::Warn:
+ e.warn(buf);
+ break;
+ case DiagLevel::Err:
+ e.error(buf);
+ break;
+ case DiagLevel::Fatal:
+ e.fatal(buf);
+ break;
+ }
+}
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f5d65d26ef4479..59bae75794571b 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -547,6 +547,8 @@ struct Ctx {
LinkerScript *script;
std::unique_ptr<TargetInfo> target;
+ ErrorHandler *e;
+
// These variables are initialized by Writer and should not be used before
// Writer is initialized.
uint8_t *bufferStart;
@@ -679,6 +681,25 @@ static inline void internalLinkerError(StringRef loc, const Twine &msg) {
llvm::getBugReportMsg());
}
+struct ELFSyncStream : SyncStream {
+ Ctx &ctx;
+ ELFSyncStream(Ctx &ctx, DiagLevel level)
+ : SyncStream(*ctx.e, level), ctx(ctx) {}
+};
+
+template <typename T>
+std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>,
+ const ELFSyncStream &>
+operator<<(const ELFSyncStream &s, T &&v) {
+ s.os << std::forward<T>(v);
+ return s;
+}
+
+ELFSyncStream Log(Ctx &ctx);
+ELFSyncStream Warn(Ctx &ctx);
+ELFSyncStream Err(Ctx &ctx);
+ELFSyncStream Fatal(Ctx &ctx);
+
} // namespace lld::elf
#endif
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index afacbbfe9099cc..4774047de8442d 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -91,6 +91,13 @@ void elf::errorOrWarn(const Twine &msg) {
error(msg);
}
+ELFSyncStream elf::Log(Ctx &ctx) { return {ctx, DiagLevel::Log}; }
+ELFSyncStream elf::Warn(Ctx &ctx) { return {ctx, DiagLevel::Warn}; }
+ELFSyncStream elf::Err(Ctx &ctx) {
+ return {ctx, ctx.arg.noinhibitExec ? DiagLevel::Warn : DiagLevel::Err};
+}
+ELFSyncStream elf::Fatal(Ctx &ctx) { return {ctx, DiagLevel::Fatal}; }
+
Ctx::Ctx() : driver(*this) {}
void Ctx::reset() {
@@ -101,6 +108,8 @@ void Ctx::reset() {
script = nullptr;
target.reset();
+ e = nullptr;
+
bufferStart = nullptr;
mainPart = nullptr;
tlsPhdr = nullptr;
@@ -169,6 +178,7 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
Ctx &ctx = elf::ctx;
LinkerScript script(ctx);
ctx.script = &script;
+ ctx.e = &context->e;
ctx.symAux.emplace_back();
ctx.symtab = std::make_unique<SymbolTable>(ctx);
@@ -2780,8 +2790,9 @@ 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 == "none")
- warn(toString(f) + ": -z force-bti: file does not have "
- "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
+ 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 == "none")
@@ -3048,7 +3059,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
oldFilenames.insert(f->getName());
for (InputFile *newFile : newInputFiles)
if (!oldFilenames.contains(newFile->getName()))
- errorOrWarn("input file '" + newFile->getName() + "' added after LTO");
+ Err(ctx) << "input file '" << newFile->getName() << "' added after LTO";
}
// Handle --exclude-libs again because lto.tmp may reference additional
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 3d02ef8b77abaa..a3e9bb9daa52ff 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -66,6 +66,12 @@ std::string lld::toString(const InputFile *f) {
return std::string(f->toStringCache);
}
+const ELFSyncStream &elf::operator<<(const ELFSyncStream &s,
+ const InputFile *f) {
+ s << toString(f);
+ return s;
+}
+
static ELFKind getELFKind(MemoryBufferRef mb, StringRef archiveName) {
unsigned char size;
unsigned char endian;
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index f80413b215047d..e00e2c83d017c2 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -386,6 +386,8 @@ ELFFileBase *createObjFile(Ctx &, MemoryBufferRef mb,
std::string replaceThinLTOSuffix(Ctx &, StringRef path);
+const ELFSyncStream &operator<<(const ELFSyncStream &, const InputFile *);
+
} // namespace elf
} // namespace lld
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 96d132a2a8f369..b38446f287bf71 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -45,6 +45,15 @@ std::string lld::toString(RelType type) {
return std::string(s);
}
+const ELFSyncStream &elf::operator<<(const ELFSyncStream &s, RelType type) {
+ StringRef buf = getELFRelocationTypeName(s.ctx.arg.emachine, type);
+ if (buf == "Unknown")
+ s << ("Unknown (" + Twine(type) + ")").str();
+ else
+ s << buf;
+ return s;
+}
+
void elf::setTarget(Ctx &ctx) {
switch (ctx.arg.emachine) {
case EM_386:
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 27986b0a127e8e..250a29d6184313 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -327,6 +327,8 @@ inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
*bufLoc = val;
return val;
}
+
+const ELFSyncStream &operator<<(const ELFSyncStream &, RelType);
} // namespace elf
} // namespace lld
diff --git a/lld/include/lld/Common/ErrorHandler.h b/lld/include/lld/Common/ErrorHandler.h
index 0b69bb6202b32c..6bc9d81c1741a8 100644
--- a/lld/include/lld/Common/ErrorHandler.h
+++ b/lld/include/lld/Common/ErrorHandler.h
@@ -73,11 +73,11 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include <mutex>
namespace llvm {
class DiagnosticInfo;
-class raw_ostream;
}
namespace lld {
@@ -152,6 +152,19 @@ void message(const Twine &msg, llvm::raw_ostream &s = outs());
void warn(const Twine &msg);
uint64_t errorCount();
+enum class DiagLevel { Log, Warn, Err, Fatal };
+
+class SyncStream {
+ ErrorHandler &e;
+ DiagLevel level;
+ std::string buf;
+
+public:
+ mutable llvm::raw_string_ostream os{buf};
+ SyncStream(ErrorHandler &e, DiagLevel level) : e(e), level(level) {}
+ ~SyncStream();
+};
+
[[noreturn]] void exitLld(int val);
void diagnosticHandler(const llvm::DiagnosticInfo &di);
More information about the llvm-commits
mailing list