-};
-
-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;
-}
-
-#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
-
-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>";
- static const std::string kSymbolizerBadString = "??";
- if (PrintFunctions) {
- std::string FunctionName = LineInfo.getFunctionName();
- if (FunctionName == kDILineInfoBadString)
- FunctionName = kSymbolizerBadString;
-#if !defined(_MSC_VER)
- if (Demangle) {
- int status = 0;
- char *DemangledName = __cxa_demangle(
- FunctionName.c_str(), 0, 0, &status);
- if (status == 0) {
- FunctionName = DemangledName;
- free(DemangledName);
- }
- }
-#endif
- outs() << FunctionName << "\n";
- }
- std::string Filename = LineInfo.getFileName();
- if (Filename == kDILineInfoBadString)
- Filename = kSymbolizerBadString;
- outs() << Filename <<
- ":" << LineInfo.getLine() <<
- ":" << LineInfo.getColumn() <<
- "\n";
-}
-
-static void symbolize(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);