[llvm] 620bff7 - [llvm-addr2line] Replace checkFileExists with getOrCreateModuleInfo

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 23 10:04:18 PDT 2023


Author: Fangrui Song
Date: 2023-06-23T10:04:13-07:00
New Revision: 620bff758d448f04483a80455e14daa91f9c2346

URL: https://github.com/llvm/llvm-project/commit/620bff758d448f04483a80455e14daa91f9c2346
DIFF: https://github.com/llvm/llvm-project/commit/620bff758d448f04483a80455e14daa91f9c2346.diff

LOG: [llvm-addr2line] Replace checkFileExists with getOrCreateModuleInfo

GNU addr2line exits immediately if -e (default to a.out) specifies a file that
cannot be open or a directory. llvm-addr2line used to wait for input on if the
input file cannot be open and addresses are not specified in command line.
Replace the D147652 checkFileExists with getOrCreateModuleInfo to avoid
a separate `sys::fs::status` operation.

Reviewed By: sepavloff

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

Added: 
    llvm/test/tools/llvm-symbolizer/input-file-err.test

Modified: 
    llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
    llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
    llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp

Removed: 
    llvm/test/tools/llvm-symbolizer/errors.test


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index 6f4e48dc6a8f5..99a7f219baaa0 100644
--- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -119,7 +119,12 @@ class LLVMSymbolizer {
     BIDFetcher = std::move(Fetcher);
   }
 
-  Error checkFileExists(StringRef Name);
+  /// Returns a SymbolizableModule or an error if loading debug info failed.
+  /// Only one attempt is made to load a module, and errors during loading are
+  /// only reported once. Subsequent calls to get module info for a module that
+  /// failed to load will return nullptr.
+  Expected<SymbolizableModule *>
+  getOrCreateModuleInfo(const std::string &ModuleName);
 
 private:
   // Bundles together object file with code/data and object file with
@@ -142,12 +147,6 @@ class LLVMSymbolizer {
   symbolizeFrameCommon(const T &ModuleSpecifier,
                        object::SectionedAddress ModuleOffset);
 
-  /// Returns a SymbolizableModule or an error if loading debug info failed.
-  /// Only one attempt is made to load a module, and errors during loading are
-  /// only reported once. Subsequent calls to get module info for a module that
-  /// failed to load will return nullptr.
-  Expected<SymbolizableModule *>
-  getOrCreateModuleInfo(const std::string &ModuleName);
   Expected<SymbolizableModule *> getOrCreateModuleInfo(const ObjectFile &Obj);
 
   /// Returns a SymbolizableModule or an error if loading debug info failed.
@@ -190,11 +189,6 @@ class LLVMSymbolizer {
   /// Update the LRU cache order when a binary is accessed.
   void recordAccess(CachedBinary &Bin);
 
-  /// Split binary file name into file and architecture parts. For example,
-  /// the name 'macho-universal:i386', will be split into 'macho-universal' and
-  /// 'i386'.
-  std::pair<std::string, std::string> splitBinaryFileName(StringRef Name);
-
   std::map<std::string, std::unique_ptr<SymbolizableModule>, std::less<>>
       Modules;
   StringMap<std::string> BuildIDPaths;

diff  --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 7de72a5970d91..459baf7b83640 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -550,24 +550,19 @@ LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj,
   return InsertResult.first->second.get();
 }
 
-std::pair<std::string, std::string>
-LLVMSymbolizer::splitBinaryFileName(StringRef Name) {
-  StringRef BinaryName = Name;
+Expected<SymbolizableModule *>
+LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
+  std::string BinaryName = ModuleName;
   std::string ArchName = Opts.DefaultArch;
-  size_t ColonPos = Name.find_last_of(':');
-  if (ColonPos != StringRef::npos) {
-    StringRef ArchStr = Name.substr(ColonPos + 1);
+  size_t ColonPos = ModuleName.find_last_of(':');
+  // Verify that substring after colon form a valid arch name.
+  if (ColonPos != std::string::npos) {
+    std::string ArchStr = ModuleName.substr(ColonPos + 1);
     if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
-      BinaryName = Name.substr(0, ColonPos);
+      BinaryName = ModuleName.substr(0, ColonPos);
       ArchName = ArchStr;
     }
   }
-  return std::make_pair(BinaryName.str(), ArchName);
-}
-
-Expected<SymbolizableModule *>
-LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
-  auto [BinaryName, ArchName] = splitBinaryFileName(ModuleName);
 
   auto I = Modules.find(ModuleName);
   if (I != Modules.end()) {
@@ -712,15 +707,6 @@ LLVMSymbolizer::DemangleName(const std::string &Name,
   return Name;
 }
 
-Error LLVMSymbolizer::checkFileExists(StringRef BinName) {
-  auto [BinaryName, ArchName] = splitBinaryFileName(BinName);
-  sys::fs::file_status Stat;
-  std::error_code EC = sys::fs::status(BinaryName, Stat);
-  if (!EC && sys::fs::is_directory(Stat))
-    EC = errc::is_a_directory;
-  return errorCodeToError(EC);
-}
-
 void LLVMSymbolizer::recordAccess(CachedBinary &Bin) {
   if (Bin->getBinary())
     LRUBinaries.splice(LRUBinaries.end(), LRUBinaries, Bin.getIterator());

diff  --git a/llvm/test/tools/llvm-symbolizer/errors.test b/llvm/test/tools/llvm-symbolizer/input-file-err.test
similarity index 73%
rename from llvm/test/tools/llvm-symbolizer/errors.test
rename to llvm/test/tools/llvm-symbolizer/input-file-err.test
index e78d1f6ef2ee3..a072b3ede12a0 100644
--- a/llvm/test/tools/llvm-symbolizer/errors.test
+++ b/llvm/test/tools/llvm-symbolizer/input-file-err.test
@@ -5,3 +5,6 @@ CHECK-NONEXISTENT-A2L: llvm-addr2line{{.*}}: error: '{{.*}}Inputs/nonexistent':
 RUN: not llvm-addr2line -e %p/Inputs 0x12 2>&1 | FileCheck %s --check-prefix=CHECK-DIRECTORY-A2L -DMSG=%errc_EISDIR
 RUN: not llvm-addr2line -e %p/Inputs 2>&1 | FileCheck %s --check-prefix=CHECK-DIRECTORY-A2L -DMSG=%errc_EISDIR
 CHECK-DIRECTORY-A2L: llvm-addr2line{{.*}}: error: '{{.*}}Inputs': [[MSG]]
+
+not llvm-addr2line --output-style=JSON -e %p/Inputs/nonexistent 2>&1 | FileCheck %s --check-prefix=NONEXIST-JSON -DMSG=%errc_ENOENT
+NONEXIST-JSON: {"Address":"0x0","Error":{"Message":"[[MSG]]"},"ModuleName":"{{.*}}nonexistent"}

diff  --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 7b49ec2f13808..a9e983055469e 100644
--- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -478,12 +478,15 @@ int main(int argc, char **argv) {
   else
     Printer = std::make_unique<LLVMPrinter>(outs(), printError, Config);
 
-  StringRef InputFile = Args.getLastArgValue(OPT_obj_EQ);
-  if (!InputFile.empty() && IsAddr2Line) {
-    Error Status = Symbolizer.checkFileExists(InputFile);
-    if (Status) {
-      handleAllErrors(std::move(Status), [&](const ErrorInfoBase &EI) {
-        printError(EI, InputFile);
+  // When an input file is specified, exit immediately if the file cannot be
+  // read. If getOrCreateModuleInfo succeeds, symbolizeInput will reuse the
+  // cached file handle.
+  if (auto *Arg = Args.getLastArg(OPT_obj_EQ); Arg && IsAddr2Line) {
+    auto Status = Symbolizer.getOrCreateModuleInfo(Arg->getValue());
+    if (!Status) {
+      Request SymRequest = {Arg->getValue(), 0};
+      handleAllErrors(Status.takeError(), [&](const ErrorInfoBase &EI) {
+        Printer->printError(SymRequest, EI);
       });
       return EXIT_FAILURE;
     }


        


More information about the llvm-commits mailing list