[llvm-commits] [llvm] r140224 - in /llvm/trunk/tools/llvm-objdump: CMakeLists.txt MachODump.cpp Makefile

Benjamin Kramer benny.kra at googlemail.com
Tue Sep 20 18:13:19 PDT 2011


Author: d0k
Date: Tue Sep 20 20:13:19 2011
New Revision: 140224

URL: http://llvm.org/viewvc/llvm-project?rev=140224&view=rev
Log:
llvm-objdump: Output line info next to the disassembly if available.

MachO-only at the moment, sorry.

Usage:
$ llvm-objdump -d -m -g -dsym=a.out.dSYM/Contents/Resources/DWARF/a.out a.out
_main:
100000e90:	55	pushq %rbp	## test.c:11:3
…

Modified:
    llvm/trunk/tools/llvm-objdump/CMakeLists.txt
    llvm/trunk/tools/llvm-objdump/MachODump.cpp
    llvm/trunk/tools/llvm-objdump/Makefile

Modified: llvm/trunk/tools/llvm-objdump/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/CMakeLists.txt?rev=140224&r1=140223&r2=140224&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-objdump/CMakeLists.txt Tue Sep 20 20:13:19 2011
@@ -1,5 +1,6 @@
 set(LLVM_LINK_COMPONENTS
   ${LLVM_TARGETS_TO_BUILD}
+  DebugInfo
   MC
   MCParser
   MCDisassembler

Modified: llvm/trunk/tools/llvm-objdump/MachODump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MachODump.cpp?rev=140224&r1=140223&r2=140224&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/MachODump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/MachODump.cpp Tue Sep 20 20:13:19 2011
@@ -18,6 +18,7 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DIContext.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCDisassembler.h"
 #include "llvm/MC/MCInst.h"
@@ -44,6 +45,12 @@
   CFG("cfg", cl::desc("Create a CFG for every symbol in the object file and"
                       "write it to a graphviz file (MachO-only)"));
 
+static cl::opt<bool>
+  UseDbg("g", cl::desc("Print line information from debug info if available"));
+
+static cl::opt<std::string>
+  DSYMFile("dsym", cl::desc("Use .dSYM file for debug info"));
+
 static const Target *GetTarget(const MachOObject *MachOObj) {
   // Figure out the target triple.
   llvm::Triple TT("unknown-unknown-unknown");
@@ -94,7 +101,6 @@
   bool operator<(const Symbol &RHS) const { return Value < RHS.Value; }
 };
 
-
 template <typename T>
 static Section copySection(const T &Sect) {
   Section S;
@@ -205,6 +211,67 @@
   Out << "}\n";
 }
 
+static void getSectionsAndSymbols(const macho::Header &Header,
+                                  MachOObject *MachOObj,
+                             InMemoryStruct<macho::SymtabLoadCommand> *SymtabLC,
+                                  std::vector<Section> &Sections,
+                                  std::vector<Symbol> &Symbols,
+                                  SmallVectorImpl<uint64_t> &FoundFns) {
+  // Make a list of all symbols in the object file.
+  for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
+    const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i);
+    if (LCI.Command.Type == macho::LCT_Segment) {
+      InMemoryStruct<macho::SegmentLoadCommand> SegmentLC;
+      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLC);
+
+      // Store the sections in this segment.
+      for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
+        InMemoryStruct<macho::Section> Sect;
+        MachOObj->ReadSection(LCI, SectNum, Sect);
+        Sections.push_back(copySection(Sect));
+
+        // Store the symbols in this section.
+        if (SymtabLC) {
+          for (unsigned i = 0; i != (*SymtabLC)->NumSymbolTableEntries; ++i) {
+            InMemoryStruct<macho::SymbolTableEntry> STE;
+            MachOObj->ReadSymbolTableEntry((*SymtabLC)->SymbolTableOffset, i,
+                                           STE);
+            Symbols.push_back(copySymbol(STE));
+          }
+        }
+      }
+    } else if (LCI.Command.Type == macho::LCT_Segment64) {
+      InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
+      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LC);
+
+      // Store the sections in this segment.
+      for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections;
+          ++SectNum) {
+        InMemoryStruct<macho::Section64> Sect64;
+        MachOObj->ReadSection64(LCI, SectNum, Sect64);
+        Sections.push_back(copySection(Sect64));
+
+        // Store the symbols in this section.
+        if (SymtabLC) {
+          for (unsigned i = 0; i != (*SymtabLC)->NumSymbolTableEntries; ++i) {
+            InMemoryStruct<macho::Symbol64TableEntry> STE;
+            MachOObj->ReadSymbol64TableEntry((*SymtabLC)->SymbolTableOffset, i,
+                                             STE);
+            Symbols.push_back(copySymbol(STE));
+          }
+        }
+      }
+    } else if (LCI.Command.Type == macho::LCT_FunctionStarts) {
+      // We found a function starts segment, parse the addresses for later
+      // consumption.
+      InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
+      MachOObj->ReadLinkeditDataLoadCommand(LCI, LLC);
+
+      MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns);
+    }
+  }
+}
+
 void llvm::DisassembleInputMachO(StringRef Filename) {
   OwningPtr<MemoryBuffer> Buff;
 
@@ -260,60 +327,13 @@
 
   std::vector<Section> Sections;
   std::vector<Symbol> Symbols;
-  std::vector<Symbol> UnsortedSymbols; // FIXME: duplication
   SmallVector<uint64_t, 8> FoundFns;
 
-  // Make a list of all symbols in the object file.
-  for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
-    const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i);
-    if (LCI.Command.Type == macho::LCT_Segment) {
-      InMemoryStruct<macho::SegmentLoadCommand> SegmentLC;
-      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLC);
-
-      // Store the sections in this segment.
-      for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
-        InMemoryStruct<macho::Section> Sect;
-        MachOObj->ReadSection(LCI, SectNum, Sect);
-        Sections.push_back(copySection(Sect));
-
-        // Store the symbols in this section.
-        for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
-          InMemoryStruct<macho::SymbolTableEntry> STE;
-          MachOObj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE);
-          Symbols.push_back(copySymbol(STE));
-          UnsortedSymbols.push_back(Symbols.back());
-        }
-      }
-    } else if (LCI.Command.Type == macho::LCT_Segment64) {
-      InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
-      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LC);
-
-      // Store the sections in this segment.
-      for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections;
-           ++SectNum) {
-        InMemoryStruct<macho::Section64> Sect64;
-        MachOObj->ReadSection64(LCI, SectNum, Sect64);
-        Sections.push_back(copySection(Sect64));
-
-        // Store the symbols in this section.
-        for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
-          InMemoryStruct<macho::Symbol64TableEntry> STE;
-          MachOObj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE);
-          Symbols.push_back(copySymbol(STE));
-          UnsortedSymbols.push_back(Symbols.back());
-        }
-      }
-    } else if (LCI.Command.Type == macho::LCT_FunctionStarts) {
-      // We found a function starts segment, parse the addresses for later
-      // consumption.
-      InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
-      MachOObj->ReadLinkeditDataLoadCommand(LCI, LLC);
-
-      MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns);
-    }
-  }
-
+  getSectionsAndSymbols(Header, MachOObj.get(), &SymtabLC, Sections, Symbols,
+                        FoundFns);
 
+  // Make a copy of the unsorted symbol list. FIXME: duplication
+  std::vector<Symbol> UnsortedSymbols(Symbols);
   // Sort the symbols by address, just in case they didn't come in that way.
   array_pod_sort(Symbols.begin(), Symbols.end());
 
@@ -323,6 +343,61 @@
   raw_ostream &DebugOut = nulls();
 #endif
 
+  StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection,
+            DebugLineSection, DebugStrSection;
+  OwningPtr<DIContext> diContext;
+  // Try to find debug info and set up the DIContext for it.
+  if (UseDbg) {
+    ArrayRef<Section> DebugSections = Sections;
+    std::vector<Section> DSYMSections;
+    OwningPtr<MachOObject> DSYMObj;
+
+    // A separate DSym file path was specified, parse it as a macho file,
+    // get the sections and supply it to the section name parsing machinery.
+    if (!DSYMFile.empty()) {
+      OwningPtr<MemoryBuffer> Buf;
+      if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) {
+        errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n';
+        return;
+      }
+      DSYMObj.reset(MachOObject::LoadFromBuffer(Buf.take()));
+      const macho::Header &Header = DSYMObj->getHeader();
+
+      std::vector<Symbol> Symbols;
+      SmallVector<uint64_t, 8> FoundFns;
+      getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols,
+                            FoundFns);
+      DebugSections = DSYMSections;
+    }
+
+    // Find the named debug info sections.
+    for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) {
+      if (!strcmp(DebugSections[SectIdx].Name, "__debug_abbrev"))
+        DebugAbbrevSection = DSYMObj->getData(DebugSections[SectIdx].Offset,
+                                              DebugSections[SectIdx].Size);
+      else if (!strcmp(DebugSections[SectIdx].Name, "__debug_info"))
+        DebugInfoSection = DSYMObj->getData(DebugSections[SectIdx].Offset,
+                                            DebugSections[SectIdx].Size);
+      else if (!strcmp(DebugSections[SectIdx].Name, "__debug_aranges"))
+        DebugArangesSection = DSYMObj->getData(DebugSections[SectIdx].Offset,
+                                               DebugSections[SectIdx].Size);
+      else if (!strcmp(DebugSections[SectIdx].Name, "__debug_line"))
+        DebugLineSection = DSYMObj->getData(DebugSections[SectIdx].Offset,
+                                            DebugSections[SectIdx].Size);
+      else if (!strcmp(DebugSections[SectIdx].Name, "__debug_str"))
+        DebugStrSection = DSYMObj->getData(DebugSections[SectIdx].Offset,
+                                           DebugSections[SectIdx].Size);
+    }
+
+    // Setup the DIContext.
+    diContext.reset(DIContext::getDWARFContext(MachOObj->isLittleEndian(),
+                                               DebugInfoSection,
+                                               DebugAbbrevSection,
+                                               DebugArangesSection,
+                                               DebugLineSection,
+                                               DebugStrSection));
+  }
+
   FunctionMapTy FunctionMap;
   FunctionListTy Functions;
 
@@ -374,6 +449,7 @@
         // Normal disassembly, print addresses, bytes and mnemonic form.
         outs() << MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex)
           << ":\n";
+        DILineInfo lastLine;
         for (uint64_t Index = Start; Index < End; Index += Size) {
           MCInst Inst;
 
@@ -382,6 +458,18 @@
             outs() << format("%8llx:\t", Sections[SectIdx].Address + Index);
             DumpBytes(StringRef(Bytes.data() + Index, Size));
             IP->printInst(&Inst, outs(), "");
+
+            // Print debug info.
+            if (diContext) {
+              DILineInfo dli =
+                diContext->getLineInfoForAddress(Sections[SectIdx].Address +
+                                                 Index);
+              // Print valid line info if it changed.
+              if (dli != lastLine && dli.getLine() != 0)
+                outs() << "\t## " << dli.getFileName() << ':'
+                       << dli.getLine() << ':' << dli.getColumn();
+              lastLine = dli;
+            }
             outs() << "\n";
           } else {
             errs() << "llvm-objdump: warning: invalid instruction encoding\n";
@@ -464,6 +552,7 @@
           if (fi->second.contains(fi->first)) // Print a header for simple loops
             outs() << "# Loop begin:\n";
 
+          DILineInfo lastLine;
           // Walk over the instructions and print them.
           for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie;
                ++ii) {
@@ -506,6 +595,18 @@
             if (targ != -1ULL)
               DumpAddress(targ, Sections, MachOObj.get(), outs());
 
+            // Print debug info.
+            if (diContext) {
+              DILineInfo dli =
+                diContext->getLineInfoForAddress(Sections[SectIdx].Address +
+                                                 Inst.Address);
+              // Print valid line info if it changed.
+              if (dli != lastLine && dli.getLine() != 0)
+                outs() << "\t## " << dli.getFileName() << ':'
+                       << dli.getLine() << ':' << dli.getColumn();
+              lastLine = dli;
+            }
+
             outs() << '\n';
           }
         }

Modified: llvm/trunk/tools/llvm-objdump/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/Makefile?rev=140224&r1=140223&r2=140224&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/Makefile (original)
+++ llvm/trunk/tools/llvm-objdump/Makefile Tue Sep 20 20:13:19 2011
@@ -9,7 +9,8 @@
 LEVEL = ../..
 
 TOOLNAME = llvm-objdump
-LINK_COMPONENTS = $(TARGETS_TO_BUILD) MC MCParser MCDisassembler Object
+LINK_COMPONENTS = $(TARGETS_TO_BUILD) DebugInfo MC MCParser MCDisassembler \
+                  Object
 
 # This tool has no plugins, optimize startup time.
 TOOL_NO_EXPORTS = 1





More information about the llvm-commits mailing list