brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · b5f29c0 Raw
183 lines · cpp
1//===-- PDBLocationToDWARFExpression.cpp ----------------------------------===//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 "PDBLocationToDWARFExpression.h"10 11#include "lldb/Core/Section.h"12#include "lldb/Core/dwarf.h"13#include "lldb/Expression/DWARFExpression.h"14#include "lldb/Symbol/Variable.h"15#include "lldb/Utility/DataBufferHeap.h"16#include "lldb/Utility/StreamBuffer.h"17 18#include "llvm/DebugInfo/CodeView/CodeView.h"19#include "llvm/DebugInfo/PDB/IPDBSession.h"20#include "llvm/DebugInfo/PDB/PDBSymbolData.h"21 22#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"23#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"24 25using namespace lldb;26using namespace lldb_private;27using namespace lldb_private::npdb;28using namespace llvm::dwarf;29using namespace llvm::pdb;30 31static std::unique_ptr<IPDBFrameData>32GetCorrespondingFrameData(const IPDBSession &session,33                          const Variable::RangeList &ranges) {34  auto enumFrameData = session.getFrameData();35  if (!enumFrameData)36    return nullptr;37 38  std::unique_ptr<IPDBFrameData> found;39  while (auto fd = enumFrameData->getNext()) {40    Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(),41                                              fd->getLengthBlock());42 43    for (size_t i = 0; i < ranges.GetSize(); i++) {44      auto range = ranges.GetEntryAtIndex(i);45      if (!range)46        continue;47 48      if (!range->DoesIntersect(fdRange))49        continue;50 51      found = std::move(fd);52 53      break;54    }55  }56 57  return found;58}59 60static bool EmitVFrameEvaluationDWARFExpression(61    llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {62  // VFrame value always stored in $TO pseudo-register63  return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,64                                              stream);65}66 67DWARFExpression ConvertPDBLocationToDWARFExpression(68    ModuleSP module, const PDBSymbolData &symbol,69    const Variable::RangeList &ranges, bool &is_constant) {70  is_constant = true;71 72  if (!module)73    return DWARFExpression();74 75  const ArchSpec &architecture = module->GetArchitecture();76  llvm::Triple::ArchType arch_type = architecture.GetMachine();77  ByteOrder byte_order = architecture.GetByteOrder();78  uint32_t address_size = architecture.GetAddressByteSize();79  uint32_t byte_size = architecture.GetDataByteSize();80  if (byte_order == eByteOrderInvalid || address_size == 0)81    return DWARFExpression();82 83  RegisterKind register_kind = eRegisterKindDWARF;84  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);85  switch (symbol.getLocationType()) {86  case PDB_LocType::Static:87  case PDB_LocType::TLS: {88    stream.PutHex8(DW_OP_addr);89 90    SectionList *section_list = module->GetSectionList();91    if (!section_list)92      return DWARFExpression();93 94    uint32_t section_id = symbol.getAddressSection();95 96    auto section = section_list->FindSectionByID(section_id);97    if (!section)98      return DWARFExpression();99 100    uint32_t offset = symbol.getAddressOffset();101    stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,102                       byte_order);103 104    is_constant = false;105 106    break;107  }108  case PDB_LocType::RegRel: {109    uint32_t reg_num;110    auto reg_id = symbol.getRegisterId();111    if (reg_id == llvm::codeview::RegisterId::VFRAME) {112      if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) {113        if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type,114                                                stream)) {115          int32_t offset = symbol.getOffset();116          stream.PutHex8(DW_OP_consts);117          stream.PutSLEB128(offset);118          stream.PutHex8(DW_OP_plus);119 120          register_kind = eRegisterKindLLDB;121 122          is_constant = false;123          break;124        }125      }126 127      register_kind = eRegisterKindGeneric;128      reg_num = LLDB_REGNUM_GENERIC_FP;129    } else {130      register_kind = eRegisterKindLLDB;131      reg_num = GetLLDBRegisterNumber(arch_type, reg_id);132      if (reg_num == LLDB_INVALID_REGNUM)133        return DWARFExpression();134    }135 136    if (reg_num > 31) {137      stream.PutHex8(DW_OP_bregx);138      stream.PutULEB128(reg_num);139    } else140      stream.PutHex8(DW_OP_breg0 + reg_num);141 142    int32_t offset = symbol.getOffset();143    stream.PutSLEB128(offset);144 145    is_constant = false;146 147    break;148  }149  case PDB_LocType::Enregistered: {150    register_kind = eRegisterKindLLDB;151    uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId());152    if (reg_num == LLDB_INVALID_REGNUM)153      return DWARFExpression();154 155    if (reg_num > 31) {156      stream.PutHex8(DW_OP_regx);157      stream.PutULEB128(reg_num);158    } else159      stream.PutHex8(DW_OP_reg0 + reg_num);160 161    is_constant = false;162 163    break;164  }165  case PDB_LocType::Constant: {166    Variant value = symbol.getValue();167    stream.PutRawBytes(&value.Value, sizeof(value.Value),168                       endian::InlHostByteOrder());169    break;170  }171  default:172    return DWARFExpression();173  }174 175  DataBufferSP buffer =176      std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());177  DataExtractor extractor(buffer, byte_order, address_size, byte_size);178  DWARFExpression result(extractor);179  result.SetRegisterKind(register_kind);180 181  return result;182}183