Add the option, -indirect-symbols, used with -macho to print the Mach-O indirect...
authorKevin Enderby <enderby@apple.com>
Thu, 22 Jan 2015 18:55:27 +0000 (18:55 +0000)
committerKevin Enderby <enderby@apple.com>
Thu, 22 Jan 2015 18:55:27 +0000 (18:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226848 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-objdump/X86/macho-indirect-symbols.test [new file with mode: 0644]
tools/llvm-objdump/MachODump.cpp
tools/llvm-objdump/llvm-objdump.cpp
tools/llvm-objdump/llvm-objdump.h

diff --git a/test/tools/llvm-objdump/X86/macho-indirect-symbols.test b/test/tools/llvm-objdump/X86/macho-indirect-symbols.test
new file mode 100644 (file)
index 0000000..4f3af18
--- /dev/null
@@ -0,0 +1,12 @@
+RUN: llvm-objdump -macho -indirect-symbols %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s
+
+CHECK: Indirect symbols for (__TEXT,__stubs) 1 entries
+CHECK: address            index name
+CHECK: 0x0000000100000f6c     2 _printf
+CHECK: Indirect symbols for (__DATA,__nl_symbol_ptr) 2 entries
+CHECK: address            index name
+CHECK: 0x0000000100001000     3 dyld_stub_binder
+CHECK: 0x0000000100001008 ABSOLUTE
+CHECK: Indirect symbols for (__DATA,__la_symbol_ptr) 1 entries
+CHECK: address            index name
+CHECK: 0x0000000100001010     2 _printf
index 34ad57167d07132b9f87b026ae7b8e2c59804fdf..d6e8e0a01a8697feaed01162a078046cf2c738bd 100644 (file)
@@ -75,6 +75,11 @@ cl::opt<bool>
                          cl::desc("Print archive headers for Mach-O archives "
                                   "(requires -macho)"));
 
+cl::opt<bool>
+    llvm::IndirectSymbols("indirect-symbols",
+                          cl::desc("Print indirect symbol table for Mach-O "
+                                   "objects (requires -macho)"));
+
 static cl::list<std::string>
     ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
               cl::ZeroOrMore);
@@ -260,6 +265,130 @@ static void getSectionsAndSymbols(const MachO::mach_header Header,
   }
 }
 
+static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
+                                     uint32_t n, uint32_t count,
+                                     uint32_t stride, uint64_t addr) {
+  MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
+  uint32_t nindirectsyms = Dysymtab.nindirectsyms;
+  if (n > nindirectsyms)
+    outs() << " (entries start past the end of the indirect symbol "
+              "table) (reserved1 field greater than the table size)";
+  else if (n + count > nindirectsyms)
+    outs() << " (entries extends past the end of the indirect symbol "
+              "table)";
+  outs() << "\n";
+  uint32_t cputype = O->getHeader().cputype;
+  if (cputype & MachO::CPU_ARCH_ABI64)
+    outs() << "address            index";
+  else
+    outs() << "address    index";
+  if (verbose)
+    outs() << " name\n";
+  else
+    outs() << "\n";
+  for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
+    if (cputype & MachO::CPU_ARCH_ABI64)
+      outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
+    else
+      outs() << format("0x%08" PRIx32, addr + j * stride) << " ";
+    MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
+    uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
+    if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
+      outs() << "LOCAL\n";
+      continue;
+    }
+    if (indirect_symbol ==
+        (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
+      outs() << "LOCAL ABSOLUTE\n";
+      continue;
+    }
+    if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
+      outs() << "ABSOLUTE\n";
+      continue;
+    }
+    outs() << format("%5u ", indirect_symbol);
+    MachO::symtab_command Symtab = O->getSymtabLoadCommand();
+    if (indirect_symbol < Symtab.nsyms) {
+      symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
+      SymbolRef Symbol = *Sym;
+      StringRef SymName;
+      Symbol.getName(SymName);
+      outs() << SymName;
+    } else {
+      outs() << "?";
+    }
+    outs() << "\n";
+  }
+}
+
+static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
+  uint32_t LoadCommandCount = O->getHeader().ncmds;
+  MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
+  for (unsigned I = 0;; ++I) {
+    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section_64 Sec = O->getSection64(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+            section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+            section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+            section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+            section_type == MachO::S_SYMBOL_STUBS) {
+          uint32_t stride;
+          if (section_type == MachO::S_SYMBOL_STUBS)
+            stride = Sec.reserved2;
+          else
+            stride = 8;
+          if (stride == 0) {
+            outs() << "Can't print indirect symbols for (" << Sec.segname << ","
+                   << Sec.sectname << ") "
+                   << "(size of stubs in reserved2 field is zero)\n";
+            continue;
+          }
+          uint32_t count = Sec.size / stride;
+          outs() << "Indirect symbols for (" << Sec.segname << ","
+                 << Sec.sectname << ") " << count << " entries";
+          uint32_t n = Sec.reserved1;
+          PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
+        }
+      }
+    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section Sec = O->getSection(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+            section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+            section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+            section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+            section_type == MachO::S_SYMBOL_STUBS) {
+          uint32_t stride;
+          if (section_type == MachO::S_SYMBOL_STUBS)
+            stride = Sec.reserved2;
+          else
+            stride = 4;
+          if (stride == 0) {
+            outs() << "Can't print indirect symbols for (" << Sec.segname << ","
+                   << Sec.sectname << ") "
+                   << "(size of stubs in reserved2 field is zero)\n";
+            continue;
+          }
+          uint32_t count = Sec.size / stride;
+          outs() << "Indirect symbols for (" << Sec.segname << ","
+                 << Sec.sectname << ") " << count << " entries";
+          uint32_t n = Sec.reserved1;
+          PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
+        }
+      }
+    }
+    if (I == LoadCommandCount - 1)
+      break;
+    else
+      Load = O->getNextLoadCommandInfo(Load);
+  }
+}
+
 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
 // and if it is and there is a list of architecture flags is specified then
 // check to make sure this Mach-O file is one of those architectures or all
@@ -305,9 +434,9 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
                          StringRef ArchitectureName = StringRef()) {
   // If we are doing some processing here on the Mach-O file print the header
   // info.  And don't print it otherwise like in the case of printing the
-  // UniversalHeaders.
+  // UniversalHeaders or ArchiveHeaders.
   if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
-      LazyBind || WeakBind) {
+      LazyBind || WeakBind || IndirectSymbols) {
     outs() << Filename;
     if (!ArchiveMemberName.empty())
       outs() << '(' << ArchiveMemberName << ')';
@@ -318,6 +447,8 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
 
   if (Disassemble)
     DisassembleMachO(Filename, MachOOF);
+  if (IndirectSymbols)
+    PrintIndirectSymbols(MachOOF, true);
   if (Relocations)
     PrintRelocations(MachOOF);
   if (SectionHeaders)
index 76c8af420568a976d940fd14291365766a1d4324..f9660fef9fc5810bbf9eec68d8e00f2f94467615 100644 (file)
@@ -893,7 +893,8 @@ int main(int argc, char **argv) {
       && !LazyBind
       && !WeakBind
       && !(UniversalHeaders && MachOOpt)
-      && !(ArchiveHeaders && MachOOpt)) {
+      && !(ArchiveHeaders && MachOOpt)
+      && !(IndirectSymbols && MachOOpt)) {
     cl::PrintHelpMessage();
     return 2;
   }
index a0e0d5a6a6c2c67f404bdb1973ab6f2e989dede6..3549a79d58516157075ea9948592271563e9b9a3 100644 (file)
@@ -36,6 +36,7 @@ extern cl::opt<bool> LazyBind;
 extern cl::opt<bool> WeakBind;
 extern cl::opt<bool> UniversalHeaders;
 extern cl::opt<bool> ArchiveHeaders;
+extern cl::opt<bool> IndirectSymbols;
 extern cl::opt<bool> Relocations;
 extern cl::opt<bool> SectionHeaders;
 extern cl::opt<bool> SectionContents;