180814287SRaphael Isemann //===-- DWARFLocationExpression.cpp ---------------------------------------===//
2a93458b0SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a93458b0SZachary Turner //
7a93458b0SZachary Turner //===----------------------------------------------------------------------===//
8a93458b0SZachary Turner
9a93458b0SZachary Turner #include "DWARFLocationExpression.h"
10a93458b0SZachary Turner
11a93458b0SZachary Turner #include "lldb/Core/Module.h"
12a93458b0SZachary Turner #include "lldb/Core/Section.h"
13a93458b0SZachary Turner #include "lldb/Core/StreamBuffer.h"
14a93458b0SZachary Turner #include "lldb/Expression/DWARFExpression.h"
15a93458b0SZachary Turner #include "lldb/Utility/ArchSpec.h"
16a93458b0SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
17d3d2b9b8SZachary Turner
18a93458b0SZachary Turner #include "llvm/BinaryFormat/Dwarf.h"
19a93458b0SZachary Turner #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
20a93458b0SZachary Turner #include "llvm/DebugInfo/CodeView/TypeIndex.h"
21a93458b0SZachary Turner #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
22a93458b0SZachary Turner #include "llvm/Support/Endian.h"
23a93458b0SZachary Turner
24a93458b0SZachary Turner #include "PdbUtil.h"
25758657e5SAleksandr Urakov #include "CodeViewRegisterMapping.h"
26758657e5SAleksandr Urakov #include "PdbFPOProgramToDWARFExpression.h"
27a93458b0SZachary Turner
28a93458b0SZachary Turner using namespace lldb;
29a93458b0SZachary Turner using namespace lldb_private;
30a93458b0SZachary Turner using namespace lldb_private::npdb;
31a93458b0SZachary Turner using namespace llvm::codeview;
32a93458b0SZachary Turner using namespace llvm::pdb;
33a93458b0SZachary Turner
GetGenericRegisterNumber(llvm::codeview::RegisterId register_id)34d3d2b9b8SZachary Turner uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
35d3d2b9b8SZachary Turner if (register_id == llvm::codeview::RegisterId::VFRAME)
36d3d2b9b8SZachary Turner return LLDB_REGNUM_GENERIC_FP;
37d3d2b9b8SZachary Turner
38d3d2b9b8SZachary Turner return LLDB_INVALID_REGNUM;
39d3d2b9b8SZachary Turner }
40d3d2b9b8SZachary Turner
GetRegisterNumber(llvm::Triple::ArchType arch_type,llvm::codeview::RegisterId register_id,RegisterKind & register_kind)41d3d2b9b8SZachary Turner static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
42d3d2b9b8SZachary Turner llvm::codeview::RegisterId register_id,
43d3d2b9b8SZachary Turner RegisterKind ®ister_kind) {
44d3d2b9b8SZachary Turner register_kind = eRegisterKindLLDB;
45d3d2b9b8SZachary Turner uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
46d3d2b9b8SZachary Turner if (reg_num != LLDB_INVALID_REGNUM)
47d3d2b9b8SZachary Turner return reg_num;
48d3d2b9b8SZachary Turner
49d3d2b9b8SZachary Turner register_kind = eRegisterKindGeneric;
50d3d2b9b8SZachary Turner return GetGenericRegisterNumber(register_id);
51d3d2b9b8SZachary Turner }
52d3d2b9b8SZachary Turner
IsSimpleTypeSignedInteger(SimpleTypeKind kind)53a93458b0SZachary Turner static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {
54a93458b0SZachary Turner switch (kind) {
55a93458b0SZachary Turner case SimpleTypeKind::Int128:
56a93458b0SZachary Turner case SimpleTypeKind::Int64:
57a93458b0SZachary Turner case SimpleTypeKind::Int64Quad:
58a93458b0SZachary Turner case SimpleTypeKind::Int32:
59a93458b0SZachary Turner case SimpleTypeKind::Int32Long:
60a93458b0SZachary Turner case SimpleTypeKind::Int16:
61a93458b0SZachary Turner case SimpleTypeKind::Int16Short:
62a93458b0SZachary Turner case SimpleTypeKind::Float128:
63a93458b0SZachary Turner case SimpleTypeKind::Float80:
64a93458b0SZachary Turner case SimpleTypeKind::Float64:
65a93458b0SZachary Turner case SimpleTypeKind::Float32:
66a93458b0SZachary Turner case SimpleTypeKind::Float16:
67a93458b0SZachary Turner case SimpleTypeKind::NarrowCharacter:
68a93458b0SZachary Turner case SimpleTypeKind::SignedCharacter:
69a93458b0SZachary Turner case SimpleTypeKind::SByte:
70a93458b0SZachary Turner return true;
71a93458b0SZachary Turner default:
72a93458b0SZachary Turner return false;
73a93458b0SZachary Turner }
74a93458b0SZachary Turner }
75a93458b0SZachary Turner
GetIntegralTypeInfo(TypeIndex ti,TpiStream & tpi)76a93458b0SZachary Turner static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,
77a93458b0SZachary Turner TpiStream &tpi) {
78a93458b0SZachary Turner if (ti.isSimple()) {
79a93458b0SZachary Turner SimpleTypeKind stk = ti.getSimpleKind();
80a93458b0SZachary Turner return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)};
81a93458b0SZachary Turner }
82a93458b0SZachary Turner
83a93458b0SZachary Turner CVType cvt = tpi.getType(ti);
84a93458b0SZachary Turner switch (cvt.kind()) {
85a93458b0SZachary Turner case LF_MODIFIER: {
86a93458b0SZachary Turner ModifierRecord mfr;
87a93458b0SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));
88a93458b0SZachary Turner return GetIntegralTypeInfo(mfr.ModifiedType, tpi);
89a93458b0SZachary Turner }
90a93458b0SZachary Turner case LF_POINTER: {
91a93458b0SZachary Turner PointerRecord pr;
92a93458b0SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));
93a93458b0SZachary Turner return GetIntegralTypeInfo(pr.ReferentType, tpi);
94a93458b0SZachary Turner }
95a93458b0SZachary Turner case LF_ENUM: {
96a93458b0SZachary Turner EnumRecord er;
97a93458b0SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
98a93458b0SZachary Turner return GetIntegralTypeInfo(er.UnderlyingType, tpi);
99a93458b0SZachary Turner }
100a93458b0SZachary Turner default:
101a93458b0SZachary Turner assert(false && "Type is not integral!");
102a93458b0SZachary Turner return {0, false};
103a93458b0SZachary Turner }
104a93458b0SZachary Turner }
105a93458b0SZachary Turner
106a93458b0SZachary Turner template <typename StreamWriter>
MakeLocationExpressionInternal(lldb::ModuleSP module,StreamWriter && writer)107a93458b0SZachary Turner static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,
108a93458b0SZachary Turner StreamWriter &&writer) {
109a93458b0SZachary Turner const ArchSpec &architecture = module->GetArchitecture();
110a93458b0SZachary Turner ByteOrder byte_order = architecture.GetByteOrder();
111a93458b0SZachary Turner uint32_t address_size = architecture.GetAddressByteSize();
112a93458b0SZachary Turner uint32_t byte_size = architecture.GetDataByteSize();
113a93458b0SZachary Turner if (byte_order == eByteOrderInvalid || address_size == 0)
11404a087acSJonas Devlieghere return DWARFExpression();
115a93458b0SZachary Turner
116a93458b0SZachary Turner RegisterKind register_kind = eRegisterKindDWARF;
117a93458b0SZachary Turner StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
118a93458b0SZachary Turner
119a93458b0SZachary Turner if (!writer(stream, register_kind))
12004a087acSJonas Devlieghere return DWARFExpression();
121a93458b0SZachary Turner
122a93458b0SZachary Turner DataBufferSP buffer =
123a93458b0SZachary Turner std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
124a93458b0SZachary Turner DataExtractor extractor(buffer, byte_order, address_size, byte_size);
125*b74a01a8SZequan Wu DWARFExpression result(extractor);
126a93458b0SZachary Turner result.SetRegisterKind(register_kind);
127a93458b0SZachary Turner
128a93458b0SZachary Turner return result;
129a93458b0SZachary Turner }
130a93458b0SZachary Turner
MakeRegisterBasedLocationExpressionInternal(llvm::codeview::RegisterId reg,llvm::Optional<int32_t> relative_offset,lldb::ModuleSP module)131d3d2b9b8SZachary Turner static DWARFExpression MakeRegisterBasedLocationExpressionInternal(
132d3d2b9b8SZachary Turner llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset,
133d3d2b9b8SZachary Turner lldb::ModuleSP module) {
134d3d2b9b8SZachary Turner return MakeLocationExpressionInternal(
135d3d2b9b8SZachary Turner module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
136d3d2b9b8SZachary Turner uint32_t reg_num = GetRegisterNumber(
137d3d2b9b8SZachary Turner module->GetArchitecture().GetMachine(), reg, register_kind);
138d3d2b9b8SZachary Turner if (reg_num == LLDB_INVALID_REGNUM)
139d3d2b9b8SZachary Turner return false;
140d3d2b9b8SZachary Turner
141d3d2b9b8SZachary Turner if (reg_num > 31) {
142d3d2b9b8SZachary Turner llvm::dwarf::LocationAtom base = relative_offset
143d3d2b9b8SZachary Turner ? llvm::dwarf::DW_OP_bregx
144d3d2b9b8SZachary Turner : llvm::dwarf::DW_OP_regx;
145d3d2b9b8SZachary Turner stream.PutHex8(base);
146d3d2b9b8SZachary Turner stream.PutULEB128(reg_num);
147d3d2b9b8SZachary Turner } else {
148d3d2b9b8SZachary Turner llvm::dwarf::LocationAtom base = relative_offset
149d3d2b9b8SZachary Turner ? llvm::dwarf::DW_OP_breg0
150d3d2b9b8SZachary Turner : llvm::dwarf::DW_OP_reg0;
151d3d2b9b8SZachary Turner stream.PutHex8(base + reg_num);
152d3d2b9b8SZachary Turner }
153d3d2b9b8SZachary Turner
154d3d2b9b8SZachary Turner if (relative_offset)
155d3d2b9b8SZachary Turner stream.PutSLEB128(*relative_offset);
156d3d2b9b8SZachary Turner
157d3d2b9b8SZachary Turner return true;
158d3d2b9b8SZachary Turner });
159d3d2b9b8SZachary Turner }
160d3d2b9b8SZachary Turner
MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg,lldb::ModuleSP module)161d3d2b9b8SZachary Turner DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression(
162d3d2b9b8SZachary Turner llvm::codeview::RegisterId reg, lldb::ModuleSP module) {
163d3d2b9b8SZachary Turner return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module);
164d3d2b9b8SZachary Turner }
165d3d2b9b8SZachary Turner
MakeRegRelLocationExpression(llvm::codeview::RegisterId reg,int32_t offset,lldb::ModuleSP module)166d3d2b9b8SZachary Turner DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression(
167d3d2b9b8SZachary Turner llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {
168d3d2b9b8SZachary Turner return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);
169d3d2b9b8SZachary Turner }
170d3d2b9b8SZachary Turner
EmitVFrameEvaluationDWARFExpression(llvm::StringRef program,llvm::Triple::ArchType arch_type,Stream & stream)171758657e5SAleksandr Urakov static bool EmitVFrameEvaluationDWARFExpression(
172758657e5SAleksandr Urakov llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
173758657e5SAleksandr Urakov // VFrame value always stored in $TO pseudo-register
174758657e5SAleksandr Urakov return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
175758657e5SAleksandr Urakov stream);
176758657e5SAleksandr Urakov }
177758657e5SAleksandr Urakov
MakeVFrameRelLocationExpression(llvm::StringRef fpo_program,int32_t offset,lldb::ModuleSP module)178758657e5SAleksandr Urakov DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression(
179758657e5SAleksandr Urakov llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) {
180758657e5SAleksandr Urakov return MakeLocationExpressionInternal(
181758657e5SAleksandr Urakov module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
182758657e5SAleksandr Urakov const ArchSpec &architecture = module->GetArchitecture();
183758657e5SAleksandr Urakov
184758657e5SAleksandr Urakov if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),
185758657e5SAleksandr Urakov stream))
186758657e5SAleksandr Urakov return false;
187758657e5SAleksandr Urakov
188758657e5SAleksandr Urakov stream.PutHex8(llvm::dwarf::DW_OP_consts);
189758657e5SAleksandr Urakov stream.PutSLEB128(offset);
190758657e5SAleksandr Urakov stream.PutHex8(llvm::dwarf::DW_OP_plus);
191758657e5SAleksandr Urakov
192758657e5SAleksandr Urakov register_kind = eRegisterKindLLDB;
193758657e5SAleksandr Urakov
194758657e5SAleksandr Urakov return true;
195758657e5SAleksandr Urakov });
196758657e5SAleksandr Urakov }
197758657e5SAleksandr Urakov
MakeGlobalLocationExpression(uint16_t section,uint32_t offset,ModuleSP module)198a93458b0SZachary Turner DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(
199a93458b0SZachary Turner uint16_t section, uint32_t offset, ModuleSP module) {
200a93458b0SZachary Turner assert(section > 0);
201a93458b0SZachary Turner assert(module);
202a93458b0SZachary Turner
203a93458b0SZachary Turner return MakeLocationExpressionInternal(
204a93458b0SZachary Turner module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
205a93458b0SZachary Turner stream.PutHex8(llvm::dwarf::DW_OP_addr);
206a93458b0SZachary Turner
207a93458b0SZachary Turner SectionList *section_list = module->GetSectionList();
208a93458b0SZachary Turner assert(section_list);
209a93458b0SZachary Turner
2107db8b5c4SPavel Labath auto section_ptr = section_list->FindSectionByID(section);
211a93458b0SZachary Turner if (!section_ptr)
212a93458b0SZachary Turner return false;
213a93458b0SZachary Turner
214a93458b0SZachary Turner stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,
215a93458b0SZachary Turner stream.GetAddressByteSize(), stream.GetByteOrder());
216a93458b0SZachary Turner
217a93458b0SZachary Turner return true;
218a93458b0SZachary Turner });
219a93458b0SZachary Turner }
220a93458b0SZachary Turner
MakeConstantLocationExpression(TypeIndex underlying_ti,TpiStream & tpi,const llvm::APSInt & constant,ModuleSP module)221a93458b0SZachary Turner DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
222a93458b0SZachary Turner TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,
223a93458b0SZachary Turner ModuleSP module) {
224a93458b0SZachary Turner const ArchSpec &architecture = module->GetArchitecture();
225a93458b0SZachary Turner uint32_t address_size = architecture.GetAddressByteSize();
226a93458b0SZachary Turner
227a93458b0SZachary Turner size_t size = 0;
228a93458b0SZachary Turner bool is_signed = false;
229a93458b0SZachary Turner std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);
230a93458b0SZachary Turner
231a93458b0SZachary Turner union {
232a93458b0SZachary Turner llvm::support::little64_t I;
233a93458b0SZachary Turner llvm::support::ulittle64_t U;
234a93458b0SZachary Turner } Value;
235a93458b0SZachary Turner
236a93458b0SZachary Turner std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();
237a93458b0SZachary Turner buffer->SetByteSize(size);
238a93458b0SZachary Turner
239a93458b0SZachary Turner llvm::ArrayRef<uint8_t> bytes;
240a93458b0SZachary Turner if (is_signed) {
241a93458b0SZachary Turner Value.I = constant.getSExtValue();
242a93458b0SZachary Turner } else {
243a93458b0SZachary Turner Value.U = constant.getZExtValue();
244a93458b0SZachary Turner }
245a93458b0SZachary Turner
246a93458b0SZachary Turner bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)
247a93458b0SZachary Turner .take_front(size);
248a93458b0SZachary Turner buffer->CopyData(bytes.data(), size);
249a93458b0SZachary Turner DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
250*b74a01a8SZequan Wu DWARFExpression result(extractor);
251a93458b0SZachary Turner return result;
252a93458b0SZachary Turner }
2535e9c9b32SZequan Wu
MakeEnregisteredLocationExpressionForClass(std::map<uint64_t,std::pair<RegisterId,uint32_t>> & members_info,lldb::ModuleSP module)2545e9c9b32SZequan Wu DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpressionForClass(
2552fa27346SZequan Wu std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info,
2565e9c9b32SZequan Wu lldb::ModuleSP module) {
2575e9c9b32SZequan Wu return MakeLocationExpressionInternal(
2585e9c9b32SZequan Wu module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
2592fa27346SZequan Wu for (auto pair : members_info) {
2602fa27346SZequan Wu std::pair<RegisterId, uint32_t> member_info = pair.second;
2615e9c9b32SZequan Wu if (member_info.first != llvm::codeview::RegisterId::NONE) {
2625e9c9b32SZequan Wu uint32_t reg_num =
2635e9c9b32SZequan Wu GetRegisterNumber(module->GetArchitecture().GetMachine(),
2645e9c9b32SZequan Wu member_info.first, register_kind);
2655e9c9b32SZequan Wu if (reg_num == LLDB_INVALID_REGNUM)
2665e9c9b32SZequan Wu return false;
2675e9c9b32SZequan Wu if (reg_num > 31) {
2685e9c9b32SZequan Wu stream.PutHex8(llvm::dwarf::DW_OP_regx);
2695e9c9b32SZequan Wu stream.PutULEB128(reg_num);
2705e9c9b32SZequan Wu } else {
2715e9c9b32SZequan Wu stream.PutHex8(llvm::dwarf::DW_OP_reg0 + reg_num);
2725e9c9b32SZequan Wu }
2735e9c9b32SZequan Wu }
2745e9c9b32SZequan Wu stream.PutHex8(llvm::dwarf::DW_OP_piece);
2755e9c9b32SZequan Wu stream.PutULEB128(member_info.second);
2765e9c9b32SZequan Wu }
2775e9c9b32SZequan Wu return true;
2785e9c9b32SZequan Wu });
2795e9c9b32SZequan Wu }
280