summaryrefslogtreecommitdiff
path: root/tools/llvm-symbolizer
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-06-28 08:15:40 +0000
committerAlexey Samsonov <samsonov@google.com>2013-06-28 08:15:40 +0000
commit8175bc3d3bc8567a90b9dd50d68c1423baffd63b (patch)
treed520197471dc8c5b49816e39bdf55f5c4817494a /tools/llvm-symbolizer
parent363720e06c4a61a6695e2b2b8f1dfdd597e52b95 (diff)
downloadllvm-8175bc3d3bc8567a90b9dd50d68c1423baffd63b.tar.gz
llvm-8175bc3d3bc8567a90b9dd50d68c1423baffd63b.tar.bz2
llvm-8175bc3d3bc8567a90b9dd50d68c1423baffd63b.tar.xz
llvm-symbolizer: add support for Mach-O universal binaries
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185137 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-symbolizer')
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp109
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.h28
-rw-r--r--tools/llvm-symbolizer/llvm-symbolizer.cpp6
3 files changed, 101 insertions, 42 deletions
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp
index 7fccedf1c4..74e9843c43 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -198,23 +198,10 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
void LLVMSymbolizer::flush() {
DeleteContainerSeconds(Modules);
+ DeleteContainerPointers(ParsedBinariesAndObjects);
}
-// 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;
- if (error(MemoryBuffer::getFile(Path, Buff)))
- return 0;
- return ObjectFile::createObjectFile(Buff.take());
-}
-
-static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
+static std::string getDarwinDWARFResourceForPath(const std::string &Path) {
StringRef Basename = sys::path::filename(Path);
const std::string &DSymDirectory = Path + ".dSYM";
SmallString<16> ResourceName = StringRef(DSymDirectory);
@@ -223,39 +210,85 @@ static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
return ResourceName.str();
}
+LLVMSymbolizer::BinaryPair
+LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
+ BinaryMapTy::iterator I = BinaryForPath.find(Path);
+ if (I != BinaryForPath.end())
+ return I->second;
+ Binary *Bin = 0;
+ Binary *DbgBin = 0;
+ OwningPtr<Binary> ParsedBinary;
+ OwningPtr<Binary> ParsedDbgBinary;
+ if (!error(createBinary(Path, ParsedBinary))) {
+ // Check if it's a universal binary.
+ Bin = ParsedBinary.take();
+ ParsedBinariesAndObjects.push_back(Bin);
+ if (Bin->isMachO() || Bin->isMachOUniversalBinary()) {
+ // On Darwin we may find DWARF in separate object file in
+ // resource directory.
+ const std::string &ResourcePath =
+ getDarwinDWARFResourceForPath(Path);
+ bool ResourceFileExists = false;
+ if (!sys::fs::exists(ResourcePath, ResourceFileExists) &&
+ ResourceFileExists &&
+ !error(createBinary(ResourcePath, ParsedDbgBinary))) {
+ DbgBin = ParsedDbgBinary.take();
+ ParsedBinariesAndObjects.push_back(DbgBin);
+ }
+ }
+ }
+ if (DbgBin == 0)
+ DbgBin = Bin;
+ BinaryPair Res = std::make_pair(Bin, DbgBin);
+ BinaryForPath[Path] = Res;
+ return Res;
+}
+
+ObjectFile *
+LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) {
+ if (Bin == 0)
+ return 0;
+ ObjectFile *Res = 0;
+ if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
+ ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find(
+ std::make_pair(UB, ArchName));
+ if (I != ObjectFileForArch.end())
+ return I->second;
+ OwningPtr<ObjectFile> ParsedObj;
+ if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
+ Res = ParsedObj.take();
+ ParsedBinariesAndObjects.push_back(Res);
+ }
+ ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
+ } else if (Bin->isObject()) {
+ Res = cast<ObjectFile>(Bin);
+ }
+ return Res;
+}
+
ModuleInfo *
LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
ModuleMapTy::iterator I = Modules.find(ModuleName);
if (I != Modules.end())
return I->second;
+ std::string BinaryName = ModuleName;
+ std::string ArchName = Opts.DefaultArch;
+ size_t ColonPos = ModuleName.find(':');
+ if (ColonPos != std::string::npos) {
+ BinaryName = ModuleName.substr(0, ColonPos);
+ ArchName = ModuleName.substr(ColonPos + 1);
+ }
+ BinaryPair Binaries = getOrCreateBinary(BinaryName);
+ ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName);
+ ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName);
- ObjectFile *Obj = getObjectFile(ModuleName);
if (Obj == 0) {
- // Module name doesn't point to a valid object file.
+ // Failed to find 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.
- ObjectFile *DbgObj = Obj;
- if (isa<MachOObjectFile>(Obj)) {
- const std::string &ResourceName =
- getDarwinDWARFResourceForModule(ModuleName);
- bool ResourceFileExists = false;
- if (!sys::fs::exists(ResourceName, ResourceFileExists) &&
- ResourceFileExists) {
- if (ObjectFile *ResourceObj = getObjectFile(ResourceName))
- DbgObj = ResourceObj;
- }
- }
- Context = DIContext::getDWARFContext(DbgObj);
- assert(Context);
- }
-
+ DIContext *Context = DIContext::getDWARFContext(DbgObj);
+ assert(Context);
ModuleInfo *Info = new ModuleInfo(Obj, Context);
Modules.insert(make_pair(ModuleName, Info));
return Info;
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h
index 188331bfa6..c7f87b1429 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.h
+++ b/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -14,7 +14,9 @@
#define LLVM_SYMBOLIZE_H
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
@@ -35,10 +37,13 @@ public:
bool PrintFunctions : 1;
bool PrintInlining : 1;
bool Demangle : 1;
+ std::string DefaultArch;
Options(bool UseSymbolTable = true, bool PrintFunctions = true,
- bool PrintInlining = true, bool Demangle = true)
+ bool PrintInlining = true, bool Demangle = true,
+ std::string DefaultArch = "")
: UseSymbolTable(UseSymbolTable), PrintFunctions(PrintFunctions),
- PrintInlining(PrintInlining), Demangle(Demangle) {
+ PrintInlining(PrintInlining), Demangle(Demangle),
+ DefaultArch(DefaultArch) {
}
};
@@ -52,12 +57,29 @@ public:
symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
void flush();
private:
+ typedef std::pair<Binary*, Binary*> BinaryPair;
+
ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName);
+ /// \brief Returns pair of pointers to binary and debug binary.
+ BinaryPair getOrCreateBinary(const std::string &Path);
+ /// \brief Returns a parsed object file for a given architecture in a
+ /// 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;
void DemangleName(std::string &Name) const;
+ // Owns all the parsed binaries and object files.
+ SmallVector<Binary*, 4> ParsedBinariesAndObjects;
+ // Owns module info objects.
typedef std::map<std::string, ModuleInfo *> ModuleMapTy;
ModuleMapTy Modules;
+ typedef std::map<std::string, BinaryPair> BinaryMapTy;
+ BinaryMapTy BinaryForPath;
+ typedef std::map<std::pair<MachOUniversalBinary *, std::string>, ObjectFile *>
+ ObjectFileForArchMapTy;
+ ObjectFileForArchMapTy ObjectFileForArch;
+
Options Opts;
static const char kBadString[];
};
@@ -77,7 +99,7 @@ private:
bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const;
- OwningPtr<ObjectFile> Module;
+ ObjectFile *Module;
OwningPtr<DIContext> DebugInfoContext;
struct SymbolDesc {
diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 0cafffaf71..c32e9494ea 100644
--- a/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -47,6 +47,10 @@ ClPrintInlining("inlining", cl::init(true),
static cl::opt<bool>
ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names"));
+static cl::opt<std::string> ClDefaultArch("default-arch", cl::init(""),
+ cl::desc("Default architecture "
+ "(for multi-arch objects)"));
+
static bool parseCommand(bool &IsData, std::string &ModuleName,
uint64_t &ModuleOffset) {
const char *kDataCmd = "DATA ";
@@ -102,7 +106,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n");
LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
- ClPrintInlining, ClDemangle);
+ ClPrintInlining, ClDemangle, ClDefaultArch);
LLVMSymbolizer Symbolizer(Opts);
bool IsData = false;