brintos

brintos / llvm-project-archived public Read only

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