Coverage Report

Created: 2022-01-25 06:29

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