[llvm-commits] [llvm] r173159 - in /llvm/trunk/tools/llvm-symbolizer: CMakeLists.txt LLVMSymbolize.cpp LLVMSymbolize.h llvm-symbolizer.cpp

Alexey Samsonov samsonov at google.com
Tue Jan 22 06:21:19 PST 2013


Author: samsonov
Date: Tue Jan 22 08:21:19 2013
New Revision: 173159

URL: http://llvm.org/viewvc/llvm-project?rev=173159&view=rev
Log:
llvm-symbolizer: factor out bits of the tool into separate LLVMSymbolize.{h,cpp} files. No functionality change.

Added:
    llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.cpp
    llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.h
Modified:
    llvm/trunk/tools/llvm-symbolizer/CMakeLists.txt
    llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp

Modified: llvm/trunk/tools/llvm-symbolizer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-symbolizer/CMakeLists.txt?rev=173159&r1=173158&r2=173159&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-symbolizer/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-symbolizer/CMakeLists.txt Tue Jan 22 08:21:19 2013
@@ -9,5 +9,6 @@
   )
 
 add_llvm_tool(llvm-symbolizer
+  LLVMSymbolize.cpp
   llvm-symbolizer.cpp
   )

Added: llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.cpp?rev=173159&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.cpp (added)
+++ llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.cpp Tue Jan 22 08:21:19 2013
@@ -0,0 +1,272 @@
+//===-- LLVMSymbolize.cpp -------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation for LLVM symbolization library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLVMSymbolize.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Path.h"
+
+#include <sstream>
+
+namespace llvm {
+namespace symbolize {
+
+static uint32_t getDILineInfoSpecifierFlags(
+    const LLVMSymbolizer::Options &Opts) {
+  uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
+                   llvm::DILineInfoSpecifier::AbsoluteFilePath;
+  if (Opts.PrintFunctions)
+    Flags |= llvm::DILineInfoSpecifier::FunctionName;
+  return Flags;
+}
+
+static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
+                                          DILineInfo &LineInfo) {
+  std::string FileName = LineInfo.getFileName();
+  LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
+                        LineInfo.getLine(), LineInfo.getColumn());
+}
+
+DILineInfo ModuleInfo::symbolizeCode(uint64_t ModuleOffset,
+    const LLVMSymbolizer::Options& Opts) const {
+  DILineInfo LineInfo;
+  if (DebugInfoContext) {
+    LineInfo = DebugInfoContext->getLineInfoForAddress(
+        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
+  }
+  // Override function name from symbol table if necessary.
+  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
+    std::string FunctionName;
+    uint64_t Start, Size;
+    if (getNameFromSymbolTable(SymbolRef::ST_Function,
+                               ModuleOffset, FunctionName, Start, Size)) {
+      patchFunctionNameInDILineInfo(FunctionName, LineInfo);
+    }
+  }
+  return LineInfo;
+}
+
+DIInliningInfo ModuleInfo::symbolizeInlinedCode(uint64_t ModuleOffset,
+    const LLVMSymbolizer::Options& Opts) const {
+  DIInliningInfo InlinedContext;
+  if (DebugInfoContext) {
+    InlinedContext = DebugInfoContext->getInliningInfoForAddress(
+        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
+  }
+  // Make sure there is at least one frame in context.
+  if (InlinedContext.getNumberOfFrames() == 0) {
+    InlinedContext.addFrame(DILineInfo());
+  }
+  // Override the function name in lower frame with name from symbol table.
+  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
+    DIInliningInfo PatchedInlinedContext;
+    for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames();
+         i < n; i++) {
+      DILineInfo LineInfo = InlinedContext.getFrame(i);
+      if (i == n - 1) {
+        std::string FunctionName;
+        uint64_t Start, Size;
+        if (getNameFromSymbolTable(SymbolRef::ST_Function,
+                                   ModuleOffset, FunctionName, Start, Size)) {
+          patchFunctionNameInDILineInfo(FunctionName, LineInfo);
+        }
+      }
+      PatchedInlinedContext.addFrame(LineInfo);
+    }
+    InlinedContext = PatchedInlinedContext;
+  }
+  return InlinedContext;
+}
+
+bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
+                               uint64_t &Start, uint64_t &Size) const {
+  return getNameFromSymbolTable(SymbolRef::ST_Data,
+                                ModuleOffset, Name, Start, Size);
+}
+
+static bool error(error_code ec) {
+  if (!ec) return false;
+  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
+  return true;
+}
+
+bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
+                                        std::string &Name, uint64_t &Addr,
+                                        uint64_t &Size) const {
+  assert(Module);
+  error_code ec;
+  for (symbol_iterator si = Module->begin_symbols(),
+                       se = Module->end_symbols();
+                       si != se; si.increment(ec)) {
+    if (error(ec)) return false;
+    uint64_t SymbolAddress;
+    uint64_t SymbolSize;
+    SymbolRef::Type SymbolType;
+    if (error(si->getAddress(SymbolAddress)) ||
+        SymbolAddress == UnknownAddressOrSize) continue;
+    if (error(si->getSize(SymbolSize)) ||
+        SymbolSize == UnknownAddressOrSize) continue;
+    if (error(si->getType(SymbolType))) continue;
+    // FIXME: If a function has alias, there are two entries in symbol table
+    // with same address size. Make sure we choose the correct one.
+    if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize &&
+        SymbolType == Type) {
+      StringRef SymbolName;
+      if (error(si->getName(SymbolName))) continue;
+      Name = SymbolName.str();
+      Addr = SymbolAddress;
+      Size = SymbolSize;
+      return true;
+    }
+  }
+  return false;
+}
+
+const std::string LLVMSymbolizer::kBadString = "??";
+
+std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
+                                          uint64_t ModuleOffset) {
+  ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
+  if (Info == 0)
+    return printDILineInfo(DILineInfo());
+  if (Opts.PrintInlining) {
+    DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
+        ModuleOffset, Opts);
+    uint32_t FramesNum = InlinedContext.getNumberOfFrames();
+    assert(FramesNum > 0);
+    std::string Result;
+    for (uint32_t i = 0; i < FramesNum; i++) {
+      DILineInfo LineInfo = InlinedContext.getFrame(i);
+      Result += printDILineInfo(LineInfo);
+    }
+    return Result;
+  }
+  DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
+  return printDILineInfo(LineInfo);
+}
+
+std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+                                          uint64_t ModuleOffset) {
+  std::string Name = kBadString;
+  uint64_t Start = 0;
+  uint64_t Size = 0;
+  if (Opts.UseSymbolTable) {
+    if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
+      if (Info->symbolizeData(ModuleOffset, Name, Start, Size))
+        DemangleName(Name);
+    }
+  }
+  std::stringstream ss;
+  ss << Name << "\n" << Start << " " << Size << "\n";
+  return ss.str();
+}
+
+// Returns true if the object endianness is known.
+static bool getObjectEndianness(const ObjectFile *Obj,
+                                bool &IsLittleEndian) {
+  // FIXME: Implement this when libLLVMObject allows to do it easily.
+  IsLittleEndian = true;
+  return true;
+}
+
+static ObjectFile *getObjectFile(const std::string &Path) {
+  OwningPtr<MemoryBuffer> Buff;
+  MemoryBuffer::getFile(Path, Buff);
+  return ObjectFile::createObjectFile(Buff.take());
+}
+
+static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
+  StringRef Basename = sys::path::filename(Path);
+  const std::string &DSymDirectory = Path + ".dSYM";
+  SmallString<16> ResourceName = StringRef(DSymDirectory);
+  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
+  sys::path::append(ResourceName, Basename);
+  return ResourceName.str();
+}
+
+ModuleInfo *LLVMSymbolizer::getOrCreateModuleInfo(
+    const std::string &ModuleName) {
+  ModuleMapTy::iterator I = Modules.find(ModuleName);
+  if (I != Modules.end())
+    return I->second;
+
+  ObjectFile *Obj = getObjectFile(ModuleName);
+  ObjectFile *DbgObj = Obj;
+  if (Obj == 0) {
+    // Module name doesn't point to a valid object file.
+    Modules.insert(make_pair(ModuleName, (ModuleInfo*)0));
+    return 0;
+  }
+
+  DIContext *Context = 0;
+  bool IsLittleEndian;
+  if (getObjectEndianness(Obj, IsLittleEndian)) {
+    // On Darwin we may find DWARF in separate object file in
+    // resource directory.
+    if (isa<MachOObjectFile>(Obj)) {
+      const std::string &ResourceName = getDarwinDWARFResourceForModule(
+          ModuleName);
+      ObjectFile *ResourceObj = getObjectFile(ResourceName);
+      if (ResourceObj != 0)
+        DbgObj = ResourceObj;
+    }
+    Context = DIContext::getDWARFContext(DbgObj);
+    assert(Context);
+  }
+
+  ModuleInfo *Info = new ModuleInfo(Obj, Context);
+  Modules.insert(make_pair(ModuleName, Info));
+  return Info;
+}
+
+std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
+  // By default, DILineInfo contains "<invalid>" for function/filename it
+  // cannot fetch. We replace it to "??" to make our output closer to addr2line.
+  static const std::string kDILineInfoBadString = "<invalid>";
+  std::stringstream Result;
+  if (Opts.PrintFunctions) {
+    std::string FunctionName = LineInfo.getFunctionName();
+    if (FunctionName == kDILineInfoBadString)
+      FunctionName = kBadString;
+    DemangleName(FunctionName);
+    Result << FunctionName << "\n";
+  }
+  std::string Filename = LineInfo.getFileName();
+  if (Filename == kDILineInfoBadString)
+    Filename = kBadString;
+  Result << Filename << ":" << LineInfo.getLine()
+                     << ":" << LineInfo.getColumn() << "\n";
+  return Result.str();
+}
+
+#if !defined(_MSC_VER)
+// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
+extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
+                                size_t *length, int *status);
+#endif
+
+void LLVMSymbolizer::DemangleName(std::string &Name) const {
+#if !defined(_MSC_VER)
+  if (!Opts.Demangle)
+    return;
+  int status = 0;
+  char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
+  if (status != 0)
+    return;
+  Name = DemangledName;
+  free(DemangledName);
+#endif
+}
+
+}  // namespace symbolize
+}  // namespace llvm

Added: llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.h?rev=173159&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.h (added)
+++ llvm/trunk/tools/llvm-symbolizer/LLVMSymbolize.h Tue Jan 22 08:21:19 2013
@@ -0,0 +1,88 @@
+//===-- LLVMSymbolize.h ----------------------------------------- C++ -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header for LLVM symbolization library.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SYMBOLIZE_H
+#define LLVM_SYMBOLIZE_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <map>
+#include <string>
+
+namespace llvm {
+
+using namespace object;
+
+namespace symbolize {
+
+class ModuleInfo;
+
+class LLVMSymbolizer {
+public:
+ struct Options {
+    bool UseSymbolTable : 1;
+    bool PrintFunctions : 1;
+    bool PrintInlining : 1;
+    bool Demangle : 1;
+    Options(bool UseSymbolTable = true, bool PrintFunctions = true,
+            bool PrintInlining = true, bool Demangle = true)
+        : UseSymbolTable(UseSymbolTable),
+          PrintFunctions(PrintFunctions),
+          PrintInlining(PrintInlining),
+          Demangle(Demangle) { }
+  };
+
+  LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) { }
+
+  // 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 symbolizeData(const std::string &ModuleName,
+                            uint64_t ModuleOffset);
+private:
+  ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName);
+  std::string printDILineInfo(DILineInfo LineInfo) const;
+  void DemangleName(std::string &Name) const;
+
+  typedef std::map<std::string, ModuleInfo*> ModuleMapTy;
+  ModuleMapTy Modules;
+  Options Opts;
+  static const std::string kBadString;
+};
+
+class ModuleInfo {
+  OwningPtr<ObjectFile> Module;
+  OwningPtr<DIContext> DebugInfoContext;
+ public:
+  ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
+      : Module(Obj), DebugInfoContext(DICtx) {}
+
+  DILineInfo symbolizeCode(
+      uint64_t ModuleOffset, const LLVMSymbolizer::Options& Opts) const;
+  DIInliningInfo symbolizeInlinedCode(
+      uint64_t ModuleOffset, const LLVMSymbolizer::Options& Opts) const;
+  bool symbolizeData(uint64_t ModuleOffset, std::string &Name,
+                     uint64_t &Start, uint64_t &Size) const;
+
+ private:
+  bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
+                              std::string &Name, uint64_t &Addr,
+                              uint64_t &Size) const;
+};
+
+}  // namespace symbolize
+}  // namespace llvm
+
+#endif  // LLVM_SYMBOLIZE_H

Modified: llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp?rev=173159&r1=173158&r2=173159&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp (original)
+++ llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp Tue Jan 22 08:21:19 2013
@@ -15,315 +15,42 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/OwningPtr.h"
+#include "LLVMSymbolize.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdio>
 #include <cstring>
-#include <map>
 #include <string>
 
 using namespace llvm;
-using namespace object;
+using namespace symbolize;
 
 static cl::opt<bool>
-UseSymbolTable("use-symbol-table", cl::init(true),
+ClUseSymbolTable("use-symbol-table", cl::init(true),
                cl::desc("Prefer names in symbol table to names "
                         "in debug info"));
 
 static cl::opt<bool>
-PrintFunctions("functions", cl::init(true),
+ClPrintFunctions("functions", cl::init(true),
                cl::desc("Print function names as well as line "
                         "information for a given address"));
 
 static cl::opt<bool>
-PrintInlining("inlining", cl::init(true),
+ClPrintInlining("inlining", cl::init(true),
               cl::desc("Print all inlined frames for a given address"));
 
 static cl::opt<bool>
-Demangle("demangle", cl::init(true),
+ClDemangle("demangle", cl::init(true),
          cl::desc("Demangle function names"));
 
-static const std::string kSymbolizerBadString = "??";
-
-static StringRef ToolInvocationPath;
-
-static bool error(error_code ec) {
-  if (!ec) return false;
-  errs() << ToolInvocationPath << ": error reading file: "
-         << ec.message() << ".\n";
-  return true;
-}
-
-static uint32_t getDILineInfoSpecifierFlags() {
-  uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
-                   llvm::DILineInfoSpecifier::AbsoluteFilePath;
-  if (PrintFunctions)
-    Flags |= llvm::DILineInfoSpecifier::FunctionName;
-  return Flags;
-}
-
-static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
-                                          DILineInfo &LineInfo) {
-  std::string FileName = LineInfo.getFileName();
-  LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
-                        LineInfo.getLine(), LineInfo.getColumn());
-}
-
-namespace {
-class ModuleInfo {
-  OwningPtr<ObjectFile> Module;
-  OwningPtr<DIContext> DebugInfoContext;
- public:
-  ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
-      : Module(Obj), DebugInfoContext(DICtx) {}
-
-  DILineInfo symbolizeCode(uint64_t ModuleOffset) const {
-    DILineInfo LineInfo;
-    if (DebugInfoContext) {
-      LineInfo = DebugInfoContext->getLineInfoForAddress(
-          ModuleOffset, getDILineInfoSpecifierFlags());
-    }
-    // Override function name from symbol table if necessary.
-    if (PrintFunctions && UseSymbolTable) {
-      std::string Function;
-      uint64_t Start, Size;
-      if (getNameFromSymbolTable(SymbolRef::ST_Function,
-                                 ModuleOffset, Function, Start, Size)) {
-        patchFunctionNameInDILineInfo(Function, LineInfo);
-      }
-    }
-    return LineInfo;
-  }
-
-  DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset) const {
-    DIInliningInfo InlinedContext;
-    if (DebugInfoContext) {
-      InlinedContext = DebugInfoContext->getInliningInfoForAddress(
-          ModuleOffset, getDILineInfoSpecifierFlags());
-    }
-    // Make sure there is at least one frame in context.
-    if (InlinedContext.getNumberOfFrames() == 0) {
-      InlinedContext.addFrame(DILineInfo());
-    }
-    // Override the function name in lower frame with name from symbol table.
-    if (PrintFunctions && UseSymbolTable) {
-      DIInliningInfo PatchedInlinedContext;
-      for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames();
-           i != n; i++) {
-        DILineInfo LineInfo = InlinedContext.getFrame(i);
-        if (i == n - 1) {
-          std::string Function;
-          uint64_t Start, Size;
-          if (getNameFromSymbolTable(SymbolRef::ST_Function,
-                                     ModuleOffset, Function, Start, Size)) {
-            patchFunctionNameInDILineInfo(Function, LineInfo);
-          }
-        }
-        PatchedInlinedContext.addFrame(LineInfo);
-      }
-      InlinedContext = PatchedInlinedContext;
-    }
-    return InlinedContext;
-  }
-
-  bool symbolizeData(uint64_t ModuleOffset, std::string &Name,
-                     uint64_t &Start, uint64_t &Size) const {
-    return getNameFromSymbolTable(SymbolRef::ST_Data,
-                                  ModuleOffset, Name, Start, Size);
-  }
-
- private:
-  bool getNameFromSymbolTable(SymbolRef::Type Type,
-                              uint64_t Address,
-                              std::string &Name,
-                              uint64_t &Addr,
-                              uint64_t &Size) const {
-    assert(Module);
-    error_code ec;
-    for (symbol_iterator si = Module->begin_symbols(),
-                         se = Module->end_symbols();
-                         si != se; si.increment(ec)) {
-      if (error(ec)) return false;
-      uint64_t SymbolAddress;
-      uint64_t SymbolSize;
-      SymbolRef::Type SymbolType;
-      if (error(si->getAddress(SymbolAddress)) ||
-          SymbolAddress == UnknownAddressOrSize) continue;
-      if (error(si->getSize(SymbolSize)) ||
-          SymbolSize == UnknownAddressOrSize) continue;
-      if (error(si->getType(SymbolType))) continue;
-      // FIXME: If a function has alias, there are two entries in symbol table
-      // with same address size. Make sure we choose the correct one.
-      if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize &&
-          SymbolType == Type) {
-        StringRef SymbolName;
-        if (error(si->getName(SymbolName))) continue;
-        Name = SymbolName.str();
-        Addr = SymbolAddress;
-        Size = SymbolSize;
-        return true;
-      }
-    }
-    return false;
-  }
-};
-
-#if !defined(_MSC_VER)
-// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
-extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
-                                size_t *length, int *status);
-#endif
-
-void DemangleName(std::string &Name) {
-#if !defined(_MSC_VER)
-  if (!Demangle)
-    return;
-  int status = 0;
-  char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
-  if (status != 0)
-    return;
-  Name = DemangledName;
-  free(DemangledName);
-#endif
-}
-
-typedef std::map<std::string, ModuleInfo*> ModuleMapTy;
-typedef ModuleMapTy::iterator ModuleMapIter;
-}  // namespace
-
-static ModuleMapTy Modules;
-
-// Returns true if the object endianness is known.
-static bool getObjectEndianness(const ObjectFile *Obj,
-                                bool &IsLittleEndian) {
-  // FIXME: Implement this when libLLVMObject allows to do it easily.
-  IsLittleEndian = true;
-  return true;
-}
-
-static ObjectFile *getObjectFile(const std::string &Path) {
-  OwningPtr<MemoryBuffer> Buff;
-  MemoryBuffer::getFile(Path, Buff);
-  return ObjectFile::createObjectFile(Buff.take());
-}
-
-static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
-  StringRef Basename = sys::path::filename(Path);
-  const std::string &DSymDirectory = Path + ".dSYM";
-  SmallString<16> ResourceName = StringRef(DSymDirectory);
-  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
-  sys::path::append(ResourceName, Basename);
-  return ResourceName.str();
-}
-
-static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) {
-  ModuleMapIter I = Modules.find(ModuleName);
-  if (I != Modules.end())
-    return I->second;
-
-  ObjectFile *Obj = getObjectFile(ModuleName);
-  ObjectFile *DbgObj = Obj;
-  if (Obj == 0) {
-    // Module name doesn't point to a valid object file.
-    Modules.insert(make_pair(ModuleName, (ModuleInfo*)0));
-    return 0;
-  }
-
-  DIContext *Context = 0;
-  bool IsLittleEndian;
-  if (getObjectEndianness(Obj, IsLittleEndian)) {
-    // On Darwin we may find DWARF in separate object file in
-    // resource directory.
-    if (isa<MachOObjectFile>(Obj)) {
-      const std::string &ResourceName = getDarwinDWARFResourceForModule(
-          ModuleName);
-      ObjectFile *ResourceObj = getObjectFile(ResourceName);
-      if (ResourceObj != 0)
-        DbgObj = ResourceObj;
-    }
-    Context = DIContext::getDWARFContext(DbgObj);
-    assert(Context);
-  }
-
-  ModuleInfo *Info = new ModuleInfo(Obj, Context);
-  Modules.insert(make_pair(ModuleName, Info));
-  return Info;
-}
-
-static void printDILineInfo(DILineInfo LineInfo) {
-  // By default, DILineInfo contains "<invalid>" for function/filename it
-  // cannot fetch. We replace it to "??" to make our output closer to addr2line.
-  static const std::string kDILineInfoBadString = "<invalid>";
-  if (PrintFunctions) {
-    std::string FunctionName = LineInfo.getFunctionName();
-    if (FunctionName == kDILineInfoBadString)
-      FunctionName = kSymbolizerBadString;
-    DemangleName(FunctionName);
-    outs() << FunctionName << "\n";
-  }
-  std::string Filename = LineInfo.getFileName();
-  if (Filename == kDILineInfoBadString)
-    Filename = kSymbolizerBadString;
-  outs() << Filename <<
-         ":" << LineInfo.getLine() <<
-         ":" << LineInfo.getColumn() <<
-         "\n";
-}
-
-static void symbolizeCode(std::string ModuleName, std::string ModuleOffsetStr) {
-  ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
-  uint64_t Offset = 0;
-  if (Info == 0 ||
-      StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) {
-    printDILineInfo(DILineInfo());
-  } else if (PrintInlining) {
-    DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(Offset);
-    uint32_t FramesNum = InlinedContext.getNumberOfFrames();
-    assert(FramesNum > 0);
-    for (uint32_t i = 0; i < FramesNum; i++) {
-      DILineInfo LineInfo = InlinedContext.getFrame(i);
-      printDILineInfo(LineInfo);
-    }
-  } else {
-    DILineInfo LineInfo = Info->symbolizeCode(Offset);
-    printDILineInfo(LineInfo);
-  }
-
-  outs() << "\n";  // Print extra empty line to mark the end of output.
-  outs().flush();
-}
-
-static void symbolizeData(std::string ModuleName, std::string ModuleOffsetStr) {
-  std::string Name = kSymbolizerBadString;
-  uint64_t Start = 0;
-  uint64_t Size = 0;
-  uint64_t Offset = 0;
-  if (UseSymbolTable) {
-    ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
-    if (Info && !StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) {
-      if (Info->symbolizeData(Offset, Name, Start, Size))
-        DemangleName(Name);
-    }
-  }
-  outs() << Name << "\n" << Start << " " << Size << "\n\n";
-  outs().flush();
-}
-
 static bool parseCommand(bool &IsData,
                          std::string &ModuleName,
-                         std::string &ModuleOffsetStr) {
+                         uint64_t &ModuleOffset) {
   const char *kDataCmd = "DATA ";
   const char *kCodeCmd = "CODE ";
   const int kMaxInputStringLength = 1024;
@@ -333,7 +60,7 @@
     return false;
   IsData = false;
   ModuleName = "";
-  ModuleOffsetStr = "";
+  std::string ModuleOffsetStr = "";
   char *pos = InputString;
   if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) {
     IsData = true;
@@ -351,6 +78,8 @@
     if (char *OffsetStr = strtok((char*)0, kDelimiters))
       ModuleOffsetStr = OffsetStr;
   }
+  if (StringRef(ModuleOffsetStr).getAsInteger(0, ModuleOffset))
+    return false;
   return true;
 }
 
@@ -361,16 +90,19 @@
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
 
   cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n");
-  ToolInvocationPath = argv[0];
+  LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
+                               ClPrintInlining, ClDemangle);
+  LLVMSymbolizer Symbolizer(Opts);
 
   bool IsData = false;
   std::string ModuleName;
-  std::string ModuleOffsetStr;
-  while (parseCommand(IsData, ModuleName, ModuleOffsetStr)) {
-    if (IsData)
-      symbolizeData(ModuleName, ModuleOffsetStr);
-    else
-      symbolizeCode(ModuleName, ModuleOffsetStr);
+  uint64_t ModuleOffset;
+  while (parseCommand(IsData, ModuleName, ModuleOffset)) {
+    std::string Result =
+        IsData ? Symbolizer.symbolizeData(ModuleName, ModuleOffset)
+               : Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
+    outs() << Result << "\n";
+    outs().flush();
   }
   return 0;
 }





More information about the llvm-commits mailing list