1f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar//===-- LLVMSymbolize.cpp -------------------------------------------------===// 2f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 3f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// The LLVM Compiler Infrastructure 4f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 5f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// License. See LICENSE.TXT for details. 7f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 8f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar//===----------------------------------------------------------------------===// 9f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 10f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// Implementation for LLVM symbolization library. 11f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 12f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar//===----------------------------------------------------------------------===// 13f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 14f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/DebugInfo/Symbolize/Symbolize.h" 15f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 16f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "SymbolizableObjectFile.h" 17f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 18f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h" 19f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Config/config.h" 20f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/DebugInfo/DWARF/DWARFContext.h" 21f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/DebugInfo/PDB/PDB.h" 22f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/DebugInfo/PDB/PDBContext.h" 23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Object/COFF.h" 24f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Object/ELFObjectFile.h" 25f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Object/MachO.h" 26f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Object/MachOUniversal.h" 27f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/COFF.h" 28f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/Casting.h" 29f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/Compression.h" 30f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/DataExtractor.h" 31f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/Errc.h" 32f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/FileSystem.h" 33f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/MemoryBuffer.h" 34f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/Path.h" 35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <algorithm> 36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <cassert> 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <cstdlib> 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <cstring> 39f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 40f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#if defined(_MSC_VER) 41f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include <Windows.h> 42f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include <DbgHelp.h> 43f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#pragma comment(lib, "dbghelp.lib") 44f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 45f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// Windows.h conflicts with our COFF header definitions. 46f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#ifdef IMAGE_FILE_MACHINE_I386 47f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#undef IMAGE_FILE_MACHINE_I386 48f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#endif 49f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#endif 50f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 51f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarnamespace llvm { 52f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarnamespace symbolize { 53f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<DILineInfo> LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, 55f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint64_t ModuleOffset) { 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SymbolizableModule *Info; 57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) 58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Info = InfoOrErr.get(); 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return InfoOrErr.takeError(); 61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // A null module means an error has already been reported. Return an empty 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // result. 64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!Info) 65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return DILineInfo(); 66f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 67f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // If the user is giving us relative addresses, add the preferred base of the 68f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // object to the offset before we do the query. It's what DIContext expects. 69f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Opts.RelativeAddresses) 70f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ModuleOffset += Info->getModulePreferredBase(); 71f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 72f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions, 73f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Opts.UseSymbolTable); 74f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Opts.Demangle) 75f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info); 76f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return LineInfo; 77f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 78f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<DIInliningInfo> 80f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarLLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, 81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint64_t ModuleOffset) { 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SymbolizableModule *Info; 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Info = InfoOrErr.get(); 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return InfoOrErr.takeError(); 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // A null module means an error has already been reported. Return an empty 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // result. 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!Info) 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return DIInliningInfo(); 92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // If the user is giving us relative addresses, add the preferred base of the 94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // object to the offset before we do the query. It's what DIContext expects. 95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Opts.RelativeAddresses) 96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ModuleOffset += Info->getModulePreferredBase(); 97f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 98f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DIInliningInfo InlinedContext = Info->symbolizeInlinedCode( 99f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable); 100f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Opts.Demangle) { 101f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (int i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) { 102f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto *Frame = InlinedContext.getMutableFrame(i); 103f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Frame->FunctionName = DemangleName(Frame->FunctionName, Info); 104f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 105f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 106f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return InlinedContext; 107f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName, 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint64_t ModuleOffset) { 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SymbolizableModule *Info; 112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) 113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Info = InfoOrErr.get(); 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else 115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return InfoOrErr.takeError(); 116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // A null module means an error has already been reported. Return an empty 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // result. 119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!Info) 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return DIGlobal(); 121f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 122f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // If the user is giving us relative addresses, add the preferred base of 123f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // the object to the offset before we do the query. It's what DIContext 124f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // expects. 125f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Opts.RelativeAddresses) 126f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ModuleOffset += Info->getModulePreferredBase(); 127f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 128f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DIGlobal Global = Info->symbolizeData(ModuleOffset); 129f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Opts.Demangle) 130f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Global.Name = DemangleName(Global.Name, Info); 131f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Global; 132f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 133f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 134f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarvoid LLVMSymbolizer::flush() { 135f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectForUBPathAndArch.clear(); 136f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar BinaryForPath.clear(); 137f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectPairForPathArch.clear(); 138f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Modules.clear(); 139f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 140f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarnamespace { 142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 143f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// For Path="/path/to/foo" and Basename="foo" assume that debug info is in 144f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// /path/to/foo.dSYM/Contents/Resources/DWARF/foo. 145f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in 146f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// /path/to/bar.dSYM/Contents/Resources/DWARF/foo. 147f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarstd::string getDarwinDWARFResourceForPath( 148f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const std::string &Path, const std::string &Basename) { 149f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SmallString<16> ResourceName = StringRef(Path); 150f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (sys::path::extension(Path) != ".dSYM") { 151f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ResourceName += ".dSYM"; 152f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 153f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); 154f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar sys::path::append(ResourceName, Basename); 155f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return ResourceName.str(); 156f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 157f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool checkFileCRC(StringRef Path, uint32_t CRCHash) { 159f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ErrorOr<std::unique_ptr<MemoryBuffer>> MB = 160f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar MemoryBuffer::getFileOrSTDIN(Path); 161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!MB) 162f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 163f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer()); 164f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 165f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool findDebugBinary(const std::string &OrigPath, 167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const std::string &DebuglinkName, uint32_t CRCHash, 168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::string &Result) { 169f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string OrigRealPath = OrigPath; 170f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#if defined(HAVE_REALPATH) 171f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (char *RP = realpath(OrigPath.c_str(), nullptr)) { 172f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar OrigRealPath = RP; 173f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar free(RP); 174f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 175f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#endif 176f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SmallString<16> OrigDir(OrigRealPath); 177f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar llvm::sys::path::remove_filename(OrigDir); 178f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SmallString<16> DebugPath = OrigDir; 179f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Try /path/to/original_binary/debuglink_name 180f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar llvm::sys::path::append(DebugPath, DebuglinkName); 181f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (checkFileCRC(DebugPath, CRCHash)) { 182f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Result = DebugPath.str(); 183f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 184f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 185f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Try /path/to/original_binary/.debug/debuglink_name 186f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DebugPath = OrigRealPath; 187f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar llvm::sys::path::append(DebugPath, ".debug", DebuglinkName); 188f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (checkFileCRC(DebugPath, CRCHash)) { 189f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Result = DebugPath.str(); 190f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 191f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 192f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Try /usr/lib/debug/path/to/original_binary/debuglink_name 193f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DebugPath = "/usr/lib/debug"; 194f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir), 195f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DebuglinkName); 196f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (checkFileCRC(DebugPath, CRCHash)) { 197f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Result = DebugPath.str(); 198f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 199f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 200f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 201f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 202f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, 204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t &CRCHash) { 205f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!Obj) 206f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 207f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const SectionRef &Section : Obj->sections()) { 208f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StringRef Name; 209f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Section.getName(Name); 210f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Name = Name.substr(Name.find_first_not_of("._")); 211f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Name == "gnu_debuglink") { 212f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StringRef Data; 213f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Section.getContents(Data); 214f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DataExtractor DE(Data, Obj->isLittleEndian(), 0); 215f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint32_t Offset = 0; 216f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (const char *DebugNameStr = DE.getCStr(&Offset)) { 217f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // 4-byte align the offset. 218f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Offset = (Offset + 3) & ~0x3; 219f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (DE.isValidOffsetForDataOfSize(Offset, 4)) { 220f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DebugName = DebugNameStr; 221f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar CRCHash = DE.getU32(&Offset); 222f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 223f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 224f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 225f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar break; 226f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 227f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 228f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 229f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 230f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 231f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarbool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj, 232f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const MachOObjectFile *Obj) { 233f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid(); 234f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArrayRef<uint8_t> bin_uuid = Obj->getUuid(); 235f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (dbg_uuid.empty() || bin_uuid.empty()) 236f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 237f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size()); 238f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 239f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 240de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} // end anonymous namespace 241de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 242f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, 243f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const MachOObjectFile *MachExeObj, const std::string &ArchName) { 244f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // On Darwin we may find DWARF in separate object file in 245f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // resource directory. 246f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::vector<std::string> DsymPaths; 247f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StringRef Filename = sys::path::filename(ExePath); 248f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename)); 249f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const auto &Path : Opts.DsymHints) { 250f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename)); 251f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 252f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const auto &Path : DsymPaths) { 253f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto DbgObjOrErr = getOrCreateObject(Path, ArchName); 254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!DbgObjOrErr) { 255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Ignore errors, the file might not exist. 256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar consumeError(DbgObjOrErr.takeError()); 257f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar continue; 258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 259f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectFile *DbgObj = DbgObjOrErr.get(); 260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!DbgObj) 261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar continue; 262f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj); 263f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!MachDbgObj) 264f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar continue; 265f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) 266f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return DbgObj; 267f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 268f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return nullptr; 269f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 270f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 271f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path, 272f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const ObjectFile *Obj, 273f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const std::string &ArchName) { 274f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string DebuglinkName; 275f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint32_t CRCHash; 276f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string DebugBinaryPath; 277f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash)) 278f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return nullptr; 279f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) 280f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return nullptr; 281f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName); 282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!DbgObjOrErr) { 283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Ignore errors, the file might not exist. 284de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar consumeError(DbgObjOrErr.takeError()); 285f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return nullptr; 286de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 287f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return DbgObjOrErr.get(); 288f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 289f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 290de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<LLVMSymbolizer::ObjectPair> 291f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarLLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, 292f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const std::string &ArchName) { 293f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); 294de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (I != ObjectPairForPathArch.end()) { 295f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return I->second; 296de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 297f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 298f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto ObjOrErr = getOrCreateObject(Path, ArchName); 299de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!ObjOrErr) { 300de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ObjectPairForPathArch.insert(std::make_pair(std::make_pair(Path, ArchName), 301de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ObjectPair(nullptr, nullptr))); 302de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return ObjOrErr.takeError(); 303f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 304f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 305f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectFile *Obj = ObjOrErr.get(); 306f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(Obj != nullptr); 307f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectFile *DbgObj = nullptr; 308f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 309f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj)) 310f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DbgObj = lookUpDsymFile(Path, MachObj, ArchName); 311f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!DbgObj) 312f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName); 313f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!DbgObj) 314f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DbgObj = Obj; 315f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectPair Res = std::make_pair(Obj, DbgObj); 316f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectPairForPathArch.insert( 317f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::make_pair(std::make_pair(Path, ArchName), Res)); 318f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Res; 319f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 320f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 321de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<ObjectFile *> 322f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarLLVMSymbolizer::getOrCreateObject(const std::string &Path, 323f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const std::string &ArchName) { 324f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const auto &I = BinaryForPath.find(Path); 325f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Binary *Bin = nullptr; 326f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (I == BinaryForPath.end()) { 327de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path); 328de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!BinOrErr) { 329de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BinaryForPath.insert(std::make_pair(Path, OwningBinary<Binary>())); 330de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return BinOrErr.takeError(); 331f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 332f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Bin = BinOrErr->getBinary(); 333f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar BinaryForPath.insert(std::make_pair(Path, std::move(BinOrErr.get()))); 334f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } else { 335de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Bin = I->second.getBinary(); 336f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 337f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 338de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!Bin) 339de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return static_cast<ObjectFile *>(nullptr); 340f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 341de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) { 342f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const auto &I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName)); 343f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (I != ObjectForUBPathAndArch.end()) { 344de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return I->second.get(); 345f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 346de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 347f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UB->getObjectForArch(ArchName); 348de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!ObjOrErr) { 349de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ObjectForUBPathAndArch.insert(std::make_pair( 350de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::make_pair(Path, ArchName), std::unique_ptr<ObjectFile>())); 351de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return ObjOrErr.takeError(); 352f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 353f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectFile *Res = ObjOrErr->get(); 354f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectForUBPathAndArch.insert(std::make_pair(std::make_pair(Path, ArchName), 355f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::move(ObjOrErr.get()))); 356f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Res; 357f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 358f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Bin->isObject()) { 359f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return cast<ObjectFile>(Bin); 360f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 361de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorCodeToError(object_error::arch_not_found); 362f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 363f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 364de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<SymbolizableModule *> 365f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarLLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { 366f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const auto &I = Modules.find(ModuleName); 367f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (I != Modules.end()) { 368de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return I->second.get(); 369f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 370f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string BinaryName = ModuleName; 371f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string ArchName = Opts.DefaultArch; 372f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar size_t ColonPos = ModuleName.find_last_of(':'); 373f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Verify that substring after colon form a valid arch name. 374f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (ColonPos != std::string::npos) { 375f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string ArchStr = ModuleName.substr(ColonPos + 1); 376f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Triple(ArchStr).getArch() != Triple::UnknownArch) { 377f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar BinaryName = ModuleName.substr(0, ColonPos); 378f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArchName = ArchStr; 379f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 380f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 381f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName); 382de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!ObjectsOrErr) { 383f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Failed to find valid object file. 384de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modules.insert( 385de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>())); 386de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return ObjectsOrErr.takeError(); 387f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 388f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ObjectPair Objects = ObjectsOrErr.get(); 389f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 390f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::unique_ptr<DIContext> Context; 391de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // If this is a COFF object containing PDB info, use a PDBContext to 392de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // symbolize. Otherwise, use DWARF. 393f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) { 394de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const debug_pdb_info *PDBInfo; 395de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef PDBFileName; 396de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto EC = CoffObject->getDebugPDBInfo(PDBInfo, PDBFileName); 397de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!EC && PDBInfo != nullptr) { 398de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar using namespace pdb; 399de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::unique_ptr<IPDBSession> Session; 400de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto Err = loadDataForEXE(PDB_ReaderType::DIA, 401de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Objects.first->getFileName(), Session)) { 402de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modules.insert( 403de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>())); 404de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::move(Err); 405de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 406f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Context.reset(new PDBContext(*CoffObject, std::move(Session))); 407f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 408f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 409f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!Context) 410f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Context.reset(new DWARFContextInMemory(*Objects.second)); 411f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(Context); 412f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto InfoOrErr = 413f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SymbolizableObjectFile::create(Objects.first, std::move(Context)); 414de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::unique_ptr<SymbolizableModule> SymMod; 415de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (InfoOrErr) 416de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SymMod = std::move(InfoOrErr.get()); 417f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar auto InsertResult = 418de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Modules.insert(std::make_pair(ModuleName, std::move(SymMod))); 419f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(InsertResult.second); 420de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = InfoOrErr.getError()) 421de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorCodeToError(EC); 422de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return InsertResult.first->second.get(); 423f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 424f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 425de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarnamespace { 426de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 427f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// Undo these various manglings for Win32 extern "C" functions: 428f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// cdecl - _foo 429f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// stdcall - _foo@12 430f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// fastcall - @foo@12 431f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// vectorcall - foo@@12 432f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// These are all different linkage names for 'foo'. 433de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarStringRef demanglePE32ExternCFunc(StringRef SymbolName) { 434f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Remove any '_' or '@' prefix. 435f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar char Front = SymbolName.empty() ? '\0' : SymbolName[0]; 436f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Front == '_' || Front == '@') 437f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SymbolName = SymbolName.drop_front(); 438f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 439f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Remove any '@[0-9]+' suffix. 440f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Front != '?') { 441f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar size_t AtPos = SymbolName.rfind('@'); 442f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (AtPos != StringRef::npos && 443f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::all_of(SymbolName.begin() + AtPos + 1, SymbolName.end(), 444f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar [](char C) { return C >= '0' && C <= '9'; })) { 445f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SymbolName = SymbolName.substr(0, AtPos); 446f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 447f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 448f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 449f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Remove any ending '@' for vectorcall. 450f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (SymbolName.endswith("@")) 451f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SymbolName = SymbolName.drop_back(); 452f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 453f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolName; 454f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 455f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 456de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} // end anonymous namespace 457de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 458f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#if !defined(_MSC_VER) 459f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// Assume that __cxa_demangle is provided by libcxxabi (except for Windows). 460f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarextern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer, 461f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar size_t *length, int *status); 462f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#endif 463f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 464f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarstd::string LLVMSymbolizer::DemangleName(const std::string &Name, 465f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const SymbolizableModule *ModInfo) { 466f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#if !defined(_MSC_VER) 467f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // We can spoil names of symbols with C linkage, so use an heuristic 468f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // approach to check if the name should be demangled. 469f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Name.substr(0, 2) == "_Z") { 470f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar int status = 0; 471f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status); 472f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (status != 0) 473f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Name; 474f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string Result = DemangledName; 475f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar free(DemangledName); 476f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Result; 477f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 478f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#else 479f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!Name.empty() && Name.front() == '?') { 480f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Only do MSVC C++ demangling on symbols starting with '?'. 481f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar char DemangledName[1024] = {0}; 482f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DWORD result = ::UnDecorateSymbolName( 483f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Name.c_str(), DemangledName, 1023, 484f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected 485f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc 486f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications 487f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers 488f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords 489f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types 490f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return (result == 0) ? Name : std::string(DemangledName); 491f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 492f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#endif 493f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (ModInfo && ModInfo->isWin32Module()) 494f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return std::string(demanglePE32ExternCFunc(Name)); 495f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Name; 496f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 497f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 498f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} // namespace symbolize 499f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} // namespace llvm 500