Path: blob/main/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
39690 views
//===-- AppleObjCRuntimeV2.h ------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H9#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H1011#include <map>12#include <memory>13#include <mutex>14#include <optional>1516#include "AppleObjCRuntime.h"17#include "lldb/lldb-private.h"1819#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"2021#include "llvm/ADT/BitVector.h"2223class RemoteNXMapTable;2425namespace lldb_private {2627class AppleObjCRuntimeV2 : public AppleObjCRuntime {28public:29~AppleObjCRuntimeV2() override = default;3031static void Initialize();3233static void Terminate();3435static lldb_private::LanguageRuntime *36CreateInstance(Process *process, lldb::LanguageType language);3738static llvm::StringRef GetPluginNameStatic() { return "apple-objc-v2"; }3940LanguageRuntime *GetPreferredLanguageRuntime(ValueObject &in_value) override;4142static char ID;4344bool isA(const void *ClassID) const override {45return ClassID == &ID || AppleObjCRuntime::isA(ClassID);46}4748static bool classof(const LanguageRuntime *runtime) {49return runtime->isA(&ID);50}5152bool GetDynamicTypeAndAddress(ValueObject &in_value,53lldb::DynamicValueType use_dynamic,54TypeAndOrName &class_type_or_name,55Address &address,56Value::ValueType &value_type) override;5758llvm::Expected<std::unique_ptr<UtilityFunction>>59CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override;6061llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }6263ObjCRuntimeVersions GetRuntimeVersion() const override {64return ObjCRuntimeVersions::eAppleObjC_V2;65}6667size_t GetByteOffsetForIvar(CompilerType &parent_ast_type,68const char *ivar_name) override;6970void UpdateISAToDescriptorMapIfNeeded() override;7172ClassDescriptorSP GetClassDescriptor(ValueObject &valobj) override;7374ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;7576DeclVendor *GetDeclVendor() override;7778lldb::addr_t LookupRuntimeSymbol(ConstString name) override;7980EncodingToTypeSP GetEncodingToType() override;8182bool IsTaggedPointer(lldb::addr_t ptr) override;8384TaggedPointerVendor *GetTaggedPointerVendor() override {85return m_tagged_pointer_vendor_up.get();86}8788lldb::addr_t GetTaggedPointerObfuscator();8990/// Returns the base address for relative method list selector strings.91lldb::addr_t GetRelativeSelectorBaseAddr() {92return m_relative_selector_base;93}9495void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {96m_relative_selector_base = relative_selector_base;97}9899void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,100lldb::addr_t &cf_false) override;101102void ModulesDidLoad(const ModuleList &module_list) override;103104bool IsSharedCacheImageLoaded(uint16_t image_index);105106std::optional<uint64_t> GetSharedCacheImageHeaderVersion();107108protected:109lldb::BreakpointResolverSP110CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,111bool throw_bp) override;112113private:114class HashTableSignature {115public:116HashTableSignature();117118bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime,119RemoteNXMapTable &hash_table);120121void UpdateSignature(const RemoteNXMapTable &hash_table);122123protected:124uint32_t m_count = 0;125uint32_t m_num_buckets = 0;126lldb::addr_t m_buckets_ptr = 0;127};128129class NonPointerISACache {130public:131static NonPointerISACache *132CreateInstance(AppleObjCRuntimeV2 &runtime,133const lldb::ModuleSP &objc_module_sp);134135ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa);136137private:138NonPointerISACache(AppleObjCRuntimeV2 &runtime,139const lldb::ModuleSP &objc_module_sp,140uint64_t objc_debug_isa_class_mask,141uint64_t objc_debug_isa_magic_mask,142uint64_t objc_debug_isa_magic_value,143uint64_t objc_debug_indexed_isa_magic_mask,144uint64_t objc_debug_indexed_isa_magic_value,145uint64_t objc_debug_indexed_isa_index_mask,146uint64_t objc_debug_indexed_isa_index_shift,147lldb::addr_t objc_indexed_classes);148149bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa);150151AppleObjCRuntimeV2 &m_runtime;152std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache;153lldb::ModuleWP m_objc_module_wp;154uint64_t m_objc_debug_isa_class_mask;155uint64_t m_objc_debug_isa_magic_mask;156uint64_t m_objc_debug_isa_magic_value;157158uint64_t m_objc_debug_indexed_isa_magic_mask;159uint64_t m_objc_debug_indexed_isa_magic_value;160uint64_t m_objc_debug_indexed_isa_index_mask;161uint64_t m_objc_debug_indexed_isa_index_shift;162lldb::addr_t m_objc_indexed_classes;163164std::vector<lldb::addr_t> m_indexed_isa_cache;165166friend class AppleObjCRuntimeV2;167168NonPointerISACache(const NonPointerISACache &) = delete;169const NonPointerISACache &operator=(const NonPointerISACache &) = delete;170};171172class TaggedPointerVendorV2173: public ObjCLanguageRuntime::TaggedPointerVendor {174public:175~TaggedPointerVendorV2() override = default;176177static TaggedPointerVendorV2 *178CreateInstance(AppleObjCRuntimeV2 &runtime,179const lldb::ModuleSP &objc_module_sp);180181protected:182AppleObjCRuntimeV2 &m_runtime;183184TaggedPointerVendorV2(AppleObjCRuntimeV2 &runtime)185: TaggedPointerVendor(), m_runtime(runtime) {}186187private:188TaggedPointerVendorV2(const TaggedPointerVendorV2 &) = delete;189const TaggedPointerVendorV2 &190operator=(const TaggedPointerVendorV2 &) = delete;191};192193class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2 {194public:195bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;196197ObjCLanguageRuntime::ClassDescriptorSP198GetClassDescriptor(lldb::addr_t ptr) override;199200protected:201TaggedPointerVendorRuntimeAssisted(202AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,203uint32_t objc_debug_taggedpointer_slot_shift,204uint32_t objc_debug_taggedpointer_slot_mask,205uint32_t objc_debug_taggedpointer_payload_lshift,206uint32_t objc_debug_taggedpointer_payload_rshift,207lldb::addr_t objc_debug_taggedpointer_classes);208209typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;210typedef Cache::iterator CacheIterator;211Cache m_cache;212uint64_t m_objc_debug_taggedpointer_mask;213uint32_t m_objc_debug_taggedpointer_slot_shift;214uint32_t m_objc_debug_taggedpointer_slot_mask;215uint32_t m_objc_debug_taggedpointer_payload_lshift;216uint32_t m_objc_debug_taggedpointer_payload_rshift;217lldb::addr_t m_objc_debug_taggedpointer_classes;218219friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;220221TaggedPointerVendorRuntimeAssisted(222const TaggedPointerVendorRuntimeAssisted &) = delete;223const TaggedPointerVendorRuntimeAssisted &224operator=(const TaggedPointerVendorRuntimeAssisted &) = delete;225};226227class TaggedPointerVendorExtended228: public TaggedPointerVendorRuntimeAssisted {229public:230ObjCLanguageRuntime::ClassDescriptorSP231GetClassDescriptor(lldb::addr_t ptr) override;232233protected:234TaggedPointerVendorExtended(235AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,236uint64_t objc_debug_taggedpointer_ext_mask,237uint32_t objc_debug_taggedpointer_slot_shift,238uint32_t objc_debug_taggedpointer_ext_slot_shift,239uint32_t objc_debug_taggedpointer_slot_mask,240uint32_t objc_debug_taggedpointer_ext_slot_mask,241uint32_t objc_debug_taggedpointer_payload_lshift,242uint32_t objc_debug_taggedpointer_payload_rshift,243uint32_t objc_debug_taggedpointer_ext_payload_lshift,244uint32_t objc_debug_taggedpointer_ext_payload_rshift,245lldb::addr_t objc_debug_taggedpointer_classes,246lldb::addr_t objc_debug_taggedpointer_ext_classes);247248bool IsPossibleExtendedTaggedPointer(lldb::addr_t ptr);249250typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;251typedef Cache::iterator CacheIterator;252Cache m_ext_cache;253uint64_t m_objc_debug_taggedpointer_ext_mask;254uint32_t m_objc_debug_taggedpointer_ext_slot_shift;255uint32_t m_objc_debug_taggedpointer_ext_slot_mask;256uint32_t m_objc_debug_taggedpointer_ext_payload_lshift;257uint32_t m_objc_debug_taggedpointer_ext_payload_rshift;258lldb::addr_t m_objc_debug_taggedpointer_ext_classes;259260friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;261262TaggedPointerVendorExtended(const TaggedPointerVendorExtended &) = delete;263const TaggedPointerVendorExtended &264operator=(const TaggedPointerVendorExtended &) = delete;265};266267class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 {268public:269bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;270271ObjCLanguageRuntime::ClassDescriptorSP272GetClassDescriptor(lldb::addr_t ptr) override;273274protected:275TaggedPointerVendorLegacy(AppleObjCRuntimeV2 &runtime)276: TaggedPointerVendorV2(runtime) {}277278friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;279280TaggedPointerVendorLegacy(const TaggedPointerVendorLegacy &) = delete;281const TaggedPointerVendorLegacy &282operator=(const TaggedPointerVendorLegacy &) = delete;283};284285struct DescriptorMapUpdateResult {286bool m_update_ran;287bool m_retry_update;288uint32_t m_num_found;289290DescriptorMapUpdateResult(bool ran, bool retry, uint32_t found) {291m_update_ran = ran;292293m_retry_update = retry;294295m_num_found = found;296}297298static DescriptorMapUpdateResult Fail() { return {false, false, 0}; }299300static DescriptorMapUpdateResult Success(uint32_t found) {301return {true, false, found};302}303304static DescriptorMapUpdateResult Retry() { return {false, true, 0}; }305};306307/// Abstraction to read the Objective-C class info.308class ClassInfoExtractor {309public:310ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {}311std::mutex &GetMutex() { return m_mutex; }312313protected:314/// The lifetime of this object is tied to that of the runtime.315AppleObjCRuntimeV2 &m_runtime;316std::mutex m_mutex;317};318319/// We can read the class info from the Objective-C runtime using320/// gdb_objc_realized_classes, objc_copyRealizedClassList or321/// objc_getRealizedClassList_trylock. The RealizedClassList variants are322/// preferred because they include lazily named classes, but they are not323/// always available or safe to call.324///325/// We potentially need more than one helper for the same process, because we326/// may need to use gdb_objc_realized_classes until dyld is initialized and327/// then switch over to objc_copyRealizedClassList or328/// objc_getRealizedClassList_trylock for lazily named classes.329class DynamicClassInfoExtractor : public ClassInfoExtractor {330public:331DynamicClassInfoExtractor(AppleObjCRuntimeV2 &runtime)332: ClassInfoExtractor(runtime) {}333334DescriptorMapUpdateResult335UpdateISAToDescriptorMap(RemoteNXMapTable &hash_table);336337private:338enum Helper {339gdb_objc_realized_classes,340objc_copyRealizedClassList,341objc_getRealizedClassList_trylock342};343344/// Compute which helper to use. If dyld is not yet fully initialized we345/// must use gdb_objc_realized_classes. Otherwise, we prefer346/// objc_getRealizedClassList_trylock and objc_copyRealizedClassList347/// respectively, depending on availability.348Helper ComputeHelper(ExecutionContext &exe_ctx) const;349350UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx,351Helper helper);352lldb::addr_t &GetClassInfoArgs(Helper helper);353354std::unique_ptr<UtilityFunction>355GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, Helper helper,356std::string code, std::string name);357358struct UtilityFunctionHelper {359std::unique_ptr<UtilityFunction> utility_function;360lldb::addr_t args = LLDB_INVALID_ADDRESS;361};362363UtilityFunctionHelper m_gdb_objc_realized_classes_helper;364UtilityFunctionHelper m_objc_copyRealizedClassList_helper;365UtilityFunctionHelper m_objc_getRealizedClassList_trylock_helper;366};367368/// Abstraction to read the Objective-C class info from the shared cache.369class SharedCacheClassInfoExtractor : public ClassInfoExtractor {370public:371SharedCacheClassInfoExtractor(AppleObjCRuntimeV2 &runtime)372: ClassInfoExtractor(runtime) {}373374DescriptorMapUpdateResult UpdateISAToDescriptorMap();375376private:377UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx);378379std::unique_ptr<UtilityFunction>380GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx);381382std::unique_ptr<UtilityFunction> m_utility_function;383lldb::addr_t m_args = LLDB_INVALID_ADDRESS;384};385386class SharedCacheImageHeaders {387public:388static std::unique_ptr<SharedCacheImageHeaders>389CreateSharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime);390391void SetNeedsUpdate() { m_needs_update = true; }392393bool IsImageLoaded(uint16_t image_index);394395uint64_t GetVersion();396397private:398SharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime,399lldb::addr_t headerInfoRWs_ptr, uint32_t count,400uint32_t entsize)401: m_runtime(runtime), m_headerInfoRWs_ptr(headerInfoRWs_ptr),402m_loaded_images(count, false), m_version(0), m_count(count),403m_entsize(entsize), m_needs_update(true) {}404llvm::Error UpdateIfNeeded();405406AppleObjCRuntimeV2 &m_runtime;407lldb::addr_t m_headerInfoRWs_ptr;408llvm::BitVector m_loaded_images;409uint64_t m_version;410uint32_t m_count;411uint32_t m_entsize;412bool m_needs_update;413};414415AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);416417ObjCISA GetPointerISA(ObjCISA isa);418419lldb::addr_t GetISAHashTablePointer();420421/// Update the generation count of realized classes. This is not an exact422/// count but rather a value that is incremented when new classes are realized423/// or destroyed. Unlike the count in gdb_objc_realized_classes, it will424/// change when lazily named classes get realized.425bool RealizedClassGenerationCountChanged();426427uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,428uint32_t num_class_infos);429430enum class SharedCacheWarningReason {431eExpressionUnableToRun,432eExpressionExecutionFailure,433eNotEnoughClassesRead434};435436void WarnIfNoClassesCached(SharedCacheWarningReason reason);437void WarnIfNoExpandedSharedCache();438439lldb::addr_t GetSharedCacheReadOnlyAddress();440lldb::addr_t GetSharedCacheBaseAddress();441442bool GetCFBooleanValuesIfNeeded();443444bool HasSymbol(ConstString Name);445446NonPointerISACache *GetNonPointerIsaCache() {447if (!m_non_pointer_isa_cache_up)448m_non_pointer_isa_cache_up.reset(449NonPointerISACache::CreateInstance(*this, m_objc_module_sp));450return m_non_pointer_isa_cache_up.get();451}452453friend class ClassDescriptorV2;454455lldb::ModuleSP m_objc_module_sp;456457DynamicClassInfoExtractor m_dynamic_class_info_extractor;458SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor;459460std::unique_ptr<DeclVendor> m_decl_vendor_up;461lldb::addr_t m_tagged_pointer_obfuscator;462lldb::addr_t m_isa_hash_table_ptr;463lldb::addr_t m_relative_selector_base;464HashTableSignature m_hash_signature;465bool m_has_object_getClass;466bool m_has_objc_copyRealizedClassList;467bool m_has_objc_getRealizedClassList_trylock;468bool m_loaded_objc_opt;469std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up;470std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up;471EncodingToTypeSP m_encoding_to_type_sp;472std::once_flag m_no_classes_cached_warning;473std::once_flag m_no_expanded_cache_warning;474std::optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;475uint64_t m_realized_class_generation_count;476std::unique_ptr<SharedCacheImageHeaders> m_shared_cache_image_headers_up;477};478479} // namespace lldb_private480481#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H482483484