//===----------------------------------------------------------------------===//
#include "LLVMSymbolize.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include <sstream>
namespace symbolize {
static bool error(error_code ec) {
- if (!ec) return false;
+ if (!ec)
+ return false;
errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
return true;
}
-static uint32_t getDILineInfoSpecifierFlags(
- const LLVMSymbolizer::Options &Opts) {
+static uint32_t
+getDILineInfoSpecifierFlags(const LLVMSymbolizer::Options &Opts) {
uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
llvm::DILineInfoSpecifier::AbsoluteFilePath;
if (Opts.PrintFunctions)
}
ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
- : Module(Obj)
- , DebugInfoContext(DICtx) {
+ : Module(Obj), DebugInfoContext(DICtx) {
error_code ec;
- for (symbol_iterator si = Module->begin_symbols(),
- se = Module->end_symbols();
- si != se; si.increment(ec)) {
+ for (symbol_iterator si = Module->begin_symbols(), se = Module->end_symbols();
+ si != se; si.increment(ec)) {
if (error(ec))
return;
SymbolRef::Type SymbolType;
if (error(si->getType(SymbolType)))
continue;
- if (SymbolType != SymbolRef::ST_Function
- && SymbolType != SymbolRef::ST_Data)
+ if (SymbolType != SymbolRef::ST_Function &&
+ SymbolType != SymbolRef::ST_Data)
continue;
uint64_t SymbolAddress;
- if (error(si->getAddress(SymbolAddress))
- || SymbolAddress == UnknownAddressOrSize)
+ if (error(si->getAddress(SymbolAddress)) ||
+ SymbolAddress == UnknownAddressOrSize)
continue;
uint64_t SymbolSize;
- if (error(si->getSize(SymbolSize))
- || SymbolSize == UnknownAddressOrSize)
+ // Getting symbol size is linear for Mach-O files, so assume that symbol
+ // occupies the memory range up to the following symbol.
+ if (isa<MachOObjectFile>(Obj))
+ SymbolSize = 0;
+ else if (error(si->getSize(SymbolSize)) ||
+ SymbolSize == UnknownAddressOrSize)
continue;
StringRef SymbolName;
if (error(si->getName(SymbolName)))
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.
- SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ?
- Functions : Objects;
- SymbolDesc SD = {SymbolAddress, SymbolAddress + SymbolSize};
+ SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
+ SymbolDesc SD = { SymbolAddress, SymbolSize };
M.insert(std::make_pair(SD, SymbolName));
}
}
bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const {
- const SymbolMapTy& M = Type == SymbolRef::ST_Function ?
- Functions : Objects;
- SymbolDesc SD = {Address, Address + 1};
- SymbolMapTy::const_iterator it = M.find(SD);
- if (it == M.end())
+ const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
+ if (M.empty())
+ return false;
+ SymbolDesc SD = { Address, Address };
+ SymbolMapTy::const_iterator it = M.upper_bound(SD);
+ if (it == M.begin())
return false;
- if (Address < it->first.Addr || Address >= it->first.AddrEnd)
+ --it;
+ if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address)
return false;
Name = it->second.str();
Addr = it->first.Addr;
- Size = it->first.AddrEnd - it->first.Addr;
+ Size = it->first.Size;
return true;
}
-DILineInfo ModuleInfo::symbolizeCode(uint64_t ModuleOffset,
- const LLVMSymbolizer::Options& Opts) const {
+DILineInfo ModuleInfo::symbolizeCode(
+ uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
DILineInfo LineInfo;
if (DebugInfoContext) {
LineInfo = DebugInfoContext->getLineInfoForAddress(
if (Opts.PrintFunctions && Opts.UseSymbolTable) {
std::string FunctionName;
uint64_t Start, Size;
- if (getNameFromSymbolTable(SymbolRef::ST_Function,
- ModuleOffset, FunctionName, 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 ModuleInfo::symbolizeInlinedCode(
+ uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
DIInliningInfo InlinedContext;
if (DebugInfoContext) {
InlinedContext = DebugInfoContext->getInliningInfoForAddress(
// 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++) {
+ 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)) {
+ if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+ FunctionName, Start, Size)) {
patchFunctionNameInDILineInfo(FunctionName, LineInfo);
}
}
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);
+ return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
+ Size);
}
const char LLVMSymbolizer::kBadString[] = "??";
if (Info == 0)
return printDILineInfo(DILineInfo());
if (Opts.PrintInlining) {
- DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
- ModuleOffset, Opts);
+ DIInliningInfo InlinedContext =
+ Info->symbolizeInlinedCode(ModuleOffset, Opts);
uint32_t FramesNum = InlinedContext.getNumberOfFrames();
assert(FramesNum > 0);
std::string Result;
return ss.str();
}
+void LLVMSymbolizer::flush() {
+ DeleteContainerSeconds(Modules);
+}
+
// Returns true if the object endianness is known.
-static bool getObjectEndianness(const ObjectFile *Obj,
- bool &IsLittleEndian) {
+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_code ec = MemoryBuffer::getFile(Path, Buff))
- error(ec);
+ if (error(MemoryBuffer::getFile(Path, Buff)))
+ return 0;
return ObjectFile::createObjectFile(Buff.take());
}
return ResourceName.str();
}
-ModuleInfo *LLVMSymbolizer::getOrCreateModuleInfo(
- const std::string &ModuleName) {
+ModuleInfo *
+LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
ModuleMapTy::iterator I = Modules.find(ModuleName);
if (I != Modules.end())
return I->second;
ObjectFile *Obj = getObjectFile(ModuleName);
if (Obj == 0) {
// Module name doesn't point to a valid object file.
- Modules.insert(make_pair(ModuleName, (ModuleInfo*)0));
+ Modules.insert(make_pair(ModuleName, (ModuleInfo *)0));
return 0;
}
// resource directory.
ObjectFile *DbgObj = Obj;
if (isa<MachOObjectFile>(Obj)) {
- const std::string &ResourceName = getDarwinDWARFResourceForModule(
- ModuleName);
- ObjectFile *ResourceObj = getObjectFile(ResourceName);
- if (ResourceObj != 0)
- DbgObj = ResourceObj;
+ 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);
std::string Filename = LineInfo.getFileName();
if (Filename == kDILineInfoBadString)
Filename = kBadString;
- Result << Filename << ":" << LineInfo.getLine()
- << ":" << LineInfo.getColumn() << "\n";
+ Result << Filename << ":" << LineInfo.getLine() << ":" << LineInfo.getColumn()
+ << "\n";
return Result.str();
}
#endif
}
-} // namespace symbolize
-} // namespace llvm
+} // namespace symbolize
+} // namespace llvm