LLDB mainline
AppleObjCClassDescriptorV2.cpp
Go to the documentation of this file.
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
10
12#include "lldb/Target/ABI.h"
15#include "lldb/Utility/Log.h"
17
18using namespace lldb;
19using namespace lldb_private;
20
22 Process *process, std::unique_ptr<objc_class_t> &objc_class) const {
23 objc_class = std::make_unique<objc_class_t>();
24
25 bool ret = objc_class->Read(process, m_objc_class_ptr);
26
27 if (!ret)
28 objc_class.reset();
29
30 return ret;
31}
32
34 switch (process->GetAddressByteSize()) {
35 case 4:
36 return 0xfffffffcUL;
37 case 8:
38 return 0x00007ffffffffff8UL;
39 default:
40 break;
41 }
42
44}
45
47 lldb::addr_t addr) {
48 size_t ptr_size = process->GetAddressByteSize();
49
50 size_t objc_class_size = ptr_size // uintptr_t isa;
51 + ptr_size // Class superclass;
52 + ptr_size // void *cache;
53 + ptr_size // IMP *vtable;
54 + ptr_size; // uintptr_t data_NEVER_USE;
55
56 DataBufferHeap objc_class_buf(objc_class_size, '\0');
58
59 process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
60 if (error.Fail()) {
61 return false;
62 }
63
64 DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size,
65 process->GetByteOrder(),
66 process->GetAddressByteSize());
67
68 lldb::offset_t cursor = 0;
69
70 m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
71 m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
72 m_cache_ptr = extractor.GetAddress_unchecked(&cursor); // void *cache;
73 m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
74 lldb::addr_t data_NEVER_USE =
75 extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
76
77 m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
78 m_data_ptr = data_NEVER_USE & GetClassDataMask(process);
79
80 if (ABISP abi_sp = process->GetABI()) {
81 m_isa = abi_sp->FixCodeAddress(m_isa);
82 m_superclass = abi_sp->FixCodeAddress(m_superclass);
83 m_data_ptr = abi_sp->FixCodeAddress(m_data_ptr);
84 }
85 return true;
86}
87
89 size_t ptr_size = process->GetAddressByteSize();
90
91 size_t size = sizeof(uint32_t) // uint32_t flags;
92 + sizeof(uint32_t) // uint32_t version;
93 + ptr_size // const class_ro_t *ro;
94 + ptr_size // union { method_list_t **method_lists;
95 // method_list_t *method_list; };
96 + ptr_size // struct chained_property_list *properties;
97 + ptr_size // const protocol_list_t **protocols;
98 + ptr_size // Class firstSubclass;
99 + ptr_size; // Class nextSiblingClass;
100
101 DataBufferHeap buffer(size, '\0');
103
104 process->ReadMemory(addr, buffer.GetBytes(), size, error);
105 if (error.Fail()) {
106 return false;
107 }
108
109 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
110 process->GetAddressByteSize());
111
112 lldb::offset_t cursor = 0;
113
114 m_flags = extractor.GetU32_unchecked(&cursor);
115 m_version = extractor.GetU32_unchecked(&cursor);
116 m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
117 if (ABISP abi_sp = process->GetABI())
118 m_ro_ptr = abi_sp->FixCodeAddress(m_ro_ptr);
119 m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
120 m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
121 m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
122 m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
123
124 if (m_ro_ptr & 1) {
125 DataBufferHeap buffer(ptr_size, '\0');
126 process->ReadMemory(m_ro_ptr ^ 1, buffer.GetBytes(), ptr_size, error);
127 if (error.Fail())
128 return false;
129 cursor = 0;
130 DataExtractor extractor(buffer.GetBytes(), ptr_size,
131 process->GetByteOrder(),
132 process->GetAddressByteSize());
133 m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
134 if (ABISP abi_sp = process->GetABI())
135 m_ro_ptr = abi_sp->FixCodeAddress(m_ro_ptr);
136 }
137
138 return true;
139}
140
142 size_t ptr_size = process->GetAddressByteSize();
143
144 size_t size = sizeof(uint32_t) // uint32_t flags;
145 + sizeof(uint32_t) // uint32_t instanceStart;
146 + sizeof(uint32_t) // uint32_t instanceSize;
147 + (ptr_size == 8 ? sizeof(uint32_t)
148 : 0) // uint32_t reserved; // __LP64__ only
149 + ptr_size // const uint8_t *ivarLayout;
150 + ptr_size // const char *name;
151 + ptr_size // const method_list_t *baseMethods;
152 + ptr_size // const protocol_list_t *baseProtocols;
153 + ptr_size // const ivar_list_t *ivars;
154 + ptr_size // const uint8_t *weakIvarLayout;
155 + ptr_size; // const property_list_t *baseProperties;
156
157 DataBufferHeap buffer(size, '\0');
159
160 process->ReadMemory(addr, buffer.GetBytes(), size, error);
161 if (error.Fail()) {
162 return false;
163 }
164
165 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
166 process->GetAddressByteSize());
167
168 lldb::offset_t cursor = 0;
169
170 m_flags = extractor.GetU32_unchecked(&cursor);
171 m_instanceStart = extractor.GetU32_unchecked(&cursor);
172 m_instanceSize = extractor.GetU32_unchecked(&cursor);
173 if (ptr_size == 8)
174 m_reserved = extractor.GetU32_unchecked(&cursor);
175 else
176 m_reserved = 0;
177 m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
178 m_name_ptr = extractor.GetAddress_unchecked(&cursor);
179 m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
180 m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
181 m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
182 m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
183 m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
184
185 DataBufferHeap name_buf(1024, '\0');
186
187 process->ReadCStringFromMemory(m_name_ptr, (char *)name_buf.GetBytes(),
188 name_buf.GetByteSize(), error);
189
190 if (error.Fail()) {
191 return false;
192 }
193
194 m_name.assign((char *)name_buf.GetBytes());
195
196 return true;
197}
198
200 Process *process, const objc_class_t &objc_class,
201 std::unique_ptr<class_ro_t> &class_ro,
202 std::unique_ptr<class_rw_t> &class_rw) const {
203 class_ro.reset();
204 class_rw.reset();
205
207 uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(
208 objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
209 if (!error.Success())
210 return false;
211
212 if (class_row_t_flags & RW_REALIZED) {
213 class_rw = std::make_unique<class_rw_t>();
214
215 if (!class_rw->Read(process, objc_class.m_data_ptr)) {
216 class_rw.reset();
217 return false;
218 }
219
220 class_ro = std::make_unique<class_ro_t>();
221
222 if (!class_ro->Read(process, class_rw->m_ro_ptr)) {
223 class_rw.reset();
224 class_ro.reset();
225 return false;
226 }
227 } else {
228 class_ro = std::make_unique<class_ro_t>();
229
230 if (!class_ro->Read(process, objc_class.m_data_ptr)) {
231 class_ro.reset();
232 return false;
233 }
234 }
235
236 return true;
237}
238
240 lldb::addr_t addr) {
241 size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE;
242 + sizeof(uint32_t); // uint32_t count;
243
244 DataBufferHeap buffer(size, '\0');
246
247 if (ABISP abi_sp = process->GetABI())
248 addr = abi_sp->FixCodeAddress(addr);
249 process->ReadMemory(addr, buffer.GetBytes(), size, error);
250 if (error.Fail()) {
251 return false;
252 }
253
254 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
255 process->GetAddressByteSize());
256
257 lldb::offset_t cursor = 0;
258
259 uint32_t entsize = extractor.GetU32_unchecked(&cursor);
260 m_is_small = (entsize & 0x80000000) != 0;
261 m_has_direct_selector = (entsize & 0x40000000) != 0;
262 m_entsize = entsize & 0xfffc;
263 m_count = extractor.GetU32_unchecked(&cursor);
264 m_first_ptr = addr + cursor;
265
266 return true;
267}
268
270 lldb::addr_t relative_selector_base_addr,
271 bool is_small, bool has_direct_sel) {
272 size_t ptr_size = process->GetAddressByteSize();
273 size_t size = GetSize(process, is_small);
274
275 DataBufferHeap buffer(size, '\0');
277
278 process->ReadMemory(addr, buffer.GetBytes(), size, error);
279 if (error.Fail()) {
280 return false;
281 }
282
283 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
284 ptr_size);
285 lldb::offset_t cursor = 0;
286
287 if (is_small) {
288 uint32_t nameref_offset = extractor.GetU32_unchecked(&cursor);
289 uint32_t types_offset = extractor.GetU32_unchecked(&cursor);
290 uint32_t imp_offset = extractor.GetU32_unchecked(&cursor);
291
292 m_name_ptr = addr + nameref_offset;
293
294 if (!has_direct_sel) {
295 // The SEL offset points to a SELRef. We need to dereference twice.
296 m_name_ptr = process->ReadUnsignedIntegerFromMemory(m_name_ptr, ptr_size,
297 0, error);
298 if (!error.Success())
299 return false;
300 } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) {
301 m_name_ptr = relative_selector_base_addr + nameref_offset;
302 }
303 m_types_ptr = addr + 4 + types_offset;
304 m_imp_ptr = addr + 8 + imp_offset;
305 } else {
306 m_name_ptr = extractor.GetAddress_unchecked(&cursor);
307 m_types_ptr = extractor.GetAddress_unchecked(&cursor);
308 m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
309 }
310
311 process->ReadCStringFromMemory(m_name_ptr, m_name, error);
312 if (error.Fail()) {
313 return false;
314 }
315
316 process->ReadCStringFromMemory(m_types_ptr, m_types, error);
317 return !error.Fail();
318}
319
321 size_t size = sizeof(uint32_t) // uint32_t entsize;
322 + sizeof(uint32_t); // uint32_t count;
323
324 DataBufferHeap buffer(size, '\0');
326
327 process->ReadMemory(addr, buffer.GetBytes(), size, error);
328 if (error.Fail()) {
329 return false;
330 }
331
332 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
333 process->GetAddressByteSize());
334
335 lldb::offset_t cursor = 0;
336
337 m_entsize = extractor.GetU32_unchecked(&cursor);
338 m_count = extractor.GetU32_unchecked(&cursor);
339 m_first_ptr = addr + cursor;
340
341 return true;
342}
343
345 size_t size = GetSize(process);
346
347 DataBufferHeap buffer(size, '\0');
349
350 process->ReadMemory(addr, buffer.GetBytes(), size, error);
351 if (error.Fail()) {
352 return false;
353 }
354
355 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
356 process->GetAddressByteSize());
357
358 lldb::offset_t cursor = 0;
359
360 m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
361 m_name_ptr = extractor.GetAddress_unchecked(&cursor);
362 m_type_ptr = extractor.GetAddress_unchecked(&cursor);
363 m_alignment = extractor.GetU32_unchecked(&cursor);
364 m_size = extractor.GetU32_unchecked(&cursor);
365
366 process->ReadCStringFromMemory(m_name_ptr, m_name, error);
367 if (error.Fail()) {
368 return false;
369 }
370
371 process->ReadCStringFromMemory(m_type_ptr, m_type, error);
372 return !error.Fail();
373}
374
376 lldb::addr_t addr) {
377 Log *log = GetLog(LLDBLog::Types);
378 size_t size = sizeof(uint64_t); // m_image_index : 16
379 // m_list_offset : 48
380
381 DataBufferHeap buffer(size, '\0');
383
384 process->ReadMemory(addr, buffer.GetBytes(), size, error);
385 // FIXME: Propagate this error up
386 if (error.Fail()) {
387 LLDB_LOG(log, "Failed to read relative_list_entry_t at address {0:x}",
388 addr);
389 return false;
390 }
391
392 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
393 process->GetAddressByteSize());
394 lldb::offset_t cursor = 0;
395 uint64_t raw_entry = extractor.GetU64_unchecked(&cursor);
396 m_image_index = raw_entry & 0xFFFF;
397 m_list_offset = llvm::SignExtend64<48>(raw_entry >> 16);
398 return true;
399}
400
402 lldb::addr_t addr) {
403 Log *log = GetLog(LLDBLog::Types);
404 size_t size = sizeof(uint32_t) // m_entsize
405 + sizeof(uint32_t); // m_count
406
407 DataBufferHeap buffer(size, '\0');
409
410 // FIXME: Propagate this error up
411 process->ReadMemory(addr, buffer.GetBytes(), size, error);
412 if (error.Fail()) {
413 LLDB_LOG(log, "Failed to read relative_list_list_t at address 0x" PRIx64,
414 addr);
415 return false;
416 }
417
418 DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
419 process->GetAddressByteSize());
420 lldb::offset_t cursor = 0;
421 m_entsize = extractor.GetU32_unchecked(&cursor);
422 m_count = extractor.GetU32_unchecked(&cursor);
423 m_first_ptr = addr + cursor;
424 return true;
425}
426
427std::optional<ClassDescriptorV2::method_list_t>
429 lldb::addr_t method_list_ptr) const {
430 Log *log = GetLog(LLDBLog::Types);
432 if (!method_list.Read(process, method_list_ptr))
433 return std::nullopt;
434
435 const size_t method_size = method_t::GetSize(process, method_list.m_is_small);
436 if (method_list.m_entsize != method_size) {
437 LLDB_LOG(log,
438 "method_list_t at address 0x" PRIx64 " has an entsize of " PRIu16
439 " but method size should be " PRIu64,
440 method_list_ptr, method_list.m_entsize, method_size);
441 return std::nullopt;
442 }
443
444 return method_list;
445}
446
448 std::function<bool(const char *, const char *)> const &instance_method_func,
449 ClassDescriptorV2::method_list_t &method_list) const {
451 auto method = std::make_unique<method_t>();
452 lldb::addr_t relative_selector_base_addr =
454 for (uint32_t i = 0, e = method_list.m_count; i < e; ++i) {
455 method->Read(process, method_list.m_first_ptr + (i * method_list.m_entsize),
456 relative_selector_base_addr, method_list.m_is_small,
457 method_list.m_has_direct_selector);
458 if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
459 break;
460 }
461 return true;
462}
463
464// The relevant data structures:
465// - relative_list_list_t
466// - uint32_t count
467// - uint32_t entsize
468// - Followed by <count> number of relative_list_entry_t of size <entsize>
469//
470// - relative_list_entry_t
471// - uint64_t image_index : 16
472// - int64_t list_offset : 48
473// - Note: The above 2 fit into 8 bytes always
474//
475// image_index corresponds to an image in the shared cache
476// list_offset is used to calculate the address of the method_list_t we want
478 std::function<bool(const char *, const char *)> const &instance_method_func,
479 lldb::addr_t relative_method_list_ptr) const {
481 auto relative_method_lists = std::make_unique<relative_list_list_t>();
482
483 // 1. Process the count and entsize of the relative_list_list_t
484 if (!relative_method_lists->Read(process, relative_method_list_ptr))
485 return false;
486
487 auto entry = std::make_unique<relative_list_entry_t>();
488 for (uint32_t i = 0; i < relative_method_lists->m_count; i++) {
489 // 2. Extract the image index and the list offset from the
490 // relative_list_entry_t
491 const lldb::addr_t entry_addr = relative_method_lists->m_first_ptr +
492 (i * relative_method_lists->m_entsize);
493 if (!entry->Read(process, entry_addr))
494 return false;
495
496 // 3. Calculate the pointer to the method_list_t from the
497 // relative_list_entry_t
498 const lldb::addr_t method_list_addr = entry_addr + entry->m_list_offset;
499
500 // 4. Get the method_list_t from the pointer
501 std::optional<method_list_t> method_list =
502 GetMethodList(process, method_list_addr);
503 if (!method_list)
504 return false;
505
506 // 5. Cache the result so we don't need to reconstruct it later.
507 m_image_to_method_lists[entry->m_image_index].emplace_back(*method_list);
508
509 // 6. If the relevant image is loaded, add the methods to the Decl
510 if (!m_runtime.IsSharedCacheImageLoaded(entry->m_image_index))
511 continue;
512
513 if (!ProcessMethodList(instance_method_func, *method_list))
514 return false;
515 }
516
517 // We need to keep track of the last time we updated so we can re-update the
518 // type information in the future
520
521 return true;
522}
523
525 std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
526 std::function<bool(const char *, const char *)> const &instance_method_func,
527 std::function<bool(const char *, const char *)> const &class_method_func,
528 std::function<bool(const char *, const char *, lldb::addr_t,
529 uint64_t)> const &ivar_func) const {
531
532 std::unique_ptr<objc_class_t> objc_class;
533 std::unique_ptr<class_ro_t> class_ro;
534 std::unique_ptr<class_rw_t> class_rw;
535
536 if (!Read_objc_class(process, objc_class))
537 return false;
538 if (!Read_class_row(process, *objc_class, class_ro, class_rw))
539 return false;
540
541 static ConstString NSObject_name("NSObject");
542
543 if (m_name != NSObject_name && superclass_func)
544 superclass_func(objc_class->m_superclass);
545
546 if (instance_method_func) {
547 // This is a relative list of lists
548 if (class_ro->m_baseMethods_ptr & 1) {
549 if (!ProcessRelativeMethodLists(instance_method_func,
550 class_ro->m_baseMethods_ptr ^ 1))
551 return false;
552 } else {
553 std::optional<method_list_t> base_method_list =
554 GetMethodList(process, class_ro->m_baseMethods_ptr);
555 if (!base_method_list)
556 return false;
557 if (!ProcessMethodList(instance_method_func, *base_method_list))
558 return false;
559 }
560 }
561
562 if (class_method_func) {
564
565 // We don't care about the metaclass's superclass, or its class methods.
566 // Its instance methods are our class methods.
567
568 if (metaclass) {
569 metaclass->Describe(
570 std::function<void(ObjCLanguageRuntime::ObjCISA)>(nullptr),
571 class_method_func,
572 std::function<bool(const char *, const char *)>(nullptr),
573 std::function<bool(const char *, const char *, lldb::addr_t,
574 uint64_t)>(nullptr));
575 }
576 }
577
578 if (ivar_func) {
579 if (class_ro->m_ivars_ptr != 0) {
580 ivar_list_t ivar_list;
581 if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
582 return false;
583
584 if (ivar_list.m_entsize != ivar_t::GetSize(process))
585 return false;
586
587 ivar_t ivar;
588
589 for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i) {
590 ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
591
592 if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(),
593 ivar.m_offset_ptr, ivar.m_size))
594 break;
595 }
596 }
597 }
598
599 return true;
600}
601
603 if (!m_name) {
605
606 if (process) {
607 std::unique_ptr<objc_class_t> objc_class;
608 std::unique_ptr<class_ro_t> class_ro;
609 std::unique_ptr<class_rw_t> class_rw;
610
611 if (!Read_objc_class(process, objc_class))
612 return m_name;
613 if (!Read_class_row(process, *objc_class, class_ro, class_rw))
614 return m_name;
615
616 m_name = ConstString(class_ro->m_name.c_str());
617 }
618 }
619 return m_name;
620}
621
624
625 if (!process)
627
628 std::unique_ptr<objc_class_t> objc_class;
629
630 if (!Read_objc_class(process, objc_class))
632
633 return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(
634 objc_class->m_superclass);
635}
636
639
640 if (!process)
642
643 std::unique_ptr<objc_class_t> objc_class;
644
645 if (!Read_objc_class(process, objc_class))
647
648 lldb::addr_t candidate_isa = m_runtime.GetPointerISA(objc_class->m_isa);
649
651 new ClassDescriptorV2(m_runtime, candidate_isa, nullptr));
652}
653
656
657 if (process) {
658 std::unique_ptr<objc_class_t> objc_class;
659 std::unique_ptr<class_ro_t> class_ro;
660 std::unique_ptr<class_rw_t> class_rw;
661
662 if (!Read_objc_class(process, objc_class))
663 return 0;
664 if (!Read_class_row(process, *objc_class, class_ro, class_rw))
665 return 0;
666
667 return class_ro->m_instanceSize;
668 }
669
670 return 0;
671}
672
673// From the ObjC runtime.
674static uint8_t IS_SWIFT_STABLE = 1U << 1;
675
677 std::unique_ptr<objc_class_t> objc_class;
678 if (auto *process = m_runtime.GetProcess())
679 if (Read_objc_class(process, objc_class))
680 if (objc_class->m_flags & IS_SWIFT_STABLE)
682
684}
685
687
688size_t ClassDescriptorV2::iVarsStorage::size() { return m_ivars.size(); }
689
691operator[](size_t idx) {
692 return m_ivars[idx];
693}
694
696 ClassDescriptorV2 &descriptor) {
697 if (m_filled)
698 return;
699 std::lock_guard<std::recursive_mutex> guard(m_mutex);
700 Log *log = GetLog(LLDBLog::Types);
701 LLDB_LOGV(log, "class_name = {0}", descriptor.GetClassName());
702 m_filled = true;
703 ObjCLanguageRuntime::EncodingToTypeSP encoding_to_type_sp(
704 runtime.GetEncodingToType());
705 Process *process(runtime.GetProcess());
706 if (!encoding_to_type_sp)
707 return;
708 descriptor.Describe(nullptr, nullptr, nullptr, [this, process,
709 encoding_to_type_sp,
710 log](const char *name,
711 const char *type,
712 lldb::addr_t offset_ptr,
713 uint64_t size) -> bool {
714 const bool for_expression = false;
715 const bool stop_loop = false;
716 LLDB_LOGV(log, "name = {0}, encoding = {1}, offset_ptr = {2:x}, size = {3}",
717 name, type, offset_ptr, size);
718 CompilerType ivar_type =
719 encoding_to_type_sp->RealizeType(type, for_expression);
720 if (ivar_type) {
721 LLDB_LOGV(log,
722 "name = {0}, encoding = {1}, offset_ptr = {2:x}, size = "
723 "{3}, type_size = {4}",
724 name, type, offset_ptr, size,
725 ivar_type.GetByteSize(nullptr).value_or(0));
726 Scalar offset_scalar;
728 const int offset_ptr_size = 4;
729 const bool is_signed = false;
730 size_t read = process->ReadScalarIntegerFromMemory(
731 offset_ptr, offset_ptr_size, is_signed, offset_scalar, error);
732 if (error.Success() && 4 == read) {
733 LLDB_LOGV(log, "offset_ptr = {0:x} --> {1}", offset_ptr,
734 offset_scalar.SInt());
735 m_ivars.push_back(
736 {ConstString(name), ivar_type, size, offset_scalar.SInt()});
737 } else
738 LLDB_LOGV(log, "offset_ptr = {0:x} --> read fail, read = %{1}",
739 offset_ptr, read);
740 }
741 return stop_loop;
742 });
743}
744
747}
static lldb::addr_t GetClassDataMask(Process *process)
static uint8_t IS_SWIFT_STABLE
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:369
#define LLDB_LOGV(log,...)
Definition: Log.h:383
EncodingToTypeSP GetEncodingToType() override
bool IsSharedCacheImageLoaded(uint16_t image_index)
lldb::addr_t GetRelativeSelectorBaseAddr()
Returns the base address for relative method list selector strings.
std::optional< uint64_t > GetSharedCacheImageHeaderVersion()
void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor)
ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override
bool Describe(std::function< void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func, std::function< bool(const char *, const char *)> const &instance_method_func, std::function< bool(const char *, const char *)> const &class_method_func, std::function< bool(const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const override
bool Read_class_row(Process *process, const objc_class_t &objc_class, std::unique_ptr< class_ro_t > &class_ro, std::unique_ptr< class_rw_t > &class_rw) const
bool ProcessRelativeMethodLists(std::function< bool(const char *, const char *)> const &instance_method_func, lldb::addr_t relative_method_list_ptr) const
bool ProcessMethodList(std::function< bool(const char *, const char *)> const &instance_method_func, method_list_t &method_list) const
bool Read_objc_class(Process *process, std::unique_ptr< objc_class_t > &objc_class) const
std::optional< uint64_t > m_last_version_updated
std::map< uint16_t, std::vector< method_list_t > > m_image_to_method_lists
ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override
lldb::LanguageType GetImplementationLanguage() const override
Determine whether this class is implemented in Swift.
std::optional< method_list_t > GetMethodList(Process *process, lldb::addr_t method_list_ptr) const
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
std::optional< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
A uniqued constant string class.
Definition: ConstString.h:40
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t GetByteSize() const override
Get the number of bytes in the data buffer.
An data extractor class.
Definition: DataExtractor.h:48
uint32_t GetU32_unchecked(lldb::offset_t *offset_ptr) const
uint64_t GetAddress_unchecked(lldb::offset_t *offset_ptr) const
uint64_t GetU64_unchecked(lldb::offset_t *offset_ptr) const
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
std::shared_ptr< EncodingToType > EncodingToTypeSP
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
size_t ReadScalarIntegerFromMemory(lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Status &error)
Definition: Process.cpp:2375
size_t ReadCStringFromMemory(lldb::addr_t vm_addr, char *cstr, size_t cstr_max_len, Status &error)
Read a NULL terminated C string from memory.
Definition: Process.cpp:2142
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
Definition: Process.cpp:1953
lldb::ByteOrder GetByteOrder() const
Definition: Process.cpp:3611
uint64_t ReadUnsignedIntegerFromMemory(lldb::addr_t load_addr, size_t byte_size, uint64_t fail_value, Status &error)
Reads an unsigned integer of the specified byte size from process memory.
Definition: Process.cpp:2217
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3615
const lldb::ABISP & GetABI()
Definition: Process.cpp:1504
Process * GetProcess()
Definition: Runtime.h:22
int SInt(int fail_value=0) const
Definition: Scalar.cpp:319
An error handling class.
Definition: Status.h:115
uint8_t * GetBytes()
Get a pointer to the data.
Definition: DataBuffer.h:108
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::ABI > ABISP
Definition: lldb-forward.h:317
uint64_t offset_t
Definition: lldb-types.h:85
LanguageType
Programming language type.
@ eLanguageTypeSwift
Swift.
@ eLanguageTypeObjC
Objective-C.
uint64_t addr_t
Definition: lldb-types.h:80
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr, lldb::addr_t relative_selector_base_addr, bool is_small, bool has_direct_sel)
static size_t GetSize(Process *process, bool is_small)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)