144 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- NativeFunctionSymbol.cpp - info about function symbols----*- 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/NativeFunctionSymbol.h"
 | 
						|
 | 
						|
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
 | 
						|
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace llvm::codeview;
 | 
						|
using namespace llvm::pdb;
 | 
						|
 | 
						|
NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
 | 
						|
                                           SymIndexId Id,
 | 
						|
                                           const codeview::ProcSym &Sym,
 | 
						|
                                           uint32_t Offset)
 | 
						|
    : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
 | 
						|
      RecordOffset(Offset) {}
 | 
						|
 | 
						|
NativeFunctionSymbol::~NativeFunctionSymbol() {}
 | 
						|
 | 
						|
void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
 | 
						|
                                PdbSymbolIdField ShowIdFields,
 | 
						|
                                PdbSymbolIdField RecurseIdFields) const {
 | 
						|
  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
 | 
						|
  dumpSymbolField(OS, "name", getName(), Indent);
 | 
						|
  dumpSymbolField(OS, "length", getLength(), Indent);
 | 
						|
  dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
 | 
						|
  dumpSymbolField(OS, "section", getAddressSection(), Indent);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t NativeFunctionSymbol::getAddressOffset() const {
 | 
						|
  return Sym.CodeOffset;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
 | 
						|
std::string NativeFunctionSymbol::getName() const {
 | 
						|
  return std::string(Sym.Name);
 | 
						|
}
 | 
						|
 | 
						|
uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
 | 
						|
 | 
						|
uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
 | 
						|
  return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
 | 
						|
}
 | 
						|
 | 
						|
uint64_t NativeFunctionSymbol::getVirtualAddress() const {
 | 
						|
  return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
 | 
						|
}
 | 
						|
 | 
						|
static bool inlineSiteContainsAddress(InlineSiteSym &IS,
 | 
						|
                                      uint32_t OffsetInFunc) {
 | 
						|
  // Returns true if inline site contains the offset.
 | 
						|
  bool Found = false;
 | 
						|
  uint32_t CodeOffset = 0;
 | 
						|
  for (auto &Annot : IS.annotations()) {
 | 
						|
    switch (Annot.OpCode) {
 | 
						|
    case BinaryAnnotationsOpCode::CodeOffset:
 | 
						|
    case BinaryAnnotationsOpCode::ChangeCodeOffset:
 | 
						|
    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
 | 
						|
      CodeOffset += Annot.U1;
 | 
						|
      if (OffsetInFunc >= CodeOffset)
 | 
						|
        Found = true;
 | 
						|
      break;
 | 
						|
    case BinaryAnnotationsOpCode::ChangeCodeLength:
 | 
						|
      CodeOffset += Annot.U1;
 | 
						|
      if (Found && OffsetInFunc < CodeOffset)
 | 
						|
        return true;
 | 
						|
      Found = false;
 | 
						|
      break;
 | 
						|
    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
 | 
						|
      CodeOffset += Annot.U2;
 | 
						|
      if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1)
 | 
						|
        return true;
 | 
						|
      Found = false;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
std::unique_ptr<IPDBEnumSymbols>
 | 
						|
NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
 | 
						|
  uint16_t Modi;
 | 
						|
  if (!Session.moduleIndexForVA(VA, Modi))
 | 
						|
    return nullptr;
 | 
						|
 | 
						|
  Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
 | 
						|
  if (!ModS) {
 | 
						|
    consumeError(ModS.takeError());
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  CVSymbolArray Syms = ModS->getSymbolArray();
 | 
						|
 | 
						|
  // Search for inline sites. There should be one matching top level inline
 | 
						|
  // site. Then search in its nested inline sites.
 | 
						|
  std::vector<SymIndexId> Frames;
 | 
						|
  uint32_t CodeOffset = VA - getVirtualAddress();
 | 
						|
  auto Start = Syms.at(RecordOffset);
 | 
						|
  auto End = Syms.at(Sym.End);
 | 
						|
  while (Start != End) {
 | 
						|
    bool Found = false;
 | 
						|
    // Find matching inline site within Start and End.
 | 
						|
    for (; Start != End; ++Start) {
 | 
						|
      if (Start->kind() != S_INLINESITE)
 | 
						|
        continue;
 | 
						|
 | 
						|
      InlineSiteSym IS =
 | 
						|
          cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
 | 
						|
      if (inlineSiteContainsAddress(IS, CodeOffset)) {
 | 
						|
        // Insert frames in reverse order.
 | 
						|
        SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
 | 
						|
            IS, getVirtualAddress(), Modi, Start.offset());
 | 
						|
        Frames.insert(Frames.begin(), Id);
 | 
						|
 | 
						|
        // Update offsets to search within this inline site.
 | 
						|
        ++Start;
 | 
						|
        End = Syms.at(IS.End);
 | 
						|
        Found = true;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      Start = Syms.at(IS.End);
 | 
						|
      if (Start == End)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!Found)
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
 | 
						|
}
 |