1 //===-- DWARFLocationExpression.cpp -----------------------------*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #include "DWARFLocationExpression.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/Section.h"
13 #include "lldb/Core/StreamBuffer.h"
14 #include "lldb/Expression/DWARFExpression.h"
15 #include "lldb/Utility/ArchSpec.h"
16 #include "lldb/Utility/DataBufferHeap.h"
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"
25 #include "CodeViewRegisterMapping.h"
26 #include "PdbFPOProgramToDWARFExpression.h"
29 using namespace lldb_private;
30 using namespace lldb_private::npdb;
31 using namespace llvm::codeview;
32 using namespace llvm::pdb;
34 uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
35 if (register_id == llvm::codeview::RegisterId::VFRAME)
36 return LLDB_REGNUM_GENERIC_FP;
38 return LLDB_INVALID_REGNUM;
41 static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
42 llvm::codeview::RegisterId register_id,
43 RegisterKind ®ister_kind) {
44 register_kind = eRegisterKindLLDB;
45 uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
46 if (reg_num != LLDB_INVALID_REGNUM)
49 register_kind = eRegisterKindGeneric;
50 return GetGenericRegisterNumber(register_id);
53 static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {
55 case SimpleTypeKind::Int128:
56 case SimpleTypeKind::Int64:
57 case SimpleTypeKind::Int64Quad:
58 case SimpleTypeKind::Int32:
59 case SimpleTypeKind::Int32Long:
60 case SimpleTypeKind::Int16:
61 case SimpleTypeKind::Int16Short:
62 case SimpleTypeKind::Float128:
63 case SimpleTypeKind::Float80:
64 case SimpleTypeKind::Float64:
65 case SimpleTypeKind::Float32:
66 case SimpleTypeKind::Float16:
67 case SimpleTypeKind::NarrowCharacter:
68 case SimpleTypeKind::SignedCharacter:
69 case SimpleTypeKind::SByte:
76 static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,
79 SimpleTypeKind stk = ti.getSimpleKind();
80 return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)};
83 CVType cvt = tpi.getType(ti);
87 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));
88 return GetIntegralTypeInfo(mfr.ModifiedType, tpi);
92 llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));
93 return GetIntegralTypeInfo(pr.ReferentType, tpi);
97 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
98 return GetIntegralTypeInfo(er.UnderlyingType, tpi);
101 assert(false && "Type is not integral!");
106 template <typename StreamWriter>
107 static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,
108 StreamWriter &&writer) {
109 const ArchSpec &architecture = module->GetArchitecture();
110 ByteOrder byte_order = architecture.GetByteOrder();
111 uint32_t address_size = architecture.GetAddressByteSize();
112 uint32_t byte_size = architecture.GetDataByteSize();
113 if (byte_order == eByteOrderInvalid || address_size == 0)
114 return DWARFExpression();
116 RegisterKind register_kind = eRegisterKindDWARF;
117 StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
119 if (!writer(stream, register_kind))
120 return DWARFExpression();
122 DataBufferSP buffer =
123 std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
124 DataExtractor extractor(buffer, byte_order, address_size, byte_size);
125 DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
126 result.SetRegisterKind(register_kind);
131 static DWARFExpression MakeRegisterBasedLocationExpressionInternal(
132 llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset,
133 lldb::ModuleSP module) {
134 return MakeLocationExpressionInternal(
135 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
136 uint32_t reg_num = GetRegisterNumber(
137 module->GetArchitecture().GetMachine(), reg, register_kind);
138 if (reg_num == LLDB_INVALID_REGNUM)
142 llvm::dwarf::LocationAtom base = relative_offset
143 ? llvm::dwarf::DW_OP_bregx
144 : llvm::dwarf::DW_OP_regx;
145 stream.PutHex8(base);
146 stream.PutULEB128(reg_num);
148 llvm::dwarf::LocationAtom base = relative_offset
149 ? llvm::dwarf::DW_OP_breg0
150 : llvm::dwarf::DW_OP_reg0;
151 stream.PutHex8(base + reg_num);
155 stream.PutSLEB128(*relative_offset);
161 DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression(
162 llvm::codeview::RegisterId reg, lldb::ModuleSP module) {
163 return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module);
166 DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression(
167 llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {
168 return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);
171 static bool EmitVFrameEvaluationDWARFExpression(
172 llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
173 // VFrame value always stored in $TO pseudo-register
174 return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
178 DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression(
179 llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) {
180 return MakeLocationExpressionInternal(
181 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
182 const ArchSpec &architecture = module->GetArchitecture();
184 if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),
188 stream.PutHex8(llvm::dwarf::DW_OP_consts);
189 stream.PutSLEB128(offset);
190 stream.PutHex8(llvm::dwarf::DW_OP_plus);
192 register_kind = eRegisterKindLLDB;
198 DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(
199 uint16_t section, uint32_t offset, ModuleSP module) {
203 return MakeLocationExpressionInternal(
204 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
205 stream.PutHex8(llvm::dwarf::DW_OP_addr);
207 SectionList *section_list = module->GetSectionList();
208 assert(section_list);
210 auto section_ptr = section_list->FindSectionByID(section);
214 stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,
215 stream.GetAddressByteSize(), stream.GetByteOrder());
221 DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
222 TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,
224 const ArchSpec &architecture = module->GetArchitecture();
225 uint32_t address_size = architecture.GetAddressByteSize();
228 bool is_signed = false;
229 std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);
232 llvm::support::little64_t I;
233 llvm::support::ulittle64_t U;
236 std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();
237 buffer->SetByteSize(size);
239 llvm::ArrayRef<uint8_t> bytes;
241 Value.I = constant.getSExtValue();
243 Value.U = constant.getZExtValue();
246 bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)
248 buffer->CopyData(bytes.data(), size);
249 DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
250 DWARFExpression result(nullptr, extractor, nullptr, 0, size);