diff options
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp')
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp index c350e0e0b3e1..0453eea26605 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -22,9 +22,12 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <cstdint> @@ -96,3 +99,50 @@ Error PublicsStream::reload() { "Corrupted publics stream."); return Error::success(); } + +// This is a reimplementation of NearestSym: +// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/PDB/dbi/gsi.cpp#L1492-L1581 +std::optional<std::pair<codeview::PublicSym32, size_t>> +PublicsStream::findByAddress(const SymbolStream &Symbols, uint16_t Segment, + uint32_t Offset) const { + // The address map is sorted by address, so we can use lower_bound to find the + // position. Each element is an offset into the symbols for a public symbol. + auto It = llvm::lower_bound( + AddressMap, std::tuple(Segment, Offset), + [&](support::ulittle32_t Cur, auto Addr) { + auto Sym = Symbols.readRecord(Cur.value()); + if (Sym.kind() != codeview::S_PUB32) + return false; // stop here, this is most likely corrupted debug info + + auto Psym = + codeview::SymbolDeserializer::deserializeAs<codeview::PublicSym32>( + Sym); + if (!Psym) { + consumeError(Psym.takeError()); + return false; + } + + return std::tie(Psym->Segment, Psym->Offset) < Addr; + }); + + if (It == AddressMap.end()) + return std::nullopt; + + auto Sym = Symbols.readRecord(It->value()); + if (Sym.kind() != codeview::S_PUB32) + return std::nullopt; // this is most likely corrupted debug info + + auto MaybePsym = + codeview::SymbolDeserializer::deserializeAs<codeview::PublicSym32>(Sym); + if (!MaybePsym) { + consumeError(MaybePsym.takeError()); + return std::nullopt; + } + codeview::PublicSym32 Psym = std::move(*MaybePsym); + + if (std::tuple(Segment, Offset) != std::tuple(Psym.Segment, Psym.Offset)) + return std::nullopt; + + std::ptrdiff_t IterOffset = It - AddressMap.begin(); + return std::pair{Psym, static_cast<size_t>(IterOffset)}; +} |
