[llvm] r246403 - [dsymutil] Implement -symtab/-s option.

Frederic Riss via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 30 17:29:09 PDT 2015


Author: friss
Date: Sun Aug 30 19:29:09 2015
New Revision: 246403

URL: http://llvm.org/viewvc/llvm-project?rev=246403&view=rev
Log:
[dsymutil] Implement -symtab/-s option.

This option dumps the STAB entries that define the debug map(s)
stored in the input binaries, and then exits.

Added:
    llvm/trunk/test/tools/dsymutil/dump-symtab.test
Modified:
    llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp
    llvm/trunk/tools/dsymutil/dsymutil.cpp
    llvm/trunk/tools/dsymutil/dsymutil.h

Added: llvm/trunk/test/tools/dsymutil/dump-symtab.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/dump-symtab.test?rev=246403&view=auto
==============================================================================
--- llvm/trunk/test/tools/dsymutil/dump-symtab.test (added)
+++ llvm/trunk/test/tools/dsymutil/dump-symtab.test Sun Aug 30 19:29:09 2015
@@ -0,0 +1,44 @@
+RUN: llvm-dsymutil -s %p/Inputs/fat-test.dylib | FileCheck -check-prefix=ALL -check-prefix=I386 %s 
+RUN: llvm-dsymutil -arch i386 -s %p/Inputs/fat-test.dylib | FileCheck -check-prefix=I386 -check-prefix=ONE %s
+
+
+ALL:  ----------------------------------------------------------------------
+ALL-NEXT:  Symbol table for: '{{.*}}fat-test.dylib' (x86_64)
+ALL-NEXT:  ----------------------------------------------------------------------
+ALL-NEXT:  Index    n_strx   n_type             n_sect n_desc n_value
+ALL-NEXT:  ======== -------- ------------------ ------ ------ ----------------
+ALL-NEXT:  [     0] 00000002 64 (N_SO         ) 00     0000   0000000000000000 '/Inputs/'
+ALL-NEXT:  [     1] 0000000b 64 (N_SO         ) 00     0000   0000000000000000 'fat-test.c'
+ALL-NEXT:  [     2] 00000016 66 (N_OSO        ) 03     0001   0000000055b1d0b9 '/Inputs/fat-test.o'
+ALL-NEXT:  [     3] 00000029 20 (N_GSYM       ) 00     0000   0000000000000000 '_x86_64_var'
+ALL-NEXT:  [     4] 00000001 64 (N_SO         ) 01     0000   0000000000000000
+ALL-NEXT:  [     5] 00000035 0f (     SECT EXT) 02     0000   0000000000001000 '_x86_64_var'
+ALL-NEXT:  [     6] 00000041 01 (     UNDF EXT) 00     0100   0000000000000000 'dyld_stub_binder'
+
+I386: ----------------------------------------------------------------------
+I386-NEXT: Symbol table for: '{{.*}}fat-test.dylib' (i386)
+I386-NEXT: ----------------------------------------------------------------------
+I386-NEXT: Index    n_strx   n_type             n_sect n_desc n_value
+I386-NEXT: ======== -------- ------------------ ------ ------ ----------------
+I386-NEXT: [     0] 00000002 64 (N_SO         ) 00     0000   0000000000000000 '/Inputs/'
+I386-NEXT: [     1] 0000000b 64 (N_SO         ) 00     0000   0000000000000000 'fat-test.c'
+I386-NEXT: [     2] 00000016 66 (N_OSO        ) 03     0001   0000000055b1d0b9 '/Inputs/fat-test.o'
+I386-NEXT: [     3] 00000029 20 (N_GSYM       ) 00     0000   0000000000000000 '_i386_var'
+I386-NEXT: [     4] 00000001 64 (N_SO         ) 01     0000   0000000000000000
+I386-NEXT: [     5] 00000033 0f (     SECT EXT) 02     0000   0000000000001000 '_i386_var'
+I386-NEXT: [     6] 0000003d 01 (     UNDF EXT) 00     0100   0000000000000000 'dyld_stub_binder'
+
+ONE-NOT: Symbol table
+
+ALL:  ----------------------------------------------------------------------
+ALL-NEXT:  Symbol table for: '{{.*}}fat-test.dylib' (x86_64h)
+ALL-NEXT:  ----------------------------------------------------------------------
+ALL-NEXT:  Index    n_strx   n_type             n_sect n_desc n_value
+ALL-NEXT:  ======== -------- ------------------ ------ ------ ----------------
+ALL-NEXT:  [     0] 00000002 64 (N_SO         ) 00     0000   0000000000000000 '/Inputs/'
+ALL-NEXT:  [     1] 0000000b 64 (N_SO         ) 00     0000   0000000000000000 'fat-test.c'
+ALL-NEXT:  [     2] 00000016 66 (N_OSO        ) 08     0001   0000000055b1d0b9 '/Inputs/fat-test.o'
+ALL-NEXT:  [     3] 00000029 20 (N_GSYM       ) 00     0000   0000000000000000 '_x86_64h_var'
+ALL-NEXT:  [     4] 00000001 64 (N_SO         ) 01     0000   0000000000000000
+ALL-NEXT:  [     5] 00000036 0f (     SECT EXT) 02     0000   0000000000001000 '_x86_64h_var'
+ALL-NEXT:  [     6] 00000043 01 (     UNDF EXT) 00     0100   0000000000000000 'dyld_stub_binder'
\ No newline at end of file

Modified: llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp?rev=246403&r1=246402&r2=246403&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp (original)
+++ llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp Sun Aug 30 19:29:09 2015
@@ -34,6 +34,9 @@ public:
   /// or isn't of a supported type.
   ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parse();
 
+  /// Walk the symbol table and dump it.
+  bool dumpStab();
+
 private:
   std::string BinaryPath;
   SmallVector<StringRef, 1> Archs;
@@ -74,6 +77,22 @@ private:
     handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
                                STE.n_value);
   }
+
+  /// Dump the symbol table output header.
+  void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
+
+  /// Dump the contents of nlist entries.
+  void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, uint32_t StringIndex,
+                       uint8_t Type, uint8_t SectionIndex, uint16_t Flags,
+                       uint64_t Value);
+
+  template <typename STEType>
+  void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, const STEType &STE) {
+    dumpSymTabEntry(OS, Index, STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
+                    STE.n_value);
+  }
+  void dumpOneBinaryStab(const MachOObjectFile &MainBinary,
+                         StringRef BinaryPath);
 };
 
 static void Warning(const Twine &Msg) { errs() << "warning: " + Msg + "\n"; }
@@ -116,6 +135,12 @@ void MachODebugMapParser::switchToNewDeb
   loadCurrentObjectFileSymbols(*ErrOrAchObj);
 }
 
+static std::string getArchName(const object::MachOObjectFile &Obj) {
+  Triple ThumbTriple;
+  Triple T = Obj.getArch(nullptr, &ThumbTriple);
+  return T.getArchName();
+}
+
 std::unique_ptr<DebugMap>
 MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary,
                                     StringRef BinaryPath) {
@@ -135,6 +160,133 @@ MachODebugMapParser::parseOneBinary(cons
   return std::move(Result);
 }
 
+// Table that maps Darwin's Mach-O stab constants to strings to allow printing.
+// llvm-nm has very similar code, the strings used here are however slightly
+// different and part of the interface of dsymutil (some project's build-systems
+// parse the ouptut of dsymutil -s), thus they shouldn't be changed.
+struct DarwinStabName {
+  uint8_t NType;
+  const char *Name;
+};
+
+static const struct DarwinStabName DarwinStabNames[] = {
+    {MachO::N_GSYM, "N_GSYM"},    {MachO::N_FNAME, "N_FNAME"},
+    {MachO::N_FUN, "N_FUN"},      {MachO::N_STSYM, "N_STSYM"},
+    {MachO::N_LCSYM, "N_LCSYM"},  {MachO::N_BNSYM, "N_BNSYM"},
+    {MachO::N_PC, "N_PC"},        {MachO::N_AST, "N_AST"},
+    {MachO::N_OPT, "N_OPT"},      {MachO::N_RSYM, "N_RSYM"},
+    {MachO::N_SLINE, "N_SLINE"},  {MachO::N_ENSYM, "N_ENSYM"},
+    {MachO::N_SSYM, "N_SSYM"},    {MachO::N_SO, "N_SO"},
+    {MachO::N_OSO, "N_OSO"},      {MachO::N_LSYM, "N_LSYM"},
+    {MachO::N_BINCL, "N_BINCL"},  {MachO::N_SOL, "N_SOL"},
+    {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
+    {MachO::N_OLEVEL, "N_OLEV"},  {MachO::N_PSYM, "N_PSYM"},
+    {MachO::N_EINCL, "N_EINCL"},  {MachO::N_ENTRY, "N_ENTRY"},
+    {MachO::N_LBRAC, "N_LBRAC"},  {MachO::N_EXCL, "N_EXCL"},
+    {MachO::N_RBRAC, "N_RBRAC"},  {MachO::N_BCOMM, "N_BCOMM"},
+    {MachO::N_ECOMM, "N_ECOMM"},  {MachO::N_ECOML, "N_ECOML"},
+    {MachO::N_LENG, "N_LENG"},    {0, 0}};
+
+static const char *getDarwinStabString(uint8_t NType) {
+  for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
+    if (DarwinStabNames[i].NType == NType)
+      return DarwinStabNames[i].Name;
+  }
+  return 0;
+}
+
+void MachODebugMapParser::dumpSymTabHeader(raw_ostream &OS, StringRef Arch) {
+  OS << "-----------------------------------"
+        "-----------------------------------\n";
+  OS << "Symbol table for: '" << BinaryPath << "' (" << Arch.data() << ")\n";
+  OS << "-----------------------------------"
+        "-----------------------------------\n";
+  OS << "Index    n_strx   n_type             n_sect n_desc n_value\n";
+  OS << "======== -------- ------------------ ------ ------ ----------------\n";
+}
+
+void MachODebugMapParser::dumpSymTabEntry(raw_ostream &OS, uint64_t Index,
+                                          uint32_t StringIndex, uint8_t Type,
+                                          uint8_t SectionIndex, uint16_t Flags,
+                                          uint64_t Value) {
+
+  // Index
+  OS << '[' << format_decimal(Index, 6) << "] "
+     // n_strx
+     << format_hex_no_prefix(StringIndex, 8) << ' '
+     // n_type...
+     << format_hex_no_prefix(Type, 2) << " (";
+
+  if (Type & MachO::N_STAB)
+    OS << left_justify(getDarwinStabString(Type), 13);
+  else {
+    if (Type & MachO::N_PEXT)
+      OS << "PEXT ";
+    else
+      OS << "     ";
+    switch (Type & MachO::N_TYPE) {
+    case MachO::N_UNDF: // 0x0 undefined, n_sect == NO_SECT
+      OS << "UNDF";
+      break;
+    case MachO::N_ABS: // 0x2 absolute, n_sect == NO_SECT
+      OS << "ABS ";
+      break;
+    case MachO::N_SECT: // 0xe defined in section number n_sect
+      OS << "SECT";
+      break;
+    case MachO::N_PBUD: // 0xc prebound undefined (defined in a dylib)
+      OS << "PBUD";
+      break;
+    case MachO::N_INDR: // 0xa indirect
+      OS << "INDR";
+      break;
+    default:
+      OS << format_hex_no_prefix(Type, 2) << "    ";
+      break;
+    }
+    if (Type & MachO::N_EXT)
+      OS << " EXT";
+    else
+      OS << "    ";
+  }
+
+  OS << ") "
+     // n_sect
+     << format_hex_no_prefix(SectionIndex, 2) << "     "
+     // n_desc
+     << format_hex_no_prefix(Flags, 4) << "   "
+     // n_value
+     << format_hex_no_prefix(Value, 16);
+
+  const char *Name = &MainBinaryStrings.data()[StringIndex];
+  if (Name && Name[0])
+    OS << " '" << Name << "'";
+
+  OS << "\n";
+}
+
+void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary,
+                                            StringRef BinaryPath) {
+  loadMainBinarySymbols(MainBinary);
+  MainBinaryStrings = MainBinary.getStringTableData();
+  raw_ostream &OS(llvm::outs());
+
+  StringRef ArchName = getArchName(MainBinary);
+  dumpSymTabHeader(OS, ArchName);
+  uint64_t Idx = 0;
+  for (const SymbolRef &Symbol : MainBinary.symbols()) {
+    const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
+    if (MainBinary.is64Bit())
+      dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI));
+    else
+      dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI));
+    Idx++;
+  }
+
+  OS << "\n\n";
+  resetParserState();
+}
+
 static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) {
   if (Archs.empty() ||
       std::find(Archs.begin(), Archs.end(), "all") != Archs.end() ||
@@ -148,6 +300,23 @@ static bool shouldLinkArch(SmallVectorIm
   return std::find(Archs.begin(), Archs.end(), Arch) != Archs.end();
 }
 
+bool MachODebugMapParser::dumpStab() {
+  auto MainBinOrError =
+      MainBinaryHolder.GetFilesAs<MachOObjectFile>(BinaryPath);
+  if (auto Error = MainBinOrError.getError()) {
+    llvm::errs() << "Cannot get '" << BinaryPath
+                 << "' as MachO file: " << Error.message() << "\n";
+    return false;
+  }
+
+  Triple T;
+  for (const auto *Binary : *MainBinOrError)
+    if (shouldLinkArch(Archs, Binary->getArch(nullptr, &T).getArchName()))
+      dumpOneBinaryStab(*Binary, BinaryPath);
+
+  return true;
+}
+
 /// This main parsing routine tries to open the main binary and if
 /// successful iterates over the STAB entries. The real parsing is
 /// done in handleStabSymbolTableEntry.
@@ -297,5 +466,11 @@ parseDebugMap(StringRef InputFile, Array
     return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
   }
 }
+
+bool dumpStab(StringRef InputFile, ArrayRef<std::string> Archs,
+              StringRef PrependPath) {
+  MachODebugMapParser Parser(InputFile, Archs, PrependPath, false);
+  return Parser.dumpStab();
+}
 }
 }

Modified: llvm/trunk/tools/dsymutil/dsymutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.cpp?rev=246403&r1=246402&r2=246403&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/dsymutil.cpp (original)
+++ llvm/trunk/tools/dsymutil/dsymutil.cpp Sun Aug 30 19:29:09 2015
@@ -48,6 +48,13 @@ static opt<std::string> OsoPrependPath(
     desc("Specify a directory to prepend to the paths of object files."),
     value_desc("path"), cat(DsymCategory));
 
+static opt<bool> DumpStab(
+    "symtab",
+    desc("Dumps the symbol table found in executable or object file(s) and\n"
+         "exits."),
+    init(false), cat(DsymCategory));
+static alias DumpStabA("s", desc("Alias for --symtab"), aliasopt(DumpStab));
+
 static opt<bool> FlatOut("flat",
                          desc("Produce a flat dSYM file (not a bundle)."),
                          init(false), cat(DsymCategory));
@@ -274,6 +281,13 @@ int main(int argc, char **argv) {
     }
 
   for (auto &InputFile : InputFiles) {
+    // Dump the symbol table for each input file and requested arch
+    if (DumpStab) {
+      if (!dumpStab(InputFile, ArchFlags, OsoPrependPath))
+        exitDsymutil(1);
+      continue;
+    }
+
     auto DebugMapPtrsOrErr = parseDebugMap(InputFile, ArchFlags, OsoPrependPath,
                                            Verbose, InputIsYAMLDebugMap);
 

Modified: llvm/trunk/tools/dsymutil/dsymutil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.h?rev=246403&r1=246402&r2=246403&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/dsymutil.h (original)
+++ llvm/trunk/tools/dsymutil/dsymutil.h Sun Aug 30 19:29:09 2015
@@ -39,6 +39,10 @@ llvm::ErrorOr<std::vector<std::unique_pt
 parseDebugMap(StringRef InputFile, ArrayRef<std::string> Archs,
               StringRef PrependPath, bool Verbose, bool InputIsYAML);
 
+/// \brief Dump the symbol table
+bool dumpStab(StringRef InputFile, ArrayRef<std::string> Archs,
+              StringRef PrependPath = "");
+
 /// \brief Link the Dwarf debuginfo as directed by the passed DebugMap
 /// \p DM into a DwarfFile named \p OutputFilename.
 /// \returns false if the link failed.




More information about the llvm-commits mailing list