[LLVMSymbolize] Factor out the logic for printing structs from DIContext. NFC.
authorAlexey Samsonov <vonosmas@gmail.com>
Tue, 3 Nov 2015 22:20:52 +0000 (22:20 +0000)
committerAlexey Samsonov <vonosmas@gmail.com>
Tue, 3 Nov 2015 22:20:52 +0000 (22:20 +0000)
Introduce DIPrinter which takes care of rendering DILineInfo and
friends. This allows LLVMSymbolizer class to return a structured data
instead of plain std::strings.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251989 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DebugInfo/Symbolize/DIPrinter.h [new file with mode: 0644]
include/llvm/DebugInfo/Symbolize/Symbolize.h
lib/DebugInfo/Symbolize/CMakeLists.txt
lib/DebugInfo/Symbolize/DIPrinter.cpp [new file with mode: 0644]
lib/DebugInfo/Symbolize/Symbolize.cpp
tools/llvm-symbolizer/llvm-symbolizer.cpp

diff --git a/include/llvm/DebugInfo/Symbolize/DIPrinter.h b/include/llvm/DebugInfo/Symbolize/DIPrinter.h
new file mode 100644 (file)
index 0000000..6e19225
--- /dev/null
@@ -0,0 +1,43 @@
+//===- llvm/DebugInfo/Symbolize/DIPrinter.h ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the DIPrinter class, which is responsible for printing
+// structures defined in DebugInfo/DIContext.h
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
+#define LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+struct DILineInfo;
+class DIInliningInfo;
+struct DIGlobal;
+
+namespace symbolize {
+
+class DIPrinter {
+  raw_ostream &OS;
+  bool PrintFunctionNames;
+
+public:
+  DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true)
+      : OS(OS), PrintFunctionNames(PrintFunctionNames) {}
+
+  DIPrinter &operator<<(const DILineInfo &Info);
+  DIPrinter &operator<<(const DIInliningInfo &Info);
+  DIPrinter &operator<<(const DIGlobal &Global);
+};
+}
+}
+
+#endif
+
index 2c47114..281d4cd 100644 (file)
@@ -51,14 +51,11 @@ public:
     flush();
   }
 
-  // Returns the result of symbolization for module name/offset as
-  // a string (possibly containing newlines).
-  std::string
-  symbolizeCode(const std::string &ModuleName, uint64_t ModuleOffset);
-  std::string symbolizeInlinedCode(const std::string &ModuleName,
-                                   uint64_t ModuleOffset);
-  std::string
-  symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
+  DILineInfo symbolizeCode(const std::string &ModuleName,
+                           uint64_t ModuleOffset);
+  DIInliningInfo symbolizeInlinedCode(const std::string &ModuleName,
+                                      uint64_t ModuleOffset);
+  DIGlobal symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
   void flush();
   static std::string DemangleName(const std::string &Name,
                                   const SymbolizableModule *ModInfo);
@@ -78,10 +75,6 @@ private:
   /// universal binary (or the binary itself if it is an object file).
   ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName);
 
-  std::string printDILineInfo(DILineInfo LineInfo) const;
-  std::string printDIInliningInfo(DIInliningInfo InlinedContext) const;
-  std::string printDIGlobal(DIGlobal Global) const;
-
   // Owns all the parsed binaries and object files.
   SmallVector<std::unique_ptr<Binary>, 4> ParsedBinariesAndObjects;
   SmallVector<std::unique_ptr<MemoryBuffer>, 4> MemoryBuffers;
@@ -100,7 +93,6 @@ private:
       ObjectPairForPathArch;
 
   Options Opts;
-  static const char kBadString[];
 };
 
 } // namespace symbolize
index 82156c1..fe5c4bf 100644 (file)
@@ -1,4 +1,5 @@
 add_llvm_library(LLVMSymbolize
+  DIPrinter.cpp
   SymbolizableObjectFile.cpp
   Symbolize.cpp
 
diff --git a/lib/DebugInfo/Symbolize/DIPrinter.cpp b/lib/DebugInfo/Symbolize/DIPrinter.cpp
new file mode 100644 (file)
index 0000000..ad5f693
--- /dev/null
@@ -0,0 +1,61 @@
+//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DIPrinter class, which is responsible for printing
+// structures defined in DebugInfo/DIContext.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
+
+#include "llvm/DebugInfo/DIContext.h"
+
+namespace llvm {
+namespace symbolize {
+
+// By default, DILineInfo contains "<invalid>" for function/filename it
+// cannot fetch. We replace it to "??" to make our output closer to addr2line.
+static const char kDILineInfoBadString[] = "<invalid>";
+static const char kBadString[] = "??";
+
+DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
+  if (PrintFunctionNames) {
+    std::string FunctionName = Info.FunctionName;
+    if (FunctionName == kDILineInfoBadString)
+      FunctionName = kBadString;
+    OS << FunctionName << "\n";
+  }
+  std::string Filename = Info.FileName;
+  if (Filename == kDILineInfoBadString)
+    Filename = kBadString;
+  OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
+  return *this;
+}
+
+DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
+  uint32_t FramesNum = Info.getNumberOfFrames();
+  if (FramesNum == 0)
+    return (*this << DILineInfo());
+  for (uint32_t i = 0; i < FramesNum; i++) {
+    *this << Info.getFrame(i);
+  }
+  return *this;
+}
+
+DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
+  std::string Name = Global.Name;
+  if (Name == kDILineInfoBadString)
+    Name = kBadString;
+  OS << Name << "\n";
+  OS << Global.Start << " " << Global.Size << "\n";
+  return *this;
+}
+
+}
+}
index fe180f2..348c2b0 100644 (file)
@@ -30,7 +30,6 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
-#include <sstream>
 #include <stdlib.h>
 
 #if defined(_MSC_VER)
@@ -55,18 +54,11 @@ static bool error(std::error_code ec) {
   return true;
 }
 
-
-// By default, DILineInfo contains "<invalid>" for function/filename it
-// cannot fetch. We replace it to "??" to make our output closer to addr2line.
-static const char kDILineInfoBadString[] = "<invalid>";
-
-const char LLVMSymbolizer::kBadString[] = "??";
-
-std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
-                                          uint64_t ModuleOffset) {
+DILineInfo LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
+                                         uint64_t ModuleOffset) {
   SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName);
   if (!Info)
-    return printDILineInfo(DILineInfo());
+    return DILineInfo();
 
   // If the user is giving us relative addresses, add the preferred base of the
   // object to the offset before we do the query. It's what DIContext expects.
@@ -77,14 +69,15 @@ std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
                                             Opts.UseSymbolTable);
   if (Opts.Demangle)
     LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
-  return printDILineInfo(LineInfo);
+  return LineInfo;
 }
 
-std::string LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
-                                                 uint64_t ModuleOffset) {
+DIInliningInfo
+LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
+                                     uint64_t ModuleOffset) {
   SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName);
   if (!Info)
-    return printDIInliningInfo(DIInliningInfo());
+    return DIInliningInfo();
 
   // If the user is giving us relative addresses, add the preferred base of the
   // object to the offset before we do the query. It's what DIContext expects.
@@ -99,16 +92,16 @@ std::string LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
       Frame->FunctionName = DemangleName(Frame->FunctionName, Info);
     }
   }
-  return printDIInliningInfo(InlinedContext);
+  return InlinedContext;
 }
 
-std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
-                                          uint64_t ModuleOffset) {
+DIGlobal LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+                                       uint64_t ModuleOffset) {
   if (!Opts.UseSymbolTable)
-    return printDIGlobal(DIGlobal());
+    return DIGlobal();
   SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName);
   if (!Info)
-    return printDIGlobal(DIGlobal());
+    return DIGlobal();
 
   // If the user is giving us relative addresses, add the preferred base of
   // the object to the offset before we do the query. It's what DIContext
@@ -119,7 +112,7 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
   DIGlobal Global = Info->symbolizeData(ModuleOffset);
   if (Opts.Demangle)
     Global.Name = DemangleName(Global.Name, Info);
-  return printDIGlobal(Global);
+  return Global;
 }
 
 void LLVMSymbolizer::flush() {
@@ -371,46 +364,6 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
   return Res;
 }
 
-std::string
-LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
-  std::stringstream Result;
-  if (Opts.PrintFunctions != FunctionNameKind::None) {
-    std::string FunctionName = LineInfo.FunctionName;
-    if (FunctionName == kDILineInfoBadString)
-      FunctionName = kBadString;
-    Result << FunctionName << "\n";
-  }
-  std::string Filename = LineInfo.FileName;
-  if (Filename == kDILineInfoBadString)
-    Filename = kBadString;
-  Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n";
-  return Result.str();
-}
-
-std::string
-LLVMSymbolizer::printDIInliningInfo(DIInliningInfo InlinedContext) const {
-  uint32_t FramesNum = InlinedContext.getNumberOfFrames();
-  if (FramesNum == 0)
-    return printDILineInfo(DILineInfo());
-  std::string Result;
-  for (uint32_t i = 0; i < FramesNum; i++) {
-    DILineInfo LineInfo = InlinedContext.getFrame(i);
-    Result += printDILineInfo(LineInfo);
-  }
-  return Result;
-}
-
-std::string
-LLVMSymbolizer::printDIGlobal(DIGlobal Global) const {
-  std::stringstream Result;
-  std::string Name = Global.Name;
-  if (Name == kDILineInfoBadString)
-    Name = kBadString;
-  Result << Name << "\n";
-  Result << Global.Start << " " << Global.Size << "\n";
-  return Result.str();
-}
-
 // Undo these various manglings for Win32 extern "C" functions:
 // cdecl       - _foo
 // stdcall     - _foo@12
index b75f1bc..99afa6d 100644 (file)
@@ -16,6 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
 #include "llvm/Support/COM.h"
 #include "llvm/Support/CommandLine.h"
@@ -148,18 +149,22 @@ int main(int argc, char **argv) {
   bool IsData = false;
   std::string ModuleName;
   uint64_t ModuleOffset;
+  DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None);
+
   while (parseCommand(IsData, ModuleName, ModuleOffset)) {
-    std::string Result =
-        IsData ? Symbolizer.symbolizeData(ModuleName, ModuleOffset)
-               : ClPrintInlining
-                     ? Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset)
-                     : Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
     if (ClPrintAddress) {
       outs() << "0x";
       outs().write_hex(ModuleOffset);
       outs() << "\n";
     }
-    outs() << Result << "\n";
+    if (IsData) {
+      Printer << Symbolizer.symbolizeData(ModuleName, ModuleOffset);
+    } else if (ClPrintInlining) {
+      Printer << Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset);
+    } else {
+      Printer << Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
+    }
+    outs() << "\n";
     outs().flush();
   }