diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/DebugInfo/Symbolize/Symbolize.cpp | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) | |
download | src-e6d1592492a3a379186bfb02bd0f4eda0669c0d5.tar.gz src-e6d1592492a3a379186bfb02bd0f4eda0669c0d5.zip |
Vendor import of stripped llvm trunk r366426 (just before the release_90vendor/llvm/llvm-trunk-r366426
branch point):
https://llvm.org/svn/llvm-project/llvm/trunk@366426
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=351278
svn path=/vendor/llvm/llvm-trunk-r366426/; revision=351279; tag=vendor/llvm/llvm-trunk-r366426
Diffstat (limited to 'lib/DebugInfo/Symbolize/Symbolize.cpp')
-rw-r--r-- | lib/DebugInfo/Symbolize/Symbolize.cpp | 223 |
1 files changed, 136 insertions, 87 deletions
diff --git a/lib/DebugInfo/Symbolize/Symbolize.cpp b/lib/DebugInfo/Symbolize/Symbolize.cpp index 59a85d6c3fcf..6a619f8f2f37 100644 --- a/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -1,9 +1,8 @@ //===-- LLVMSymbolize.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -17,7 +16,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/COFF.h" -#include "llvm/Config/config.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBContext.h" @@ -25,6 +23,7 @@ #include "llvm/Object/COFF.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" +#include "llvm/Support/CRC.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compression.h" #include "llvm/Support/DataExtractor.h" @@ -34,7 +33,6 @@ #include "llvm/Support/Path.h" #include <algorithm> #include <cassert> -#include <cstdlib> #include <cstring> #if defined(_MSC_VER) @@ -54,14 +52,8 @@ namespace llvm { namespace symbolize { Expected<DILineInfo> -LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, - uint64_t ModuleOffset, StringRef DWPName) { - SymbolizableModule *Info; - if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName)) - Info = InfoOrErr.get(); - else - return InfoOrErr.takeError(); - +LLVMSymbolizer::symbolizeCodeCommon(SymbolizableModule *Info, + object::SectionedAddress ModuleOffset) { // A null module means an error has already been reported. Return an empty // result. if (!Info) @@ -70,7 +62,7 @@ LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, // 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. if (Opts.RelativeAddresses) - ModuleOffset += Info->getModulePreferredBase(); + ModuleOffset.Address += Info->getModulePreferredBase(); DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable); @@ -79,11 +71,37 @@ LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, return LineInfo; } +Expected<DILineInfo> +LLVMSymbolizer::symbolizeCode(const ObjectFile &Obj, + object::SectionedAddress ModuleOffset) { + StringRef ModuleName = Obj.getFileName(); + auto I = Modules.find(ModuleName); + if (I != Modules.end()) + return symbolizeCodeCommon(I->second.get(), ModuleOffset); + + std::unique_ptr<DIContext> Context = + DWARFContext::create(Obj, nullptr, DWARFContext::defaultErrorHandler); + Expected<SymbolizableModule *> InfoOrErr = + createModuleInfo(&Obj, std::move(Context), ModuleName); + if (!InfoOrErr) + return InfoOrErr.takeError(); + return symbolizeCodeCommon(*InfoOrErr, ModuleOffset); +} + +Expected<DILineInfo> +LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, + object::SectionedAddress ModuleOffset) { + Expected<SymbolizableModule *> InfoOrErr = getOrCreateModuleInfo(ModuleName); + if (!InfoOrErr) + return InfoOrErr.takeError(); + return symbolizeCodeCommon(*InfoOrErr, ModuleOffset); +} + Expected<DIInliningInfo> LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, - uint64_t ModuleOffset, StringRef DWPName) { + object::SectionedAddress ModuleOffset) { SymbolizableModule *Info; - if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName)) + if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) Info = InfoOrErr.get(); else return InfoOrErr.takeError(); @@ -96,7 +114,7 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, // 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. if (Opts.RelativeAddresses) - ModuleOffset += Info->getModulePreferredBase(); + ModuleOffset.Address += Info->getModulePreferredBase(); DIInliningInfo InlinedContext = Info->symbolizeInlinedCode( ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable); @@ -109,8 +127,9 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, return InlinedContext; } -Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName, - uint64_t ModuleOffset) { +Expected<DIGlobal> +LLVMSymbolizer::symbolizeData(const std::string &ModuleName, + object::SectionedAddress ModuleOffset) { SymbolizableModule *Info; if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) Info = InfoOrErr.get(); @@ -126,7 +145,7 @@ Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName, // the object to the offset before we do the query. It's what DIContext // expects. if (Opts.RelativeAddresses) - ModuleOffset += Info->getModulePreferredBase(); + ModuleOffset.Address += Info->getModulePreferredBase(); DIGlobal Global = Info->symbolizeData(ModuleOffset); if (Opts.Demangle) @@ -134,6 +153,29 @@ Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName, return Global; } +Expected<std::vector<DILocal>> +LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName, + object::SectionedAddress 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 std::vector<DILocal>(); + + // 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. + if (Opts.RelativeAddresses) + ModuleOffset.Address += Info->getModulePreferredBase(); + + return Info->symbolizeFrame(ModuleOffset); +} + void LLVMSymbolizer::flush() { ObjectForUBPathAndArch.clear(); BinaryForPath.clear(); @@ -163,42 +205,45 @@ bool checkFileCRC(StringRef Path, uint32_t CRCHash) { MemoryBuffer::getFileOrSTDIN(Path); if (!MB) return false; - return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer()); + return CRCHash == llvm::crc32(0, MB.get()->getBuffer()); } bool findDebugBinary(const std::string &OrigPath, const std::string &DebuglinkName, uint32_t CRCHash, + const std::string &FallbackDebugPath, std::string &Result) { - std::string OrigRealPath = OrigPath; -#if defined(HAVE_REALPATH) - if (char *RP = realpath(OrigPath.c_str(), nullptr)) { - OrigRealPath = RP; - free(RP); - } -#endif - SmallString<16> OrigDir(OrigRealPath); + SmallString<16> OrigDir(OrigPath); llvm::sys::path::remove_filename(OrigDir); SmallString<16> DebugPath = OrigDir; - // Try /path/to/original_binary/debuglink_name + // Try relative/path/to/original_binary/debuglink_name llvm::sys::path::append(DebugPath, DebuglinkName); if (checkFileCRC(DebugPath, CRCHash)) { Result = DebugPath.str(); return true; } - // Try /path/to/original_binary/.debug/debuglink_name + // Try relative/path/to/original_binary/.debug/debuglink_name DebugPath = OrigDir; llvm::sys::path::append(DebugPath, ".debug", DebuglinkName); if (checkFileCRC(DebugPath, CRCHash)) { Result = DebugPath.str(); return true; } + // Make the path absolute so that lookups will go to + // "/usr/lib/debug/full/path/to/debug", not + // "/usr/lib/debug/to/debug" + llvm::sys::fs::make_absolute(OrigDir); + if (!FallbackDebugPath.empty()) { + // Try <FallbackDebugPath>/absolute/path/to/original_binary/debuglink_name + DebugPath = FallbackDebugPath; + } else { #if defined(__NetBSD__) - // Try /usr/libdata/debug/path/to/original_binary/debuglink_name - DebugPath = "/usr/libdata/debug"; + // Try /usr/libdata/debug/absolute/path/to/original_binary/debuglink_name + DebugPath = "/usr/libdata/debug"; #else - // Try /usr/lib/debug/path/to/original_binary/debuglink_name - DebugPath = "/usr/lib/debug"; + // Try /usr/lib/debug/absolute/path/to/original_binary/debuglink_name + DebugPath = "/usr/lib/debug"; #endif + } llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir), DebuglinkName); if (checkFileCRC(DebugPath, CRCHash)) { @@ -217,9 +262,12 @@ bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, Section.getName(Name); Name = Name.substr(Name.find_first_not_of("._")); if (Name == "gnu_debuglink") { - StringRef Data; - Section.getContents(Data); - DataExtractor DE(Data, Obj->isLittleEndian(), 0); + Expected<StringRef> ContentsOrErr = Section.getContents(); + if (!ContentsOrErr) { + consumeError(ContentsOrErr.takeError()); + return false; + } + DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0); uint32_t Offset = 0; if (const char *DebugNameStr = DE.getCStr(&Offset)) { // 4-byte align the offset. @@ -284,7 +332,8 @@ ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path, std::string DebugBinaryPath; if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash)) return nullptr; - if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) + if (!findDebugBinary(Path, DebuglinkName, CRCHash, Opts.FallbackDebugPath, + DebugBinaryPath)) return nullptr; auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName); if (!DbgObjOrErr) { @@ -298,15 +347,14 @@ ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path, 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()) { + auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); + if (I != ObjectPairForPathArch.end()) return I->second; - } auto ObjOrErr = getOrCreateObject(Path, ArchName); if (!ObjOrErr) { - ObjectPairForPathArch.insert(std::make_pair(std::make_pair(Path, ArchName), - ObjectPair(nullptr, nullptr))); + ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), + ObjectPair(nullptr, nullptr)); return ObjOrErr.takeError(); } @@ -321,46 +369,43 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, if (!DbgObj) DbgObj = Obj; ObjectPair Res = std::make_pair(Obj, DbgObj); - ObjectPairForPathArch.insert( - std::make_pair(std::make_pair(Path, ArchName), Res)); + ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res); return Res; } 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()) { + Binary *Bin; + auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>()); + if (!Pair.second) { + Bin = Pair.first->second.getBinary(); + } else { Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path); - if (!BinOrErr) { - BinaryForPath.insert(std::make_pair(Path, OwningBinary<Binary>())); + if (!BinOrErr) return BinOrErr.takeError(); - } - Bin = BinOrErr->getBinary(); - BinaryForPath.insert(std::make_pair(Path, std::move(BinOrErr.get()))); - } else { - Bin = I->second.getBinary(); + Pair.first->second = std::move(BinOrErr.get()); + Bin = Pair.first->second.getBinary(); } if (!Bin) return static_cast<ObjectFile *>(nullptr); if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) { - const auto &I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName)); - if (I != ObjectForUBPathAndArch.end()) { + auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName)); + if (I != ObjectForUBPathAndArch.end()) return I->second.get(); - } + Expected<std::unique_ptr<ObjectFile>> ObjOrErr = UB->getObjectForArch(ArchName); if (!ObjOrErr) { - ObjectForUBPathAndArch.insert(std::make_pair( - std::make_pair(Path, ArchName), std::unique_ptr<ObjectFile>())); + ObjectForUBPathAndArch.emplace(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), - std::move(ObjOrErr.get()))); + ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName), + std::move(ObjOrErr.get())); return Res; } if (Bin->isObject()) { @@ -370,12 +415,28 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path, } Expected<SymbolizableModule *> -LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName, - StringRef DWPName) { - const auto &I = Modules.find(ModuleName); - if (I != Modules.end()) { +LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj, + std::unique_ptr<DIContext> Context, + StringRef ModuleName) { + auto InfoOrErr = + SymbolizableObjectFile::create(Obj, std::move(Context)); + std::unique_ptr<SymbolizableModule> SymMod; + if (InfoOrErr) + SymMod = std::move(*InfoOrErr); + auto InsertResult = + Modules.insert(std::make_pair(ModuleName, std::move(SymMod))); + assert(InsertResult.second); + if (std::error_code EC = InfoOrErr.getError()) + return errorCodeToError(EC); + return InsertResult.first->second.get(); +} + +Expected<SymbolizableModule *> +LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { + auto I = Modules.find(ModuleName); + if (I != Modules.end()) return I->second.get(); - } + std::string BinaryName = ModuleName; std::string ArchName = Opts.DefaultArch; size_t ColonPos = ModuleName.find_last_of(':'); @@ -390,8 +451,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName, auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName); if (!ObjectsOrErr) { // Failed to find valid object file. - Modules.insert( - std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>())); + Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>()); return ObjectsOrErr.takeError(); } ObjectPair Objects = ObjectsOrErr.get(); @@ -408,8 +468,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName, 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>())); + Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>()); // Return along the PDB filename to provide more context return createFileError(PDBFileName, std::move(Err)); } @@ -417,20 +476,10 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName, } } if (!Context) - Context = DWARFContext::create(*Objects.second, nullptr, - DWARFContext::defaultErrorHandler, DWPName); - 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(SymMod))); - assert(InsertResult.second); - if (auto EC = InfoOrErr.getError()) - return errorCodeToError(EC); - return InsertResult.first->second.get(); + Context = + DWARFContext::create(*Objects.second, nullptr, + DWARFContext::defaultErrorHandler, Opts.DWPName); + return createModuleInfo(Objects.first, std::move(Context), ModuleName); } namespace { |