[llvm] bef2592 - [llvm-nm]add helper function to print out the object file name, archive name, architecture name

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 9 11:45:42 PST 2022


Author: zhijian
Date: 2022-03-09T14:45:27-05:00
New Revision: bef2592c092f453078d8762d6d3d9c811f23c25d

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

LOG: [llvm-nm]add helper function to print out the object file name, archive name, architecture name

Summary:

1. added helper function printObjectNamesInfo() to print out  object file name, archive name, architecture name.
2.  One small behaviors change.

     in the function dumpMachOUniversalBinaryArchAll , delete the functionality:

if (moreThanOneArch)
               outs() << "\n";

Reviewer : James Henderson,Fangrui Song
Differential Revision: https://reviews.llvm.org/D120357

Added: 
    

Modified: 
    llvm/test/Object/nm-universal-binary.test
    llvm/tools/llvm-nm/llvm-nm.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/Object/nm-universal-binary.test b/llvm/test/Object/nm-universal-binary.test
index 379f8cdc776dd..1a1d80a7aee3c 100644
--- a/llvm/test/Object/nm-universal-binary.test
+++ b/llvm/test/Object/nm-universal-binary.test
@@ -35,25 +35,27 @@ CHECK-OBJ-armv7m: error: file: {{.*}} does not contain architecture
 
 CHECK-OBJ-foobar: error: for the --arch option: Unknown architecture named 'foobar'
 
-CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
-CHECK-AR: 0000000000000068 s EH_frame0
-CHECK-AR: 000000000000003b s L_.str
-CHECK-AR: 0000000000000000 T _main
-CHECK-AR: 0000000000000080 S _main.eh
-CHECK-AR:                  U _printf
+CHECK-AR:       {{^$}}
+CHECK-AR-NEXT:  macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
+CHECK-AR:       0000000000000068 s EH_frame0
+CHECK-AR:       000000000000003b s L_.str
+CHECK-AR:       0000000000000000 T _main
+CHECK-AR:       0000000000000080 S _main.eh
+CHECK-AR:                        U _printf
 CHECK-AR: macho-universal-archive.x86_64.i386(foo.o) (for architecture i386):
 CHECK-AR: 00000008 D _bar
 CHECK-AR: 00000000 T _foo
 
-CHECK-64-AR: macho-universal64-archive.x86_64.i386(foo.o) (for architecture i386):
-CHECK-64-AR: 00000008 D _bar
-CHECK-64-AR: 00000000 T _foo
-CHECK-64-AR: macho-universal64-archive.x86_64.i386(hello.o) (for architecture x86_64):
-CHECK-64-AR: 0000000000000068 s EH_frame0
-CHECK-64-AR: 000000000000003b s L_.str
-CHECK-64-AR: 0000000000000000 T _main
-CHECK-64-AR: 0000000000000080 S _main.eh
-CHECK-64-AR:                  U _printf
+CHECK-64-AR:      {{^$}}
+CHECK-64-AR-NEXT: macho-universal64-archive.x86_64.i386(foo.o) (for architecture i386):
+CHECK-64-AR:      00000008 D _bar
+CHECK-64-AR:      00000000 T _foo
+CHECK-64-AR:      macho-universal64-archive.x86_64.i386(hello.o) (for architecture x86_64):
+CHECK-64-AR:      0000000000000068 s EH_frame0
+CHECK-64-AR:      000000000000003b s L_.str
+CHECK-64-AR:      0000000000000000 T _main
+CHECK-64-AR:      0000000000000080 S _main.eh
+CHECK-64-AR:                       U _printf
 
 CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o):
 CHECK-AR-i386: 00000008 D _bar

diff  --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index 5e67e76447cd1..4e415f2fa777c 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -1154,7 +1154,7 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
 
 // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
 // option to dump only those symbols from that section in a Mach-O file.
-// It is called once for each Mach-O file from dumpSymbolNamesFromObject()
+// It is called once for each Mach-O file from getSymbolNamesFromObject()
 // to get the section number for that named section from the command line
 // arguments. It returns the section number for that section in the Mach-O
 // file or zero it is not present.
@@ -1176,7 +1176,7 @@ static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
 // getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
 // option to dump only those symbols from that section in a Mach-O file.
 // It is called once for each symbol in a Mach-O file from
-// dumpSymbolNamesFromObject() and returns the section number for that symbol
+// getSymbolNamesFromObject() and returns the section number for that symbol
 // if it is in a section, else it returns 0.
 static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) {
   DataRefImpl Symb = Sym.getRawDataRefImpl();
@@ -1742,37 +1742,37 @@ static void getXCOFFExports(XCOFFObjectFile *XCOFFObj, StringRef ArchiveName) {
   }
 }
 
-static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
-                                      StringRef ArchiveName = {},
-                                      StringRef ArchitectureName = {}) {
-  if (!shouldDump(Obj))
-    return;
-
-  if (ExportSymbols && Obj.isXCOFF()) {
-    XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);
-    getXCOFFExports(XCOFFObj, ArchiveName);
-    return;
-  }
+static Expected<SymbolicFile::basic_symbol_iterator_range>
+getDynamicSyms(SymbolicFile &Obj) {
+  const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
+  if (!E)
+    return createError("File format has no dynamic symbol table");
+  return E->getDynamicSymbolIterators();
+}
 
+// Returns false if an error is encounted or true otherwise.
+static bool getSymbolNamesFromObject(SymbolicFile &Obj) {
   auto Symbols = Obj.symbols();
   std::vector<VersionEntry> SymbolVersions;
+
   if (DynamicSyms) {
-    const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
-    if (!E) {
-      error("File format has no dynamic symbol table", Obj.getFileName());
-      return;
+    Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =
+        getDynamicSyms(Obj);
+    if (!SymbolsOrErr) {
+      error(SymbolsOrErr.takeError(), Obj.getFileName());
+      return false;
+    }
+    Symbols = *SymbolsOrErr;
+    if (const auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) {
+      if (Expected<std::vector<VersionEntry>> VersionsOrErr =
+              E->readDynsymVersions())
+        SymbolVersions = std::move(*VersionsOrErr);
+      else
+        WithColor::warning(errs(), ToolName)
+            << "unable to read symbol versions: "
+            << toString(VersionsOrErr.takeError()) << "\n";
     }
-    Symbols = E->getDynamicSymbolIterators();
-
-    if (Expected<std::vector<VersionEntry>> VersionsOrErr =
-            E->readDynsymVersions())
-      SymbolVersions = std::move(*VersionsOrErr);
-    else
-      WithColor::warning(errs(), ToolName)
-          << "unable to read symbol versions: "
-          << toString(VersionsOrErr.takeError()) << "\n";
   }
-
   // If a "-s segname sectname" option was specified and this is a Mach-O
   // file get the section number for that section in this object file.
   unsigned int Nsect = 0;
@@ -1781,7 +1781,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
     Nsect = getNsectForSegSect(MachO);
     // If this section is not in the object file no symbols are printed.
     if (Nsect == 0)
-      return;
+      return false;
   }
 
   if (!(MachO && DyldInfoOnly)) {
@@ -1791,7 +1791,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
       Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
       if (!SymFlagsOrErr) {
         error(SymFlagsOrErr.takeError(), Obj.getFileName());
-        return;
+        return false;
       }
 
       // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they
@@ -1857,19 +1857,64 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
   // all symbols from the dyld export trie as well as the bind info.
   if (MachO && !NoDyldInfo)
     dumpSymbolsFromDLInfoMachO(*MachO);
+  return true;
+}
 
-  if (ExportSymbols)
+static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,
+                             StringRef ArchitectureName,
+                             StringRef ObjectFileName) {
+  outs() << "\n";
+  if (ArchiveName.empty() || !PrintArchiveName)
+    outs() << ObjectFileName;
+  else
+    outs() << ArchiveName << "(" << ObjectFileName << ")";
+  if (!ArchitectureName.empty())
+    outs() << " (for architecture " << ArchitectureName << ")";
+  outs() << ":\n";
+}
+
+static Expected<bool> hasSymbols(SymbolicFile &Obj) {
+  if (DynamicSyms) {
+    Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =
+        getDynamicSyms(Obj);
+    if (!DynamicSymsOrErr)
+      return DynamicSymsOrErr.takeError();
+    return !DynamicSymsOrErr->empty();
+  }
+  return !Obj.symbols().empty();
+}
+
+static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool PrintSymbolObject,
+                                      bool PrintObjectLabel,
+                                      StringRef ArchiveName = {},
+                                      StringRef ArchitectureName = {},
+                                      StringRef ObjectName = {},
+                                      bool PrintArchiveName = true) {
+  if (!shouldDump(Obj))
     return;
 
+  if (ExportSymbols && Obj.isXCOFF()) {
+    XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);
+    getXCOFFExports(XCOFFObj, ArchiveName);
+    return;
+  }
+
+  if (PrintObjectLabel && !ExportSymbols)
+    printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
+                     ObjectName.empty() ? Obj.getFileName() : ObjectName);
+  if (!getSymbolNamesFromObject(Obj) || ExportSymbols)
+    return;
   CurrentFilename = Obj.getFileName();
 
-  if (Symbols.empty() && SymbolList.empty() && !Quiet) {
+  // If there is an error in hasSymbols(), the error should be encountered in
+  // function getSymbolNamesFromObject first.
+  if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
     writeFileName(errs(), ArchiveName, ArchitectureName);
     errs() << "no symbols\n";
   }
 
   sortSymbolList();
-  printSymbolList(Obj, printName, ArchiveName, ArchitectureName);
+  printSymbolList(Obj, PrintSymbolObject, ArchiveName, ArchitectureName);
 }
 
 // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
@@ -1948,15 +1993,10 @@ static void dumpArchive(Archive *A, std::string &Filename,
       }
       if (!checkMachOAndArchFlags(O, Filename))
         return;
-      if (!PrintFileName && shouldDump(*O) && !ExportSymbols) {
-        outs() << "\n";
-        if (isa<MachOObjectFile>(O)) {
-          outs() << Filename << "(" << O->getFileName() << ")";
-        } else
-          outs() << O->getFileName();
-        outs() << ":\n";
-      }
-      dumpSymbolNamesFromObject(*O, false, Filename);
+      dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/false, !PrintFileName,
+                                Filename,
+                                /*ArchitectureName=*/{}, O->getFileName(),
+                                /*PrintArchiveName=*/false);
     }
   }
   if (Err)
@@ -1982,16 +2022,11 @@ static void dumpMachOUniversalBinaryMatchArchFlags(MachOUniversalBinary *UB,
         ArchitectureName.clear();
         if (ObjOrErr) {
           ObjectFile &Obj = *ObjOrErr.get();
-          if (ArchFlags.size() > 1) {
-            if (PrintFileName)
-              ArchitectureName = I->getArchFlagName();
-            else
-              outs() << "\n"
-                     << Obj.getFileName() << " (for architecture "
-                     << I->getArchFlagName() << ")"
-                     << ":\n";
-          }
-          dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName);
+          if (ArchFlags.size() > 1)
+            ArchitectureName = I->getArchFlagName();
+          dumpSymbolNamesFromObject(Obj, /*PrintSymbolObject=*/false,
+                                    (ArchFlags.size() > 1) && !PrintFileName,
+                                    ArchiveName, ArchitectureName);
         } else if (auto E =
                        isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
           error(std::move(E), Filename,
@@ -2015,20 +2050,11 @@ static void dumpMachOUniversalBinaryMatchArchFlags(MachOUniversalBinary *UB,
               continue;
             }
             if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
-              if (PrintFileName) {
-                ArchiveName = std::string(A->getFileName());
-                if (ArchFlags.size() > 1)
-                  ArchitectureName = I->getArchFlagName();
-              } else {
-                outs() << "\n" << A->getFileName();
-                outs() << "(" << O->getFileName() << ")";
-                if (ArchFlags.size() > 1) {
-                  outs() << " (for architecture " << I->getArchFlagName()
-                         << ")";
-                }
-                outs() << ":\n";
-              }
-              dumpSymbolNamesFromObject(*O, false, ArchiveName,
+              ArchiveName = std::string(A->getFileName());
+              if (ArchFlags.size() > 1)
+                ArchitectureName = I->getArchFlagName();
+              dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/false,
+                                        !PrintFileName, ArchiveName,
                                         ArchitectureName);
             }
           }
@@ -2066,7 +2092,8 @@ static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
       std::string ArchiveName;
       if (ObjOrErr) {
         ObjectFile &Obj = *ObjOrErr.get();
-        dumpSymbolNamesFromObject(Obj, false);
+        dumpSymbolNamesFromObject(Obj, /*PrintSymbolObject=*/false,
+                                  /*PrintObjectLabel=*/false);
       } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
         error(std::move(E), Filename);
       else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
@@ -2082,13 +2109,9 @@ static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
             continue;
           }
           if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
-            if (PrintFileName)
-              ArchiveName = std::string(A->getFileName());
-            else
-              outs() << "\n"
-                     << A->getFileName() << "(" << O->getFileName() << ")"
-                     << ":\n";
-            dumpSymbolNamesFromObject(*O, false, ArchiveName);
+            ArchiveName = std::string(A->getFileName());
+            dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/false,
+                                      !PrintFileName, ArchiveName);
           }
         }
         if (Err)
@@ -2118,18 +2141,10 @@ static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
     ArchitectureName.clear();
     if (ObjOrErr) {
       ObjectFile &Obj = *ObjOrErr.get();
-      if (PrintFileName) {
-        if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
-          ArchitectureName = O.getArchFlagName();
-      } else {
-        if (moreThanOneArch)
-          outs() << "\n";
-        outs() << Obj.getFileName();
-        if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
-          outs() << " (for architecture " << O.getArchFlagName() << ")";
-        outs() << ":\n";
-      }
-      dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName);
+      if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
+        ArchitectureName = O.getArchFlagName();
+      dumpSymbolNamesFromObject(Obj, /*PrintSymbolObject=*/false,
+                                !PrintFileName, ArchiveName, ArchitectureName);
     } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
       error(std::move(E), Filename,
             moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
@@ -2147,21 +2162,12 @@ static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
           continue;
         }
         if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
-          if (PrintFileName) {
-            ArchiveName = std::string(A->getFileName());
-            if (isa<MachOObjectFile>(F) && moreThanOneArch)
-              ArchitectureName = O.getArchFlagName();
-          } else {
-            outs() << "\n" << A->getFileName();
-            if (isa<MachOObjectFile>(F)) {
-              outs() << "(" << F->getFileName() << ")";
-              if (moreThanOneArch)
-                outs() << " (for architecture " << O.getArchFlagName() << ")";
-            } else
-              outs() << ":" << F->getFileName();
-            outs() << ":\n";
-          }
-          dumpSymbolNamesFromObject(*F, false, ArchiveName, ArchitectureName);
+          ArchiveName = std::string(A->getFileName());
+          if (isa<MachOObjectFile>(F) && moreThanOneArch)
+            ArchitectureName = O.getArchFlagName();
+          dumpSymbolNamesFromObject(*F, /*PrintSymbolObject=*/false,
+                                    !PrintFileName, ArchiveName,
+                                    ArchitectureName);
         }
       }
       if (Err)
@@ -2203,13 +2209,12 @@ static void dumpTapiUniversal(TapiUniversal *TU, std::string &Filename) {
       continue;
     if (!AddInlinedInfo && !I.isTopLevelLib())
       continue;
-    if (auto ObjOrErr = I.getAsObjectFile()) {
-      outs() << "\n"
-             << I.getInstallName() << " (for architecture " << ArchName << ")"
-             << ":\n";
-      dumpSymbolNamesFromObject(*ObjOrErr.get(), false, {}, ArchName);
-    } else if (Error E =
-                   isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
+    if (auto ObjOrErr = I.getAsObjectFile())
+      dumpSymbolNamesFromObject(*ObjOrErr.get(), /*PrintSymbolObject=*/false,
+                                /*PrintObjectLabel=*/true,
+                                /*ArchiveName=*/{}, ArchName,
+                                I.getInstallName());
+    else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
       error(std::move(E), Filename, ArchName);
     }
   }
@@ -2223,7 +2228,8 @@ static void dumpSymbolicFile(SymbolicFile *O, std::string &Filename) {
   }
   if (!checkMachOAndArchFlags(O, Filename))
     return;
-  dumpSymbolNamesFromObject(*O, true);
+  dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/true,
+                            /*PrintObjectLabel=*/false);
 }
 
 static void dumpSymbolNamesFromFile(std::string &Filename) {


        


More information about the llvm-commits mailing list