Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- NSDictionary.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 <mutex>
10
11
#include "clang/AST/DeclCXX.h"
12
13
#include "CFBasicHash.h"
14
#include "NSDictionary.h"
15
16
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
17
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
18
19
#include "lldb/Core/ValueObject.h"
20
#include "lldb/Core/ValueObjectConstResult.h"
21
#include "lldb/DataFormatters/FormattersHelpers.h"
22
#include "lldb/Target/Language.h"
23
#include "lldb/Target/StackFrame.h"
24
#include "lldb/Target/Target.h"
25
#include "lldb/Utility/DataBufferHeap.h"
26
#include "lldb/Utility/Endian.h"
27
#include "lldb/Utility/Status.h"
28
#include "lldb/Utility/Stream.h"
29
30
using namespace lldb;
31
using namespace lldb_private;
32
using namespace lldb_private::formatters;
33
34
NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Prefix(
35
    ConstString p)
36
0
    : m_prefix(p) {}
37
38
bool NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Match(
39
0
    ConstString class_name) {
40
0
  return class_name.GetStringRef().startswith(m_prefix.GetStringRef());
41
0
}
42
43
NSDictionary_Additionals::AdditionalFormatterMatching::Full::Full(ConstString n)
44
0
    : m_name(n) {}
45
46
bool NSDictionary_Additionals::AdditionalFormatterMatching::Full::Match(
47
0
    ConstString class_name) {
48
0
  return (class_name == m_name);
49
0
}
50
51
NSDictionary_Additionals::AdditionalFormatters<
52
    CXXFunctionSummaryFormat::Callback> &
53
0
NSDictionary_Additionals::GetAdditionalSummaries() {
54
0
  static AdditionalFormatters<CXXFunctionSummaryFormat::Callback> g_map;
55
0
  return g_map;
56
0
}
57
58
NSDictionary_Additionals::AdditionalFormatters<
59
    CXXSyntheticChildren::CreateFrontEndCallback> &
60
4
NSDictionary_Additionals::GetAdditionalSynthetics() {
61
4
  static AdditionalFormatters<CXXSyntheticChildren::CreateFrontEndCallback>
62
4
      g_map;
63
4
  return g_map;
64
4
}
65
66
60
static CompilerType GetLLDBNSPairType(TargetSP target_sp) {
67
60
  CompilerType compiler_type;
68
60
  TypeSystemClangSP scratch_ts_sp =
69
60
      ScratchTypeSystemClang::GetForTarget(*target_sp);
70
71
60
  if (!scratch_ts_sp)
72
0
    return compiler_type;
73
74
60
  static constexpr llvm::StringLiteral g_lldb_autogen_nspair("__lldb_autogen_nspair");
75
76
60
  compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(g_lldb_autogen_nspair);
77
78
60
  if (!compiler_type) {
79
24
    compiler_type = scratch_ts_sp->CreateRecordType(
80
24
        nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
81
24
        g_lldb_autogen_nspair, clang::TTK_Struct, lldb::eLanguageTypeC);
82
83
24
    if (compiler_type) {
84
24
      TypeSystemClang::StartTagDeclarationDefinition(compiler_type);
85
24
      CompilerType id_compiler_type =
86
24
          scratch_ts_sp->GetBasicType(eBasicTypeObjCID);
87
24
      TypeSystemClang::AddFieldToRecordType(
88
24
          compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0);
89
24
      TypeSystemClang::AddFieldToRecordType(
90
24
          compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0);
91
24
      TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type);
92
24
    }
93
24
  }
94
60
  return compiler_type;
95
60
}
96
97
namespace lldb_private {
98
namespace formatters {
99
class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
100
public:
101
  NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
102
103
  ~NSDictionaryISyntheticFrontEnd() override;
104
105
  size_t CalculateNumChildren() override;
106
107
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
108
109
  bool Update() override;
110
111
  bool MightHaveChildren() override;
112
113
  size_t GetIndexOfChildWithName(ConstString name) override;
114
115
private:
116
  struct DataDescriptor_32 {
117
    uint32_t _used : 26;
118
    uint32_t _szidx : 6;
119
  };
120
121
  struct DataDescriptor_64 {
122
    uint64_t _used : 58;
123
    uint32_t _szidx : 6;
124
  };
125
126
  struct DictionaryItemDescriptor {
127
    lldb::addr_t key_ptr;
128
    lldb::addr_t val_ptr;
129
    lldb::ValueObjectSP valobj_sp;
130
  };
131
132
  ExecutionContextRef m_exe_ctx_ref;
133
  uint8_t m_ptr_size = 8;
134
  lldb::ByteOrder m_order = lldb::eByteOrderInvalid;
135
  DataDescriptor_32 *m_data_32 = nullptr;
136
  DataDescriptor_64 *m_data_64 = nullptr;
137
  lldb::addr_t m_data_ptr = LLDB_INVALID_ADDRESS;
138
  CompilerType m_pair_type;
139
  std::vector<DictionaryItemDescriptor> m_children;
140
};
141
142
class NSConstantDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
143
public:
144
  NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
145
146
  size_t CalculateNumChildren() override;
147
148
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
149
150
  bool Update() override;
151
152
  bool MightHaveChildren() override;
153
154
  size_t GetIndexOfChildWithName(ConstString name) override;
155
156
private:
157
  ExecutionContextRef m_exe_ctx_ref;
158
  CompilerType m_pair_type;
159
  uint8_t m_ptr_size = 8;
160
  lldb::ByteOrder m_order = lldb::eByteOrderInvalid;
161
  unsigned int m_size = 0;
162
  lldb::addr_t m_keys_ptr = LLDB_INVALID_ADDRESS;
163
  lldb::addr_t m_objects_ptr = LLDB_INVALID_ADDRESS;
164
165
  struct DictionaryItemDescriptor {
166
    lldb::addr_t key_ptr;
167
    lldb::addr_t val_ptr;
168
    lldb::ValueObjectSP valobj_sp;
169
  };
170
171
  std::vector<DictionaryItemDescriptor> m_children;
172
};
173
174
class NSCFDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
175
public:
176
  NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
177
178
  size_t CalculateNumChildren() override;
179
180
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
181
182
  bool Update() override;
183
184
  bool MightHaveChildren() override;
185
186
  size_t GetIndexOfChildWithName(ConstString name) override;
187
188
private:
189
  struct DictionaryItemDescriptor {
190
    lldb::addr_t key_ptr;
191
    lldb::addr_t val_ptr;
192
    lldb::ValueObjectSP valobj_sp;
193
  };
194
195
  ExecutionContextRef m_exe_ctx_ref;
196
  uint8_t m_ptr_size = 8;
197
  lldb::ByteOrder m_order = lldb::eByteOrderInvalid;
198
199
  CFBasicHash m_hashtable;
200
201
  CompilerType m_pair_type;
202
  std::vector<DictionaryItemDescriptor> m_children;
203
};
204
205
class NSDictionary1SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
206
public:
207
  NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
208
209
18
  ~NSDictionary1SyntheticFrontEnd() override = default;
210
211
  size_t CalculateNumChildren() override;
212
213
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
214
215
  bool Update() override;
216
217
  bool MightHaveChildren() override;
218
219
  size_t GetIndexOfChildWithName(ConstString name) override;
220
221
private:
222
  ValueObjectSP m_pair;
223
};
224
225
template <typename D32, typename D64>
226
class GenericNSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
227
public:
228
  GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
229
230
  ~GenericNSDictionaryMSyntheticFrontEnd() override;
231
232
  size_t CalculateNumChildren() override;
233
234
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
235
236
  bool Update() override;
237
238
  bool MightHaveChildren() override;
239
240
  size_t GetIndexOfChildWithName(ConstString name) override;
241
242
private:
243
  struct DictionaryItemDescriptor {
244
    lldb::addr_t key_ptr;
245
    lldb::addr_t val_ptr;
246
    lldb::ValueObjectSP valobj_sp;
247
  };
248
249
  ExecutionContextRef m_exe_ctx_ref;
250
  uint8_t m_ptr_size = 8;
251
  lldb::ByteOrder m_order = lldb::eByteOrderInvalid;
252
  D32 *m_data_32;
253
  D64 *m_data_64;
254
  CompilerType m_pair_type;
255
  std::vector<DictionaryItemDescriptor> m_children;
256
};
257
  
258
namespace Foundation1100 {
259
  class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
260
  public:
261
    NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
262
    
263
    ~NSDictionaryMSyntheticFrontEnd() override;
264
    
265
    size_t CalculateNumChildren() override;
266
    
267
    lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
268
    
269
    bool Update() override;
270
    
271
    bool MightHaveChildren() override;
272
    
273
    size_t GetIndexOfChildWithName(ConstString name) override;
274
    
275
  private:
276
    struct DataDescriptor_32 {
277
      uint32_t _used : 26;
278
      uint32_t _kvo : 1;
279
      uint32_t _size;
280
      uint32_t _mutations;
281
      uint32_t _objs_addr;
282
      uint32_t _keys_addr;
283
    };
284
    
285
    struct DataDescriptor_64 {
286
      uint64_t _used : 58;
287
      uint32_t _kvo : 1;
288
      uint64_t _size;
289
      uint64_t _mutations;
290
      uint64_t _objs_addr;
291
      uint64_t _keys_addr;
292
    };
293
    
294
    struct DictionaryItemDescriptor {
295
      lldb::addr_t key_ptr;
296
      lldb::addr_t val_ptr;
297
      lldb::ValueObjectSP valobj_sp;
298
    };
299
    
300
    ExecutionContextRef m_exe_ctx_ref;
301
    uint8_t m_ptr_size = 8;
302
    lldb::ByteOrder m_order = lldb::eByteOrderInvalid;
303
    DataDescriptor_32 *m_data_32 = nullptr;
304
    DataDescriptor_64 *m_data_64 = nullptr;
305
    CompilerType m_pair_type;
306
    std::vector<DictionaryItemDescriptor> m_children;
307
  };
308
}
309
  
310
namespace Foundation1428 {
311
  namespace {
312
    struct DataDescriptor_32 {
313
      uint32_t _used : 26;
314
      uint32_t _kvo : 1;
315
      uint32_t _size;
316
      uint32_t _buffer;
317
0
      uint64_t GetSize() { return _size; }
318
    };
319
    
320
    struct DataDescriptor_64 {
321
      uint64_t _used : 58;
322
      uint32_t _kvo : 1;
323
      uint64_t _size;
324
      uint64_t _buffer;
325
0
      uint64_t GetSize() { return _size; }
326
    };
327
  }
328
329
  using NSDictionaryMSyntheticFrontEnd =
330
    GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
331
}
332
  
333
namespace Foundation1437 {
334
    static const uint64_t NSDictionaryCapacities[] = {
335
        0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
336
        2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
337
        214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
338
        6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
339
        111638519, 180634607, 292272623, 472907251
340
    };
341
    
342
    static const size_t NSDictionaryNumSizeBuckets =
343
        sizeof(NSDictionaryCapacities) / sizeof(uint64_t);
344
345
    namespace {
346
    struct DataDescriptor_32 {
347
      uint32_t _buffer;
348
      uint32_t _muts;
349
      uint32_t _used : 25;
350
      uint32_t _kvo : 1;
351
      uint32_t _szidx : 6;
352
353
0
      uint64_t GetSize() {
354
0
        return (_szidx) >= NSDictionaryNumSizeBuckets ?
355
0
            0 : NSDictionaryCapacities[_szidx];
356
0
      }
357
    };
358
    
359
    struct DataDescriptor_64 {
360
      uint64_t _buffer;
361
      uint32_t _muts;
362
      uint32_t _used : 25;
363
      uint32_t _kvo : 1;
364
      uint32_t _szidx : 6;
365
366
34
      uint64_t GetSize() {
367
34
        return (_szidx) >= NSDictionaryNumSizeBuckets ?
368
34
            
00
: NSDictionaryCapacities[_szidx];
369
34
      }
370
    };
371
    } // namespace
372
373
  using NSDictionaryMSyntheticFrontEnd =
374
    GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
375
  
376
  template <typename DD>
377
  uint64_t
378
  __NSDictionaryMSize_Impl(lldb_private::Process &process,
379
46
                           lldb::addr_t valobj_addr, Status &error) {
380
46
    const lldb::addr_t start_of_descriptor =
381
46
        valobj_addr + process.GetAddressByteSize();
382
46
    DD descriptor = DD();
383
46
    process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor),
384
46
                       error);
385
46
    if (error.Fail()) {
386
0
      return 0;
387
0
    }
388
46
    return descriptor._used;
389
46
  }
Unexecuted instantiation: NSDictionary.cpp:unsigned long long lldb_private::formatters::Foundation1437::__NSDictionaryMSize_Impl<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32>(lldb_private::Process&, unsigned long long, lldb_private::Status&)
NSDictionary.cpp:unsigned long long lldb_private::formatters::Foundation1437::__NSDictionaryMSize_Impl<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>(lldb_private::Process&, unsigned long long, lldb_private::Status&)
Line
Count
Source
379
46
                           lldb::addr_t valobj_addr, Status &error) {
380
46
    const lldb::addr_t start_of_descriptor =
381
46
        valobj_addr + process.GetAddressByteSize();
382
46
    DD descriptor = DD();
383
46
    process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor),
384
46
                       error);
385
46
    if (error.Fail()) {
386
0
      return 0;
387
0
    }
388
46
    return descriptor._used;
389
46
  }
390
  
391
  uint64_t
392
  __NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,
393
46
               Status &error) {
394
46
    if (process.GetAddressByteSize() == 4) {
395
0
      return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr,
396
0
                                                         error);
397
46
    } else {
398
46
      return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr,
399
46
                                                         error);
400
46
    }
401
46
  }
402
403
}
404
} // namespace formatters
405
} // namespace lldb_private
406
407
template <bool name_entries>
408
bool lldb_private::formatters::NSDictionarySummaryProvider(
409
176
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
410
176
  static constexpr llvm::StringLiteral g_TypeHint("NSDictionary");
411
176
  ProcessSP process_sp = valobj.GetProcessSP();
412
176
  if (!process_sp)
413
0
    return false;
414
415
176
  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
416
417
176
  if (!runtime)
418
0
    return false;
419
420
176
  ObjCLanguageRuntime::ClassDescriptorSP descriptor(
421
176
      runtime->GetNonKVOClassDescriptor(valobj));
422
423
176
  if (!descriptor || 
!descriptor->IsValid()173
)
424
3
    return false;
425
426
173
  uint32_t ptr_size = process_sp->GetAddressByteSize();
427
173
  bool is_64bit = (ptr_size == 8);
428
429
173
  lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
430
431
173
  if (!valobj_addr)
432
1
    return false;
433
434
172
  uint64_t value = 0;
435
436
172
  ConstString class_name(descriptor->GetClassName());
437
438
172
  static const ConstString g_DictionaryI("__NSDictionaryI");
439
172
  static const ConstString g_DictionaryM("__NSDictionaryM");
440
172
  static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
441
172
  static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
442
172
  static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
443
172
  static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
444
172
  static const ConstString g_Dictionary0("__NSDictionary0");
445
172
  static const ConstString g_DictionaryCF("__CFDictionary");
446
172
  static const ConstString g_DictionaryNSCF("__NSCFDictionary");
447
172
  static const ConstString g_DictionaryCFRef("CFDictionaryRef");
448
172
  static const ConstString g_ConstantDictionary("NSConstantDictionary");
449
450
172
  if (class_name.IsEmpty())
451
0
    return false;
452
453
172
  if (class_name == g_DictionaryI || 
class_name == g_DictionaryMImmutable82
) {
454
90
    Status error;
455
90
    value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
456
90
                                                      ptr_size, 0, error);
457
90
    if (error.Fail())
458
0
      return false;
459
460
90
    value &= (is_64bit ? ~0xFC00000000000000UL : 
~0xFC000000U0
);
461
90
  } else 
if (82
class_name == g_ConstantDictionary82
) {
462
0
    Status error;
463
0
    value = process_sp->ReadUnsignedIntegerFromMemory(
464
0
        valobj_addr + 2 * ptr_size, ptr_size, 0, error);
465
0
    if (error.Fail())
466
0
      return false;
467
82
  } else if (class_name == g_DictionaryM || 
class_name == g_DictionaryMLegacy42
||
468
82
             
class_name == g_DictionaryMFrozen42
) {
469
46
    AppleObjCRuntime *apple_runtime =
470
46
    llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
471
46
    Status error;
472
46
    if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
473
46
      value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr,
474
46
                                                  error);
475
46
    } else {
476
0
      value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
477
0
                                                        ptr_size, 0, error);
478
0
      value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
479
0
    }
480
46
    if (error.Fail())
481
0
      return false;
482
46
  } else 
if (36
class_name == g_Dictionary136
) {
483
4
    value = 1;
484
32
  } else if (class_name == g_Dictionary0) {
485
2
    value = 0;
486
30
  } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
487
30
             
class_name == g_DictionaryCFRef0
) {
488
30
    ExecutionContext exe_ctx(process_sp);
489
30
    CFBasicHash cfbh;
490
30
    if (!cfbh.Update(valobj_addr, exe_ctx))
491
0
      return false;
492
30
    value = cfbh.GetCount();
493
30
  } else {
494
0
    auto &map(NSDictionary_Additionals::GetAdditionalSummaries());
495
0
    for (auto &candidate : map) {
496
0
      if (candidate.first && candidate.first->Match(class_name))
497
0
        return candidate.second(valobj, stream, options);
498
0
    }
499
0
    return false;
500
0
  }
501
502
172
  llvm::StringRef prefix, suffix;
503
172
  if (Language *language = Language::FindPlugin(options.GetLanguage()))
504
172
    std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
505
506
172
  stream << prefix;
507
172
  stream.Printf("%" PRIu64 " %s%s", value, "key/value pair",
508
172
                value == 1 ? 
""12
:
"s"160
);
509
172
  stream << suffix;
510
172
  return true;
511
172
}
bool lldb_private::formatters::NSDictionarySummaryProvider<true>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&)
Line
Count
Source
409
18
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
410
18
  static constexpr llvm::StringLiteral g_TypeHint("NSDictionary");
411
18
  ProcessSP process_sp = valobj.GetProcessSP();
412
18
  if (!process_sp)
413
0
    return false;
414
415
18
  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
416
417
18
  if (!runtime)
418
0
    return false;
419
420
18
  ObjCLanguageRuntime::ClassDescriptorSP descriptor(
421
18
      runtime->GetNonKVOClassDescriptor(valobj));
422
423
18
  if (!descriptor || 
!descriptor->IsValid()17
)
424
1
    return false;
425
426
17
  uint32_t ptr_size = process_sp->GetAddressByteSize();
427
17
  bool is_64bit = (ptr_size == 8);
428
429
17
  lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
430
431
17
  if (!valobj_addr)
432
1
    return false;
433
434
16
  uint64_t value = 0;
435
436
16
  ConstString class_name(descriptor->GetClassName());
437
438
16
  static const ConstString g_DictionaryI("__NSDictionaryI");
439
16
  static const ConstString g_DictionaryM("__NSDictionaryM");
440
16
  static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
441
16
  static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
442
16
  static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
443
16
  static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
444
16
  static const ConstString g_Dictionary0("__NSDictionary0");
445
16
  static const ConstString g_DictionaryCF("__CFDictionary");
446
16
  static const ConstString g_DictionaryNSCF("__NSCFDictionary");
447
16
  static const ConstString g_DictionaryCFRef("CFDictionaryRef");
448
16
  static const ConstString g_ConstantDictionary("NSConstantDictionary");
449
450
16
  if (class_name.IsEmpty())
451
0
    return false;
452
453
16
  if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
454
0
    Status error;
455
0
    value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
456
0
                                                      ptr_size, 0, error);
457
0
    if (error.Fail())
458
0
      return false;
459
460
0
    value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
461
16
  } else if (class_name == g_ConstantDictionary) {
462
0
    Status error;
463
0
    value = process_sp->ReadUnsignedIntegerFromMemory(
464
0
        valobj_addr + 2 * ptr_size, ptr_size, 0, error);
465
0
    if (error.Fail())
466
0
      return false;
467
16
  } else if (class_name == g_DictionaryM || 
class_name == g_DictionaryMLegacy10
||
468
16
             
class_name == g_DictionaryMFrozen10
) {
469
6
    AppleObjCRuntime *apple_runtime =
470
6
    llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
471
6
    Status error;
472
6
    if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
473
6
      value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr,
474
6
                                                  error);
475
6
    } else {
476
0
      value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
477
0
                                                        ptr_size, 0, error);
478
0
      value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
479
0
    }
480
6
    if (error.Fail())
481
0
      return false;
482
10
  } else if (class_name == g_Dictionary1) {
483
0
    value = 1;
484
10
  } else if (class_name == g_Dictionary0) {
485
0
    value = 0;
486
10
  } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
487
10
             
class_name == g_DictionaryCFRef0
) {
488
10
    ExecutionContext exe_ctx(process_sp);
489
10
    CFBasicHash cfbh;
490
10
    if (!cfbh.Update(valobj_addr, exe_ctx))
491
0
      return false;
492
10
    value = cfbh.GetCount();
493
10
  } else {
494
0
    auto &map(NSDictionary_Additionals::GetAdditionalSummaries());
495
0
    for (auto &candidate : map) {
496
0
      if (candidate.first && candidate.first->Match(class_name))
497
0
        return candidate.second(valobj, stream, options);
498
0
    }
499
0
    return false;
500
0
  }
501
502
16
  llvm::StringRef prefix, suffix;
503
16
  if (Language *language = Language::FindPlugin(options.GetLanguage()))
504
16
    std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
505
506
16
  stream << prefix;
507
16
  stream.Printf("%" PRIu64 " %s%s", value, "key/value pair",
508
16
                value == 1 ? 
""0
: "s");
509
16
  stream << suffix;
510
16
  return true;
511
16
}
bool lldb_private::formatters::NSDictionarySummaryProvider<false>(lldb_private::ValueObject&, lldb_private::Stream&, lldb_private::TypeSummaryOptions const&)
Line
Count
Source
409
158
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
410
158
  static constexpr llvm::StringLiteral g_TypeHint("NSDictionary");
411
158
  ProcessSP process_sp = valobj.GetProcessSP();
412
158
  if (!process_sp)
413
0
    return false;
414
415
158
  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
416
417
158
  if (!runtime)
418
0
    return false;
419
420
158
  ObjCLanguageRuntime::ClassDescriptorSP descriptor(
421
158
      runtime->GetNonKVOClassDescriptor(valobj));
422
423
158
  if (!descriptor || 
!descriptor->IsValid()156
)
424
2
    return false;
425
426
156
  uint32_t ptr_size = process_sp->GetAddressByteSize();
427
156
  bool is_64bit = (ptr_size == 8);
428
429
156
  lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
430
431
156
  if (!valobj_addr)
432
0
    return false;
433
434
156
  uint64_t value = 0;
435
436
156
  ConstString class_name(descriptor->GetClassName());
437
438
156
  static const ConstString g_DictionaryI("__NSDictionaryI");
439
156
  static const ConstString g_DictionaryM("__NSDictionaryM");
440
156
  static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
441
156
  static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
442
156
  static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
443
156
  static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
444
156
  static const ConstString g_Dictionary0("__NSDictionary0");
445
156
  static const ConstString g_DictionaryCF("__CFDictionary");
446
156
  static const ConstString g_DictionaryNSCF("__NSCFDictionary");
447
156
  static const ConstString g_DictionaryCFRef("CFDictionaryRef");
448
156
  static const ConstString g_ConstantDictionary("NSConstantDictionary");
449
450
156
  if (class_name.IsEmpty())
451
0
    return false;
452
453
156
  if (class_name == g_DictionaryI || 
class_name == g_DictionaryMImmutable66
) {
454
90
    Status error;
455
90
    value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
456
90
                                                      ptr_size, 0, error);
457
90
    if (error.Fail())
458
0
      return false;
459
460
90
    value &= (is_64bit ? ~0xFC00000000000000UL : 
~0xFC000000U0
);
461
90
  } else 
if (66
class_name == g_ConstantDictionary66
) {
462
0
    Status error;
463
0
    value = process_sp->ReadUnsignedIntegerFromMemory(
464
0
        valobj_addr + 2 * ptr_size, ptr_size, 0, error);
465
0
    if (error.Fail())
466
0
      return false;
467
66
  } else if (class_name == g_DictionaryM || 
class_name == g_DictionaryMLegacy32
||
468
66
             
class_name == g_DictionaryMFrozen32
) {
469
40
    AppleObjCRuntime *apple_runtime =
470
40
    llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
471
40
    Status error;
472
40
    if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
473
40
      value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr,
474
40
                                                  error);
475
40
    } else {
476
0
      value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
477
0
                                                        ptr_size, 0, error);
478
0
      value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
479
0
    }
480
40
    if (error.Fail())
481
0
      return false;
482
40
  } else 
if (26
class_name == g_Dictionary126
) {
483
4
    value = 1;
484
22
  } else if (class_name == g_Dictionary0) {
485
2
    value = 0;
486
20
  } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
487
20
             
class_name == g_DictionaryCFRef0
) {
488
20
    ExecutionContext exe_ctx(process_sp);
489
20
    CFBasicHash cfbh;
490
20
    if (!cfbh.Update(valobj_addr, exe_ctx))
491
0
      return false;
492
20
    value = cfbh.GetCount();
493
20
  } else {
494
0
    auto &map(NSDictionary_Additionals::GetAdditionalSummaries());
495
0
    for (auto &candidate : map) {
496
0
      if (candidate.first && candidate.first->Match(class_name))
497
0
        return candidate.second(valobj, stream, options);
498
0
    }
499
0
    return false;
500
0
  }
501
502
156
  llvm::StringRef prefix, suffix;
503
156
  if (Language *language = Language::FindPlugin(options.GetLanguage()))
504
156
    std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
505
506
156
  stream << prefix;
507
156
  stream.Printf("%" PRIu64 " %s%s", value, "key/value pair",
508
156
                value == 1 ? 
""12
:
"s"144
);
509
156
  stream << suffix;
510
156
  return true;
511
156
}
512
513
SyntheticChildrenFrontEnd *
514
lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
515
229
    CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
516
229
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
517
229
  if (!process_sp)
518
0
    return nullptr;
519
229
  AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
520
229
      ObjCLanguageRuntime::Get(*process_sp));
521
229
  if (!runtime)
522
0
    return nullptr;
523
524
229
  CompilerType valobj_type(valobj_sp->GetCompilerType());
525
229
  Flags flags(valobj_type.GetTypeInfo());
526
527
229
  if (flags.IsClear(eTypeIsPointer)) {
528
4
    Status error;
529
4
    valobj_sp = valobj_sp->AddressOf(error);
530
4
    if (error.Fail() || !valobj_sp)
531
0
      return nullptr;
532
4
  }
533
534
229
  ObjCLanguageRuntime::ClassDescriptorSP descriptor(
535
229
      runtime->GetClassDescriptor(*valobj_sp));
536
537
229
  if (!descriptor || 
!descriptor->IsValid()226
)
538
3
    return nullptr;
539
540
226
  ConstString class_name(descriptor->GetClassName());
541
542
226
  static const ConstString g_DictionaryI("__NSDictionaryI");
543
226
  static const ConstString g_DictionaryM("__NSDictionaryM");
544
226
  static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
545
226
  static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
546
226
  static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
547
226
  static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
548
226
  static const ConstString g_Dictionary0("__NSDictionary0");
549
226
  static const ConstString g_DictionaryCF("__CFDictionary");
550
226
  static const ConstString g_DictionaryNSCF("__NSCFDictionary");
551
226
  static const ConstString g_DictionaryCFRef("CFDictionaryRef");
552
226
  static const ConstString g_ConstantDictionary("NSConstantDictionary");
553
554
226
  if (class_name.IsEmpty())
555
0
    return nullptr;
556
557
226
  if (class_name == g_DictionaryI) {
558
98
    return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
559
128
  } else if (class_name == g_ConstantDictionary) {
560
0
    return (new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
561
128
  } else if (class_name == g_DictionaryM || 
class_name == g_DictionaryMFrozen68
) {
562
70
    if (runtime->GetFoundationVersion() >= 1437) {
563
70
      return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp));
564
70
    } else 
if (0
runtime->GetFoundationVersion() >= 14280
) {
565
0
      return (new Foundation1428::NSDictionaryMSyntheticFrontEnd(valobj_sp));
566
0
    } else {
567
0
      return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
568
0
    }
569
70
  } else 
if (58
class_name == g_DictionaryMLegacy58
) {
570
0
    return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
571
58
  } else if (class_name == g_Dictionary1) {
572
18
    return (new NSDictionary1SyntheticFrontEnd(valobj_sp));
573
40
  } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
574
40
             
class_name == g_DictionaryCFRef4
) {
575
36
    return (new NSCFDictionarySyntheticFrontEnd(valobj_sp));
576
36
  } else {
577
4
    auto &map(NSDictionary_Additionals::GetAdditionalSynthetics());
578
4
    for (auto &candidate : map) {
579
0
      if (candidate.first && candidate.first->Match((class_name)))
580
0
        return candidate.second(synth, valobj_sp);
581
0
    }
582
4
  }
583
584
4
  return nullptr;
585
226
}
586
587
lldb_private::formatters::NSDictionaryISyntheticFrontEnd::
588
    NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
589
98
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}
590
591
lldb_private::formatters::NSDictionaryISyntheticFrontEnd::
592
98
    ~NSDictionaryISyntheticFrontEnd() {
593
98
  delete m_data_32;
594
98
  m_data_32 = nullptr;
595
98
  delete m_data_64;
596
98
  m_data_64 = nullptr;
597
98
}
598
599
size_t lldb_private::formatters::NSDictionaryISyntheticFrontEnd::
600
0
    GetIndexOfChildWithName(ConstString name) {
601
0
  const char *item_name = name.GetCString();
602
0
  uint32_t idx = ExtractIndexFromString(item_name);
603
0
  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
604
0
    return UINT32_MAX;
605
0
  return idx;
606
0
}
607
608
size_t lldb_private::formatters::NSDictionaryISyntheticFrontEnd::
609
94
    CalculateNumChildren() {
610
94
  if (!m_data_32 && !m_data_64)
611
0
    return 0;
612
94
  return (m_data_32 ? 
m_data_32->_used0
: m_data_64->_used);
613
94
}
614
615
82
bool lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() {
616
82
  m_children.clear();
617
82
  delete m_data_32;
618
82
  m_data_32 = nullptr;
619
82
  delete m_data_64;
620
82
  m_data_64 = nullptr;
621
82
  m_ptr_size = 0;
622
82
  ValueObjectSP valobj_sp = m_backend.GetSP();
623
82
  if (!valobj_sp)
624
0
    return false;
625
82
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
626
82
  Status error;
627
82
  error.Clear();
628
82
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
629
82
  if (!process_sp)
630
0
    return false;
631
82
  m_ptr_size = process_sp->GetAddressByteSize();
632
82
  m_order = process_sp->GetByteOrder();
633
82
  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
634
82
  if (m_ptr_size == 4) {
635
0
    m_data_32 = new DataDescriptor_32();
636
0
    process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
637
0
                           error);
638
82
  } else {
639
82
    m_data_64 = new DataDescriptor_64();
640
82
    process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
641
82
                           error);
642
82
  }
643
82
  if (error.Fail())
644
0
    return false;
645
82
  m_data_ptr = data_location + m_ptr_size;
646
82
  return false;
647
82
}
648
649
bool lldb_private::formatters::NSDictionaryISyntheticFrontEnd::
650
4
    MightHaveChildren() {
651
4
  return true;
652
4
}
653
654
lldb::ValueObjectSP
655
lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex(
656
70
    size_t idx) {
657
70
  uint32_t num_children = CalculateNumChildren();
658
659
70
  if (idx >= num_children)
660
0
    return lldb::ValueObjectSP();
661
662
70
  if (m_children.empty()) {
663
    // do the scan phase
664
30
    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
665
666
30
    uint32_t tries = 0;
667
30
    uint32_t test_idx = 0;
668
669
132
    while (tries < num_children) {
670
102
      key_at_idx = m_data_ptr + (2 * test_idx * m_ptr_size);
671
102
      val_at_idx = key_at_idx + m_ptr_size;
672
102
      ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
673
102
      if (!process_sp)
674
0
        return lldb::ValueObjectSP();
675
102
      Status error;
676
102
      key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
677
102
      if (error.Fail())
678
0
        return lldb::ValueObjectSP();
679
102
      val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
680
102
      if (error.Fail())
681
0
        return lldb::ValueObjectSP();
682
683
102
      test_idx++;
684
685
102
      if (!key_at_idx || 
!val_at_idx70
)
686
32
        continue;
687
70
      tries++;
688
689
70
      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
690
70
                                             lldb::ValueObjectSP()};
691
692
70
      m_children.push_back(descriptor);
693
70
    }
694
30
  }
695
696
70
  if (idx >= m_children.size()) // should never happen
697
0
    return lldb::ValueObjectSP();
698
699
70
  DictionaryItemDescriptor &dict_item = m_children[idx];
700
70
  if (!dict_item.valobj_sp) {
701
70
    if (!m_pair_type.IsValid()) {
702
30
      TargetSP target_sp(m_backend.GetTargetSP());
703
30
      if (!target_sp)
704
0
        return ValueObjectSP();
705
30
      m_pair_type = GetLLDBNSPairType(target_sp);
706
30
    }
707
70
    if (!m_pair_type.IsValid())
708
0
      return ValueObjectSP();
709
710
70
    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
711
712
70
    if (m_ptr_size == 8) {
713
70
      uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
714
70
      *data_ptr = dict_item.key_ptr;
715
70
      *(data_ptr + 1) = dict_item.val_ptr;
716
70
    } else {
717
0
      uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
718
0
      *data_ptr = dict_item.key_ptr;
719
0
      *(data_ptr + 1) = dict_item.val_ptr;
720
0
    }
721
722
70
    StreamString idx_name;
723
70
    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
724
70
    DataExtractor data(buffer_sp, m_order, m_ptr_size);
725
70
    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
726
70
                                                    m_exe_ctx_ref, m_pair_type);
727
70
  }
728
70
  return dict_item.valobj_sp;
729
70
}
730
731
lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::
732
    NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
733
36
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_hashtable(),
734
36
      m_pair_type() {}
735
736
size_t lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::
737
0
    GetIndexOfChildWithName(ConstString name) {
738
0
  const char *item_name = name.GetCString();
739
0
  const uint32_t idx = ExtractIndexFromString(item_name);
740
0
  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
741
0
    return UINT32_MAX;
742
0
  return idx;
743
0
}
744
745
size_t lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::
746
16
    CalculateNumChildren() {
747
16
  if (!m_hashtable.IsValid())
748
0
    return 0;
749
16
  return m_hashtable.GetCount();
750
16
}
751
752
34
bool lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::Update() {
753
34
  m_children.clear();
754
34
  ValueObjectSP valobj_sp = m_backend.GetSP();
755
34
  m_ptr_size = 0;
756
34
  if (!valobj_sp)
757
0
    return false;
758
34
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
759
760
34
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
761
34
  if (!process_sp)
762
0
    return false;
763
34
  m_ptr_size = process_sp->GetAddressByteSize();
764
34
  m_order = process_sp->GetByteOrder();
765
34
  return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref);
766
34
}
767
768
bool lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::
769
0
    MightHaveChildren() {
770
0
  return true;
771
0
}
772
773
lldb::ValueObjectSP
774
lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::GetChildAtIndex(
775
12
    size_t idx) {
776
12
  lldb::addr_t m_keys_ptr = m_hashtable.GetKeyPointer();
777
12
  lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer();
778
779
12
  const uint32_t num_children = CalculateNumChildren();
780
781
12
  if (idx >= num_children)
782
0
    return lldb::ValueObjectSP();
783
784
12
  if (m_children.empty()) {
785
4
    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
786
4
    if (!process_sp)
787
0
      return lldb::ValueObjectSP();
788
789
4
    Status error;
790
4
    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
791
792
4
    uint32_t tries = 0;
793
4
    uint32_t test_idx = 0;
794
795
    // Iterate over inferior memory, reading key/value pointers by shifting each
796
    // cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read
797
    // fails, otherwise, continue until the number of tries matches the number
798
    // of childen.
799
22
    while (tries < num_children) {
800
18
      key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
801
18
      val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
802
803
18
      key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
804
18
      if (error.Fail())
805
0
        return lldb::ValueObjectSP();
806
18
      val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
807
18
      if (error.Fail())
808
0
        return lldb::ValueObjectSP();
809
810
18
      test_idx++;
811
812
18
      if (!key_at_idx || 
!val_at_idx12
)
813
6
        continue;
814
12
      tries++;
815
816
12
      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
817
12
                                             lldb::ValueObjectSP()};
818
819
12
      m_children.push_back(descriptor);
820
12
    }
821
4
  }
822
823
12
  if (idx >= m_children.size()) // should never happen
824
0
    return lldb::ValueObjectSP();
825
826
12
  DictionaryItemDescriptor &dict_item = m_children[idx];
827
12
  if (!dict_item.valobj_sp) {
828
12
    if (!m_pair_type.IsValid()) {
829
4
      TargetSP target_sp(m_backend.GetTargetSP());
830
4
      if (!target_sp)
831
0
        return ValueObjectSP();
832
4
      m_pair_type = GetLLDBNSPairType(target_sp);
833
4
    }
834
12
    if (!m_pair_type.IsValid())
835
0
      return ValueObjectSP();
836
837
12
    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
838
839
12
    switch (m_ptr_size) {
840
0
    case 0: // architecture has no clue - fail
841
0
      return lldb::ValueObjectSP();
842
0
    case 4: {
843
0
      uint32_t *data_ptr = reinterpret_cast<uint32_t *>(buffer_sp->GetBytes());
844
0
      *data_ptr = dict_item.key_ptr;
845
0
      *(data_ptr + 1) = dict_item.val_ptr;
846
0
    } break;
847
12
    case 8: {
848
12
      uint64_t *data_ptr = reinterpret_cast<uint64_t *>(buffer_sp->GetBytes());
849
12
      *data_ptr = dict_item.key_ptr;
850
12
      *(data_ptr + 1) = dict_item.val_ptr;
851
12
    } break;
852
0
    default:
853
0
      lldbassert(false && "pointer size is not 4 nor 8");
854
12
    }
855
856
12
    StreamString idx_name;
857
12
    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
858
12
    DataExtractor data(buffer_sp, m_order, m_ptr_size);
859
12
    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
860
12
                                                    m_exe_ctx_ref, m_pair_type);
861
12
  }
862
12
  return dict_item.valobj_sp;
863
12
}
864
865
lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::
866
    NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
867
0
    : SyntheticChildrenFrontEnd(*valobj_sp) {}
868
869
size_t lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::
870
0
    GetIndexOfChildWithName(ConstString name) {
871
0
  const char *item_name = name.GetCString();
872
0
  uint32_t idx = ExtractIndexFromString(item_name);
873
0
  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
874
0
    return UINT32_MAX;
875
0
  return idx;
876
0
}
877
878
size_t lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::
879
0
    CalculateNumChildren() {
880
0
  return m_size;
881
0
}
882
883
0
bool lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::Update() {
884
0
  ValueObjectSP valobj_sp = m_backend.GetSP();
885
0
  if (!valobj_sp)
886
0
    return false;
887
0
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
888
0
  Status error;
889
0
  error.Clear();
890
0
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
891
0
  if (!process_sp)
892
0
    return false;
893
0
  m_ptr_size = process_sp->GetAddressByteSize();
894
0
  m_order = process_sp->GetByteOrder();
895
0
  uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
896
0
  m_size = process_sp->ReadUnsignedIntegerFromMemory(
897
0
      valobj_addr + 2 * m_ptr_size, m_ptr_size, 0, error);
898
0
  if (error.Fail())
899
0
    return false;
900
0
  m_keys_ptr =
901
0
      process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size, error);
902
0
  if (error.Fail())
903
0
    return false;
904
0
  m_objects_ptr =
905
0
      process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size, error);
906
0
  return !error.Fail();
907
0
}
908
909
bool lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::
910
0
    MightHaveChildren() {
911
0
  return true;
912
0
}
913
914
lldb::ValueObjectSP lldb_private::formatters::
915
0
    NSConstantDictionarySyntheticFrontEnd::GetChildAtIndex(size_t idx) {
916
0
  uint32_t num_children = CalculateNumChildren();
917
918
0
  if (idx >= num_children)
919
0
    return lldb::ValueObjectSP();
920
921
0
  if (m_children.empty()) {
922
    // do the scan phase
923
0
    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
924
0
    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
925
0
    if (!process_sp)
926
0
      return lldb::ValueObjectSP();
927
928
0
    for (unsigned int child = 0; child < num_children; ++child) {
929
0
      Status error;
930
0
      key_at_idx = process_sp->ReadPointerFromMemory(
931
0
          m_keys_ptr + child * m_ptr_size, error);
932
0
      if (error.Fail())
933
0
        return lldb::ValueObjectSP();
934
0
      val_at_idx = process_sp->ReadPointerFromMemory(
935
0
          m_objects_ptr + child * m_ptr_size, error);
936
0
      if (error.Fail())
937
0
        return lldb::ValueObjectSP();
938
0
      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
939
0
                                             lldb::ValueObjectSP()};
940
0
      m_children.push_back(descriptor);
941
0
    }
942
0
  }
943
944
0
  if (idx >= m_children.size()) // should never happen
945
0
    return lldb::ValueObjectSP();
946
947
0
  DictionaryItemDescriptor &dict_item = m_children[idx];
948
0
  if (!dict_item.valobj_sp) {
949
0
    if (!m_pair_type.IsValid()) {
950
0
      TargetSP target_sp(m_backend.GetTargetSP());
951
0
      if (!target_sp)
952
0
        return ValueObjectSP();
953
0
      m_pair_type = GetLLDBNSPairType(target_sp);
954
0
    }
955
0
    if (!m_pair_type.IsValid())
956
0
      return ValueObjectSP();
957
958
0
    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
959
960
0
    if (m_ptr_size == 8) {
961
0
      uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
962
0
      *data_ptr = dict_item.key_ptr;
963
0
      *(data_ptr + 1) = dict_item.val_ptr;
964
0
    } else {
965
0
      uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
966
0
      *data_ptr = dict_item.key_ptr;
967
0
      *(data_ptr + 1) = dict_item.val_ptr;
968
0
    }
969
970
0
    StreamString idx_name;
971
0
    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
972
0
    DataExtractor data(buffer_sp, m_order, m_ptr_size);
973
0
    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
974
0
                                                    m_exe_ctx_ref, m_pair_type);
975
0
  }
976
0
  return dict_item.valobj_sp;
977
0
}
978
979
lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
980
    NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
981
18
    : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_pair(nullptr) {}
982
983
size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
984
0
    GetIndexOfChildWithName(ConstString name) {
985
0
  static const ConstString g_zero("[0]");
986
0
  return name == g_zero ? 0 : UINT32_MAX;
987
0
}
988
989
size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
990
4
    CalculateNumChildren() {
991
4
  return 1;
992
4
}
993
994
8
bool lldb_private::formatters::NSDictionary1SyntheticFrontEnd::Update() {
995
8
  m_pair.reset();
996
8
  return false;
997
8
}
998
999
bool lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
1000
0
    MightHaveChildren() {
1001
0
  return true;
1002
0
}
1003
1004
lldb::ValueObjectSP
1005
lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex(
1006
4
    size_t idx) {
1007
4
  if (idx != 0)
1008
0
    return lldb::ValueObjectSP();
1009
1010
4
  if (m_pair.get())
1011
0
    return m_pair;
1012
1013
4
  auto process_sp(m_backend.GetProcessSP());
1014
4
  if (!process_sp)
1015
0
    return nullptr;
1016
1017
4
  auto ptr_size = process_sp->GetAddressByteSize();
1018
1019
4
  lldb::addr_t key_ptr =
1020
4
      m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS) + ptr_size;
1021
4
  lldb::addr_t value_ptr = key_ptr + ptr_size;
1022
1023
4
  Status error;
1024
1025
4
  lldb::addr_t value_at_idx = process_sp->ReadPointerFromMemory(key_ptr, error);
1026
4
  if (error.Fail())
1027
0
    return nullptr;
1028
4
  lldb::addr_t key_at_idx = process_sp->ReadPointerFromMemory(value_ptr, error);
1029
4
  if (error.Fail())
1030
0
    return nullptr;
1031
1032
4
  auto pair_type =
1033
4
      GetLLDBNSPairType(process_sp->GetTarget().shared_from_this());
1034
1035
4
  WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0));
1036
1037
4
  if (ptr_size == 8) {
1038
4
    uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1039
4
    *data_ptr = key_at_idx;
1040
4
    *(data_ptr + 1) = value_at_idx;
1041
4
  } else {
1042
0
    uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1043
0
    *data_ptr = key_at_idx;
1044
0
    *(data_ptr + 1) = value_at_idx;
1045
0
  }
1046
1047
4
  DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1048
4
  m_pair = CreateValueObjectFromData(
1049
4
      "[0]", data, m_backend.GetExecutionContextRef(), pair_type);
1050
1051
4
  return m_pair;
1052
4
}
1053
1054
template <typename D32, typename D64>
1055
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32, D64>::
1056
    GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
1057
70
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
1058
70
      m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {}
NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::GenericNSDictionaryMSyntheticFrontEnd(std::__1::shared_ptr<lldb_private::ValueObject>)
Line
Count
Source
1057
70
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
1058
70
      m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::GenericNSDictionaryMSyntheticFrontEnd(std::__1::shared_ptr<lldb_private::ValueObject>)
1059
1060
template <typename D32, typename D64>
1061
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::
1062
70
    ~GenericNSDictionaryMSyntheticFrontEnd<D32,D64>() {
1063
70
  delete m_data_32;
1064
70
  m_data_32 = nullptr;
1065
70
  delete m_data_64;
1066
70
  m_data_64 = nullptr;
1067
70
}
NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::~GenericNSDictionaryMSyntheticFrontEnd()
Line
Count
Source
1062
70
    ~GenericNSDictionaryMSyntheticFrontEnd<D32,D64>() {
1063
70
  delete m_data_32;
1064
70
  m_data_32 = nullptr;
1065
70
  delete m_data_64;
1066
70
  m_data_64 = nullptr;
1067
70
}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::~GenericNSDictionaryMSyntheticFrontEnd()
1068
1069
template <typename D32, typename D64>
1070
size_t lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<
1071
0
    D32, D64>::GetIndexOfChildWithName(ConstString name) {
1072
0
  const char *item_name = name.GetCString();
1073
0
  uint32_t idx = ExtractIndexFromString(item_name);
1074
0
  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1075
0
    return UINT32_MAX;
1076
0
  return idx;
1077
0
}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::GetIndexOfChildWithName(lldb_private::ConstString)
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::GetIndexOfChildWithName(lldb_private::ConstString)
1078
1079
template <typename D32, typename D64>
1080
size_t
1081
54
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::CalculateNumChildren() {
1082
54
  if (!m_data_32 && !m_data_64)
1083
0
    return 0;
1084
54
  return (m_data_32 ? 
m_data_32->_used0
: m_data_64->_used);
1085
54
}
NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::CalculateNumChildren()
Line
Count
Source
1081
54
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::CalculateNumChildren() {
1082
54
  if (!m_data_32 && !m_data_64)
1083
0
    return 0;
1084
54
  return (m_data_32 ? 
m_data_32->_used0
: m_data_64->_used);
1085
54
}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::CalculateNumChildren()
1086
1087
template <typename D32, typename D64>
1088
bool
1089
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::
1090
52
  Update() {
1091
52
  m_children.clear();
1092
52
  ValueObjectSP valobj_sp = m_backend.GetSP();
1093
52
  m_ptr_size = 0;
1094
52
  delete m_data_32;
1095
52
  m_data_32 = nullptr;
1096
52
  delete m_data_64;
1097
52
  m_data_64 = nullptr;
1098
52
  if (!valobj_sp)
1099
0
    return false;
1100
52
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1101
52
  Status error;
1102
52
  error.Clear();
1103
52
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1104
52
  if (!process_sp)
1105
0
    return false;
1106
52
  m_ptr_size = process_sp->GetAddressByteSize();
1107
52
  m_order = process_sp->GetByteOrder();
1108
52
  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1109
52
  if (m_ptr_size == 4) {
1110
0
    m_data_32 = new D32();
1111
0
    process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
1112
0
                           error);
1113
52
  } else {
1114
52
    m_data_64 = new D64();
1115
52
    process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
1116
52
                           error);
1117
52
  }
1118
1119
52
  return error.Success();
1120
52
}
NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::Update()
Line
Count
Source
1090
52
  Update() {
1091
52
  m_children.clear();
1092
52
  ValueObjectSP valobj_sp = m_backend.GetSP();
1093
52
  m_ptr_size = 0;
1094
52
  delete m_data_32;
1095
52
  m_data_32 = nullptr;
1096
52
  delete m_data_64;
1097
52
  m_data_64 = nullptr;
1098
52
  if (!valobj_sp)
1099
0
    return false;
1100
52
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1101
52
  Status error;
1102
52
  error.Clear();
1103
52
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1104
52
  if (!process_sp)
1105
0
    return false;
1106
52
  m_ptr_size = process_sp->GetAddressByteSize();
1107
52
  m_order = process_sp->GetByteOrder();
1108
52
  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1109
52
  if (m_ptr_size == 4) {
1110
0
    m_data_32 = new D32();
1111
0
    process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
1112
0
                           error);
1113
52
  } else {
1114
52
    m_data_64 = new D64();
1115
52
    process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
1116
52
                           error);
1117
52
  }
1118
1119
52
  return error.Success();
1120
52
}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::Update()
1121
1122
template <typename D32, typename D64>
1123
bool
1124
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::
1125
4
    MightHaveChildren() {
1126
4
  return true;
1127
4
}
NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::MightHaveChildren()
Line
Count
Source
1125
4
    MightHaveChildren() {
1126
4
  return true;
1127
4
}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::MightHaveChildren()
1128
1129
template <typename D32, typename D64>
1130
lldb::ValueObjectSP
1131
lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<
1132
34
    D32, D64>::GetChildAtIndex(size_t idx) {
1133
34
  lldb::addr_t m_keys_ptr;
1134
34
  lldb::addr_t m_values_ptr;
1135
34
  if (m_data_32) {
1136
0
    uint32_t size = m_data_32->GetSize();
1137
0
    m_keys_ptr = m_data_32->_buffer;
1138
0
    m_values_ptr = m_data_32->_buffer + (m_ptr_size * size);
1139
34
  } else {
1140
34
    uint32_t size = m_data_64->GetSize();
1141
34
    m_keys_ptr = m_data_64->_buffer;
1142
34
    m_values_ptr = m_data_64->_buffer + (m_ptr_size * size);
1143
34
  }
1144
1145
34
  uint32_t num_children = CalculateNumChildren();
1146
1147
34
  if (idx >= num_children)
1148
0
    return lldb::ValueObjectSP();
1149
1150
34
  if (m_children.empty()) {
1151
    // do the scan phase
1152
22
    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1153
1154
22
    uint32_t tries = 0;
1155
22
    uint32_t test_idx = 0;
1156
1157
164
    while (tries < num_children) {
1158
142
      key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1159
142
      val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1160
142
      ;
1161
142
      ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1162
142
      if (!process_sp)
1163
0
        return lldb::ValueObjectSP();
1164
142
      Status error;
1165
142
      key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1166
142
      if (error.Fail())
1167
0
        return lldb::ValueObjectSP();
1168
142
      val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1169
142
      if (error.Fail())
1170
0
        return lldb::ValueObjectSP();
1171
1172
142
      test_idx++;
1173
1174
142
      if (!key_at_idx || 
!val_at_idx90
)
1175
52
        continue;
1176
90
      tries++;
1177
1178
90
      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1179
90
                                             lldb::ValueObjectSP()};
1180
1181
90
      m_children.push_back(descriptor);
1182
90
    }
1183
22
  }
1184
1185
34
  if (idx >= m_children.size()) // should never happen
1186
0
    return lldb::ValueObjectSP();
1187
1188
34
  DictionaryItemDescriptor &dict_item = m_children[idx];
1189
34
  if (!dict_item.valobj_sp) {
1190
34
    if (!m_pair_type.IsValid()) {
1191
22
      TargetSP target_sp(m_backend.GetTargetSP());
1192
22
      if (!target_sp)
1193
0
        return ValueObjectSP();
1194
22
      m_pair_type = GetLLDBNSPairType(target_sp);
1195
22
    }
1196
34
    if (!m_pair_type.IsValid())
1197
0
      return ValueObjectSP();
1198
1199
34
    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1200
1201
34
    if (m_ptr_size == 8) {
1202
34
      uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1203
34
      *data_ptr = dict_item.key_ptr;
1204
34
      *(data_ptr + 1) = dict_item.val_ptr;
1205
34
    } else {
1206
0
      uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1207
0
      *data_ptr = dict_item.key_ptr;
1208
0
      *(data_ptr + 1) = dict_item.val_ptr;
1209
0
    }
1210
1211
34
    StreamString idx_name;
1212
34
    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1213
34
    DataExtractor data(buffer_sp, m_order, m_ptr_size);
1214
34
    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1215
34
                                                    m_exe_ctx_ref, m_pair_type);
1216
34
  }
1217
34
  return dict_item.valobj_sp;
1218
34
}
NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1437::(anonymous namespace)::DataDescriptor_64>::GetChildAtIndex(unsigned long)
Line
Count
Source
1132
34
    D32, D64>::GetChildAtIndex(size_t idx) {
1133
34
  lldb::addr_t m_keys_ptr;
1134
34
  lldb::addr_t m_values_ptr;
1135
34
  if (m_data_32) {
1136
0
    uint32_t size = m_data_32->GetSize();
1137
0
    m_keys_ptr = m_data_32->_buffer;
1138
0
    m_values_ptr = m_data_32->_buffer + (m_ptr_size * size);
1139
34
  } else {
1140
34
    uint32_t size = m_data_64->GetSize();
1141
34
    m_keys_ptr = m_data_64->_buffer;
1142
34
    m_values_ptr = m_data_64->_buffer + (m_ptr_size * size);
1143
34
  }
1144
1145
34
  uint32_t num_children = CalculateNumChildren();
1146
1147
34
  if (idx >= num_children)
1148
0
    return lldb::ValueObjectSP();
1149
1150
34
  if (m_children.empty()) {
1151
    // do the scan phase
1152
22
    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1153
1154
22
    uint32_t tries = 0;
1155
22
    uint32_t test_idx = 0;
1156
1157
164
    while (tries < num_children) {
1158
142
      key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1159
142
      val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1160
142
      ;
1161
142
      ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1162
142
      if (!process_sp)
1163
0
        return lldb::ValueObjectSP();
1164
142
      Status error;
1165
142
      key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1166
142
      if (error.Fail())
1167
0
        return lldb::ValueObjectSP();
1168
142
      val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1169
142
      if (error.Fail())
1170
0
        return lldb::ValueObjectSP();
1171
1172
142
      test_idx++;
1173
1174
142
      if (!key_at_idx || 
!val_at_idx90
)
1175
52
        continue;
1176
90
      tries++;
1177
1178
90
      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1179
90
                                             lldb::ValueObjectSP()};
1180
1181
90
      m_children.push_back(descriptor);
1182
90
    }
1183
22
  }
1184
1185
34
  if (idx >= m_children.size()) // should never happen
1186
0
    return lldb::ValueObjectSP();
1187
1188
34
  DictionaryItemDescriptor &dict_item = m_children[idx];
1189
34
  if (!dict_item.valobj_sp) {
1190
34
    if (!m_pair_type.IsValid()) {
1191
22
      TargetSP target_sp(m_backend.GetTargetSP());
1192
22
      if (!target_sp)
1193
0
        return ValueObjectSP();
1194
22
      m_pair_type = GetLLDBNSPairType(target_sp);
1195
22
    }
1196
34
    if (!m_pair_type.IsValid())
1197
0
      return ValueObjectSP();
1198
1199
34
    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1200
1201
34
    if (m_ptr_size == 8) {
1202
34
      uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1203
34
      *data_ptr = dict_item.key_ptr;
1204
34
      *(data_ptr + 1) = dict_item.val_ptr;
1205
34
    } else {
1206
0
      uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1207
0
      *data_ptr = dict_item.key_ptr;
1208
0
      *(data_ptr + 1) = dict_item.val_ptr;
1209
0
    }
1210
1211
34
    StreamString idx_name;
1212
34
    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1213
34
    DataExtractor data(buffer_sp, m_order, m_ptr_size);
1214
34
    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1215
34
                                                    m_exe_ctx_ref, m_pair_type);
1216
34
  }
1217
34
  return dict_item.valobj_sp;
1218
34
}
Unexecuted instantiation: NSDictionary.cpp:lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_32, lldb_private::formatters::Foundation1428::(anonymous namespace)::DataDescriptor_64>::GetChildAtIndex(unsigned long)
1219
1220
lldb_private::formatters::Foundation1100::NSDictionaryMSyntheticFrontEnd::
1221
    NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
1222
0
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}
1223
1224
lldb_private::formatters::Foundation1100::
1225
0
  NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd() {
1226
0
  delete m_data_32;
1227
0
  m_data_32 = nullptr;
1228
0
  delete m_data_64;
1229
0
  m_data_64 = nullptr;
1230
0
}
1231
1232
size_t
1233
lldb_private::formatters::Foundation1100::
1234
0
  NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
1235
0
  const char *item_name = name.GetCString();
1236
0
  uint32_t idx = ExtractIndexFromString(item_name);
1237
0
  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1238
0
    return UINT32_MAX;
1239
0
  return idx;
1240
0
}
1241
1242
size_t
1243
lldb_private::formatters::Foundation1100::
1244
0
  NSDictionaryMSyntheticFrontEnd::CalculateNumChildren() {
1245
0
  if (!m_data_32 && !m_data_64)
1246
0
    return 0;
1247
0
  return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1248
0
}
1249
1250
bool
1251
lldb_private::formatters::Foundation1100::
1252
0
  NSDictionaryMSyntheticFrontEnd::Update() {
1253
0
  m_children.clear();
1254
0
  ValueObjectSP valobj_sp = m_backend.GetSP();
1255
0
  m_ptr_size = 0;
1256
0
  delete m_data_32;
1257
0
  m_data_32 = nullptr;
1258
0
  delete m_data_64;
1259
0
  m_data_64 = nullptr;
1260
0
  if (!valobj_sp)
1261
0
    return false;
1262
0
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1263
0
  Status error;
1264
0
  error.Clear();
1265
0
  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1266
0
  if (!process_sp)
1267
0
    return false;
1268
0
  m_ptr_size = process_sp->GetAddressByteSize();
1269
0
  m_order = process_sp->GetByteOrder();
1270
0
  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1271
0
  if (m_ptr_size == 4) {
1272
0
    m_data_32 = new DataDescriptor_32();
1273
0
    process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
1274
0
                           error);
1275
0
  } else {
1276
0
    m_data_64 = new DataDescriptor_64();
1277
0
    process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
1278
0
                           error);
1279
0
  }
1280
1281
0
  return error.Success();
1282
0
}
1283
1284
bool
1285
lldb_private::formatters::Foundation1100::
1286
0
  NSDictionaryMSyntheticFrontEnd::MightHaveChildren() {
1287
0
  return true;
1288
0
}
1289
1290
lldb::ValueObjectSP
1291
lldb_private::formatters::Foundation1100::
1292
0
  NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
1293
0
  lldb::addr_t m_keys_ptr =
1294
0
      (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1295
0
  lldb::addr_t m_values_ptr =
1296
0
      (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1297
1298
0
  uint32_t num_children = CalculateNumChildren();
1299
1300
0
  if (idx >= num_children)
1301
0
    return lldb::ValueObjectSP();
1302
1303
0
  if (m_children.empty()) {
1304
    // do the scan phase
1305
0
    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1306
1307
0
    uint32_t tries = 0;
1308
0
    uint32_t test_idx = 0;
1309
1310
0
    while (tries < num_children) {
1311
0
      key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1312
0
      val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1313
0
      ;
1314
0
      ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1315
0
      if (!process_sp)
1316
0
        return lldb::ValueObjectSP();
1317
0
      Status error;
1318
0
      key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1319
0
      if (error.Fail())
1320
0
        return lldb::ValueObjectSP();
1321
0
      val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1322
0
      if (error.Fail())
1323
0
        return lldb::ValueObjectSP();
1324
1325
0
      test_idx++;
1326
1327
0
      if (!key_at_idx || !val_at_idx)
1328
0
        continue;
1329
0
      tries++;
1330
1331
0
      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1332
0
                                             lldb::ValueObjectSP()};
1333
1334
0
      m_children.push_back(descriptor);
1335
0
    }
1336
0
  }
1337
1338
0
  if (idx >= m_children.size()) // should never happen
1339
0
    return lldb::ValueObjectSP();
1340
1341
0
  DictionaryItemDescriptor &dict_item = m_children[idx];
1342
0
  if (!dict_item.valobj_sp) {
1343
0
    if (!m_pair_type.IsValid()) {
1344
0
      TargetSP target_sp(m_backend.GetTargetSP());
1345
0
      if (!target_sp)
1346
0
        return ValueObjectSP();
1347
0
      m_pair_type = GetLLDBNSPairType(target_sp);
1348
0
    }
1349
0
    if (!m_pair_type.IsValid())
1350
0
      return ValueObjectSP();
1351
1352
0
    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1353
1354
0
    if (m_ptr_size == 8) {
1355
0
      uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1356
0
      *data_ptr = dict_item.key_ptr;
1357
0
      *(data_ptr + 1) = dict_item.val_ptr;
1358
0
    } else {
1359
0
      uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1360
0
      *data_ptr = dict_item.key_ptr;
1361
0
      *(data_ptr + 1) = dict_item.val_ptr;
1362
0
    }
1363
1364
0
    StreamString idx_name;
1365
0
    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1366
0
    DataExtractor data(buffer_sp, m_order, m_ptr_size);
1367
0
    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1368
0
                                                    m_exe_ctx_ref, m_pair_type);
1369
0
  }
1370
0
  return dict_item.valobj_sp;
1371
0
}
1372
1373
template bool lldb_private::formatters::NSDictionarySummaryProvider<true>(
1374
    ValueObject &, Stream &, const TypeSummaryOptions &);
1375
1376
template bool lldb_private::formatters::NSDictionarySummaryProvider<false>(
1377
    ValueObject &, Stream &, const TypeSummaryOptions &);