Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
35293 views
//===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"910#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"11#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"12#include "llvm/DebugInfo/CodeView/SymbolRecord.h"13#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"14#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"15#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"16#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"17#include "llvm/DebugInfo/PDB/Native/NativeSession.h"18#include "llvm/DebugInfo/PDB/Native/PDBFile.h"19#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"20#include "llvm/DebugInfo/PDB/Native/TpiStream.h"21#include "llvm/DebugInfo/PDB/PDBExtras.h"2223using namespace llvm;24using namespace llvm::codeview;25using namespace llvm::pdb;2627NativeInlineSiteSymbol::NativeInlineSiteSymbol(28NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym,29uint64_t ParentAddr)30: NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym),31ParentAddr(ParentAddr) {}3233NativeInlineSiteSymbol::~NativeInlineSiteSymbol() = default;3435void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent,36PdbSymbolIdField ShowIdFields,37PdbSymbolIdField RecurseIdFields) const {38NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);39dumpSymbolField(OS, "name", getName(), Indent);40}4142static std::optional<InlineeSourceLine>43findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) {44for (const auto &SS : ModS.getSubsectionsArray()) {45if (SS.kind() != DebugSubsectionKind::InlineeLines)46continue;4748DebugInlineeLinesSubsectionRef InlineeLines;49BinaryStreamReader Reader(SS.getRecordData());50if (auto EC = InlineeLines.initialize(Reader)) {51consumeError(std::move(EC));52continue;53}5455for (const InlineeSourceLine &Line : InlineeLines)56if (Line.Header->Inlinee == Id)57return Line;58}59return std::nullopt;60}6162std::string NativeInlineSiteSymbol::getName() const {63auto Tpi = Session.getPDBFile().getPDBTpiStream();64if (!Tpi) {65consumeError(Tpi.takeError());66return "";67}68auto Ipi = Session.getPDBFile().getPDBIpiStream();69if (!Ipi) {70consumeError(Ipi.takeError());71return "";72}7374LazyRandomTypeCollection &Types = Tpi->typeCollection();75LazyRandomTypeCollection &Ids = Ipi->typeCollection();76CVType InlineeType = Ids.getType(Sym.Inlinee);77std::string QualifiedName;78if (InlineeType.kind() == LF_MFUNC_ID) {79MemberFuncIdRecord MFRecord;80cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType,81MFRecord));82TypeIndex ClassTy = MFRecord.getClassType();83QualifiedName.append(std::string(Types.getTypeName(ClassTy)));84QualifiedName.append("::");85} else if (InlineeType.kind() == LF_FUNC_ID) {86FuncIdRecord FRecord;87cantFail(88TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord));89TypeIndex ParentScope = FRecord.getParentScope();90if (!ParentScope.isNoneType()) {91QualifiedName.append(std::string(Ids.getTypeName(ParentScope)));92QualifiedName.append("::");93}94}9596QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee)));97return QualifiedName;98}99100void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc,101uint32_t &LineOffset,102uint32_t &FileOffset) const {103LineOffset = 0;104FileOffset = 0;105uint32_t CodeOffset = 0;106std::optional<uint32_t> CodeOffsetBase;107std::optional<uint32_t> CodeOffsetEnd;108std::optional<int32_t> CurLineOffset;109std::optional<int32_t> NextLineOffset;110std::optional<uint32_t> NextFileOffset;111auto UpdateCodeOffset = [&](uint32_t Delta) {112if (!CodeOffsetBase)113CodeOffsetBase = CodeOffset;114else if (!CodeOffsetEnd)115CodeOffsetEnd = *CodeOffsetBase + Delta;116};117auto UpdateLineOffset = [&](int32_t Delta) {118LineOffset += Delta;119if (!CodeOffsetBase || !CurLineOffset)120CurLineOffset = LineOffset;121else122NextLineOffset = LineOffset;123};124auto UpdateFileOffset = [&](uint32_t Offset) {125if (!CodeOffsetBase)126FileOffset = Offset;127else128NextFileOffset = Offset;129};130auto ValidateAndReset = [&]() {131// Current range is finished. Check if OffsetInFunc is in the range.132if (CodeOffsetBase && CodeOffsetEnd && CurLineOffset) {133if (CodeOffsetBase <= OffsetInFunc && OffsetInFunc < CodeOffsetEnd) {134LineOffset = *CurLineOffset;135return true;136}137// Set base, end, file offset and line offset for next range.138if (NextFileOffset)139FileOffset = *NextFileOffset;140if (NextLineOffset) {141CurLineOffset = NextLineOffset;142NextLineOffset = std::nullopt;143}144CodeOffsetBase = CodeOffsetEnd;145CodeOffsetEnd = NextFileOffset = std::nullopt;146}147return false;148};149for (const auto &Annot : Sym.annotations()) {150switch (Annot.OpCode) {151case BinaryAnnotationsOpCode::CodeOffset:152case BinaryAnnotationsOpCode::ChangeCodeOffset:153case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:154CodeOffset += Annot.U1;155UpdateCodeOffset(Annot.U1);156break;157case BinaryAnnotationsOpCode::ChangeCodeLength:158UpdateCodeOffset(Annot.U1);159break;160case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:161CodeOffset += Annot.U2;162UpdateCodeOffset(Annot.U2);163UpdateCodeOffset(Annot.U1);164break;165case BinaryAnnotationsOpCode::ChangeLineOffset:166UpdateLineOffset(Annot.S1);167break;168case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:169CodeOffset += Annot.U1;170UpdateCodeOffset(Annot.U1);171UpdateLineOffset(Annot.S1);172break;173case BinaryAnnotationsOpCode::ChangeFile:174UpdateFileOffset(Annot.U1);175break;176default:177break;178}179180if (ValidateAndReset())181return;182}183}184185std::unique_ptr<IPDBEnumLineNumbers>186NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA,187uint32_t Length) const {188uint16_t Modi;189if (!Session.moduleIndexForVA(VA, Modi))190return nullptr;191192Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);193if (!ModS) {194consumeError(ModS.takeError());195return nullptr;196}197198Expected<DebugChecksumsSubsectionRef> Checksums =199ModS->findChecksumsSubsection();200if (!Checksums) {201consumeError(Checksums.takeError());202return nullptr;203}204205// Get the line number offset and source file offset.206uint32_t SrcLineOffset;207uint32_t SrcFileOffset;208getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset);209210// Get line info from inlinee line table.211std::optional<InlineeSourceLine> Inlinee =212findInlineeByTypeIndex(Sym.Inlinee, ModS.get());213214if (!Inlinee)215return nullptr;216217uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset;218uint32_t SrcCol = 0; // Inline sites don't seem to have column info.219uint32_t FileChecksumOffset =220(SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset;221222auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset);223uint32_t SrcFileId =224Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter);225226uint32_t LineSect, LineOff;227Session.addressForVA(VA, LineSect, LineOff);228NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length,229SrcFileId, Modi);230auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId);231std::vector<NativeLineNumber> Lines{LineNum};232233return std::make_unique<NativeEnumLineNumbers>(std::move(Lines));234}235236237