[lld] 1f13713 - [ELF] Change getSrcMsg to use ELFSyncStream. NFC

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 29 17:18:28 PST 2024


Author: Fangrui Song
Date: 2024-11-29T17:18:22-08:00
New Revision: 1f13713dbb323d678c37efd5aa98a69e8f633b26

URL: https://github.com/llvm/llvm-project/commit/1f13713dbb323d678c37efd5aa98a69e8f633b26
DIFF: https://github.com/llvm/llvm-project/commit/1f13713dbb323d678c37efd5aa98a69e8f633b26.diff

LOG: [ELF] Change getSrcMsg to use ELFSyncStream. NFC

Added: 
    

Modified: 
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h
    lld/ELF/InputSection.cpp
    lld/ELF/InputSection.h
    lld/ELF/Relocations.cpp
    lld/ELF/Symbols.cpp
    lld/ELF/Target.cpp
    lld/include/lld/Common/ErrorHandler.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 3af9bc02a255a6..30fbb5d9fe4527 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -367,39 +367,6 @@ void elf::parseFiles(Ctx &ctx,
 }
 
 // Concatenates arguments to construct a string representing an error location.
-static std::string createFileLineMsg(StringRef path, unsigned line) {
-  std::string filename = std::string(path::filename(path));
-  std::string lineno = ":" + std::to_string(line);
-  if (filename == path)
-    return filename + lineno;
-  return filename + lineno + " (" + path.str() + lineno + ")";
-}
-
-std::string InputFile::getSrcMsg(const InputSectionBase &sec, const Symbol &sym,
-                                 uint64_t offset) {
-  if (kind() != ObjKind)
-    return "";
-
-  // First, look up the DWARF line table.
-  ArrayRef<InputSectionBase *> sections = getSections();
-  auto it = llvm::find(sections, &sec);
-  uint64_t sectionIndex = it != sections.end()
-                              ? it - sections.begin()
-                              : object::SectionedAddress::UndefSection;
-  DWARFCache *dwarf = cast<ELFFileBase>(this)->getDwarf();
-  if (std::optional<DILineInfo> info =
-          dwarf->getDILineInfo(offset, sectionIndex))
-    return createFileLineMsg(info->FileName, info->Line);
-
-  // If it failed, look up again as a variable.
-  if (std::optional<std::pair<std::string, unsigned>> fileLine =
-          dwarf->getVariableLoc(sym.getName()))
-    return createFileLineMsg(fileLine->first, fileLine->second);
-
-  // File.sourceFile contains STT_FILE symbol, and that is a last resort.
-  return std::string(cast<ELFFileBase>(this)->sourceFile);
-}
-
 StringRef InputFile::getNameForScript() const {
   if (archiveName.empty())
     return getName();

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index b567cda6831293..79545c4bdeb5d0 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -147,9 +147,6 @@ class InputFile {
   // True if this is an argument for --just-symbols. Usually false.
   bool justSymbols = false;
 
-  std::string getSrcMsg(const InputSectionBase &sec, const Symbol &sym,
-                        uint64_t offset);
-
   // On PPC64 we need to keep track of which files contain small code model
   // relocations that access the .toc section. To minimize the chance of a
   // relocation overflow, files that do contain said relocations should have

diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 48facf3312b0c5..51065b63f7b83a 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -16,6 +16,7 @@
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/DWARF.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
@@ -316,15 +317,40 @@ std::string InputSectionBase::getLocation(uint64_t offset) const {
   return filename + ":(" + secAndOffset;
 }
 
-// This function is intended to be used for constructing an error message.
-// The returned message looks like this:
+static void printFileLine(const ELFSyncStream &s, StringRef path,
+                          unsigned line) {
+  StringRef filename = path::filename(path);
+  s << filename << ':' << line;
+  if (filename != path)
+    s << " (" << path << ':' << line << ')';
+}
+
+// Print an error message that looks like this:
 //
 //   foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42)
-//
-//  Returns an empty string if there's no way to get line info.
-std::string InputSectionBase::getSrcMsg(const Symbol &sym,
-                                        uint64_t offset) const {
-  return file->getSrcMsg(*this, sym, offset);
+const ELFSyncStream &elf::operator<<(const ELFSyncStream &s,
+                                     InputSectionBase::SrcMsg &&msg) {
+  auto &sec = msg.sec;
+  if (sec.file->kind() != InputFile::ObjKind)
+    return s;
+  auto &file = cast<ELFFileBase>(*sec.file);
+
+  // First, look up the DWARF line table.
+  ArrayRef<InputSectionBase *> sections = file.getSections();
+  auto it = llvm::find(sections, &sec);
+  uint64_t sectionIndex = it != sections.end()
+                              ? it - sections.begin()
+                              : object::SectionedAddress::UndefSection;
+  DWARFCache *dwarf = file.getDwarf();
+  if (auto info = dwarf->getDILineInfo(msg.offset, sectionIndex))
+    printFileLine(s, info->FileName, info->Line);
+  else if (auto fileLine = dwarf->getVariableLoc(msg.sym.getName()))
+    // If it failed, look up again as a variable.
+    printFileLine(s, fileLine->first, fileLine->second);
+  else
+    // File.sourceFile contains STT_FILE symbol, and that is a last resort.
+    s << file.sourceFile;
+  return s;
 }
 
 // Returns a filename string along with an optional section name. This

diff  --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 91678aeeaf7671..60988dfacbd746 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -147,6 +147,11 @@ class InputSectionBase : public SectionBase {
     const InputSectionBase *sec;
     uint64_t offset;
   };
+  struct SrcMsg {
+    const InputSectionBase &sec;
+    const Symbol &sym;
+    uint64_t offset;
+  };
 
   template <class ELFT>
   InputSectionBase(ObjFile<ELFT> &file, const typename ELFT::Shdr &header,
@@ -252,8 +257,10 @@ class InputSectionBase : public SectionBase {
 
   // Returns a source location string. Used to construct an error message.
   std::string getLocation(uint64_t offset) const;
-  std::string getSrcMsg(const Symbol &sym, uint64_t offset) const;
   ObjMsg getObjMsg(uint64_t offset) const { return {this, offset}; }
+  SrcMsg getSrcMsg(const Symbol &sym, uint64_t offset) const {
+    return {*this, sym, offset};
+  }
 
   // Each section knows how to relocate itself. These functions apply
   // relocations, assuming that Buf points to this section's copy in
@@ -522,6 +529,8 @@ const ELFSyncStream &operator<<(const ELFSyncStream &,
                                 const InputSectionBase *);
 const ELFSyncStream &operator<<(const ELFSyncStream &,
                                 InputSectionBase::ObjMsg &&);
+const ELFSyncStream &operator<<(const ELFSyncStream &,
+                                InputSectionBase::SrcMsg &&);
 } // namespace elf
 } // namespace lld
 

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index d311dba41741c0..605321b3cc9e3f 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -91,9 +91,10 @@ static void printLocation(ELFSyncStream &s, InputSectionBase &sec,
                           const Symbol &sym, uint64_t off) {
   printDefinedLocation(s, sym);
   s << "\n>>> referenced by ";
-  std::string src = sec.getSrcMsg(sym, off);
-  if (!src.empty())
-    s << src << "\n>>>               ";
+  auto tell = s.tell();
+  s << sec.getSrcMsg(sym, off);
+  if (tell != s.tell())
+    s << "\n>>>               ";
   s << sec.getObjMsg(off);
 }
 
@@ -738,9 +739,12 @@ static void reportUndefinedSymbol(Ctx &ctx, const UndefinedDiag &undef,
     // In the absence of line number information, utilize DW_TAG_variable (if
     // present) for the enclosing symbol (e.g. var in `int *a[] = {&undef};`).
     Symbol *enclosing = sec.getEnclosingSymbol(offset);
-    std::string src = sec.getSrcMsg(enclosing ? *enclosing : sym, offset);
-    if (!src.empty())
-      msg << src << "\n>>>               ";
+
+    ELFSyncStream msg1(ctx, DiagLevel::None);
+    auto tell = msg.tell();
+    msg << sec.getSrcMsg(enclosing ? *enclosing : sym, offset);
+    if (tell != msg.tell())
+      msg << "\n>>>               ";
     msg << sec.getObjMsg(offset);
   }
 

diff  --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 82215f305978f2..444ed5e69d362b 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -543,16 +543,17 @@ void elf::reportDuplicate(Ctx &ctx, const Symbol &sym, const InputFile *newFile,
   //   >>> defined at baz.c:563
   //   >>>            baz.o in archive libbaz.a
   auto *sec1 = cast<InputSectionBase>(d->section);
-  std::string src1 = sec1->getSrcMsg(sym, d->value);
-  std::string src2 = errSec->getSrcMsg(sym, errOffset);
-
   auto diag = Err(ctx);
   diag << "duplicate symbol: " << &sym << "\n>>> defined at ";
-  if (!src1.empty())
-    diag << src1 << "\n>>>            ";
+  auto tell = diag.tell();
+  diag << sec1->getSrcMsg(sym, d->value);
+  if (tell != diag.tell())
+    diag << "\n>>>            ";
   diag << sec1->getObjMsg(d->value) << "\n>>> defined at ";
-  if (!src2.empty())
-    diag << src2 << "\n>>>            ";
+  tell = diag.tell();
+  diag << errSec->getSrcMsg(sym, errOffset);
+  if (tell != diag.tell())
+    diag << "\n>>>            ";
   diag << errSec->getObjMsg(errOffset);
 }
 

diff  --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 63d813e550f938..c90ef8505aaddb 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -106,10 +106,11 @@ ErrorPlace elf::getErrorPlace(Ctx &ctx, const uint8_t *loc) {
     if (isecLoc <= loc && loc < isecLoc + isec->getSize()) {
       std::string objLoc = isec->getLocation(loc - isecLoc);
       // Return object file location and source file location.
-      // TODO: Refactor getSrcMsg not to take a variable.
       Undefined dummy(ctx.internalFile, "", STB_LOCAL, 0, 0);
-      return {isec, objLoc + ": ",
-              isec->file ? isec->getSrcMsg(dummy, loc - isecLoc) : ""};
+      ELFSyncStream msg(ctx, DiagLevel::None);
+      if (isec->file)
+        msg << isec->getSrcMsg(dummy, loc - isecLoc);
+      return {isec, objLoc + ": ", std::string(msg.str())};
     }
   }
   return {};

diff  --git a/lld/include/lld/Common/ErrorHandler.h b/lld/include/lld/Common/ErrorHandler.h
index 79e20be2bb6be8..4db1fec268d766 100644
--- a/lld/include/lld/Common/ErrorHandler.h
+++ b/lld/include/lld/Common/ErrorHandler.h
@@ -167,6 +167,7 @@ class SyncStream {
   SyncStream(SyncStream &&o) : e(o.e), level(o.level), buf(std::move(o.buf)) {}
   ~SyncStream();
   StringRef str() { return os.str(); }
+  uint64_t tell() { return os.tell(); }
 };
 
 [[noreturn]] void exitLld(int val);


        


More information about the llvm-commits mailing list