summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/Symbolize
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /lib/DebugInfo/Symbolize
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
Notes
Diffstat (limited to 'lib/DebugInfo/Symbolize')
-rw-r--r--lib/DebugInfo/Symbolize/DIPrinter.cpp20
-rw-r--r--lib/DebugInfo/Symbolize/Makefile15
-rw-r--r--lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp18
-rw-r--r--lib/DebugInfo/Symbolize/Symbolize.cpp185
4 files changed, 140 insertions, 98 deletions
diff --git a/lib/DebugInfo/Symbolize/DIPrinter.cpp b/lib/DebugInfo/Symbolize/DIPrinter.cpp
index a9dee7abeed1..be5c603a38ef 100644
--- a/lib/DebugInfo/Symbolize/DIPrinter.cpp
+++ b/lib/DebugInfo/Symbolize/DIPrinter.cpp
@@ -13,9 +13,19 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
-
+#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
namespace llvm {
namespace symbolize {
@@ -26,7 +36,7 @@ static const char kDILineInfoBadString[] = "<invalid>";
static const char kBadString[] = "??";
// Prints source code around in the FileName the Line.
-void DIPrinter::printContext(std::string FileName, int64_t Line) {
+void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
if (PrintSourceContext <= 0)
return;
@@ -61,7 +71,7 @@ void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
if (FunctionName == kDILineInfoBadString)
FunctionName = kBadString;
- StringRef Delimiter = (PrintPretty == true) ? " at " : "\n";
+ StringRef Delimiter = PrintPretty ? " at " : "\n";
StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
OS << Prefix << FunctionName << Delimiter;
}
@@ -97,5 +107,5 @@ DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
return *this;
}
-}
-}
+} // end namespace symbolize
+} // end namespace llvm
diff --git a/lib/DebugInfo/Symbolize/Makefile b/lib/DebugInfo/Symbolize/Makefile
deleted file mode 100644
index 17aac9396585..000000000000
--- a/lib/DebugInfo/Symbolize/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lib/DebugInfo/Symbolize/Makefile --------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../..
-LIBRARYNAME = LLVMSymbolize
-BUILD_ARCHIVE := 1
-
-include $(LEVEL)/Makefile.common
-
diff --git a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
index e31462459844..f6940080089f 100644
--- a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
+++ b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "SymbolizableObjectFile.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Object/SymbolSize.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -119,12 +120,15 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
uint64_t SymbolSize,
DataExtractor *OpdExtractor,
uint64_t OpdAddress) {
- SymbolRef::Type SymbolType = Symbol.getType();
+ Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType();
+ if (!SymbolTypeOrErr)
+ return errorToErrorCode(SymbolTypeOrErr.takeError());
+ SymbolRef::Type SymbolType = *SymbolTypeOrErr;
if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
return std::error_code();
- ErrorOr<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
- if (auto EC = SymbolAddressOrErr.getError())
- return EC;
+ Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
+ if (!SymbolAddressOrErr)
+ return errorToErrorCode(SymbolAddressOrErr.takeError());
uint64_t SymbolAddress = *SymbolAddressOrErr;
if (OpdExtractor) {
// For big-endian PowerPC64 ELF, symbols in the .opd section refer to
@@ -138,9 +142,9 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
OpdExtractor->isValidOffsetForAddress(OpdOffset32))
SymbolAddress = OpdExtractor->getAddress(&OpdOffset32);
}
- ErrorOr<StringRef> SymbolNameOrErr = Symbol.getName();
- if (auto EC = SymbolNameOrErr.getError())
- return EC;
+ Expected<StringRef> SymbolNameOrErr = Symbol.getName();
+ if (!SymbolNameOrErr)
+ return errorToErrorCode(SymbolNameOrErr.takeError());
StringRef SymbolName = *SymbolNameOrErr;
// Mach-O symbol table names have leading underscore, skip it.
if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
diff --git a/lib/DebugInfo/Symbolize/Symbolize.cpp b/lib/DebugInfo/Symbolize/Symbolize.cpp
index 3da1963bb791..adbe0cb69edb 100644
--- a/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -20,6 +20,7 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/DebugInfo/PDB/PDBContext.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
@@ -31,7 +32,10 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include <stdlib.h>
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
#if defined(_MSC_VER)
#include <Windows.h>
@@ -47,12 +51,18 @@
namespace llvm {
namespace symbolize {
-ErrorOr<DILineInfo> LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
+Expected<DILineInfo> LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
uint64_t ModuleOffset) {
- auto InfoOrErr = getOrCreateModuleInfo(ModuleName);
- if (auto EC = InfoOrErr.getError())
- return EC;
- SymbolizableModule *Info = InfoOrErr.get();
+ SymbolizableModule *Info;
+ if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
+ Info = InfoOrErr.get();
+ else
+ return InfoOrErr.takeError();
+
+ // A null module means an error has already been reported. Return an empty
+ // result.
+ if (!Info)
+ 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.
@@ -66,13 +76,19 @@ ErrorOr<DILineInfo> LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
return LineInfo;
}
-ErrorOr<DIInliningInfo>
+Expected<DIInliningInfo>
LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
uint64_t ModuleOffset) {
- auto InfoOrErr = getOrCreateModuleInfo(ModuleName);
- if (auto EC = InfoOrErr.getError())
- return EC;
- SymbolizableModule *Info = InfoOrErr.get();
+ SymbolizableModule *Info;
+ if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
+ Info = InfoOrErr.get();
+ else
+ return InfoOrErr.takeError();
+
+ // A null module means an error has already been reported. Return an empty
+ // result.
+ if (!Info)
+ 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.
@@ -90,12 +106,18 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
return InlinedContext;
}
-ErrorOr<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
- uint64_t ModuleOffset) {
- auto InfoOrErr = getOrCreateModuleInfo(ModuleName);
- if (auto EC = InfoOrErr.getError())
- return EC;
- SymbolizableModule *Info = InfoOrErr.get();
+Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+ uint64_t ModuleOffset) {
+ SymbolizableModule *Info;
+ if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
+ Info = InfoOrErr.get();
+ else
+ return InfoOrErr.takeError();
+
+ // A null module means an error has already been reported. Return an empty
+ // result.
+ if (!Info)
+ 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
@@ -116,11 +138,12 @@ void LLVMSymbolizer::flush() {
Modules.clear();
}
+namespace {
+
// For Path="/path/to/foo" and Basename="foo" assume that debug info is in
// /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
// /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
-static
std::string getDarwinDWARFResourceForPath(
const std::string &Path, const std::string &Basename) {
SmallString<16> ResourceName = StringRef(Path);
@@ -132,7 +155,7 @@ std::string getDarwinDWARFResourceForPath(
return ResourceName.str();
}
-static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
+bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
MemoryBuffer::getFileOrSTDIN(Path);
if (!MB)
@@ -140,9 +163,9 @@ static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer());
}
-static bool findDebugBinary(const std::string &OrigPath,
- const std::string &DebuglinkName, uint32_t CRCHash,
- std::string &Result) {
+bool findDebugBinary(const std::string &OrigPath,
+ const std::string &DebuglinkName, uint32_t CRCHash,
+ std::string &Result) {
std::string OrigRealPath = OrigPath;
#if defined(HAVE_REALPATH)
if (char *RP = realpath(OrigPath.c_str(), nullptr)) {
@@ -177,8 +200,8 @@ static bool findDebugBinary(const std::string &OrigPath,
return false;
}
-static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
- uint32_t &CRCHash) {
+bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
+ uint32_t &CRCHash) {
if (!Obj)
return false;
for (const SectionRef &Section : Obj->sections()) {
@@ -205,7 +228,6 @@ static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugNam
return false;
}
-static
bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
const MachOObjectFile *Obj) {
ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
@@ -215,6 +237,8 @@ bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
}
+} // end anonymous namespace
+
ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
const MachOObjectFile *MachExeObj, const std::string &ArchName) {
// On Darwin we may find DWARF in separate object file in
@@ -227,9 +251,14 @@ ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
}
for (const auto &Path : DsymPaths) {
auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
- if (!DbgObjOrErr)
+ if (!DbgObjOrErr) {
+ // Ignore errors, the file might not exist.
+ consumeError(DbgObjOrErr.takeError());
continue;
+ }
ObjectFile *DbgObj = DbgObjOrErr.get();
+ if (!DbgObj)
+ continue;
const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
if (!MachDbgObj)
continue;
@@ -250,23 +279,27 @@ ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
return nullptr;
auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
- if (!DbgObjOrErr)
+ if (!DbgObjOrErr) {
+ // Ignore errors, the file might not exist.
+ consumeError(DbgObjOrErr.takeError());
return nullptr;
+ }
return DbgObjOrErr.get();
}
-ErrorOr<LLVMSymbolizer::ObjectPair>
+Expected<LLVMSymbolizer::ObjectPair>
LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
const std::string &ArchName) {
const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
- if (I != ObjectPairForPathArch.end())
+ if (I != ObjectPairForPathArch.end()) {
return I->second;
+ }
auto ObjOrErr = getOrCreateObject(Path, ArchName);
- if (auto EC = ObjOrErr.getError()) {
- ObjectPairForPathArch.insert(
- std::make_pair(std::make_pair(Path, ArchName), EC));
- return EC;
+ if (!ObjOrErr) {
+ ObjectPairForPathArch.insert(std::make_pair(std::make_pair(Path, ArchName),
+ ObjectPair(nullptr, nullptr)));
+ return ObjOrErr.takeError();
}
ObjectFile *Obj = ObjOrErr.get();
@@ -285,40 +318,37 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
return Res;
}
-ErrorOr<ObjectFile *>
+Expected<ObjectFile *>
LLVMSymbolizer::getOrCreateObject(const std::string &Path,
const std::string &ArchName) {
const auto &I = BinaryForPath.find(Path);
Binary *Bin = nullptr;
if (I == BinaryForPath.end()) {
- ErrorOr<OwningBinary<Binary>> BinOrErr = createBinary(Path);
- if (auto EC = BinOrErr.getError()) {
- BinaryForPath.insert(std::make_pair(Path, EC));
- return EC;
+ Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path);
+ if (!BinOrErr) {
+ BinaryForPath.insert(std::make_pair(Path, OwningBinary<Binary>()));
+ return BinOrErr.takeError();
}
Bin = BinOrErr->getBinary();
BinaryForPath.insert(std::make_pair(Path, std::move(BinOrErr.get())));
- } else if (auto EC = I->second.getError()) {
- return EC;
} else {
- Bin = I->second->getBinary();
+ Bin = I->second.getBinary();
}
- assert(Bin != nullptr);
+ if (!Bin)
+ return static_cast<ObjectFile *>(nullptr);
- if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
+ if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) {
const auto &I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
if (I != ObjectForUBPathAndArch.end()) {
- if (auto EC = I->second.getError())
- return EC;
- return I->second->get();
+ return I->second.get();
}
- ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
+ Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
UB->getObjectForArch(ArchName);
- if (auto EC = ObjOrErr.getError()) {
- ObjectForUBPathAndArch.insert(
- std::make_pair(std::make_pair(Path, ArchName), EC));
- return EC;
+ if (!ObjOrErr) {
+ ObjectForUBPathAndArch.insert(std::make_pair(
+ std::make_pair(Path, ArchName), std::unique_ptr<ObjectFile>()));
+ return ObjOrErr.takeError();
}
ObjectFile *Res = ObjOrErr->get();
ObjectForUBPathAndArch.insert(std::make_pair(std::make_pair(Path, ArchName),
@@ -328,17 +358,14 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path,
if (Bin->isObject()) {
return cast<ObjectFile>(Bin);
}
- return object_error::arch_not_found;
+ return errorCodeToError(object_error::arch_not_found);
}
-ErrorOr<SymbolizableModule *>
+Expected<SymbolizableModule *>
LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
const auto &I = Modules.find(ModuleName);
if (I != Modules.end()) {
- auto &InfoOrErr = I->second;
- if (auto EC = InfoOrErr.getError())
- return EC;
- return InfoOrErr->get();
+ return I->second.get();
}
std::string BinaryName = ModuleName;
std::string ArchName = Opts.DefaultArch;
@@ -352,21 +379,30 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
}
}
auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
- if (auto EC = ObjectsOrErr.getError()) {
+ if (!ObjectsOrErr) {
// Failed to find valid object file.
- Modules.insert(std::make_pair(ModuleName, EC));
- return EC;
+ Modules.insert(
+ std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>()));
+ return ObjectsOrErr.takeError();
}
ObjectPair Objects = ObjectsOrErr.get();
std::unique_ptr<DIContext> Context;
+ // If this is a COFF object containing PDB info, use a PDBContext to
+ // symbolize. Otherwise, use DWARF.
if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
- // If this is a COFF object, assume it contains PDB debug information. If
- // we don't find any we will fall back to the DWARF case.
- std::unique_ptr<IPDBSession> Session;
- PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
- Objects.first->getFileName(), Session);
- if (Error == PDB_ErrorCode::Success) {
+ const debug_pdb_info *PDBInfo;
+ StringRef PDBFileName;
+ auto EC = CoffObject->getDebugPDBInfo(PDBInfo, PDBFileName);
+ if (!EC && PDBInfo != nullptr) {
+ using namespace pdb;
+ std::unique_ptr<IPDBSession> Session;
+ if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,
+ Objects.first->getFileName(), Session)) {
+ Modules.insert(
+ std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>()));
+ return std::move(Err);
+ }
Context.reset(new PDBContext(*CoffObject, std::move(Session)));
}
}
@@ -375,21 +411,26 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
assert(Context);
auto InfoOrErr =
SymbolizableObjectFile::create(Objects.first, std::move(Context));
+ std::unique_ptr<SymbolizableModule> SymMod;
+ if (InfoOrErr)
+ SymMod = std::move(InfoOrErr.get());
auto InsertResult =
- Modules.insert(std::make_pair(ModuleName, std::move(InfoOrErr)));
+ Modules.insert(std::make_pair(ModuleName, std::move(SymMod)));
assert(InsertResult.second);
- if (auto EC = InsertResult.first->second.getError())
- return EC;
- return InsertResult.first->second->get();
+ if (auto EC = InfoOrErr.getError())
+ return errorCodeToError(EC);
+ return InsertResult.first->second.get();
}
+namespace {
+
// Undo these various manglings for Win32 extern "C" functions:
// cdecl - _foo
// stdcall - _foo@12
// fastcall - @foo@12
// vectorcall - foo@@12
// These are all different linkage names for 'foo'.
-static StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
+StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
// Remove any '_' or '@' prefix.
char Front = SymbolName.empty() ? '\0' : SymbolName[0];
if (Front == '_' || Front == '@')
@@ -412,6 +453,8 @@ static StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
return SymbolName;
}
+} // end anonymous namespace
+
#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,