Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LibCxx.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 "LibCxx.h"
10
11
#include "lldb/Core/Debugger.h"
12
#include "lldb/Core/FormatEntity.h"
13
#include "lldb/Core/ValueObject.h"
14
#include "lldb/Core/ValueObjectConstResult.h"
15
#include "lldb/DataFormatters/FormattersHelpers.h"
16
#include "lldb/DataFormatters/StringPrinter.h"
17
#include "lldb/DataFormatters/TypeSummary.h"
18
#include "lldb/DataFormatters/VectorIterator.h"
19
#include "lldb/Target/SectionLoadList.h"
20
#include "lldb/Target/Target.h"
21
#include "lldb/Utility/ConstString.h"
22
#include "lldb/Utility/DataBufferHeap.h"
23
#include "lldb/Utility/Endian.h"
24
#include "lldb/Utility/Status.h"
25
#include "lldb/Utility/Stream.h"
26
27
#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
28
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
29
#include "lldb/lldb-enumerations.h"
30
#include <optional>
31
#include <tuple>
32
33
using namespace lldb;
34
using namespace lldb_private;
35
using namespace lldb_private::formatters;
36
37
lldb::ValueObjectSP lldb_private::formatters::GetChildMemberWithName(
38
606
    ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) {
39
662
  for (ConstString name : alternative_names) {
40
662
    lldb::ValueObjectSP child_sp = obj.GetChildMemberWithName(name);
41
42
662
    if (child_sp)
43
550
      return child_sp;
44
662
  }
45
56
  return {};
46
606
}
47
48
lldb::ValueObjectSP
49
lldb_private::formatters::GetFirstValueOfLibCXXCompressedPair(
50
196
    ValueObject &pair) {
51
196
  ValueObjectSP value;
52
196
  ValueObjectSP first_child = pair.GetChildAtIndex(0);
53
196
  if (first_child)
54
196
    value = first_child->GetChildMemberWithName("__value_");
55
196
  if (!value) {
56
    // pre-r300140 member name
57
0
    value = pair.GetChildMemberWithName("__first_");
58
0
  }
59
196
  return value;
60
196
}
61
62
lldb::ValueObjectSP
63
lldb_private::formatters::GetSecondValueOfLibCXXCompressedPair(
64
36
    ValueObject &pair) {
65
36
  ValueObjectSP value;
66
36
  if (pair.GetNumChildren() > 1) {
67
4
    ValueObjectSP second_child = pair.GetChildAtIndex(1);
68
4
    if (second_child) {
69
4
      value = second_child->GetChildMemberWithName("__value_");
70
4
    }
71
4
  }
72
36
  if (!value) {
73
    // pre-r300140 member name
74
32
    value = pair.GetChildMemberWithName("__second_");
75
32
  }
76
36
  return value;
77
36
}
78
79
bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
80
20
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
81
82
20
  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
83
84
20
  if (!valobj_sp)
85
0
    return false;
86
87
20
  ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
88
20
  Process *process = exe_ctx.GetProcessPtr();
89
90
20
  if (process == nullptr)
91
0
    return false;
92
93
20
  CPPLanguageRuntime *cpp_runtime = CPPLanguageRuntime::Get(*process);
94
95
20
  if (!cpp_runtime)
96
0
    return false;
97
98
20
  CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
99
20
      cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
100
101
20
  switch (callable_info.callable_case) {
102
0
  case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid:
103
0
    stream.Printf(" __f_ = %" PRIu64, callable_info.member_f_pointer_value);
104
0
    return false;
105
0
    break;
106
16
  case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda:
107
16
    stream.Printf(
108
16
        " Lambda in File %s at Line %u",
109
16
        callable_info.callable_line_entry.file.GetFilename().GetCString(),
110
16
        callable_info.callable_line_entry.line);
111
16
    break;
112
0
  case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject:
113
0
    stream.Printf(
114
0
        " Function in File %s at Line %u",
115
0
        callable_info.callable_line_entry.file.GetFilename().GetCString(),
116
0
        callable_info.callable_line_entry.line);
117
0
    break;
118
4
  case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction:
119
4
    stream.Printf(" Function = %s ",
120
4
                  callable_info.callable_symbol.GetName().GetCString());
121
4
    break;
122
20
  }
123
124
20
  return true;
125
20
}
126
127
bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
128
75
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
129
75
  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
130
75
  if (!valobj_sp)
131
0
    return false;
132
75
  ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
133
75
  ValueObjectSP count_sp(
134
75
      valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_owners_"}));
135
75
  ValueObjectSP weakcount_sp(
136
75
      valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_weak_owners_"}));
137
138
75
  if (!ptr_sp)
139
0
    return false;
140
141
75
  if (ptr_sp->GetValueAsUnsigned(0) == 0) {
142
8
    stream.Printf("nullptr");
143
8
    return true;
144
67
  } else {
145
67
    bool print_pointee = false;
146
67
    Status error;
147
67
    ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
148
67
    if (pointee_sp && 
error.Success()66
) {
149
66
      if (pointee_sp->DumpPrintableRepresentation(
150
66
              stream, ValueObject::eValueObjectRepresentationStyleSummary,
151
66
              lldb::eFormatInvalid,
152
66
              ValueObject::PrintableRepresentationSpecialCases::eDisable,
153
66
              false))
154
66
        print_pointee = true;
155
66
    }
156
67
    if (!print_pointee)
157
1
      stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
158
67
  }
159
160
67
  if (count_sp)
161
67
    stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
162
163
67
  if (weakcount_sp)
164
67
    stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
165
166
67
  return true;
167
75
}
168
169
bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
170
68
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
171
68
  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
172
68
  if (!valobj_sp)
173
0
    return false;
174
175
68
  ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
176
68
  if (!ptr_sp)
177
0
    return false;
178
179
68
  ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp);
180
68
  if (!ptr_sp)
181
0
    return false;
182
183
68
  if (ptr_sp->GetValueAsUnsigned(0) == 0) {
184
8
    stream.Printf("nullptr");
185
8
    return true;
186
60
  } else {
187
60
    bool print_pointee = false;
188
60
    Status error;
189
60
    ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
190
60
    if (pointee_sp && error.Success()) {
191
60
      if (pointee_sp->DumpPrintableRepresentation(
192
60
              stream, ValueObject::eValueObjectRepresentationStyleSummary,
193
60
              lldb::eFormatInvalid,
194
60
              ValueObject::PrintableRepresentationSpecialCases::eDisable,
195
60
              false))
196
60
        print_pointee = true;
197
60
    }
198
60
    if (!print_pointee)
199
0
      stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
200
60
  }
201
202
60
  return true;
203
68
}
204
205
/*
206
 (lldb) fr var ibeg --raw --ptr-depth 1
207
 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
208
 std::__1::basic_string<char, std::__1::char_traits<char>,
209
 std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
210
 std::__1::basic_string<char, std::__1::char_traits<char>,
211
 std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
212
 __i_ = {
213
 __ptr_ = 0x0000000100103870 {
214
 std::__1::__tree_node_base<void *> = {
215
 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
216
 __left_ = 0x0000000000000000
217
 }
218
 __right_ = 0x0000000000000000
219
 __parent_ = 0x00000001001038b0
220
 __is_black_ = true
221
 }
222
 __value_ = {
223
 first = 0
224
 second = { std::string }
225
 */
226
227
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
228
    LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
229
12
    : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
230
12
  if (valobj_sp)
231
12
    Update();
232
12
}
233
234
24
bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
235
24
  m_pair_sp.reset();
236
24
  m_pair_ptr = nullptr;
237
238
24
  ValueObjectSP valobj_sp = m_backend.GetSP();
239
24
  if (!valobj_sp)
240
0
    return false;
241
242
24
  TargetSP target_sp(valobj_sp->GetTargetSP());
243
244
24
  if (!target_sp)
245
0
    return false;
246
247
24
  if (!valobj_sp)
248
0
    return false;
249
250
  // this must be a ValueObject* because it is a child of the ValueObject we
251
  // are producing children for it if were a ValueObjectSP, we would end up
252
  // with a loop (iterator -> synthetic -> child -> parent == iterator) and
253
  // that would in turn leak memory by never allowing the ValueObjects to die
254
  // and free their memory
255
24
  m_pair_ptr = valobj_sp
256
24
                   ->GetValueForExpressionPath(
257
24
                       ".__i_.__ptr_->__value_", nullptr, nullptr,
258
24
                       ValueObject::GetValueForExpressionPathOptions()
259
24
                           .DontCheckDotVsArrowSyntax()
260
24
                           .SetSyntheticChildrenTraversal(
261
24
                               ValueObject::GetValueForExpressionPathOptions::
262
24
                                   SyntheticChildrenTraversal::None),
263
24
                       nullptr)
264
24
                   .get();
265
266
24
  if (!m_pair_ptr) {
267
24
    m_pair_ptr = valobj_sp
268
24
                     ->GetValueForExpressionPath(
269
24
                         ".__i_.__ptr_", nullptr, nullptr,
270
24
                         ValueObject::GetValueForExpressionPathOptions()
271
24
                             .DontCheckDotVsArrowSyntax()
272
24
                             .SetSyntheticChildrenTraversal(
273
24
                                 ValueObject::GetValueForExpressionPathOptions::
274
24
                                     SyntheticChildrenTraversal::None),
275
24
                         nullptr)
276
24
                     .get();
277
24
    if (m_pair_ptr) {
278
24
      auto __i_(valobj_sp->GetChildMemberWithName("__i_"));
279
24
      if (!__i_) {
280
0
        m_pair_ptr = nullptr;
281
0
        return false;
282
0
      }
283
24
      CompilerType pair_type(
284
24
          __i_->GetCompilerType().GetTypeTemplateArgument(0));
285
24
      std::string name;
286
24
      uint64_t bit_offset_ptr;
287
24
      uint32_t bitfield_bit_size_ptr;
288
24
      bool is_bitfield_ptr;
289
24
      pair_type = pair_type.GetFieldAtIndex(
290
24
          0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
291
24
      if (!pair_type) {
292
0
        m_pair_ptr = nullptr;
293
0
        return false;
294
0
      }
295
296
24
      auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
297
24
      m_pair_ptr = nullptr;
298
24
      if (addr && addr != LLDB_INVALID_ADDRESS) {
299
24
        auto ts = pair_type.GetTypeSystem();
300
24
        auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
301
24
        if (!ast_ctx)
302
0
          return false;
303
304
        // Mimick layout of std::__tree_iterator::__ptr_ and read it in
305
        // from process memory.
306
        //
307
        // The following shows the contiguous block of memory:
308
        //
309
        //        +-----------------------------+ class __tree_end_node
310
        // __ptr_ | pointer __left_;            |
311
        //        +-----------------------------+ class __tree_node_base
312
        //        | pointer __right_;           |
313
        //        | __parent_pointer __parent_; |
314
        //        | bool __is_black_;           |
315
        //        +-----------------------------+ class __tree_node
316
        //        | __node_value_type __value_; | <<< our key/value pair
317
        //        +-----------------------------+
318
        //
319
24
        CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
320
24
            llvm::StringRef(),
321
24
            {{"ptr0",
322
24
              ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
323
24
             {"ptr1",
324
24
              ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
325
24
             {"ptr2",
326
24
              ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
327
24
             {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
328
24
             {"payload", pair_type}});
329
24
        std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
330
24
        if (!size)
331
0
          return false;
332
24
        WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
333
24
        ProcessSP process_sp(target_sp->GetProcessSP());
334
24
        Status error;
335
24
        process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
336
24
                               buffer_sp->GetByteSize(), error);
337
24
        if (error.Fail())
338
0
          return false;
339
24
        DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
340
24
                                process_sp->GetAddressByteSize());
341
24
        auto pair_sp = CreateValueObjectFromData(
342
24
            "pair", extractor, valobj_sp->GetExecutionContextRef(),
343
24
            tree_node_type);
344
24
        if (pair_sp)
345
24
          m_pair_sp = pair_sp->GetChildAtIndex(4);
346
24
      }
347
24
    }
348
24
  }
349
350
24
  return false;
351
24
}
352
353
size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
354
12
    CalculateNumChildren() {
355
12
  return 2;
356
12
}
357
358
lldb::ValueObjectSP
359
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
360
24
    size_t idx) {
361
24
  if (m_pair_ptr)
362
0
    return m_pair_ptr->GetChildAtIndex(idx);
363
24
  if (m_pair_sp)
364
24
    return m_pair_sp->GetChildAtIndex(idx);
365
0
  return lldb::ValueObjectSP();
366
24
}
367
368
bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
369
0
    MightHaveChildren() {
370
0
  return true;
371
0
}
372
373
size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
374
0
    GetIndexOfChildWithName(ConstString name) {
375
0
  if (name == "first")
376
0
    return 0;
377
0
  if (name == "second")
378
0
    return 1;
379
0
  return UINT32_MAX;
380
0
}
381
382
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
383
12
    ~LibCxxMapIteratorSyntheticFrontEnd() {
384
  // this will be deleted when its parent dies (since it's a child object)
385
  // delete m_pair_ptr;
386
12
}
387
388
SyntheticChildrenFrontEnd *
389
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
390
12
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
391
12
  return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
392
12
                    : 
nullptr0
);
393
12
}
394
395
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
396
    LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
397
14
    : SyntheticChildrenFrontEnd(*valobj_sp) {
398
14
  if (valobj_sp)
399
14
    Update();
400
14
}
401
402
bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
403
28
    Update() {
404
28
  m_pair_sp.reset();
405
28
  m_iter_ptr = nullptr;
406
407
28
  ValueObjectSP valobj_sp = m_backend.GetSP();
408
28
  if (!valobj_sp)
409
0
    return false;
410
411
28
  TargetSP target_sp(valobj_sp->GetTargetSP());
412
413
28
  if (!target_sp)
414
0
    return false;
415
416
28
  if (!valobj_sp)
417
0
    return false;
418
419
28
  auto exprPathOptions = ValueObject::GetValueForExpressionPathOptions()
420
28
                             .DontCheckDotVsArrowSyntax()
421
28
                             .SetSyntheticChildrenTraversal(
422
28
                                 ValueObject::GetValueForExpressionPathOptions::
423
28
                                     SyntheticChildrenTraversal::None);
424
425
  // This must be a ValueObject* because it is a child of the ValueObject we
426
  // are producing children for it if were a ValueObjectSP, we would end up
427
  // with a loop (iterator -> synthetic -> child -> parent == iterator) and
428
  // that would in turn leak memory by never allowing the ValueObjects to die
429
  // and free their memory.
430
28
  m_iter_ptr =
431
28
      valobj_sp
432
28
          ->GetValueForExpressionPath(".__i_.__node_", nullptr, nullptr,
433
28
                                      exprPathOptions, nullptr)
434
28
          .get();
435
436
28
  if (m_iter_ptr) {
437
28
    auto iter_child(valobj_sp->GetChildMemberWithName("__i_"));
438
28
    if (!iter_child) {
439
0
      m_iter_ptr = nullptr;
440
0
      return false;
441
0
    }
442
443
28
    CompilerType node_type(iter_child->GetCompilerType()
444
28
                               .GetTypeTemplateArgument(0)
445
28
                               .GetPointeeType());
446
447
28
    CompilerType pair_type(node_type.GetTypeTemplateArgument(0));
448
449
28
    std::string name;
450
28
    uint64_t bit_offset_ptr;
451
28
    uint32_t bitfield_bit_size_ptr;
452
28
    bool is_bitfield_ptr;
453
454
28
    pair_type = pair_type.GetFieldAtIndex(
455
28
        0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
456
28
    if (!pair_type) {
457
0
      m_iter_ptr = nullptr;
458
0
      return false;
459
0
    }
460
461
28
    uint64_t addr = m_iter_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
462
28
    m_iter_ptr = nullptr;
463
464
28
    if (addr == 0 || 
addr == 16
LLDB_INVALID_ADDRESS16
)
465
12
      return false;
466
467
16
    auto ts = pair_type.GetTypeSystem();
468
16
    auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
469
16
    if (!ast_ctx)
470
0
      return false;
471
472
    // Mimick layout of std::__hash_iterator::__node_ and read it in
473
    // from process memory.
474
    //
475
    // The following shows the contiguous block of memory:
476
    //
477
    //         +-----------------------------+ class __hash_node_base
478
    // __node_ | __next_pointer __next_;     |
479
    //         +-----------------------------+ class __hash_node
480
    //         | size_t __hash_;             |
481
    //         | __node_value_type __value_; | <<< our key/value pair
482
    //         +-----------------------------+
483
    //
484
16
    CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
485
16
        llvm::StringRef(),
486
16
        {{"__next_",
487
16
          ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
488
16
         {"__hash_", ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedLongLong)},
489
16
         {"__value_", pair_type}});
490
16
    std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
491
16
    if (!size)
492
0
      return false;
493
16
    WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
494
16
    ProcessSP process_sp(target_sp->GetProcessSP());
495
16
    Status error;
496
16
    process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
497
16
                           buffer_sp->GetByteSize(), error);
498
16
    if (error.Fail())
499
0
      return false;
500
16
    DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
501
16
                            process_sp->GetAddressByteSize());
502
16
    auto pair_sp = CreateValueObjectFromData(
503
16
        "pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
504
16
    if (pair_sp)
505
16
      m_pair_sp = pair_sp->GetChildAtIndex(2);
506
16
  }
507
508
16
  return false;
509
28
}
510
511
size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
512
14
    CalculateNumChildren() {
513
14
  return 2;
514
14
}
515
516
lldb::ValueObjectSP lldb_private::formatters::
517
52
    LibCxxUnorderedMapIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
518
52
  if (m_pair_sp)
519
16
    return m_pair_sp->GetChildAtIndex(idx);
520
36
  return lldb::ValueObjectSP();
521
52
}
522
523
bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
524
6
    MightHaveChildren() {
525
6
  return true;
526
6
}
527
528
size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
529
0
    GetIndexOfChildWithName(ConstString name) {
530
0
  if (name == "first")
531
0
    return 0;
532
0
  if (name == "second")
533
0
    return 1;
534
0
  return UINT32_MAX;
535
0
}
536
537
SyntheticChildrenFrontEnd *
538
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(
539
14
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
540
14
  return (valobj_sp ? new LibCxxUnorderedMapIteratorSyntheticFrontEnd(valobj_sp)
541
14
                    : 
nullptr0
);
542
14
}
543
544
/*
545
 (lldb) fr var ibeg --raw --ptr-depth 1 -T
546
 (std::__1::__wrap_iter<int *>) ibeg = {
547
 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
548
 (int) *__i = 1
549
 }
550
 }
551
*/
552
553
SyntheticChildrenFrontEnd *
554
lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
555
14
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
556
14
  return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(
557
14
                          valobj_sp, {ConstString("__i_"), ConstString("__i")})
558
14
                    : 
nullptr0
);
559
14
}
560
561
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
562
    LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
563
22
    : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
564
22
  if (valobj_sp)
565
22
    Update();
566
22
}
567
568
size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
569
21
    CalculateNumChildren() {
570
21
  return (m_cntrl ? 1 : 
00
);
571
21
}
572
573
lldb::ValueObjectSP
574
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
575
26
    size_t idx) {
576
26
  if (!m_cntrl)
577
0
    return lldb::ValueObjectSP();
578
579
26
  ValueObjectSP valobj_sp = m_backend.GetSP();
580
26
  if (!valobj_sp)
581
0
    return lldb::ValueObjectSP();
582
583
26
  if (idx == 0)
584
21
    return valobj_sp->GetChildMemberWithName("__ptr_");
585
586
5
  if (idx == 1) {
587
5
    if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
588
5
      Status status;
589
5
      auto value_type_sp =
590
5
            valobj_sp->GetCompilerType()
591
5
              .GetTypeTemplateArgument(0).GetPointerType();
592
5
      ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
593
5
      ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
594
5
      if (status.Success()) {
595
5
        return value_sp;
596
5
      }
597
5
    }
598
5
  }
599
600
0
  return lldb::ValueObjectSP();
601
5
}
602
603
44
bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
604
44
  m_cntrl = nullptr;
605
606
44
  ValueObjectSP valobj_sp = m_backend.GetSP();
607
44
  if (!valobj_sp)
608
0
    return false;
609
610
44
  TargetSP target_sp(valobj_sp->GetTargetSP());
611
44
  if (!target_sp)
612
0
    return false;
613
614
44
  lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
615
616
44
  m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
617
                            // dependency
618
44
  return false;
619
44
}
620
621
bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
622
1
    MightHaveChildren() {
623
1
  return true;
624
1
}
625
626
size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
627
5
    GetIndexOfChildWithName(ConstString name) {
628
5
  if (name == "__ptr_")
629
0
    return 0;
630
5
  if (name == "$$dereference$$")
631
5
    return 1;
632
0
  return UINT32_MAX;
633
5
}
634
635
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
636
22
    ~LibcxxSharedPtrSyntheticFrontEnd() = default;
637
638
SyntheticChildrenFrontEnd *
639
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
640
22
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
641
22
  return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
642
22
                    : 
nullptr0
);
643
22
}
644
645
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
646
    LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
647
18
    : SyntheticChildrenFrontEnd(*valobj_sp) {
648
18
  if (valobj_sp)
649
18
    Update();
650
18
}
651
652
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
653
0
    ~LibcxxUniquePtrSyntheticFrontEnd() = default;
654
655
SyntheticChildrenFrontEnd *
656
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
657
18
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
658
18
  return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
659
18
                    : 
nullptr0
);
660
18
}
661
662
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
663
18
    CalculateNumChildren() {
664
18
  if (m_value_ptr_sp)
665
18
    return m_deleter_sp ? 
22
:
116
;
666
0
  return 0;
667
18
}
668
669
lldb::ValueObjectSP
670
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
671
24
    size_t idx) {
672
24
  if (!m_value_ptr_sp)
673
0
    return lldb::ValueObjectSP();
674
675
24
  if (idx == 0)
676
18
    return m_value_ptr_sp;
677
678
6
  if (idx == 1)
679
2
    return m_deleter_sp;
680
681
4
  if (idx == 2) {
682
4
    Status status;
683
4
    auto value_sp = m_value_ptr_sp->Dereference(status);
684
4
    if (status.Success()) {
685
4
      return value_sp;
686
4
    }
687
4
  }
688
689
0
  return lldb::ValueObjectSP();
690
4
}
691
692
36
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
693
36
  ValueObjectSP valobj_sp = m_backend.GetSP();
694
36
  if (!valobj_sp)
695
0
    return false;
696
697
36
  ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
698
36
  if (!ptr_sp)
699
0
    return false;
700
701
  // Retrieve the actual pointer and the deleter, and clone them to give them
702
  // user-friendly names.
703
36
  ValueObjectSP value_pointer_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp);
704
36
  if (value_pointer_sp)
705
36
    m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer"));
706
707
36
  ValueObjectSP deleter_sp = GetSecondValueOfLibCXXCompressedPair(*ptr_sp);
708
36
  if (deleter_sp)
709
4
    m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
710
711
36
  return false;
712
36
}
713
714
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
715
0
    MightHaveChildren() {
716
0
  return true;
717
0
}
718
719
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
720
4
    GetIndexOfChildWithName(ConstString name) {
721
4
  if (name == "pointer")
722
0
    return 0;
723
4
  if (name == "deleter")
724
0
    return 1;
725
4
  if (name == "$$dereference$$")
726
4
    return 2;
727
0
  return UINT32_MAX;
728
4
}
729
730
bool lldb_private::formatters::LibcxxContainerSummaryProvider(
731
817
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
732
817
  if (valobj.IsPointerType()) {
733
52
    uint64_t value = valobj.GetValueAsUnsigned(0);
734
52
    if (!value)
735
0
      return false;
736
52
    stream.Printf("0x%016" PRIx64 " ", value);
737
52
  }
738
817
  return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
739
817
                                       nullptr, nullptr, &valobj, false, false);
740
817
}
741
742
/// The field layout in a libc++ string (cap, side, data or data, size, cap).
743
namespace {
744
enum class StringLayout { CSD, DSC };
745
}
746
747
/// Determine the size in bytes of \p valobj (a libc++ std::string object) and
748
/// extract its data payload. Return the size + payload pair.
749
// TODO: Support big-endian architectures.
750
static std::optional<std::pair<uint64_t, ValueObjectSP>>
751
1.08k
ExtractLibcxxStringInfo(ValueObject &valobj) {
752
1.08k
  ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName("__r_");
753
1.08k
  if (!valobj_r_sp || !valobj_r_sp->GetError().Success())
754
2
    return {};
755
756
  // __r_ is a compressed_pair of the actual data and the allocator. The data we
757
  // want is in the first base class.
758
1.08k
  ValueObjectSP valobj_r_base_sp = valobj_r_sp->GetChildAtIndex(0);
759
1.08k
  if (!valobj_r_base_sp)
760
0
    return {};
761
762
1.08k
  ValueObjectSP valobj_rep_sp =
763
1.08k
      valobj_r_base_sp->GetChildMemberWithName("__value_");
764
1.08k
  if (!valobj_rep_sp)
765
0
    return {};
766
767
1.08k
  ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l");
768
1.08k
  if (!l)
769
0
    return {};
770
771
1.08k
  StringLayout layout = l->GetIndexOfChildWithName("__data_") == 0
772
1.08k
                            ? 
StringLayout::DSC30
773
1.08k
                            : 
StringLayout::CSD1.05k
;
774
775
1.08k
  bool short_mode = false; // this means the string is in short-mode and the
776
                           // data is stored inline
777
1.08k
  bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
778
                              // flag (pre-D123580).
779
1.08k
  uint64_t size;
780
1.08k
  uint64_t size_mode_value = 0;
781
782
1.08k
  ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName("__s");
783
1.08k
  if (!short_sp)
784
0
    return {};
785
786
1.08k
  ValueObjectSP is_long = short_sp->GetChildMemberWithName("__is_long_");
787
1.08k
  ValueObjectSP size_sp = short_sp->GetChildMemberWithName("__size_");
788
1.08k
  if (!size_sp)
789
0
    return {};
790
791
1.08k
  if (is_long) {
792
1.06k
    using_bitmasks = false;
793
1.06k
    short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
794
1.06k
    size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
795
1.06k
  } else {
796
    // The string mode is encoded in the size field.
797
24
    size_mode_value = size_sp->GetValueAsUnsigned(0);
798
24
    uint8_t mode_mask = layout == StringLayout::DSC ? 
0x8012
:
112
;
799
24
    short_mode = (size_mode_value & mode_mask) == 0;
800
24
  }
801
802
1.08k
  if (short_mode) {
803
944
    ValueObjectSP location_sp = short_sp->GetChildMemberWithName("__data_");
804
944
    if (using_bitmasks)
805
12
      size = (layout == StringLayout::DSC) ? 
size_mode_value6
806
12
                                           : 
((size_mode_value >> 1) % 256)6
;
807
808
    // When the small-string optimization takes place, the data must fit in the
809
    // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
810
    // likely that the string isn't initialized and we're reading garbage.
811
944
    ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
812
944
    const std::optional<uint64_t> max_bytes =
813
944
        location_sp->GetCompilerType().GetByteSize(
814
944
            exe_ctx.GetBestExecutionContextScope());
815
944
    if (!max_bytes || size > *max_bytes || 
!location_sp934
)
816
10
      return {};
817
818
934
    return std::make_pair(size, location_sp);
819
944
  }
820
821
  // we can use the layout_decider object as the data pointer
822
142
  ValueObjectSP location_sp = l->GetChildMemberWithName("__data_");
823
142
  ValueObjectSP size_vo = l->GetChildMemberWithName("__size_");
824
142
  ValueObjectSP capacity_vo = l->GetChildMemberWithName("__cap_");
825
142
  if (!size_vo || !location_sp || !capacity_vo)
826
0
    return {};
827
142
  size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
828
142
  uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
829
142
  if (!using_bitmasks && 
layout == StringLayout::CSD130
)
830
121
    capacity *= 2;
831
142
  if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
832
142
      capacity < size)
833
6
    return {};
834
136
  return std::make_pair(size, location_sp);
835
142
}
836
837
static bool
838
LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream,
839
                             const TypeSummaryOptions &summary_options,
840
76
                             ValueObjectSP location_sp, size_t size) {
841
76
  if (size == 0) {
842
16
    stream.Printf("L\"\"");
843
16
    return true;
844
16
  }
845
60
  if (!location_sp)
846
0
    return false;
847
848
60
  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
849
60
  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
850
60
    const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
851
60
    if (size > max_size) {
852
0
      size = max_size;
853
0
      options.SetIsTruncated(true);
854
0
    }
855
60
  }
856
857
60
  DataExtractor extractor;
858
60
  const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
859
60
  if (bytes_read < size)
860
0
    return false;
861
862
  // std::wstring::size() is measured in 'characters', not bytes
863
60
  TypeSystemClangSP scratch_ts_sp =
864
60
      ScratchTypeSystemClang::GetForTarget(*valobj.GetTargetSP());
865
60
  if (!scratch_ts_sp)
866
0
    return false;
867
868
60
  auto wchar_t_size =
869
60
      scratch_ts_sp->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
870
60
  if (!wchar_t_size)
871
0
    return false;
872
873
60
  options.SetData(std::move(extractor));
874
60
  options.SetStream(&stream);
875
60
  options.SetPrefixToken("L");
876
60
  options.SetQuote('"');
877
60
  options.SetSourceSize(size);
878
60
  options.SetBinaryZeroIsTerminator(false);
879
880
60
  switch (*wchar_t_size) {
881
0
  case 1:
882
0
    return StringPrinter::ReadBufferAndDumpToStream<
883
0
        lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
884
0
        options);
885
0
    break;
886
887
0
  case 2:
888
0
    return StringPrinter::ReadBufferAndDumpToStream<
889
0
        lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
890
0
        options);
891
0
    break;
892
893
60
  case 4:
894
60
    return StringPrinter::ReadBufferAndDumpToStream<
895
60
        lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
896
60
        options);
897
60
  }
898
0
  return false;
899
60
}
900
901
bool lldb_private::formatters::LibcxxWStringSummaryProvider(
902
    ValueObject &valobj, Stream &stream,
903
22
    const TypeSummaryOptions &summary_options) {
904
22
  auto string_info = ExtractLibcxxStringInfo(valobj);
905
22
  if (!string_info)
906
0
    return false;
907
22
  uint64_t size;
908
22
  ValueObjectSP location_sp;
909
22
  std::tie(size, location_sp) = *string_info;
910
911
22
  return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
912
22
                                        location_sp, size);
913
22
}
914
915
template <StringPrinter::StringElementType element_type>
916
static bool
917
LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
918
                            const TypeSummaryOptions &summary_options,
919
                            std::string prefix_token, ValueObjectSP location_sp,
920
1.15k
                            uint64_t size) {
921
922
1.15k
  if (size == 0) {
923
58
    stream.Printf("\"\"");
924
58
    return true;
925
58
  }
926
927
1.09k
  if (!location_sp)
928
0
    return false;
929
930
1.09k
  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
931
932
1.09k
  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
933
1.09k
    const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
934
1.09k
    if (size > max_size) {
935
12
      size = max_size;
936
12
      options.SetIsTruncated(true);
937
12
    }
938
1.09k
  }
939
940
1.09k
  {
941
1.09k
    DataExtractor extractor;
942
1.09k
    const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
943
1.09k
    if (bytes_read < size)
944
6
      return false;
945
946
1.09k
    options.SetData(std::move(extractor));
947
1.09k
  }
948
0
  options.SetStream(&stream);
949
1.09k
  if (prefix_token.empty())
950
1.05k
    options.SetPrefixToken(nullptr);
951
32
  else
952
32
    options.SetPrefixToken(prefix_token);
953
1.09k
  options.SetQuote('"');
954
1.09k
  options.SetSourceSize(size);
955
1.09k
  options.SetBinaryZeroIsTerminator(false);
956
1.09k
  return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
957
1.09k
}
LibCxx.cpp:bool LibcxxStringSummaryProvider<(lldb_private::formatters::StringPrinter::StringElementType)0>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::shared_ptr<lldb_private::ValueObject>, unsigned long long)
Line
Count
Source
920
1.09k
                            uint64_t size) {
921
922
1.09k
  if (size == 0) {
923
26
    stream.Printf("\"\"");
924
26
    return true;
925
26
  }
926
927
1.06k
  if (!location_sp)
928
0
    return false;
929
930
1.06k
  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
931
932
1.06k
  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
933
1.06k
    const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
934
1.06k
    if (size > max_size) {
935
12
      size = max_size;
936
12
      options.SetIsTruncated(true);
937
12
    }
938
1.06k
  }
939
940
1.06k
  {
941
1.06k
    DataExtractor extractor;
942
1.06k
    const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
943
1.06k
    if (bytes_read < size)
944
6
      return false;
945
946
1.05k
    options.SetData(std::move(extractor));
947
1.05k
  }
948
0
  options.SetStream(&stream);
949
1.05k
  if (prefix_token.empty())
950
1.05k
    options.SetPrefixToken(nullptr);
951
0
  else
952
0
    options.SetPrefixToken(prefix_token);
953
1.05k
  options.SetQuote('"');
954
1.05k
  options.SetSourceSize(size);
955
1.05k
  options.SetBinaryZeroIsTerminator(false);
956
1.05k
  return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
957
1.06k
}
LibCxx.cpp:bool LibcxxStringSummaryProvider<(lldb_private::formatters::StringPrinter::StringElementType)2>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::shared_ptr<lldb_private::ValueObject>, unsigned long long)
Line
Count
Source
920
32
                            uint64_t size) {
921
922
32
  if (size == 0) {
923
16
    stream.Printf("\"\"");
924
16
    return true;
925
16
  }
926
927
16
  if (!location_sp)
928
0
    return false;
929
930
16
  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
931
932
16
  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
933
16
    const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
934
16
    if (size > max_size) {
935
0
      size = max_size;
936
0
      options.SetIsTruncated(true);
937
0
    }
938
16
  }
939
940
16
  {
941
16
    DataExtractor extractor;
942
16
    const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
943
16
    if (bytes_read < size)
944
0
      return false;
945
946
16
    options.SetData(std::move(extractor));
947
16
  }
948
0
  options.SetStream(&stream);
949
16
  if (prefix_token.empty())
950
0
    options.SetPrefixToken(nullptr);
951
16
  else
952
16
    options.SetPrefixToken(prefix_token);
953
16
  options.SetQuote('"');
954
16
  options.SetSourceSize(size);
955
16
  options.SetBinaryZeroIsTerminator(false);
956
16
  return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
957
16
}
LibCxx.cpp:bool LibcxxStringSummaryProvider<(lldb_private::formatters::StringPrinter::StringElementType)3>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::shared_ptr<lldb_private::ValueObject>, unsigned long long)
Line
Count
Source
920
32
                            uint64_t size) {
921
922
32
  if (size == 0) {
923
16
    stream.Printf("\"\"");
924
16
    return true;
925
16
  }
926
927
16
  if (!location_sp)
928
0
    return false;
929
930
16
  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
931
932
16
  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
933
16
    const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
934
16
    if (size > max_size) {
935
0
      size = max_size;
936
0
      options.SetIsTruncated(true);
937
0
    }
938
16
  }
939
940
16
  {
941
16
    DataExtractor extractor;
942
16
    const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
943
16
    if (bytes_read < size)
944
0
      return false;
945
946
16
    options.SetData(std::move(extractor));
947
16
  }
948
0
  options.SetStream(&stream);
949
16
  if (prefix_token.empty())
950
0
    options.SetPrefixToken(nullptr);
951
16
  else
952
16
    options.SetPrefixToken(prefix_token);
953
16
  options.SetQuote('"');
954
16
  options.SetSourceSize(size);
955
16
  options.SetBinaryZeroIsTerminator(false);
956
16
  return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
957
16
}
958
959
template <StringPrinter::StringElementType element_type>
960
static bool
961
LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
962
                            const TypeSummaryOptions &summary_options,
963
1.06k
                            std::string prefix_token) {
964
1.06k
  auto string_info = ExtractLibcxxStringInfo(valobj);
965
1.06k
  if (!string_info)
966
18
    return false;
967
1.04k
  uint64_t size;
968
1.04k
  ValueObjectSP location_sp;
969
1.04k
  std::tie(size, location_sp) = *string_info;
970
971
1.04k
  return LibcxxStringSummaryProvider<element_type>(
972
1.04k
      valobj, stream, summary_options, prefix_token, location_sp, size);
973
1.06k
}
LibCxx.cpp:bool LibcxxStringSummaryProvider<(lldb_private::formatters::StringPrinter::StringElementType)0>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
963
1.05k
                            std::string prefix_token) {
964
1.05k
  auto string_info = ExtractLibcxxStringInfo(valobj);
965
1.05k
  if (!string_info)
966
18
    return false;
967
1.03k
  uint64_t size;
968
1.03k
  ValueObjectSP location_sp;
969
1.03k
  std::tie(size, location_sp) = *string_info;
970
971
1.03k
  return LibcxxStringSummaryProvider<element_type>(
972
1.03k
      valobj, stream, summary_options, prefix_token, location_sp, size);
973
1.05k
}
LibCxx.cpp:bool LibcxxStringSummaryProvider<(lldb_private::formatters::StringPrinter::StringElementType)2>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
963
8
                            std::string prefix_token) {
964
8
  auto string_info = ExtractLibcxxStringInfo(valobj);
965
8
  if (!string_info)
966
0
    return false;
967
8
  uint64_t size;
968
8
  ValueObjectSP location_sp;
969
8
  std::tie(size, location_sp) = *string_info;
970
971
8
  return LibcxxStringSummaryProvider<element_type>(
972
8
      valobj, stream, summary_options, prefix_token, location_sp, size);
973
8
}
LibCxx.cpp:bool LibcxxStringSummaryProvider<(lldb_private::formatters::StringPrinter::StringElementType)3>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
963
8
                            std::string prefix_token) {
964
8
  auto string_info = ExtractLibcxxStringInfo(valobj);
965
8
  if (!string_info)
966
0
    return false;
967
8
  uint64_t size;
968
8
  ValueObjectSP location_sp;
969
8
  std::tie(size, location_sp) = *string_info;
970
971
8
  return LibcxxStringSummaryProvider<element_type>(
972
8
      valobj, stream, summary_options, prefix_token, location_sp, size);
973
8
}
974
template <StringPrinter::StringElementType element_type>
975
static bool formatStringImpl(ValueObject &valobj, Stream &stream,
976
                             const TypeSummaryOptions &summary_options,
977
1.06k
                             std::string prefix_token) {
978
1.06k
  StreamString scratch_stream;
979
1.06k
  const bool success = LibcxxStringSummaryProvider<element_type>(
980
1.06k
      valobj, scratch_stream, summary_options, prefix_token);
981
1.06k
  if (success)
982
1.04k
    stream << scratch_stream.GetData();
983
24
  else
984
24
    stream << "Summary Unavailable";
985
1.06k
  return true;
986
1.06k
}
LibCxx.cpp:bool formatStringImpl<(lldb_private::formatters::StringPrinter::StringElementType)0>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
977
1.05k
                             std::string prefix_token) {
978
1.05k
  StreamString scratch_stream;
979
1.05k
  const bool success = LibcxxStringSummaryProvider<element_type>(
980
1.05k
      valobj, scratch_stream, summary_options, prefix_token);
981
1.05k
  if (success)
982
1.02k
    stream << scratch_stream.GetData();
983
24
  else
984
24
    stream << "Summary Unavailable";
985
1.05k
  return true;
986
1.05k
}
LibCxx.cpp:bool formatStringImpl<(lldb_private::formatters::StringPrinter::StringElementType)2>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
977
8
                             std::string prefix_token) {
978
8
  StreamString scratch_stream;
979
8
  const bool success = LibcxxStringSummaryProvider<element_type>(
980
8
      valobj, scratch_stream, summary_options, prefix_token);
981
8
  if (success)
982
8
    stream << scratch_stream.GetData();
983
0
  else
984
0
    stream << "Summary Unavailable";
985
8
  return true;
986
8
}
LibCxx.cpp:bool formatStringImpl<(lldb_private::formatters::StringPrinter::StringElementType)3>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
977
8
                             std::string prefix_token) {
978
8
  StreamString scratch_stream;
979
8
  const bool success = LibcxxStringSummaryProvider<element_type>(
980
8
      valobj, scratch_stream, summary_options, prefix_token);
981
8
  if (success)
982
8
    stream << scratch_stream.GetData();
983
0
  else
984
0
    stream << "Summary Unavailable";
985
8
  return true;
986
8
}
987
988
bool lldb_private::formatters::LibcxxStringSummaryProviderASCII(
989
    ValueObject &valobj, Stream &stream,
990
1.05k
    const TypeSummaryOptions &summary_options) {
991
1.05k
  return formatStringImpl<StringPrinter::StringElementType::ASCII>(
992
1.05k
      valobj, stream, summary_options, "");
993
1.05k
}
994
995
bool lldb_private::formatters::LibcxxStringSummaryProviderUTF16(
996
    ValueObject &valobj, Stream &stream,
997
8
    const TypeSummaryOptions &summary_options) {
998
8
  return formatStringImpl<StringPrinter::StringElementType::UTF16>(
999
8
      valobj, stream, summary_options, "u");
1000
8
}
1001
1002
bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32(
1003
    ValueObject &valobj, Stream &stream,
1004
8
    const TypeSummaryOptions &summary_options) {
1005
8
  return formatStringImpl<StringPrinter::StringElementType::UTF32>(
1006
8
      valobj, stream, summary_options, "U");
1007
8
}
1008
1009
static std::tuple<bool, ValueObjectSP, size_t>
1010
168
LibcxxExtractStringViewData(ValueObject& valobj) {
1011
168
  auto dataobj = GetChildMemberWithName(
1012
168
      valobj, {ConstString("__data_"), ConstString("__data")});
1013
168
  auto sizeobj = GetChildMemberWithName(
1014
168
      valobj, {ConstString("__size_"), ConstString("__size")});
1015
168
  if (!dataobj || !sizeobj)
1016
0
    return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
1017
1018
168
  if (!dataobj->GetError().Success() || 
!sizeobj->GetError().Success()160
)
1019
8
    return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
1020
1021
160
  bool success{false};
1022
160
  uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
1023
160
  if (!success)
1024
0
    return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
1025
1026
160
  return std::make_tuple(true,dataobj,size);
1027
160
}
1028
1029
template <StringPrinter::StringElementType element_type>
1030
static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
1031
                                 const TypeSummaryOptions &summary_options,
1032
114
                                 std::string prefix_token) {
1033
1034
114
  bool success;
1035
114
  ValueObjectSP dataobj;
1036
114
  size_t size;
1037
114
  std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
1038
1039
114
  if (!success) {
1040
8
    stream << "Summary Unavailable";
1041
8
    return true;
1042
8
  }
1043
1044
106
  return LibcxxStringSummaryProvider<element_type>(
1045
106
      valobj, stream, summary_options, prefix_token, dataobj, size);
1046
114
}
LibCxx.cpp:bool formatStringViewImpl<(lldb_private::formatters::StringPrinter::StringElementType)0>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
1032
66
                                 std::string prefix_token) {
1033
1034
66
  bool success;
1035
66
  ValueObjectSP dataobj;
1036
66
  size_t size;
1037
66
  std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
1038
1039
66
  if (!success) {
1040
8
    stream << "Summary Unavailable";
1041
8
    return true;
1042
8
  }
1043
1044
58
  return LibcxxStringSummaryProvider<element_type>(
1045
58
      valobj, stream, summary_options, prefix_token, dataobj, size);
1046
66
}
LibCxx.cpp:bool formatStringViewImpl<(lldb_private::formatters::StringPrinter::StringElementType)2>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
1032
24
                                 std::string prefix_token) {
1033
1034
24
  bool success;
1035
24
  ValueObjectSP dataobj;
1036
24
  size_t size;
1037
24
  std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
1038
1039
24
  if (!success) {
1040
0
    stream << "Summary Unavailable";
1041
0
    return true;
1042
0
  }
1043
1044
24
  return LibcxxStringSummaryProvider<element_type>(
1045
24
      valobj, stream, summary_options, prefix_token, dataobj, size);
1046
24
}
LibCxx.cpp:bool formatStringViewImpl<(lldb_private::formatters::StringPrinter::StringElementType)3>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
1032
24
                                 std::string prefix_token) {
1033
1034
24
  bool success;
1035
24
  ValueObjectSP dataobj;
1036
24
  size_t size;
1037
24
  std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
1038
1039
24
  if (!success) {
1040
0
    stream << "Summary Unavailable";
1041
0
    return true;
1042
0
  }
1043
1044
24
  return LibcxxStringSummaryProvider<element_type>(
1045
24
      valobj, stream, summary_options, prefix_token, dataobj, size);
1046
24
}
1047
1048
bool lldb_private::formatters::LibcxxStringViewSummaryProviderASCII(
1049
    ValueObject &valobj, Stream &stream,
1050
66
    const TypeSummaryOptions &summary_options) {
1051
66
  return formatStringViewImpl<StringPrinter::StringElementType::ASCII>(
1052
66
      valobj, stream, summary_options, "");
1053
66
}
1054
1055
bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16(
1056
    ValueObject &valobj, Stream &stream,
1057
24
    const TypeSummaryOptions &summary_options) {
1058
24
  return formatStringViewImpl<StringPrinter::StringElementType::UTF16>(
1059
24
      valobj, stream, summary_options, "u");
1060
24
}
1061
1062
bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32(
1063
    ValueObject &valobj, Stream &stream,
1064
24
    const TypeSummaryOptions &summary_options) {
1065
24
  return formatStringViewImpl<StringPrinter::StringElementType::UTF32>(
1066
24
      valobj, stream, summary_options, "U");
1067
24
}
1068
1069
bool lldb_private::formatters::LibcxxWStringViewSummaryProvider(
1070
    ValueObject &valobj, Stream &stream,
1071
54
    const TypeSummaryOptions &summary_options) {
1072
1073
54
  bool success;
1074
54
  ValueObjectSP dataobj;
1075
54
  size_t size;
1076
54
  std::tie( success, dataobj, size ) = LibcxxExtractStringViewData(valobj);
1077
1078
54
  if (!success) {
1079
0
    stream << "Summary Unavailable";
1080
0
    return true;
1081
0
  }
1082
1083
1084
54
  return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
1085
54
                                        dataobj, size);
1086
54
}