brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 75adf73 Raw
301 lines · cpp
1//===-- DWARFLocationExpression.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 "DWARFLocationExpression.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Core/Section.h"13#include "lldb/Expression/DWARFExpression.h"14#include "lldb/Utility/ArchSpec.h"15#include "lldb/Utility/DataBufferHeap.h"16#include "lldb/Utility/StreamBuffer.h"17 18#include "llvm/BinaryFormat/Dwarf.h"19#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"20#include "llvm/DebugInfo/CodeView/TypeIndex.h"21#include "llvm/DebugInfo/PDB/Native/TpiStream.h"22#include "llvm/Support/Endian.h"23 24#include "PdbUtil.h"25#include "CodeViewRegisterMapping.h"26#include "PdbFPOProgramToDWARFExpression.h"27#include <optional>28 29using namespace lldb;30using namespace lldb_private;31using namespace lldb_private::npdb;32using namespace llvm::codeview;33using namespace llvm::pdb;34 35uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {36  if (register_id == llvm::codeview::RegisterId::VFRAME)37    return LLDB_REGNUM_GENERIC_FP;38 39  return LLDB_INVALID_REGNUM;40}41 42static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,43                                  llvm::codeview::RegisterId register_id,44                                  RegisterKind &register_kind) {45  register_kind = eRegisterKindLLDB;46  uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);47  if (reg_num != LLDB_INVALID_REGNUM)48    return reg_num;49 50  register_kind = eRegisterKindGeneric;51  return GetGenericRegisterNumber(register_id);52}53 54static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {55  switch (kind) {56  case SimpleTypeKind::Int128:57  case SimpleTypeKind::Int64:58  case SimpleTypeKind::Int64Quad:59  case SimpleTypeKind::Int32:60  case SimpleTypeKind::Int32Long:61  case SimpleTypeKind::Int16:62  case SimpleTypeKind::Int16Short:63  case SimpleTypeKind::Float128:64  case SimpleTypeKind::Float80:65  case SimpleTypeKind::Float64:66  case SimpleTypeKind::Float32:67  case SimpleTypeKind::Float16:68  case SimpleTypeKind::NarrowCharacter:69  case SimpleTypeKind::SignedCharacter:70  case SimpleTypeKind::SByte:71    return true;72  default:73    return false;74  }75}76 77static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,78                                                   TpiStream &tpi) {79  if (ti.isSimple()) {80    SimpleTypeKind stk = ti.getSimpleKind();81    return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)};82  }83 84  CVType cvt = tpi.getType(ti);85  switch (cvt.kind()) {86  case LF_MODIFIER: {87    ModifierRecord mfr;88    llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));89    return GetIntegralTypeInfo(mfr.ModifiedType, tpi);90  }91  case LF_POINTER: {92    PointerRecord pr;93    llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));94    return GetIntegralTypeInfo(pr.ReferentType, tpi);95  }96  case LF_ENUM: {97    EnumRecord er;98    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));99    return GetIntegralTypeInfo(er.UnderlyingType, tpi);100  }101  default:102    assert(false && "Type is not integral!");103    return {0, false};104  }105}106 107template <typename StreamWriter>108static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,109                                                      StreamWriter &&writer) {110  const ArchSpec &architecture = module->GetArchitecture();111  ByteOrder byte_order = architecture.GetByteOrder();112  uint32_t address_size = architecture.GetAddressByteSize();113  uint32_t byte_size = architecture.GetDataByteSize();114  if (byte_order == eByteOrderInvalid || address_size == 0)115    return DWARFExpression();116 117  RegisterKind register_kind = eRegisterKindDWARF;118  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);119 120  if (!writer(stream, register_kind))121    return DWARFExpression();122 123  DataBufferSP buffer =124      std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());125  DataExtractor extractor(buffer, byte_order, address_size, byte_size);126  DWARFExpression result(extractor);127  result.SetRegisterKind(register_kind);128 129  return result;130}131 132static bool MakeRegisterBasedLocationExpressionInternal(133    Stream &stream, llvm::codeview::RegisterId reg, RegisterKind &register_kind,134    std::optional<int32_t> relative_offset, lldb::ModuleSP module) {135  uint32_t reg_num = GetRegisterNumber(module->GetArchitecture().GetMachine(),136                                       reg, register_kind);137  if (reg_num == LLDB_INVALID_REGNUM)138    return false;139 140  if (reg_num > 31) {141    llvm::dwarf::LocationAtom base =142        relative_offset ? llvm::dwarf::DW_OP_bregx : llvm::dwarf::DW_OP_regx;143    stream.PutHex8(base);144    stream.PutULEB128(reg_num);145  } else {146    llvm::dwarf::LocationAtom base =147        relative_offset ? llvm::dwarf::DW_OP_breg0 : llvm::dwarf::DW_OP_reg0;148    stream.PutHex8(base + reg_num);149  }150 151  if (relative_offset)152    stream.PutSLEB128(*relative_offset);153 154  return true;155}156 157static DWARFExpression MakeRegisterBasedLocationExpressionInternal(158    llvm::codeview::RegisterId reg, std::optional<int32_t> relative_offset,159    lldb::ModuleSP module) {160  return MakeLocationExpressionInternal(161      module, [&](Stream &stream, RegisterKind &register_kind) -> bool {162        return MakeRegisterBasedLocationExpressionInternal(163            stream, reg, register_kind, relative_offset, module);164      });165}166 167DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression(168    llvm::codeview::RegisterId reg, lldb::ModuleSP module) {169  return MakeRegisterBasedLocationExpressionInternal(reg, std::nullopt, module);170}171 172DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression(173    llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {174  return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);175}176 177static bool EmitVFrameEvaluationDWARFExpression(178    llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {179  // VFrame value always stored in $TO pseudo-register180  return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,181                                              stream);182}183 184DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression(185    llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) {186  return MakeLocationExpressionInternal(187      module, [&](Stream &stream, RegisterKind &register_kind) -> bool {188        const ArchSpec &architecture = module->GetArchitecture();189 190        if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),191                                                 stream))192          return false;193 194        stream.PutHex8(llvm::dwarf::DW_OP_consts);195        stream.PutSLEB128(offset);196        stream.PutHex8(llvm::dwarf::DW_OP_plus);197 198        register_kind = eRegisterKindLLDB;199 200        return true;201      });202}203 204DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(205    uint16_t section, uint32_t offset, ModuleSP module) {206  assert(section > 0);207  assert(module);208 209  return MakeLocationExpressionInternal(210      module, [&](Stream &stream, RegisterKind &register_kind) -> bool {211        stream.PutHex8(llvm::dwarf::DW_OP_addr);212 213        SectionList *section_list = module->GetSectionList();214        assert(section_list);215 216        auto section_ptr = section_list->FindSectionByID(section);217        if (!section_ptr)218          return false;219 220        stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,221                           stream.GetAddressByteSize(), stream.GetByteOrder());222 223        return true;224      });225}226 227DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(228    TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,229    ModuleSP module) {230  const ArchSpec &architecture = module->GetArchitecture();231  uint32_t address_size = architecture.GetAddressByteSize();232 233  size_t size = 0;234  bool is_signed = false;235  std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);236 237  union {238    llvm::support::little64_t I;239    llvm::support::ulittle64_t U;240  } Value;241 242  std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();243  buffer->SetByteSize(size);244 245  llvm::ArrayRef<uint8_t> bytes;246  if (is_signed) {247    Value.I = constant.getSExtValue();248  } else {249    Value.U = constant.getZExtValue();250  }251 252  bytes = llvm::ArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)253              .take_front(size);254  buffer->CopyData(bytes.data(), size);255  DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);256  DWARFExpression result(extractor);257  return result;258}259 260DWARFExpression261lldb_private::npdb::MakeEnregisteredLocationExpressionForComposite(262    const std::map<uint64_t, MemberValLocation> &offset_to_location,263    std::map<uint64_t, size_t> &offset_to_size, size_t total_size,264    lldb::ModuleSP module) {265  return MakeLocationExpressionInternal(266      module, [&](Stream &stream, RegisterKind &register_kind) -> bool {267        size_t cur_offset = 0;268        bool is_simple_type = offset_to_size.empty();269        // Iterate through offset_to_location because offset_to_size might be270        // empty if the variable is a simple type.271        for (const auto &offset_loc : offset_to_location) {272          if (cur_offset < offset_loc.first) {273            stream.PutHex8(llvm::dwarf::DW_OP_piece);274            stream.PutULEB128(offset_loc.first - cur_offset);275            cur_offset = offset_loc.first;276          }277          MemberValLocation loc = offset_loc.second;278          std::optional<int32_t> offset =279              loc.is_at_reg ? std::nullopt280                            : std::optional<int32_t>(loc.reg_offset);281          if (!MakeRegisterBasedLocationExpressionInternal(282                  stream, (RegisterId)loc.reg_id, register_kind, offset,283                  module))284            return false;285          if (!is_simple_type) {286            stream.PutHex8(llvm::dwarf::DW_OP_piece);287            stream.PutULEB128(offset_to_size[offset_loc.first]);288            cur_offset = offset_loc.first + offset_to_size[offset_loc.first];289          }290        }291        // For simple type, it specifies the byte size of the value described by292        // the previous dwarf expr. For udt, it's the remaining byte size at end293        // of a struct.294        if (total_size > cur_offset) {295          stream.PutHex8(llvm::dwarf::DW_OP_piece);296          stream.PutULEB128(total_size - cur_offset);297        }298        return true;299      });300}301