Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
39644 views
//===-- DWARFLocationExpression.cpp ---------------------------------------===//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 "DWARFLocationExpression.h"910#include "lldb/Core/Module.h"11#include "lldb/Core/Section.h"12#include "lldb/Expression/DWARFExpression.h"13#include "lldb/Utility/ArchSpec.h"14#include "lldb/Utility/DataBufferHeap.h"15#include "lldb/Utility/StreamBuffer.h"1617#include "llvm/BinaryFormat/Dwarf.h"18#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"19#include "llvm/DebugInfo/CodeView/TypeIndex.h"20#include "llvm/DebugInfo/PDB/Native/TpiStream.h"21#include "llvm/Support/Endian.h"2223#include "PdbUtil.h"24#include "CodeViewRegisterMapping.h"25#include "PdbFPOProgramToDWARFExpression.h"26#include <optional>2728using namespace lldb;29using namespace lldb_private;30using namespace lldb_private::npdb;31using namespace llvm::codeview;32using namespace llvm::pdb;3334uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {35if (register_id == llvm::codeview::RegisterId::VFRAME)36return LLDB_REGNUM_GENERIC_FP;3738return LLDB_INVALID_REGNUM;39}4041static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,42llvm::codeview::RegisterId register_id,43RegisterKind ®ister_kind) {44register_kind = eRegisterKindLLDB;45uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);46if (reg_num != LLDB_INVALID_REGNUM)47return reg_num;4849register_kind = eRegisterKindGeneric;50return GetGenericRegisterNumber(register_id);51}5253static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {54switch (kind) {55case SimpleTypeKind::Int128:56case SimpleTypeKind::Int64:57case SimpleTypeKind::Int64Quad:58case SimpleTypeKind::Int32:59case SimpleTypeKind::Int32Long:60case SimpleTypeKind::Int16:61case SimpleTypeKind::Int16Short:62case SimpleTypeKind::Float128:63case SimpleTypeKind::Float80:64case SimpleTypeKind::Float64:65case SimpleTypeKind::Float32:66case SimpleTypeKind::Float16:67case SimpleTypeKind::NarrowCharacter:68case SimpleTypeKind::SignedCharacter:69case SimpleTypeKind::SByte:70return true;71default:72return false;73}74}7576static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,77TpiStream &tpi) {78if (ti.isSimple()) {79SimpleTypeKind stk = ti.getSimpleKind();80return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)};81}8283CVType cvt = tpi.getType(ti);84switch (cvt.kind()) {85case LF_MODIFIER: {86ModifierRecord mfr;87llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));88return GetIntegralTypeInfo(mfr.ModifiedType, tpi);89}90case LF_POINTER: {91PointerRecord pr;92llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));93return GetIntegralTypeInfo(pr.ReferentType, tpi);94}95case LF_ENUM: {96EnumRecord er;97llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));98return GetIntegralTypeInfo(er.UnderlyingType, tpi);99}100default:101assert(false && "Type is not integral!");102return {0, false};103}104}105106template <typename StreamWriter>107static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,108StreamWriter &&writer) {109const ArchSpec &architecture = module->GetArchitecture();110ByteOrder byte_order = architecture.GetByteOrder();111uint32_t address_size = architecture.GetAddressByteSize();112uint32_t byte_size = architecture.GetDataByteSize();113if (byte_order == eByteOrderInvalid || address_size == 0)114return DWARFExpression();115116RegisterKind register_kind = eRegisterKindDWARF;117StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);118119if (!writer(stream, register_kind))120return DWARFExpression();121122DataBufferSP buffer =123std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());124DataExtractor extractor(buffer, byte_order, address_size, byte_size);125DWARFExpression result(extractor);126result.SetRegisterKind(register_kind);127128return result;129}130131static bool MakeRegisterBasedLocationExpressionInternal(132Stream &stream, llvm::codeview::RegisterId reg, RegisterKind ®ister_kind,133std::optional<int32_t> relative_offset, lldb::ModuleSP module) {134uint32_t reg_num = GetRegisterNumber(module->GetArchitecture().GetMachine(),135reg, register_kind);136if (reg_num == LLDB_INVALID_REGNUM)137return false;138139if (reg_num > 31) {140llvm::dwarf::LocationAtom base =141relative_offset ? llvm::dwarf::DW_OP_bregx : llvm::dwarf::DW_OP_regx;142stream.PutHex8(base);143stream.PutULEB128(reg_num);144} else {145llvm::dwarf::LocationAtom base =146relative_offset ? llvm::dwarf::DW_OP_breg0 : llvm::dwarf::DW_OP_reg0;147stream.PutHex8(base + reg_num);148}149150if (relative_offset)151stream.PutSLEB128(*relative_offset);152153return true;154}155156static DWARFExpression MakeRegisterBasedLocationExpressionInternal(157llvm::codeview::RegisterId reg, std::optional<int32_t> relative_offset,158lldb::ModuleSP module) {159return MakeLocationExpressionInternal(160module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {161return MakeRegisterBasedLocationExpressionInternal(162stream, reg, register_kind, relative_offset, module);163});164}165166DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression(167llvm::codeview::RegisterId reg, lldb::ModuleSP module) {168return MakeRegisterBasedLocationExpressionInternal(reg, std::nullopt, module);169}170171DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression(172llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {173return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);174}175176static bool EmitVFrameEvaluationDWARFExpression(177llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {178// VFrame value always stored in $TO pseudo-register179return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,180stream);181}182183DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression(184llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) {185return MakeLocationExpressionInternal(186module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {187const ArchSpec &architecture = module->GetArchitecture();188189if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),190stream))191return false;192193stream.PutHex8(llvm::dwarf::DW_OP_consts);194stream.PutSLEB128(offset);195stream.PutHex8(llvm::dwarf::DW_OP_plus);196197register_kind = eRegisterKindLLDB;198199return true;200});201}202203DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(204uint16_t section, uint32_t offset, ModuleSP module) {205assert(section > 0);206assert(module);207208return MakeLocationExpressionInternal(209module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {210stream.PutHex8(llvm::dwarf::DW_OP_addr);211212SectionList *section_list = module->GetSectionList();213assert(section_list);214215auto section_ptr = section_list->FindSectionByID(section);216if (!section_ptr)217return false;218219stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,220stream.GetAddressByteSize(), stream.GetByteOrder());221222return true;223});224}225226DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(227TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,228ModuleSP module) {229const ArchSpec &architecture = module->GetArchitecture();230uint32_t address_size = architecture.GetAddressByteSize();231232size_t size = 0;233bool is_signed = false;234std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);235236union {237llvm::support::little64_t I;238llvm::support::ulittle64_t U;239} Value;240241std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();242buffer->SetByteSize(size);243244llvm::ArrayRef<uint8_t> bytes;245if (is_signed) {246Value.I = constant.getSExtValue();247} else {248Value.U = constant.getZExtValue();249}250251bytes = llvm::ArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)252.take_front(size);253buffer->CopyData(bytes.data(), size);254DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);255DWARFExpression result(extractor);256return result;257}258259DWARFExpression260lldb_private::npdb::MakeEnregisteredLocationExpressionForComposite(261const std::map<uint64_t, MemberValLocation> &offset_to_location,262std::map<uint64_t, size_t> &offset_to_size, size_t total_size,263lldb::ModuleSP module) {264return MakeLocationExpressionInternal(265module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {266size_t cur_offset = 0;267bool is_simple_type = offset_to_size.empty();268// Iterate through offset_to_location because offset_to_size might be269// empty if the variable is a simple type.270for (const auto &offset_loc : offset_to_location) {271if (cur_offset < offset_loc.first) {272stream.PutHex8(llvm::dwarf::DW_OP_piece);273stream.PutULEB128(offset_loc.first - cur_offset);274cur_offset = offset_loc.first;275}276MemberValLocation loc = offset_loc.second;277std::optional<int32_t> offset =278loc.is_at_reg ? std::nullopt279: std::optional<int32_t>(loc.reg_offset);280if (!MakeRegisterBasedLocationExpressionInternal(281stream, (RegisterId)loc.reg_id, register_kind, offset,282module))283return false;284if (!is_simple_type) {285stream.PutHex8(llvm::dwarf::DW_OP_piece);286stream.PutULEB128(offset_to_size[offset_loc.first]);287cur_offset = offset_loc.first + offset_to_size[offset_loc.first];288}289}290// For simple type, it specifies the byte size of the value described by291// the previous dwarf expr. For udt, it's the remaining byte size at end292// of a struct.293if (total_size > cur_offset) {294stream.PutHex8(llvm::dwarf::DW_OP_piece);295stream.PutULEB128(total_size - cur_offset);296}297return true;298});299}300301302