Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
39642 views
1
//===-- LibStdcpp.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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "LibStdcpp.h"
10
#include "LibCxx.h"
11
12
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
13
#include "lldb/Core/ValueObject.h"
14
#include "lldb/Core/ValueObjectConstResult.h"
15
#include "lldb/DataFormatters/StringPrinter.h"
16
#include "lldb/DataFormatters/VectorIterator.h"
17
#include "lldb/Target/Target.h"
18
#include "lldb/Utility/DataBufferHeap.h"
19
#include "lldb/Utility/Endian.h"
20
#include "lldb/Utility/Status.h"
21
#include "lldb/Utility/Stream.h"
22
#include <optional>
23
24
using namespace lldb;
25
using namespace lldb_private;
26
using namespace lldb_private::formatters;
27
28
namespace {
29
30
class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
31
/*
32
(std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char,
33
std::char_traits<char>, std::allocator<char> > > >) ibeg = {
34
(_Base_ptr) _M_node = 0x0000000100103910 {
35
(std::_Rb_tree_color) _M_color = _S_black
36
(std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
37
(std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
38
(std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
39
}
40
}
41
*/
42
43
public:
44
explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
45
46
llvm::Expected<uint32_t> CalculateNumChildren() override;
47
48
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
49
50
lldb::ChildCacheState Update() override;
51
52
bool MightHaveChildren() override;
53
54
size_t GetIndexOfChildWithName(ConstString name) override;
55
56
private:
57
ExecutionContextRef m_exe_ctx_ref;
58
lldb::addr_t m_pair_address = 0;
59
CompilerType m_pair_type;
60
lldb::ValueObjectSP m_pair_sp;
61
};
62
63
class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
64
public:
65
explicit LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
66
67
llvm::Expected<uint32_t> CalculateNumChildren() override;
68
69
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
70
71
lldb::ChildCacheState Update() override;
72
73
bool MightHaveChildren() override;
74
75
size_t GetIndexOfChildWithName(ConstString name) override;
76
private:
77
78
// The lifetime of a ValueObject and all its derivative ValueObjects
79
// (children, clones, etc.) is managed by a ClusterManager. These
80
// objects are only destroyed when every shared pointer to any of them
81
// is destroyed, so we must not store a shared pointer to any ValueObject
82
// derived from our backend ValueObject (since we're in the same cluster).
83
ValueObject* m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
84
ValueObject* m_obj_obj = nullptr; // Underlying object (held, not owned)
85
};
86
87
} // end of anonymous namespace
88
89
LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd(
90
lldb::ValueObjectSP valobj_sp)
91
: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type(),
92
m_pair_sp() {
93
if (valobj_sp)
94
Update();
95
}
96
97
lldb::ChildCacheState LibstdcppMapIteratorSyntheticFrontEnd::Update() {
98
ValueObjectSP valobj_sp = m_backend.GetSP();
99
if (!valobj_sp)
100
return lldb::ChildCacheState::eRefetch;
101
102
TargetSP target_sp(valobj_sp->GetTargetSP());
103
104
if (!target_sp)
105
return lldb::ChildCacheState::eRefetch;
106
107
bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
108
109
if (!valobj_sp)
110
return lldb::ChildCacheState::eRefetch;
111
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
112
113
ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName("_M_node"));
114
if (!_M_node_sp)
115
return lldb::ChildCacheState::eRefetch;
116
117
m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
118
if (m_pair_address == 0)
119
return lldb::ChildCacheState::eRefetch;
120
121
m_pair_address += (is_64bit ? 32 : 16);
122
123
CompilerType my_type(valobj_sp->GetCompilerType());
124
if (my_type.GetNumTemplateArguments() >= 1) {
125
CompilerType pair_type = my_type.GetTypeTemplateArgument(0);
126
if (!pair_type)
127
return lldb::ChildCacheState::eRefetch;
128
m_pair_type = pair_type;
129
} else
130
return lldb::ChildCacheState::eRefetch;
131
132
return lldb::ChildCacheState::eReuse;
133
}
134
135
llvm::Expected<uint32_t>
136
LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren() {
137
return 2;
138
}
139
140
lldb::ValueObjectSP
141
LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
142
if (m_pair_address != 0 && m_pair_type) {
143
if (!m_pair_sp)
144
m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address,
145
m_exe_ctx_ref, m_pair_type);
146
if (m_pair_sp)
147
return m_pair_sp->GetChildAtIndex(idx);
148
}
149
return lldb::ValueObjectSP();
150
}
151
152
bool LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
153
154
size_t LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
155
ConstString name) {
156
if (name == "first")
157
return 0;
158
if (name == "second")
159
return 1;
160
return UINT32_MAX;
161
}
162
163
SyntheticChildrenFrontEnd *
164
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator(
165
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
166
return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)
167
: nullptr);
168
}
169
170
/*
171
(lldb) fr var ibeg --ptr-depth 1
172
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >)
173
ibeg = {
174
_M_current = 0x00000001001037a0 {
175
*_M_current = 1
176
}
177
}
178
*/
179
180
SyntheticChildrenFrontEnd *
181
lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator(
182
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
183
return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(
184
valobj_sp, {ConstString("_M_current")})
185
: nullptr);
186
}
187
188
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::
189
VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp,
190
llvm::ArrayRef<ConstString> item_names)
191
: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
192
m_item_names(item_names), m_item_sp() {
193
if (valobj_sp)
194
Update();
195
}
196
197
lldb::ChildCacheState VectorIteratorSyntheticFrontEnd::Update() {
198
m_item_sp.reset();
199
200
ValueObjectSP valobj_sp = m_backend.GetSP();
201
if (!valobj_sp)
202
return lldb::ChildCacheState::eRefetch;
203
204
if (!valobj_sp)
205
return lldb::ChildCacheState::eRefetch;
206
207
ValueObjectSP item_ptr =
208
formatters::GetChildMemberWithName(*valobj_sp, m_item_names);
209
if (!item_ptr)
210
return lldb::ChildCacheState::eRefetch;
211
if (item_ptr->GetValueAsUnsigned(0) == 0)
212
return lldb::ChildCacheState::eRefetch;
213
Status err;
214
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
215
m_item_sp = CreateValueObjectFromAddress(
216
"item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref,
217
item_ptr->GetCompilerType().GetPointeeType());
218
if (err.Fail())
219
m_item_sp.reset();
220
return lldb::ChildCacheState::eRefetch;
221
}
222
223
llvm::Expected<uint32_t>
224
VectorIteratorSyntheticFrontEnd::CalculateNumChildren() {
225
return 1;
226
}
227
228
lldb::ValueObjectSP
229
VectorIteratorSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
230
if (idx == 0)
231
return m_item_sp;
232
return lldb::ValueObjectSP();
233
}
234
235
bool VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
236
237
size_t VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
238
ConstString name) {
239
if (name == "item")
240
return 0;
241
return UINT32_MAX;
242
}
243
244
bool lldb_private::formatters::LibStdcppStringSummaryProvider(
245
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
246
const bool scalar_is_load_addr = true;
247
AddressType addr_type;
248
lldb::addr_t addr_of_string = LLDB_INVALID_ADDRESS;
249
if (valobj.IsPointerOrReferenceType()) {
250
Status error;
251
ValueObjectSP pointee_sp = valobj.Dereference(error);
252
if (pointee_sp && error.Success())
253
addr_of_string = pointee_sp->GetAddressOf(scalar_is_load_addr, &addr_type);
254
} else
255
addr_of_string =
256
valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
257
if (addr_of_string != LLDB_INVALID_ADDRESS) {
258
switch (addr_type) {
259
case eAddressTypeLoad: {
260
ProcessSP process_sp(valobj.GetProcessSP());
261
if (!process_sp)
262
return false;
263
264
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
265
Status error;
266
lldb::addr_t addr_of_data =
267
process_sp->ReadPointerFromMemory(addr_of_string, error);
268
if (error.Fail() || addr_of_data == 0 ||
269
addr_of_data == LLDB_INVALID_ADDRESS)
270
return false;
271
options.SetLocation(addr_of_data);
272
options.SetTargetSP(valobj.GetTargetSP());
273
options.SetStream(&stream);
274
options.SetNeedsZeroTermination(false);
275
options.SetBinaryZeroIsTerminator(true);
276
lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
277
addr_of_string + process_sp->GetAddressByteSize(), error);
278
if (error.Fail())
279
return false;
280
options.SetSourceSize(size_of_data);
281
options.SetHasSourceSize(true);
282
283
if (!StringPrinter::ReadStringAndDumpToStream<
284
StringPrinter::StringElementType::UTF8>(options)) {
285
stream.Printf("Summary Unavailable");
286
return true;
287
} else
288
return true;
289
} break;
290
case eAddressTypeHost:
291
break;
292
case eAddressTypeInvalid:
293
case eAddressTypeFile:
294
break;
295
}
296
}
297
return false;
298
}
299
300
bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
301
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
302
const bool scalar_is_load_addr = true;
303
AddressType addr_type;
304
lldb::addr_t addr_of_string =
305
valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
306
if (addr_of_string != LLDB_INVALID_ADDRESS) {
307
switch (addr_type) {
308
case eAddressTypeLoad: {
309
ProcessSP process_sp(valobj.GetProcessSP());
310
if (!process_sp)
311
return false;
312
313
CompilerType wchar_compiler_type =
314
valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
315
316
if (!wchar_compiler_type)
317
return false;
318
319
// Safe to pass nullptr for exe_scope here.
320
std::optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
321
if (!size)
322
return false;
323
const uint32_t wchar_size = *size;
324
325
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
326
Status error;
327
lldb::addr_t addr_of_data =
328
process_sp->ReadPointerFromMemory(addr_of_string, error);
329
if (error.Fail() || addr_of_data == 0 ||
330
addr_of_data == LLDB_INVALID_ADDRESS)
331
return false;
332
options.SetLocation(addr_of_data);
333
options.SetTargetSP(valobj.GetTargetSP());
334
options.SetStream(&stream);
335
options.SetNeedsZeroTermination(false);
336
options.SetBinaryZeroIsTerminator(false);
337
lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
338
addr_of_string + process_sp->GetAddressByteSize(), error);
339
if (error.Fail())
340
return false;
341
options.SetSourceSize(size_of_data);
342
options.SetHasSourceSize(true);
343
options.SetPrefixToken("L");
344
345
switch (wchar_size) {
346
case 8:
347
return StringPrinter::ReadStringAndDumpToStream<
348
StringPrinter::StringElementType::UTF8>(options);
349
case 16:
350
return StringPrinter::ReadStringAndDumpToStream<
351
StringPrinter::StringElementType::UTF16>(options);
352
case 32:
353
return StringPrinter::ReadStringAndDumpToStream<
354
StringPrinter::StringElementType::UTF32>(options);
355
default:
356
stream.Printf("size for wchar_t is not valid");
357
return true;
358
}
359
return true;
360
} break;
361
case eAddressTypeHost:
362
break;
363
case eAddressTypeInvalid:
364
case eAddressTypeFile:
365
break;
366
}
367
}
368
return false;
369
}
370
371
LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(
372
lldb::ValueObjectSP valobj_sp)
373
: SyntheticChildrenFrontEnd(*valobj_sp) {
374
if (valobj_sp)
375
Update();
376
}
377
378
llvm::Expected<uint32_t>
379
LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() {
380
return 1;
381
}
382
383
lldb::ValueObjectSP
384
LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
385
if (idx == 0)
386
return m_ptr_obj->GetSP();
387
if (idx == 1) {
388
if (m_ptr_obj && !m_obj_obj) {
389
Status error;
390
ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
391
if (error.Success())
392
m_obj_obj = obj_obj->Clone(ConstString("object")).get();
393
}
394
if (m_obj_obj)
395
return m_obj_obj->GetSP();
396
}
397
return lldb::ValueObjectSP();
398
}
399
400
lldb::ChildCacheState LibStdcppSharedPtrSyntheticFrontEnd::Update() {
401
auto backend = m_backend.GetSP();
402
if (!backend)
403
return lldb::ChildCacheState::eRefetch;
404
405
auto valobj_sp = backend->GetNonSyntheticValue();
406
if (!valobj_sp)
407
return lldb::ChildCacheState::eRefetch;
408
409
auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("_M_ptr");
410
if (!ptr_obj_sp)
411
return lldb::ChildCacheState::eRefetch;
412
413
m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
414
m_obj_obj = nullptr;
415
416
return lldb::ChildCacheState::eRefetch;
417
}
418
419
bool LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() { return true; }
420
421
size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
422
ConstString name) {
423
if (name == "pointer")
424
return 0;
425
if (name == "object" || name == "$$dereference$$")
426
return 1;
427
return UINT32_MAX;
428
}
429
430
SyntheticChildrenFrontEnd *
431
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
432
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
433
return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp)
434
: nullptr);
435
}
436
437
bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
438
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
439
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
440
if (!valobj_sp)
441
return false;
442
443
ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("_M_ptr"));
444
if (!ptr_sp)
445
return false;
446
447
ValueObjectSP usecount_sp(
448
valobj_sp->GetChildAtNamePath({"_M_refcount", "_M_pi", "_M_use_count"}));
449
if (!usecount_sp)
450
return false;
451
452
if (ptr_sp->GetValueAsUnsigned(0) == 0 ||
453
usecount_sp->GetValueAsUnsigned(0) == 0) {
454
stream.Printf("nullptr");
455
return true;
456
}
457
458
Status error;
459
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
460
if (pointee_sp && error.Success()) {
461
if (pointee_sp->DumpPrintableRepresentation(
462
stream, ValueObject::eValueObjectRepresentationStyleSummary,
463
lldb::eFormatInvalid,
464
ValueObject::PrintableRepresentationSpecialCases::eDisable,
465
false)) {
466
return true;
467
}
468
}
469
470
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
471
return true;
472
}
473
474