]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / SymbolFile / NativePDB / DWARFLocationExpression.cpp
1 //===-- DWARFLocationExpression.cpp -----------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "DWARFLocationExpression.h"
10
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"
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
28 using namespace lldb;
29 using namespace lldb_private;
30 using namespace lldb_private::npdb;
31 using namespace llvm::codeview;
32 using namespace llvm::pdb;
33
34 uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
35   if (register_id == llvm::codeview::RegisterId::VFRAME)
36     return LLDB_REGNUM_GENERIC_FP;
37
38   return LLDB_INVALID_REGNUM;
39 }
40
41 static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
42                                   llvm::codeview::RegisterId register_id,
43                                   RegisterKind &register_kind) {
44   register_kind = eRegisterKindLLDB;
45   uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
46   if (reg_num != LLDB_INVALID_REGNUM)
47     return reg_num;
48
49   register_kind = eRegisterKindGeneric;
50   return GetGenericRegisterNumber(register_id);
51 }
52
53 static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {
54   switch (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:
70     return true;
71   default:
72     return false;
73   }
74 }
75
76 static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,
77                                                    TpiStream &tpi) {
78   if (ti.isSimple()) {
79     SimpleTypeKind stk = ti.getSimpleKind();
80     return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)};
81   }
82
83   CVType cvt = tpi.getType(ti);
84   switch (cvt.kind()) {
85   case LF_MODIFIER: {
86     ModifierRecord mfr;
87     llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));
88     return GetIntegralTypeInfo(mfr.ModifiedType, tpi);
89   }
90   case LF_POINTER: {
91     PointerRecord pr;
92     llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));
93     return GetIntegralTypeInfo(pr.ReferentType, tpi);
94   }
95   case LF_ENUM: {
96     EnumRecord er;
97     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
98     return GetIntegralTypeInfo(er.UnderlyingType, tpi);
99   }
100   default:
101     assert(false && "Type is not integral!");
102     return {0, false};
103   }
104 }
105
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();
115
116   RegisterKind register_kind = eRegisterKindDWARF;
117   StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
118
119   if (!writer(stream, register_kind))
120     return DWARFExpression();
121
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);
127
128   return result;
129 }
130
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 &register_kind) -> bool {
136         uint32_t reg_num = GetRegisterNumber(
137             module->GetArchitecture().GetMachine(), reg, register_kind);
138         if (reg_num == LLDB_INVALID_REGNUM)
139           return false;
140
141         if (reg_num > 31) {
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);
147         } else {
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);
152         }
153
154         if (relative_offset)
155           stream.PutSLEB128(*relative_offset);
156
157         return true;
158       });
159 }
160
161 DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression(
162     llvm::codeview::RegisterId reg, lldb::ModuleSP module) {
163   return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module);
164 }
165
166 DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression(
167     llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {
168   return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);
169 }
170
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,
175                                               stream);
176 }
177
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 &register_kind) -> bool {
182         const ArchSpec &architecture = module->GetArchitecture();
183
184         if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),
185                                                  stream))
186           return false;
187
188         stream.PutHex8(llvm::dwarf::DW_OP_consts);
189         stream.PutSLEB128(offset);
190         stream.PutHex8(llvm::dwarf::DW_OP_plus);
191
192         register_kind = eRegisterKindLLDB;
193
194         return true;
195       });
196 }
197
198 DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(
199     uint16_t section, uint32_t offset, ModuleSP module) {
200   assert(section > 0);
201   assert(module);
202
203   return MakeLocationExpressionInternal(
204       module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
205         stream.PutHex8(llvm::dwarf::DW_OP_addr);
206
207         SectionList *section_list = module->GetSectionList();
208         assert(section_list);
209
210         auto section_ptr = section_list->FindSectionByID(section);
211         if (!section_ptr)
212           return false;
213
214         stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,
215                            stream.GetAddressByteSize(), stream.GetByteOrder());
216
217         return true;
218       });
219 }
220
221 DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
222     TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,
223     ModuleSP module) {
224   const ArchSpec &architecture = module->GetArchitecture();
225   uint32_t address_size = architecture.GetAddressByteSize();
226
227   size_t size = 0;
228   bool is_signed = false;
229   std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);
230
231   union {
232     llvm::support::little64_t I;
233     llvm::support::ulittle64_t U;
234   } Value;
235
236   std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();
237   buffer->SetByteSize(size);
238
239   llvm::ArrayRef<uint8_t> bytes;
240   if (is_signed) {
241     Value.I = constant.getSExtValue();
242   } else {
243     Value.U = constant.getZExtValue();
244   }
245
246   bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)
247               .take_front(size);
248   buffer->CopyData(bytes.data(), size);
249   DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
250   DWARFExpression result(nullptr, extractor, nullptr, 0, size);
251   return result;
252 }