diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h @@ -0,0 +1,39 @@ +//==- NativeEnumLineNumbers.h - Native Line Number Enumerator ------------*-==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMLINENUMBERS_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMLINENUMBERS_H + +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" + +namespace llvm { +namespace pdb { +class IPDBLineNumber; + +class NativeEnumLineNumbers : public IPDBEnumChildren { +public: + explicit NativeEnumLineNumbers(std::vector LineNums); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + std::vector Lines; + uint32_t Index; +}; +} // namespace pdb +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h @@ -0,0 +1,49 @@ +//===- NativeLineNumber.h - Native line number implementation ---*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVELINENUMBER_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVELINENUMBER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { +class NativeLineNumber : public IPDBLineNumber { +public: + explicit NativeLineNumber(const NativeSession &Session, + const codeview::LineInfo Line, uint32_t Length, + uint32_t Section, uint32_t Offset, + uint32_t SrcFileId); + + uint32_t getLineNumber() const override; + uint32_t getLineNumberEnd() const override; + uint32_t getColumnNumber() const override; + uint32_t getColumnNumberEnd() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + uint32_t getSourceFileId() const override; + uint32_t getCompilandId() const override; + bool isStatement() const override; + +private: + const NativeSession &Session; + const codeview::LineInfo Line; + uint32_t Section; + uint32_t Offset; + uint32_t Length; + uint32_t SrcFileId; +}; +} // namespace pdb +} // namespace llvm +#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h @@ -0,0 +1,40 @@ +//===- NativeSourceFile.h - Native source file implementation ---*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVESOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESOURCEFILE_H + +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" + +namespace llvm { +namespace pdb { +class NativeSession; + +class NativeSourceFile : public IPDBSourceFile { +public: + explicit NativeSourceFile(NativeSession &Session, uint32_t FileId, + const codeview::FileChecksumEntry &Checksum); + + std::string getFileName() const override; + uint32_t getUniqueId() const override; + std::string getChecksum() const override; + PDB_Checksum getChecksumType() const override; + std::unique_ptr> + getCompilands() const override; + +private: + NativeSession &Session; + uint32_t FileId; + const codeview::FileChecksumEntry Checksum; +}; +} // namespace pdb +} // namespace llvm +#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -11,11 +11,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntervalMap.h" +#include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h" #include #include @@ -50,6 +53,10 @@ /// appear in the PDB file. std::vector Compilands; + /// List of source files, indexed by unique source file index. + mutable std::vector> SourceFiles; + mutable DenseMap FileNameOffsetToId; + /// Map from global symbol offset to SymIndexId. DenseMap GlobalOffsetToSymbolId; @@ -63,6 +70,18 @@ IMap::Allocator IMapAllocator; IMap AddrToModuleIndex; + Expected getModuleDebugStream(uint32_t Index) const; + + struct LineTableEntry { + uint64_t Addr; + codeview::LineInfo Line; + uint32_t FileNameIndex; + bool IsTerminalEntry; + }; + + std::vector findLineTable(uint16_t Modi) const; + mutable DenseMap> LineTable; + SymIndexId createSymbolPlaceholder() { SymIndexId Id = Cache.size(); Cache.push_back(nullptr); @@ -94,10 +113,6 @@ std::unique_ptr findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset); - void parseSectionContribs(); - Optional getModuleIndexForAddr(uint32_t Sect, - uint32_t Offset) const; - public: SymbolCache(NativeSession &Session, DbiStream *Dbi); @@ -151,6 +166,9 @@ std::unique_ptr findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type); + std::unique_ptr + findLineNumbersByVA(uint64_t VA, uint32_t Length) const; + std::unique_ptr getOrCreateCompiland(uint32_t Index); uint32_t getNumCompilands() const; @@ -162,6 +180,13 @@ ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const { return static_cast(getNativeSymbolById(SymbolId)); } + + std::unique_ptr getSourceFileById(SymIndexId FileId) const; + SymIndexId + getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const; + + void parseSectionContribs(); + Optional getModuleIndexForAddr(uint64_t Addr) const; }; } // namespace pdb diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -52,12 +52,15 @@ Native/NativeCompilandSymbol.cpp Native/NativeEnumGlobals.cpp Native/NativeEnumInjectedSources.cpp + Native/NativeEnumLineNumbers.cpp Native/NativeEnumModules.cpp Native/NativeEnumTypes.cpp Native/NativeExeSymbol.cpp Native/NativeFunctionSymbol.cpp + Native/NativeLineNumber.cpp Native/NativePublicSymbol.cpp Native/NativeRawSymbol.cpp + Native/NativeSourceFile.cpp Native/NativeSymbolEnumerator.cpp Native/NativeTypeArray.cpp Native/NativeTypeBuiltin.cpp diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp @@ -0,0 +1,42 @@ +//==- NativeEnumLineNumbers.cpp - Native Type Enumerator impl ----*- C++ -*-==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeEnumLineNumbers::NativeEnumLineNumbers( + std::vector LineNums) + : Lines(std::move(LineNums)), Index(0) {} + +uint32_t NativeEnumLineNumbers::getChildCount() const { + return static_cast(Lines.size()); +} + +std::unique_ptr +NativeEnumLineNumbers::getChildAtIndex(uint32_t N) const { + if (N >= getChildCount()) + return nullptr; + return std::make_unique(Lines[N]); +} + +std::unique_ptr NativeEnumLineNumbers::getNext() { + return getChildAtIndex(Index++); +} + +void NativeEnumLineNumbers::reset() { Index = 0; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp @@ -0,0 +1,49 @@ +//===- NativeLineNumber.cpp - Native line number implementation -*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" + +using namespace llvm; +using namespace llvm::pdb; + +NativeLineNumber::NativeLineNumber(const NativeSession &Session, + const codeview::LineInfo Line, + uint32_t Section, uint32_t Offset, + uint32_t Length, uint32_t SrcFileId) + : Session(Session), Line(Line), Section(Section), Offset(Offset), + Length(Length), SrcFileId(SrcFileId) {} + +uint32_t NativeLineNumber::getLineNumber() const { return Line.getStartLine(); } + +uint32_t NativeLineNumber::getLineNumberEnd() const { + return Line.getEndLine(); +} + +uint32_t NativeLineNumber::getColumnNumber() const { return 0; } + +uint32_t NativeLineNumber::getColumnNumberEnd() const { return 0; } + +uint32_t NativeLineNumber::getAddressSection() const { return Section; } + +uint32_t NativeLineNumber::getAddressOffset() const { return Offset; } + +uint32_t NativeLineNumber::getRelativeVirtualAddress() const { + return Session.getRVAFromSectOffset(Section, Offset); +} + +uint64_t NativeLineNumber::getVirtualAddress() const { + return Session.getVAFromSectOffset(Section, Offset); +} + +uint32_t NativeLineNumber::getLength() const { return Length; } + +uint32_t NativeLineNumber::getSourceFileId() const { return SrcFileId; } + +uint32_t NativeLineNumber::getCompilandId() const { return 0; } + +bool NativeLineNumber::isStatement() const { return Line.isStatement(); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -43,7 +43,6 @@ using namespace llvm; using namespace llvm::msf; using namespace llvm::pdb; -using namespace llvm::codeview; static DbiStream *getDbiStreamPtr(PDBFile &File) { Expected DbiS = File.getPDBDbiStream(); @@ -182,6 +181,12 @@ if (auto File = loadPdbFile(PdbPath, Allocator)) return std::string(PdbPath); else + consumeError(File.takeError()); + + // Check path that was in the executable. + if (auto File = loadPdbFile(PathFromExe, Allocator)) + return std::string(PathFromExe); + else return File.takeError(); return make_error("PDB not found"); @@ -262,18 +267,19 @@ std::unique_ptr NativeSession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { - return nullptr; + return Cache.findLineNumbersByVA(Address, Length); } std::unique_ptr NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const { - return nullptr; + return findLineNumbersByAddress(getLoadAddress() + RVA, Length); } std::unique_ptr NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return nullptr; + uint64_t VA = getVAFromSectOffset(Section, Offset); + return findLineNumbersByAddress(VA, Length); } std::unique_ptr @@ -313,7 +319,7 @@ std::unique_ptr NativeSession::getSourceFileById(uint32_t FileId) const { - return nullptr; + return Cache.getSourceFileById(FileId); } std::unique_ptr NativeSession::getDebugStreams() const { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp @@ -0,0 +1,47 @@ +//===- NativeSourceFile.cpp - Native line number implementaiton -*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +using namespace llvm; +using namespace llvm::pdb; + +NativeSourceFile::NativeSourceFile(NativeSession &Session, uint32_t FileId, + const codeview::FileChecksumEntry &Checksum) + : Session(Session), FileId(FileId), Checksum(Checksum) {} + +std::string NativeSourceFile::getFileName() const { + auto ST = Session.getPDBFile().getStringTable(); + if (!ST) { + consumeError(ST.takeError()); + return ""; + } + auto FileName = ST->getStringTable().getString(Checksum.FileNameOffset); + if (!FileName) { + consumeError(FileName.takeError()); + return ""; + } + + return std::string(FileName.get()); +} + +uint32_t NativeSourceFile::getUniqueId() const { return FileId; } + +std::string NativeSourceFile::getChecksum() const { + return toStringRef(Checksum.Checksum).str(); +} + +PDB_Checksum NativeSourceFile::getChecksumType() const { + return static_cast(Checksum.Kind); +} + +std::unique_ptr> +NativeSourceFile::getCompilands() const { + return nullptr; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -7,9 +7,9 @@ #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" -#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h" @@ -71,6 +71,7 @@ : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) { // Id 0 is reserved for the invalid symbol. Cache.push_back(nullptr); + SourceFiles.push_back(nullptr); if (Dbi) Compilands.resize(Dbi->modules().getModuleCount()); @@ -287,6 +288,26 @@ return Id; } +Expected +SymbolCache::getModuleDebugStream(uint32_t Index) const { + assert(Dbi && "Dbi stream not present"); + + DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index); + + uint16_t ModiStream = Modi.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + return make_error("Module stream not present"); + + std::unique_ptr ModStreamData = + Session.getPDBFile().createIndexedStream(ModiStream); + + ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); + if (auto EC = ModS.reload()) + return std::move(EC); + + return std::move(ModS); +} + std::unique_ptr SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) { @@ -318,23 +339,18 @@ if (!Dbi) return nullptr; - auto Modi = getModuleIndexForAddr(Sect, Offset); + auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset)); if (!Modi) return nullptr; - DbiModuleDescriptor ModDesc = Dbi->modules().getModuleDescriptor(*Modi); - uint16_t StreamIndex = ModDesc.getModuleStreamIndex(); - if (StreamIndex == kInvalidStreamIndex) - return nullptr; - auto ModStreamData = Session.getPDBFile().createIndexedStream(StreamIndex); - ModuleDebugStreamRef ModS(ModDesc, std::move(ModStreamData)); - if (auto EC = ModS.reload()) { - consumeError(std::move(EC)); + auto ExpectedModS = getModuleDebugStream(*Modi); + if (!ExpectedModS) { + consumeError(ExpectedModS.takeError()); return nullptr; } + CVSymbolArray Syms = ExpectedModS->getSymbolArray(); // Search for the symbol in this module. - CVSymbolArray Syms = ModS.getSymbolArray(); for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) { if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32) continue; @@ -342,6 +358,7 @@ if (Sect == PS.Segment && Offset >= PS.CodeOffset && Offset < PS.CodeOffset + PS.CodeSize) { SymIndexId Id = createSymbol(PS); + AddressToFunctionSymId.insert({{Sect, Offset}, Id}); return getSymbolById(Id); } @@ -392,6 +409,8 @@ } else Count = Half; } + if (It == AddrMap.begin()) + return nullptr; --It; Expected Sym = readSymbolFromStream(SymStream, *It); @@ -401,9 +420,165 @@ } auto PS = cantFail(SymbolDeserializer::deserializeAs(Sym.get())); SymIndexId Id = createSymbol(PS); + AddressToPublicSymId.insert({{Sect, Offset}, Id}); return getSymbolById(Id); } +std::vector +SymbolCache::findLineTable(uint16_t Modi) const { + // Check if this module has already been added. + auto LineTableIter = LineTable.find(Modi); + if (LineTableIter != LineTable.end()) + return LineTableIter->second; + + std::vector &ModuleLineTable = LineTable[Modi]; + + // If there is an error or there are no lines, just return the + // empty vector. + Expected ExpectedModS = getModuleDebugStream(Modi); + if (!ExpectedModS) { + consumeError(ExpectedModS.takeError()); + return ModuleLineTable; + } + + std::vector> EntryList; + for (const auto &SS : ExpectedModS->getSubsectionsArray()) { + if (SS.kind() != DebugSubsectionKind::Lines) + continue; + + DebugLinesSubsectionRef Lines; + BinaryStreamReader Reader(SS.getRecordData()); + if (auto EC = Lines.initialize(Reader)) { + consumeError(std::move(EC)); + continue; + } + + uint32_t RelocSegment = Lines.header()->RelocSegment; + uint32_t RelocOffset = Lines.header()->RelocOffset; + for (const LineColumnEntry &Group : Lines) { + if (Group.LineNumbers.empty()) + continue; + + std::vector Entries; + for (const LineNumberEntry &LN : Group.LineNumbers) { + LineInfo Line(LN.Flags); + uint64_t VA = + Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset); + Entries.push_back({VA, Line, Group.NameIndex, false}); + } + + // Add a terminal entry line to mark the end of this subsection. + LineInfo LastLine(Group.LineNumbers.back().Flags); + uint64_t VA = Session.getVAFromSectOffset( + RelocSegment, RelocOffset + Lines.header()->CodeSize); + Entries.push_back({VA, LastLine, Group.NameIndex, true}); + EntryList.push_back(Entries); + } + } + + // Sort EntryList, and add flattened contents to the line table. + std::sort(EntryList.begin(), EntryList.end(), + [](const std::vector &LHS, + const std::vector &RHS) { + return LHS[0].Addr < RHS[0].Addr; + }); + for (size_t I = 0; I < EntryList.size(); ++I) + ModuleLineTable.insert(ModuleLineTable.end(), EntryList[I].begin(), + EntryList[I].end()); + + return ModuleLineTable; +} + +std::unique_ptr +SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { + Optional MaybeModi = getModuleIndexForAddr(VA); + if (!MaybeModi) + return nullptr; + uint16_t Modi = *MaybeModi; + + std::vector Lines = findLineTable(Modi); + if (Lines.empty()) + return nullptr; + + // Find the first line in the line table whose address is not greater than + // the one we are searching for. + auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) { + return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry)); + }); + + // Try to back up if we've gone too far. + if (LineIter == Lines.end() || LineIter->Addr > VA) { + if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry) + return nullptr; + --LineIter; + } + + Expected ExpectedModS = getModuleDebugStream(Modi); + if (!ExpectedModS) { + consumeError(ExpectedModS.takeError()); + return nullptr; + } + Expected ExpectedChecksums = + ExpectedModS->findChecksumsSubsection(); + if (!ExpectedChecksums) { + consumeError(ExpectedChecksums.takeError()); + return nullptr; + } + + // Populate a vector of NativeLineNumbers that have addresses in the given + // address range. + Optional EndModi = getModuleIndexForAddr(VA + Length); + if (!EndModi) + return nullptr; + std::vector LineNumbers; + while (Modi <= *EndModi) { + // If we reached the end of the current module, increment Modi and get the + // new line table and checksums array. + if (LineIter == Lines.end()) { + ++Modi; + + ExpectedModS = getModuleDebugStream(Modi); + if (!ExpectedModS) { + consumeError(ExpectedModS.takeError()); + break; + } + ExpectedChecksums = ExpectedModS->findChecksumsSubsection(); + if (!ExpectedChecksums) { + consumeError(ExpectedChecksums.takeError()); + break; + } + + Lines = findLineTable(Modi); + LineIter = Lines.begin(); + + if (Lines.empty()) + continue; + } + + if (LineIter->IsTerminalEntry) { + ++LineIter; + continue; + } + + // If the line is still within the address range, create a NativeLineNumber + // and add to the list. + if (LineIter->Addr > VA + Length) + break; + + uint32_t LineSect, LineOff; + Session.addressForVA(LineIter->Addr, LineSect, LineOff); + uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr; + auto ChecksumIter = + ExpectedChecksums->getArray().at(LineIter->FileNameIndex); + uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter); + NativeLineNumber LineNum(Session, LineIter->Line, LineSect, LineOff, + LineLength, SrcFileId); + LineNumbers.push_back(LineNum); + ++LineIter; + } + return std::make_unique(std::move(LineNumbers)); +} + std::unique_ptr SymbolCache::getOrCreateCompiland(uint32_t Index) { if (!Dbi) @@ -421,6 +596,31 @@ return Session.getConcreteSymbolById(Compilands[Index]); } +std::unique_ptr +SymbolCache::getSourceFileById(SymIndexId FileId) const { + assert(FileId < SourceFiles.size()); + + // Id 0 is reserved. + if (FileId == 0) + return nullptr; + + return std::unique_ptr( + new NativeSourceFile(*SourceFiles[FileId].get())); +} + +SymIndexId +SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const { + auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset); + if (Iter != FileNameOffsetToId.end()) + return Iter->second; + + SymIndexId Id = SourceFiles.size(); + auto SrcFile = std::make_unique(Session, Id, Checksums); + SourceFiles.push_back(std::move(SrcFile)); + FileNameOffsetToId[Checksums.FileNameOffset] = Id; + return Id; +} + void SymbolCache::parseSectionContribs() { if (!Dbi) return; @@ -451,9 +651,8 @@ Dbi->visitSectionContributions(V); } -Optional SymbolCache::getModuleIndexForAddr(uint32_t Sect, - uint32_t Offset) const { - auto Iter = AddrToModuleIndex.find(Session.getVAFromSectOffset(Sect, Offset)); +Optional SymbolCache::getModuleIndexForAddr(uint64_t Addr) const { + auto Iter = AddrToModuleIndex.find(Addr); if (Iter == AddrToModuleIndex.end()) return None; return Iter.value(); diff --git a/llvm/lib/DebugInfo/PDB/PDB.cpp b/llvm/lib/DebugInfo/PDB/PDB.cpp --- a/llvm/lib/DebugInfo/PDB/PDB.cpp +++ b/llvm/lib/DebugInfo/PDB/PDB.cpp @@ -37,15 +37,10 @@ std::unique_ptr &Session) { // Create the correct concrete instance type based on the value of Type. if (Type == PDB_ReaderType::Native) { - if (auto Err = NativeSession::createFromExe(Path, Session)) { - consumeError(std::move(Err)); - - Expected PdbPath = NativeSession::searchForPdb({Path}); - if (!PdbPath) - return PdbPath.takeError(); - return NativeSession::createFromPdbPath(PdbPath.get(), Session); - } - return Error::success(); + Expected PdbPath = NativeSession::searchForPdb({Path}); + if (!PdbPath) + return PdbPath.takeError(); + return NativeSession::createFromPdbPath(PdbPath.get(), Session); } #if LLVM_ENABLE_DIA_SDK diff --git a/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test b/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test --- a/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test +++ b/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test @@ -21,19 +21,27 @@ Currently only finding function/public symbol names is implemented. CHECK: foo(void) +CHECK-NEXT: test.cpp:10 CHECK: {{^private_symbol$}} +CHECK-NEXT: test.cpp:13:0 CHECK: {{^main}} +CHECK-NEXT: test.cpp:16:0 CHECK: {{^foo_cdecl$}} CHECK: {{^foo_stdcall$}} CHECK: {{^foo_fastcall$}} CHECK: {{^foo_vectorcall$}} CHECK: NS::Foo::bar(void) +CHECK-NEXT: test.cpp:6:0 CHECK-NO-DEMANGLE: ?foo@@YAXXZ +CHECK-NO-DEMANGLE-NEXT: test.cpp:10 CHECK-NO-DEMANGLE: private_symbol +CHECK-NO-DEMANGLE-NEXT: test.cpp:13 CHECK-NO-DEMANGLE: _main +CHECK-NO-DEMANGLE-NEXT: test.cpp:16 CHECK-NO-DEMANGLE: _foo_cdecl CHECK-NO-DEMANGLE: _foo_stdcall@0 CHECK-NO-DEMANGLE: @foo_fastcall@0 CHECK-NO-DEMANGLE: foo_vectorcall@@0 CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ +CHECK-NO-DEMANGLE-NEXT: test.cpp:6 diff --git a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn @@ -30,13 +30,16 @@ "Native/NativeCompilandSymbol.cpp", "Native/NativeEnumGlobals.cpp", "Native/NativeEnumInjectedSources.cpp", + "Native/NativeEnumLineNumbers.cpp", "Native/NativeEnumModules.cpp", "Native/NativeEnumTypes.cpp", "Native/NativeExeSymbol.cpp", "Native/NativeFunctionSymbol.cpp", + "Native/NativeLineNumber.cpp", "Native/NativePublicSymbol.cpp", "Native/NativeRawSymbol.cpp", "Native/NativeSession.cpp", + "Native/NativeSourceFile.cpp", "Native/NativeSymbolEnumerator.cpp", "Native/NativeTypeArray.cpp", "Native/NativeTypeBuiltin.cpp",