Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- AppleObjCClassDescriptorV2.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 "AppleObjCClassDescriptorV2.h"
10
11
#include "lldb/Expression/FunctionCaller.h"
12
#include "lldb/Target/ABI.h"
13
#include "lldb/Utility/Log.h"
14
15
using namespace lldb;
16
using namespace lldb_private;
17
18
bool ClassDescriptorV2::Read_objc_class(
19
2.81k
    Process *process, std::unique_ptr<objc_class_t> &objc_class) const {
20
2.81k
  objc_class = std::make_unique<objc_class_t>();
21
22
2.81k
  bool ret = objc_class->Read(process, m_objc_class_ptr);
23
24
2.81k
  if (!ret)
25
0
    objc_class.reset();
26
27
2.81k
  return ret;
28
2.81k
}
29
30
2.81k
static lldb::addr_t GetClassDataMask(Process *process) {
31
2.81k
  switch (process->GetAddressByteSize()) {
32
0
  case 4:
33
0
    return 0xfffffffcUL;
34
2.81k
  case 8:
35
2.81k
    return 0x00007ffffffffff8UL;
36
0
  default:
37
0
    break;
38
2.81k
  }
39
40
0
  return LLDB_INVALID_ADDRESS;
41
2.81k
}
42
43
bool ClassDescriptorV2::objc_class_t::Read(Process *process,
44
2.81k
                                           lldb::addr_t addr) {
45
2.81k
  size_t ptr_size = process->GetAddressByteSize();
46
47
2.81k
  size_t objc_class_size = ptr_size    // uintptr_t isa;
48
2.81k
                           + ptr_size  // Class superclass;
49
2.81k
                           + ptr_size  // void *cache;
50
2.81k
                           + ptr_size  // IMP *vtable;
51
2.81k
                           + ptr_size; // uintptr_t data_NEVER_USE;
52
53
2.81k
  DataBufferHeap objc_class_buf(objc_class_size, '\0');
54
2.81k
  Status error;
55
56
2.81k
  process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
57
2.81k
  if (error.Fail()) {
58
0
    return false;
59
0
  }
60
61
2.81k
  DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size,
62
2.81k
                          process->GetByteOrder(),
63
2.81k
                          process->GetAddressByteSize());
64
65
2.81k
  lldb::offset_t cursor = 0;
66
67
2.81k
  m_isa = extractor.GetAddress_unchecked(&cursor);        // uintptr_t isa;
68
2.81k
  m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
69
2.81k
  m_cache_ptr = extractor.GetAddress_unchecked(&cursor);  // void *cache;
70
2.81k
  m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
71
2.81k
  lldb::addr_t data_NEVER_USE =
72
2.81k
      extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
73
74
2.81k
  m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
75
2.81k
  m_data_ptr = data_NEVER_USE & GetClassDataMask(process);
76
77
2.81k
  if (ABISP abi_sp = process->GetABI()) {
78
2.81k
    m_isa = abi_sp->FixCodeAddress(m_isa);
79
2.81k
    m_superclass = abi_sp->FixCodeAddress(m_superclass);
80
2.81k
  }
81
2.81k
  return true;
82
2.81k
}
83
84
1.91k
bool ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr) {
85
1.91k
  size_t ptr_size = process->GetAddressByteSize();
86
87
1.91k
  size_t size = sizeof(uint32_t)   // uint32_t flags;
88
1.91k
                + sizeof(uint32_t) // uint32_t version;
89
1.91k
                + ptr_size         // const class_ro_t *ro;
90
1.91k
                + ptr_size         // union { method_list_t **method_lists;
91
                                   // method_list_t *method_list; };
92
1.91k
                + ptr_size         // struct chained_property_list *properties;
93
1.91k
                + ptr_size         // const protocol_list_t **protocols;
94
1.91k
                + ptr_size         // Class firstSubclass;
95
1.91k
                + ptr_size;        // Class nextSiblingClass;
96
97
1.91k
  DataBufferHeap buffer(size, '\0');
98
1.91k
  Status error;
99
100
1.91k
  process->ReadMemory(addr, buffer.GetBytes(), size, error);
101
1.91k
  if (error.Fail()) {
102
0
    return false;
103
0
  }
104
105
1.91k
  DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
106
1.91k
                          process->GetAddressByteSize());
107
108
1.91k
  lldb::offset_t cursor = 0;
109
110
1.91k
  m_flags = extractor.GetU32_unchecked(&cursor);
111
1.91k
  m_version = extractor.GetU32_unchecked(&cursor);
112
1.91k
  m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
113
1.91k
  if (ABISP abi_sp = process->GetABI())
114
1.91k
    m_ro_ptr = abi_sp->FixCodeAddress(m_ro_ptr);
115
1.91k
  m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
116
1.91k
  m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
117
1.91k
  m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
118
1.91k
  m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
119
120
1.91k
  if (m_ro_ptr & 1) {
121
683
    DataBufferHeap buffer(ptr_size, '\0');
122
683
    process->ReadMemory(m_ro_ptr ^ 1, buffer.GetBytes(), ptr_size, error);
123
683
    if (error.Fail())
124
0
      return false;
125
683
    cursor = 0;
126
683
    DataExtractor extractor(buffer.GetBytes(), ptr_size,
127
683
                            process->GetByteOrder(),
128
683
                            process->GetAddressByteSize());
129
683
    m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
130
683
    if (ABISP abi_sp = process->GetABI())
131
683
      m_ro_ptr = abi_sp->FixCodeAddress(m_ro_ptr);
132
683
  }
133
134
1.91k
  return true;
135
1.91k
}
136
137
1.95k
bool ClassDescriptorV2::class_ro_t::Read(Process *process, lldb::addr_t addr) {
138
1.95k
  size_t ptr_size = process->GetAddressByteSize();
139
140
1.95k
  size_t size = sizeof(uint32_t)   // uint32_t flags;
141
1.95k
                + sizeof(uint32_t) // uint32_t instanceStart;
142
1.95k
                + sizeof(uint32_t) // uint32_t instanceSize;
143
1.95k
                + (ptr_size == 8 ? sizeof(uint32_t)
144
1.95k
                                 : 
00
) // uint32_t reserved; // __LP64__ only
145
1.95k
                + ptr_size            // const uint8_t *ivarLayout;
146
1.95k
                + ptr_size            // const char *name;
147
1.95k
                + ptr_size            // const method_list_t *baseMethods;
148
1.95k
                + ptr_size            // const protocol_list_t *baseProtocols;
149
1.95k
                + ptr_size            // const ivar_list_t *ivars;
150
1.95k
                + ptr_size            // const uint8_t *weakIvarLayout;
151
1.95k
                + ptr_size;           // const property_list_t *baseProperties;
152
153
1.95k
  DataBufferHeap buffer(size, '\0');
154
1.95k
  Status error;
155
156
1.95k
  process->ReadMemory(addr, buffer.GetBytes(), size, error);
157
1.95k
  if (error.Fail()) {
158
0
    return false;
159
0
  }
160
161
1.95k
  DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
162
1.95k
                          process->GetAddressByteSize());
163
164
1.95k
  lldb::offset_t cursor = 0;
165
166
1.95k
  m_flags = extractor.GetU32_unchecked(&cursor);
167
1.95k
  m_instanceStart = extractor.GetU32_unchecked(&cursor);
168
1.95k
  m_instanceSize = extractor.GetU32_unchecked(&cursor);
169
1.95k
  if (ptr_size == 8)
170
1.95k
    m_reserved = extractor.GetU32_unchecked(&cursor);
171
0
  else
172
0
    m_reserved = 0;
173
1.95k
  m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
174
1.95k
  m_name_ptr = extractor.GetAddress_unchecked(&cursor);
175
1.95k
  m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
176
1.95k
  m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
177
1.95k
  m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
178
1.95k
  m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
179
1.95k
  m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
180
181
1.95k
  DataBufferHeap name_buf(1024, '\0');
182
183
1.95k
  process->ReadCStringFromMemory(m_name_ptr, (char *)name_buf.GetBytes(),
184
1.95k
                                 name_buf.GetByteSize(), error);
185
186
1.95k
  if (error.Fail()) {
187
0
    return false;
188
0
  }
189
190
1.95k
  m_name.assign((char *)name_buf.GetBytes());
191
192
1.95k
  return true;
193
1.95k
}
194
195
bool ClassDescriptorV2::Read_class_row(
196
    Process *process, const objc_class_t &objc_class,
197
    std::unique_ptr<class_ro_t> &class_ro,
198
1.95k
    std::unique_ptr<class_rw_t> &class_rw) const {
199
1.95k
  class_ro.reset();
200
1.95k
  class_rw.reset();
201
202
1.95k
  Status error;
203
1.95k
  uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(
204
1.95k
      objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
205
1.95k
  if (!error.Success())
206
0
    return false;
207
208
1.95k
  if (class_row_t_flags & RW_REALIZED) {
209
1.91k
    class_rw = std::make_unique<class_rw_t>();
210
211
1.91k
    if (!class_rw->Read(process, objc_class.m_data_ptr)) {
212
0
      class_rw.reset();
213
0
      return false;
214
0
    }
215
216
1.91k
    class_ro = std::make_unique<class_ro_t>();
217
218
1.91k
    if (!class_ro->Read(process, class_rw->m_ro_ptr)) {
219
0
      class_rw.reset();
220
0
      class_ro.reset();
221
0
      return false;
222
0
    }
223
1.91k
  } else {
224
39
    class_ro = std::make_unique<class_ro_t>();
225
226
39
    if (!class_ro->Read(process, objc_class.m_data_ptr)) {
227
0
      class_ro.reset();
228
0
      return false;
229
0
    }
230
39
  }
231
232
1.95k
  return true;
233
1.95k
}
234
235
bool ClassDescriptorV2::method_list_t::Read(Process *process,
236
795
                                            lldb::addr_t addr) {
237
795
  size_t size = sizeof(uint32_t)    // uint32_t entsize_NEVER_USE;
238
795
                + sizeof(uint32_t); // uint32_t count;
239
240
795
  DataBufferHeap buffer(size, '\0');
241
795
  Status error;
242
243
795
  if (ABISP abi_sp = process->GetABI())
244
795
    addr = abi_sp->FixCodeAddress(addr);
245
795
  process->ReadMemory(addr, buffer.GetBytes(), size, error);
246
795
  if (error.Fail()) {
247
68
    return false;
248
68
  }
249
250
727
  DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
251
727
                          process->GetAddressByteSize());
252
253
727
  lldb::offset_t cursor = 0;
254
255
727
  uint32_t entsize = extractor.GetU32_unchecked(&cursor);
256
727
  m_is_small = (entsize & 0x80000000) != 0;
257
727
  m_has_direct_selector = (entsize & 0x40000000) != 0;
258
727
  m_entsize = entsize & 0xfffc;
259
727
  m_count = extractor.GetU32_unchecked(&cursor);
260
727
  m_first_ptr = addr + cursor;
261
262
727
  return true;
263
795
}
264
265
bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
266
                                       lldb::addr_t relative_selector_base_addr,
267
24.3k
                                       bool is_small, bool has_direct_sel) {
268
24.3k
  size_t ptr_size = process->GetAddressByteSize();
269
24.3k
  size_t size = GetSize(process, is_small);
270
271
24.3k
  DataBufferHeap buffer(size, '\0');
272
24.3k
  Status error;
273
274
24.3k
  process->ReadMemory(addr, buffer.GetBytes(), size, error);
275
24.3k
  if (error.Fail()) {
276
0
    return false;
277
0
  }
278
279
24.3k
  DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
280
24.3k
                          ptr_size);
281
24.3k
  lldb::offset_t cursor = 0;
282
283
24.3k
  if (is_small) {
284
0
    uint32_t nameref_offset = extractor.GetU32_unchecked(&cursor);
285
0
    uint32_t types_offset = extractor.GetU32_unchecked(&cursor);
286
0
    uint32_t imp_offset = extractor.GetU32_unchecked(&cursor);
287
288
0
    m_name_ptr = addr + nameref_offset;
289
290
0
    if (!has_direct_sel) {
291
      // The SEL offset points to a SELRef. We need to dereference twice.
292
0
      m_name_ptr = process->ReadUnsignedIntegerFromMemory(m_name_ptr, ptr_size,
293
0
                                                          0, error);
294
0
      if (!error.Success())
295
0
        return false;
296
0
    } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) {
297
0
      m_name_ptr = relative_selector_base_addr + nameref_offset;
298
0
    }
299
0
    m_types_ptr = addr + 4 + types_offset;
300
0
    m_imp_ptr = addr + 8 + imp_offset;
301
24.3k
  } else {
302
24.3k
    m_name_ptr = extractor.GetAddress_unchecked(&cursor);
303
24.3k
    m_types_ptr = extractor.GetAddress_unchecked(&cursor);
304
24.3k
    m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
305
24.3k
  }
306
307
24.3k
  process->ReadCStringFromMemory(m_name_ptr, m_name, error);
308
24.3k
  if (error.Fail()) {
309
0
    return false;
310
0
  }
311
312
24.3k
  process->ReadCStringFromMemory(m_types_ptr, m_types, error);
313
24.3k
  return !error.Fail();
314
24.3k
}
315
316
308
bool ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr) {
317
308
  size_t size = sizeof(uint32_t)    // uint32_t entsize;
318
308
                + sizeof(uint32_t); // uint32_t count;
319
320
308
  DataBufferHeap buffer(size, '\0');
321
308
  Status error;
322
323
308
  process->ReadMemory(addr, buffer.GetBytes(), size, error);
324
308
  if (error.Fail()) {
325
0
    return false;
326
0
  }
327
328
308
  DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
329
308
                          process->GetAddressByteSize());
330
331
308
  lldb::offset_t cursor = 0;
332
333
308
  m_entsize = extractor.GetU32_unchecked(&cursor);
334
308
  m_count = extractor.GetU32_unchecked(&cursor);
335
308
  m_first_ptr = addr + cursor;
336
337
308
  return true;
338
308
}
339
340
684
bool ClassDescriptorV2::ivar_t::Read(Process *process, lldb::addr_t addr) {
341
684
  size_t size = GetSize(process);
342
343
684
  DataBufferHeap buffer(size, '\0');
344
684
  Status error;
345
346
684
  process->ReadMemory(addr, buffer.GetBytes(), size, error);
347
684
  if (error.Fail()) {
348
0
    return false;
349
0
  }
350
351
684
  DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
352
684
                          process->GetAddressByteSize());
353
354
684
  lldb::offset_t cursor = 0;
355
356
684
  m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
357
684
  m_name_ptr = extractor.GetAddress_unchecked(&cursor);
358
684
  m_type_ptr = extractor.GetAddress_unchecked(&cursor);
359
684
  m_alignment = extractor.GetU32_unchecked(&cursor);
360
684
  m_size = extractor.GetU32_unchecked(&cursor);
361
362
684
  process->ReadCStringFromMemory(m_name_ptr, m_name, error);
363
684
  if (error.Fail()) {
364
0
    return false;
365
0
  }
366
367
684
  process->ReadCStringFromMemory(m_type_ptr, m_type, error);
368
684
  return !error.Fail();
369
684
}
370
371
bool ClassDescriptorV2::Describe(
372
    std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
373
    std::function<bool(const char *, const char *)> const &instance_method_func,
374
    std::function<bool(const char *, const char *)> const &class_method_func,
375
    std::function<bool(const char *, const char *, lldb::addr_t,
376
868
                       uint64_t)> const &ivar_func) const {
377
868
  lldb_private::Process *process = m_runtime.GetProcess();
378
379
868
  std::unique_ptr<objc_class_t> objc_class;
380
868
  std::unique_ptr<class_ro_t> class_ro;
381
868
  std::unique_ptr<class_rw_t> class_rw;
382
383
868
  if (!Read_objc_class(process, objc_class))
384
0
    return false;
385
868
  if (!Read_class_row(process, *objc_class, class_ro, class_rw))
386
0
    return false;
387
388
868
  static ConstString NSObject_name("NSObject");
389
390
868
  if (m_name != NSObject_name && 
superclass_func737
)
391
268
    superclass_func(objc_class->m_superclass);
392
393
868
  if (instance_method_func) {
394
795
    std::unique_ptr<method_list_t> base_method_list;
395
396
795
    base_method_list = std::make_unique<method_list_t>();
397
795
    if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
398
68
      return false;
399
400
727
    bool is_small = base_method_list->m_is_small;
401
727
    bool has_direct_selector = base_method_list->m_has_direct_selector;
402
403
727
    if (base_method_list->m_entsize != method_t::GetSize(process, is_small))
404
0
      return false;
405
406
727
    std::unique_ptr<method_t> method = std::make_unique<method_t>();
407
727
    lldb::addr_t relative_selector_base_addr =
408
727
        m_runtime.GetRelativeSelectorBaseAddr();
409
25.0k
    for (uint32_t i = 0, e = base_method_list->m_count; i < e; 
++i24.3k
) {
410
24.3k
      method->Read(process,
411
24.3k
                   base_method_list->m_first_ptr +
412
24.3k
                       (i * base_method_list->m_entsize),
413
24.3k
                   relative_selector_base_addr, is_small, has_direct_selector);
414
415
24.3k
      if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
416
0
        break;
417
24.3k
    }
418
727
  }
419
420
800
  if (class_method_func) {
421
396
    AppleObjCRuntime::ClassDescriptorSP metaclass(GetMetaclass());
422
423
    // We don't care about the metaclass's superclass, or its class methods.
424
    // Its instance methods are our class methods.
425
426
396
    if (metaclass) {
427
396
      metaclass->Describe(
428
396
          std::function<void(ObjCLanguageRuntime::ObjCISA)>(nullptr),
429
396
          class_method_func,
430
396
          std::function<bool(const char *, const char *)>(nullptr),
431
396
          std::function<bool(const char *, const char *, lldb::addr_t,
432
396
                             uint64_t)>(nullptr));
433
396
    }
434
396
  }
435
436
800
  if (ivar_func) {
437
469
    if (class_ro->m_ivars_ptr != 0) {
438
308
      ivar_list_t ivar_list;
439
308
      if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
440
0
        return false;
441
442
308
      if (ivar_list.m_entsize != ivar_t::GetSize(process))
443
0
        return false;
444
445
308
      ivar_t ivar;
446
447
986
      for (uint32_t i = 0, e = ivar_list.m_count; i < e; 
++i678
) {
448
684
        ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
449
450
684
        if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(),
451
684
                      ivar.m_offset_ptr, ivar.m_size))
452
6
          break;
453
684
      }
454
308
    }
455
469
  }
456
457
800
  return true;
458
800
}
459
460
8.33k
ConstString ClassDescriptorV2::GetClassName() {
461
8.33k
  if (!m_name) {
462
1.08k
    lldb_private::Process *process = m_runtime.GetProcess();
463
464
1.08k
    if (process) {
465
1.08k
      std::unique_ptr<objc_class_t> objc_class;
466
1.08k
      std::unique_ptr<class_ro_t> class_ro;
467
1.08k
      std::unique_ptr<class_rw_t> class_rw;
468
469
1.08k
      if (!Read_objc_class(process, objc_class))
470
0
        return m_name;
471
1.08k
      if (!Read_class_row(process, *objc_class, class_ro, class_rw))
472
0
        return m_name;
473
474
1.08k
      m_name = ConstString(class_ro->m_name.c_str());
475
1.08k
    }
476
1.08k
  }
477
8.33k
  return m_name;
478
8.33k
}
479
480
462
ObjCLanguageRuntime::ClassDescriptorSP ClassDescriptorV2::GetSuperclass() {
481
462
  lldb_private::Process *process = m_runtime.GetProcess();
482
483
462
  if (!process)
484
0
    return ObjCLanguageRuntime::ClassDescriptorSP();
485
486
462
  std::unique_ptr<objc_class_t> objc_class;
487
488
462
  if (!Read_objc_class(process, objc_class))
489
0
    return ObjCLanguageRuntime::ClassDescriptorSP();
490
491
462
  return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(
492
462
      objc_class->m_superclass);
493
462
}
494
495
396
ObjCLanguageRuntime::ClassDescriptorSP ClassDescriptorV2::GetMetaclass() const {
496
396
  lldb_private::Process *process = m_runtime.GetProcess();
497
498
396
  if (!process)
499
0
    return ObjCLanguageRuntime::ClassDescriptorSP();
500
501
396
  std::unique_ptr<objc_class_t> objc_class;
502
503
396
  if (!Read_objc_class(process, objc_class))
504
0
    return ObjCLanguageRuntime::ClassDescriptorSP();
505
506
396
  lldb::addr_t candidate_isa = m_runtime.GetPointerISA(objc_class->m_isa);
507
508
396
  return ObjCLanguageRuntime::ClassDescriptorSP(
509
396
      new ClassDescriptorV2(m_runtime, candidate_isa, nullptr));
510
396
}
511
512
0
uint64_t ClassDescriptorV2::GetInstanceSize() {
513
0
  lldb_private::Process *process = m_runtime.GetProcess();
514
515
0
  if (process) {
516
0
    std::unique_ptr<objc_class_t> objc_class;
517
0
    std::unique_ptr<class_ro_t> class_ro;
518
0
    std::unique_ptr<class_rw_t> class_rw;
519
520
0
    if (!Read_objc_class(process, objc_class))
521
0
      return 0;
522
0
    if (!Read_class_row(process, *objc_class, class_ro, class_rw))
523
0
      return 0;
524
525
0
    return class_ro->m_instanceSize;
526
0
  }
527
528
0
  return 0;
529
0
}
530
531
97.5M
ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_ivars(), m_mutex() {}
532
533
636
size_t ClassDescriptorV2::iVarsStorage::size() { return m_ivars.size(); }
534
535
ClassDescriptorV2::iVarDescriptor &ClassDescriptorV2::iVarsStorage::
536
261
operator[](size_t idx) {
537
261
  return m_ivars[idx];
538
261
}
539
540
void ClassDescriptorV2::iVarsStorage::fill(AppleObjCRuntimeV2 &runtime,
541
636
                                           ClassDescriptorV2 &descriptor) {
542
636
  if (m_filled)
543
569
    return;
544
67
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
545
67
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
546
67
  LLDB_LOGV(log, "class_name = {0}", descriptor.GetClassName());
547
67
  m_filled = true;
548
67
  ObjCLanguageRuntime::EncodingToTypeSP encoding_to_type_sp(
549
67
      runtime.GetEncodingToType());
550
67
  Process *process(runtime.GetProcess());
551
67
  if (!encoding_to_type_sp)
552
0
    return;
553
67
  descriptor.Describe(nullptr, nullptr, nullptr, [this, process,
554
67
                                                  encoding_to_type_sp,
555
67
                                                  log](const char *name,
556
67
                                                       const char *type,
557
67
                                                       lldb::addr_t offset_ptr,
558
198
                                                       uint64_t size) -> bool {
559
198
    const bool for_expression = false;
560
198
    const bool stop_loop = false;
561
198
    LLDB_LOGV(log, "name = {0}, encoding = {1}, offset_ptr = {2:x}, size = {3}",
562
198
              name, type, offset_ptr, size);
563
198
    CompilerType ivar_type =
564
198
        encoding_to_type_sp->RealizeType(type, for_expression);
565
198
    if (ivar_type) {
566
186
      LLDB_LOGV(log,
567
186
                "name = {0}, encoding = {1}, offset_ptr = {2:x}, size = "
568
186
                "{3}, type_size = {4}",
569
186
                name, type, offset_ptr, size,
570
186
                ivar_type.GetByteSize(nullptr).getValueOr(0));
571
186
      Scalar offset_scalar;
572
186
      Status error;
573
186
      const int offset_ptr_size = 4;
574
186
      const bool is_signed = false;
575
186
      size_t read = process->ReadScalarIntegerFromMemory(
576
186
          offset_ptr, offset_ptr_size, is_signed, offset_scalar, error);
577
186
      if (error.Success() && 4 == read) {
578
186
        LLDB_LOGV(log, "offset_ptr = {0:x} --> {1}", offset_ptr,
579
186
                  offset_scalar.SInt());
580
186
        m_ivars.push_back(
581
186
            {ConstString(name), ivar_type, size, offset_scalar.SInt()});
582
186
      } else
583
0
        LLDB_LOGV(log, "offset_ptr = {0:x} --> read fail, read = %{1}",
584
186
                  offset_ptr, read);
585
186
    }
586
198
    return stop_loop;
587
198
  });
588
67
}
589
590
636
void ClassDescriptorV2::GetIVarInformation() {
591
636
  m_ivars_storage.fill(m_runtime, *this);
592
636
}