LLDB mainline
AppleObjCRuntimeV2.h
Go to the documentation of this file.
1//===-- AppleObjCRuntimeV2.h ------------------------------------*- C++ -*-===//
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#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H
10#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H
11
12#include <map>
13#include <memory>
14#include <mutex>
15#include <optional>
16
17#include "AppleObjCRuntime.h"
18#include "lldb/lldb-private.h"
19
21
22#include "llvm/ADT/BitVector.h"
23#include "llvm/ADT/SmallSet.h"
24
26
27namespace lldb_private {
28
30public:
31 ~AppleObjCRuntimeV2() override = default;
32
33 static void Initialize();
34
35 static void Terminate();
36
38 CreateInstance(Process *process, lldb::LanguageType language);
39
40 static llvm::StringRef GetPluginNameStatic() { return "apple-objc-v2"; }
41
43
44 static char ID;
45
46 bool isA(const void *ClassID) const override {
47 return ClassID == &ID || AppleObjCRuntime::isA(ClassID);
48 }
49
50 static bool classof(const LanguageRuntime *runtime) {
51 return runtime->isA(&ID);
52 }
53
55 lldb::DynamicValueType use_dynamic,
56 TypeAndOrName &class_type_or_name,
57 Address &address, Value::ValueType &value_type,
58 llvm::ArrayRef<uint8_t> &local_buffer) override;
59
60 llvm::Expected<std::unique_ptr<UtilityFunction>>
61 CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override;
62
63 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
64
68
69 size_t GetByteOffsetForIvar(CompilerType &parent_ast_type,
70 const char *ivar_name) override;
71
73
74 ClassDescriptorSP GetClassDescriptor(ValueObject &valobj) override;
75
76 ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;
77
78 DeclVendor *GetDeclVendor() override;
79
81
82 EncodingToTypeSP GetEncodingToType() override;
83
84 bool IsTaggedPointer(lldb::addr_t ptr) override;
85
89
91
92 /// Returns the base address for relative method list selector strings.
96
97 void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {
98 m_relative_selector_base = relative_selector_base;
99 }
100
102 lldb::addr_t &cf_false) override;
103
104 void ModulesDidLoad(const ModuleList &module_list) override;
105
106 bool IsSharedCacheImageLoaded(uint16_t image_index);
107
108 std::optional<uint64_t> GetSharedCacheImageHeaderVersion();
109
111
112protected:
114 CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,
115 bool throw_bp) override;
116
117private:
119 public:
121
122 bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime,
123 RemoteNXMapTable &hash_table);
124
125 void UpdateSignature(const RemoteNXMapTable &hash_table);
126
127 protected:
128 uint32_t m_count = 0;
129 uint32_t m_num_buckets = 0;
131 };
132
134 public:
135 static NonPointerISACache *
137 const lldb::ModuleSP &objc_module_sp);
138
140
141 private:
143 const lldb::ModuleSP &objc_module_sp,
144 uint64_t objc_debug_isa_class_mask,
145 uint64_t objc_debug_isa_magic_mask,
146 uint64_t objc_debug_isa_magic_value,
147 uint64_t objc_debug_indexed_isa_magic_mask,
148 uint64_t objc_debug_indexed_isa_magic_value,
149 uint64_t objc_debug_indexed_isa_index_mask,
150 uint64_t objc_debug_indexed_isa_index_shift,
151 lldb::addr_t objc_indexed_classes);
152
153 bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa);
154
156 std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
161
167
168 std::vector<lldb::addr_t> m_indexed_isa_cache;
169
170 friend class AppleObjCRuntimeV2;
171
174 };
175
178 public:
179 ~TaggedPointerVendorV2() override = default;
180
181 static TaggedPointerVendorV2 *
183 const lldb::ModuleSP &objc_module_sp);
184
185 protected:
187
190
191 private:
195 };
196
198 public:
199 bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
200
202 GetClassDescriptor(lldb::addr_t ptr) override;
203
204 protected:
206 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
207 uint32_t objc_debug_taggedpointer_slot_shift,
208 uint32_t objc_debug_taggedpointer_slot_mask,
209 uint32_t objc_debug_taggedpointer_payload_lshift,
210 uint32_t objc_debug_taggedpointer_payload_rshift,
211 lldb::addr_t objc_debug_taggedpointer_classes);
212
213 typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
214 typedef Cache::iterator CacheIterator;
222
224
226 const TaggedPointerVendorRuntimeAssisted &) = delete;
229 };
230
233 public:
235 GetClassDescriptor(lldb::addr_t ptr) override;
236
237 protected:
239 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
240 uint64_t objc_debug_taggedpointer_ext_mask,
241 uint32_t objc_debug_taggedpointer_slot_shift,
242 uint32_t objc_debug_taggedpointer_ext_slot_shift,
243 uint32_t objc_debug_taggedpointer_slot_mask,
244 uint32_t objc_debug_taggedpointer_ext_slot_mask,
245 uint32_t objc_debug_taggedpointer_payload_lshift,
246 uint32_t objc_debug_taggedpointer_payload_rshift,
247 uint32_t objc_debug_taggedpointer_ext_payload_lshift,
248 uint32_t objc_debug_taggedpointer_ext_payload_rshift,
249 lldb::addr_t objc_debug_taggedpointer_classes,
250 lldb::addr_t objc_debug_taggedpointer_ext_classes);
251
253
254 typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
255 typedef Cache::iterator CacheIterator;
263
265
269 };
270
288
292 uint32_t m_num_found;
293
294 DescriptorMapUpdateResult(bool ran, bool retry, uint32_t found) {
295 m_update_ran = ran;
296
297 m_retry_update = retry;
298
299 m_num_found = found;
300 }
301
302 static DescriptorMapUpdateResult Fail() { return {false, false, 0}; }
303
304 static DescriptorMapUpdateResult Success(uint32_t found) {
305 return {true, false, found};
306 }
307
308 static DescriptorMapUpdateResult Retry() { return {false, true, 0}; }
309 };
310
311 /// Abstraction to read the Objective-C class info.
313 public:
315 std::mutex &GetMutex() { return m_mutex; }
316
317 protected:
318 /// The lifetime of this object is tied to that of the runtime.
320 std::mutex m_mutex;
321 };
322
323 /// We can read the class info from the Objective-C runtime using
324 /// gdb_objc_realized_classes, objc_copyRealizedClassList or
325 /// objc_getRealizedClassList_trylock. The RealizedClassList variants are
326 /// preferred because they include lazily named classes, but they are not
327 /// always available or safe to call.
328 ///
329 /// We potentially need more than one helper for the same process, because we
330 /// may need to use gdb_objc_realized_classes until dyld is initialized and
331 /// then switch over to objc_copyRealizedClassList or
332 /// objc_getRealizedClassList_trylock for lazily named classes.
334 public:
337
340
341 private:
347
348 /// Compute which helper to use. If dyld is not yet fully initialized we
349 /// must use gdb_objc_realized_classes. Otherwise, we prefer
350 /// objc_getRealizedClassList_trylock and objc_copyRealizedClassList
351 /// respectively, depending on availability.
352 Helper ComputeHelper(ExecutionContext &exe_ctx) const;
353
355 Helper helper);
357
358 std::unique_ptr<UtilityFunction>
360 std::string code, std::string name);
361
363 std::unique_ptr<UtilityFunction> utility_function;
365 };
366
370 };
371
372 /// Abstraction to read the Objective-C class info from the shared cache.
389
391 public:
392 static std::unique_ptr<SharedCacheImageHeaders>
394
396
397 bool IsImageLoaded(uint16_t image_index);
398
399 uint64_t GetVersion();
400
401 private:
403 lldb::addr_t headerInfoRWs_ptr, uint32_t count,
404 uint32_t entsize)
405 : m_runtime(runtime), m_headerInfoRWs_ptr(headerInfoRWs_ptr),
406 m_loaded_images(count, false), m_version(0), m_count(count),
407 m_entsize(entsize), m_needs_update(true) {}
408 llvm::Error UpdateIfNeeded();
409
412 llvm::BitVector m_loaded_images;
413 uint64_t m_version;
414 uint32_t m_count;
415 uint32_t m_entsize;
417 };
418
419 AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);
420
422
424
425 using ValueObjectSet = llvm::SmallPtrSet<ValueObject *, 8>;
427 ValueObjectSet &seen);
428
429 /// Update the generation count of realized classes. This is not an exact
430 /// count but rather a value that is incremented when new classes are realized
431 /// or destroyed. Unlike the count in gdb_objc_realized_classes, it will
432 /// change when lazily named classes get realized.
434
436 uint32_t num_class_infos);
437
443
446
449
451
452 bool HasSymbol(ConstString Name);
453
460
461 friend class ClassDescriptorV2;
462
464
467
468 std::unique_ptr<DeclVendor> m_decl_vendor_up;
477 std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up;
478 std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up;
482 std::optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;
484 std::unique_ptr<SharedCacheImageHeaders> m_shared_cache_image_headers_up;
485};
486
487} // namespace lldb_private
488
489#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H
A section + offset based address class.
Definition Address.h:62
AppleObjCRuntimeV2 & m_runtime
The lifetime of this object is tied to that of the runtime.
We can read the class info from the Objective-C runtime using gdb_objc_realized_classes,...
UtilityFunction * GetClassInfoUtilityFunction(ExecutionContext &exe_ctx, Helper helper)
Helper ComputeHelper(ExecutionContext &exe_ctx) const
Compute which helper to use.
std::unique_ptr< UtilityFunction > GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, Helper helper, std::string code, std::string name)
void UpdateSignature(const RemoteNXMapTable &hash_table)
bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
NonPointerISACache(AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp, uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, uint64_t objc_debug_isa_magic_value, uint64_t objc_debug_indexed_isa_magic_mask, uint64_t objc_debug_indexed_isa_magic_value, uint64_t objc_debug_indexed_isa_index_mask, uint64_t objc_debug_indexed_isa_index_shift, lldb::addr_t objc_indexed_classes)
bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa)
ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa)
static NonPointerISACache * CreateInstance(AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp)
NonPointerISACache(const NonPointerISACache &)=delete
const NonPointerISACache & operator=(const NonPointerISACache &)=delete
std::map< ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP > m_cache
Abstraction to read the Objective-C class info from the shared cache.
UtilityFunction * GetClassInfoUtilityFunction(ExecutionContext &exe_ctx)
std::unique_ptr< UtilityFunction > GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx)
SharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime, lldb::addr_t headerInfoRWs_ptr, uint32_t count, uint32_t entsize)
static std::unique_ptr< SharedCacheImageHeaders > CreateSharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime)
ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(lldb::addr_t ptr) override
std::map< uint8_t, ObjCLanguageRuntime::ClassDescriptorSP > Cache
const TaggedPointerVendorExtended & operator=(const TaggedPointerVendorExtended &)=delete
TaggedPointerVendorExtended(const TaggedPointerVendorExtended &)=delete
TaggedPointerVendorExtended(AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, uint64_t objc_debug_taggedpointer_ext_mask, uint32_t objc_debug_taggedpointer_slot_shift, uint32_t objc_debug_taggedpointer_ext_slot_shift, uint32_t objc_debug_taggedpointer_slot_mask, uint32_t objc_debug_taggedpointer_ext_slot_mask, uint32_t objc_debug_taggedpointer_payload_lshift, uint32_t objc_debug_taggedpointer_payload_rshift, uint32_t objc_debug_taggedpointer_ext_payload_lshift, uint32_t objc_debug_taggedpointer_ext_payload_rshift, lldb::addr_t objc_debug_taggedpointer_classes, lldb::addr_t objc_debug_taggedpointer_ext_classes)
ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(lldb::addr_t ptr) override
const TaggedPointerVendorLegacy & operator=(const TaggedPointerVendorLegacy &)=delete
TaggedPointerVendorLegacy(const TaggedPointerVendorLegacy &)=delete
const TaggedPointerVendorRuntimeAssisted & operator=(const TaggedPointerVendorRuntimeAssisted &)=delete
ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(lldb::addr_t ptr) override
TaggedPointerVendorRuntimeAssisted(AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, uint32_t objc_debug_taggedpointer_slot_shift, uint32_t objc_debug_taggedpointer_slot_mask, uint32_t objc_debug_taggedpointer_payload_lshift, uint32_t objc_debug_taggedpointer_payload_rshift, lldb::addr_t objc_debug_taggedpointer_classes)
TaggedPointerVendorRuntimeAssisted(const TaggedPointerVendorRuntimeAssisted &)=delete
std::map< uint8_t, ObjCLanguageRuntime::ClassDescriptorSP > Cache
TaggedPointerVendorV2(const TaggedPointerVendorV2 &)=delete
static TaggedPointerVendorV2 * CreateInstance(AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp)
const TaggedPointerVendorV2 & operator=(const TaggedPointerVendorV2 &)=delete
llvm::Expected< std::unique_ptr< UtilityFunction > > CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override
bool IsTaggedPointer(lldb::addr_t ptr) override
uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data, uint32_t num_class_infos)
llvm::SmallPtrSet< ValueObject *, 8 > ValueObjectSet
bool RealizedClassGenerationCountChanged()
Update the generation count of realized classes.
void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base)
static llvm::StringRef GetPluginNameStatic()
EncodingToTypeSP GetEncodingToType() override
~AppleObjCRuntimeV2() override=default
AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp)
TaggedPointerVendor * GetTaggedPointerVendor() override
bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type, llvm::ArrayRef< uint8_t > &local_buffer) override
This call should return true if it could set the name and/or the type Sets address to the address of ...
NonPointerISACache * GetNonPointerIsaCache()
size_t GetByteOffsetForIvar(CompilerType &parent_ast_type, const char *ivar_name) override
StructuredData::ObjectSP GetLanguageSpecificData(SymbolContext sc) override
Language runtime plugins can use this API to report language-specific runtime information about this ...
SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor
DynamicClassInfoExtractor m_dynamic_class_info_extractor
ObjCRuntimeVersions GetRuntimeVersion() const override
ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override
static bool classof(const LanguageRuntime *runtime)
bool isA(const void *ClassID) const override
std::unique_ptr< SharedCacheImageHeaders > m_shared_cache_image_headers_up
lldb::addr_t LookupRuntimeSymbol(ConstString name) override
ClassDescriptorSP GetClassDescriptor(ValueObject &valobj) override
void ModulesDidLoad(const ModuleList &module_list) override
Called when modules have been loaded in the process.
bool IsSharedCacheImageLoaded(uint16_t image_index)
lldb::addr_t GetRelativeSelectorBaseAddr()
Returns the base address for relative method list selector strings.
std::optional< std::pair< lldb::addr_t, lldb::addr_t > > m_CFBoolean_values
llvm::StringRef GetPluginName() override
std::unique_ptr< DeclVendor > m_decl_vendor_up
std::unique_ptr< TaggedPointerVendor > m_tagged_pointer_vendor_up
std::unique_ptr< NonPointerISACache > m_non_pointer_isa_cache_up
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, lldb::addr_t &cf_false) override
lldb::BreakpointResolverSP CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp, bool throw_bp) override
LanguageRuntime * GetPreferredLanguageRuntime(ValueObject &in_value) override
Return the preferred language runtime instance, which in most cases will be the current instance.
std::optional< uint64_t > GetSharedCacheImageHeaderVersion()
ClassDescriptorSP GetClassDescriptorImpl(ValueObject &valobj, ValueObjectSet &seen)
void WarnIfNoClassesCached(SharedCacheWarningReason reason)
static lldb_private::LanguageRuntime * CreateInstance(Process *process, lldb::LanguageType language)
bool isA(const void *ClassID) const override
Generic representation of a type in a programming language.
A uniqued constant string class.
Definition ConstString.h:40
An data extractor class.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
virtual bool isA(const void *ClassID) const
A collection class for Module objects.
Definition ModuleList.h:104
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
std::shared_ptr< EncodingToType > EncodingToTypeSP
A plug-in interface definition class for debugging a process.
Definition Process.h:357
std::shared_ptr< Object > ObjectSP
Defines a symbol context baton that can be handed other debug core functions.
Sometimes you can find the name of the type corresponding to an object, but we don't have debug infor...
Definition Type.h:779
"lldb/Expression/UtilityFunction.h" Encapsulates a bit of source code that provides a function that i...
ValueType
Type that describes Value::m_value.
Definition Value.h:41
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::BreakpointResolver > BreakpointResolverSP
std::weak_ptr< lldb_private::Module > ModuleWP
LanguageType
Programming language type.
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
static DescriptorMapUpdateResult Success(uint32_t found)
DescriptorMapUpdateResult(bool ran, bool retry, uint32_t found)