347 lines
12 KiB
C++
347 lines
12 KiB
C++
//===-- AppleObjCRuntimeV2.h ------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef liblldb_AppleObjCRuntimeV2_h_
|
|
#define liblldb_AppleObjCRuntimeV2_h_
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
#include <map>
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "AppleObjCRuntime.h"
|
|
#include "lldb/Target/ObjCLanguageRuntime.h"
|
|
#include "lldb/lldb-private.h"
|
|
|
|
class RemoteNXMapTable;
|
|
|
|
namespace lldb_private {
|
|
|
|
class AppleObjCRuntimeV2 : public AppleObjCRuntime {
|
|
public:
|
|
~AppleObjCRuntimeV2() override = default;
|
|
|
|
//------------------------------------------------------------------
|
|
// Static Functions
|
|
//------------------------------------------------------------------
|
|
static void Initialize();
|
|
|
|
static void Terminate();
|
|
|
|
static lldb_private::LanguageRuntime *
|
|
CreateInstance(Process *process, lldb::LanguageType language);
|
|
|
|
static lldb_private::ConstString GetPluginNameStatic();
|
|
|
|
static bool classof(const ObjCLanguageRuntime *runtime) {
|
|
switch (runtime->GetRuntimeVersion()) {
|
|
case ObjCRuntimeVersions::eAppleObjC_V2:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// These are generic runtime functions:
|
|
bool GetDynamicTypeAndAddress(ValueObject &in_value,
|
|
lldb::DynamicValueType use_dynamic,
|
|
TypeAndOrName &class_type_or_name,
|
|
Address &address,
|
|
Value::ValueType &value_type) override;
|
|
|
|
UtilityFunction *CreateObjectChecker(const char *) override;
|
|
|
|
//------------------------------------------------------------------
|
|
// PluginInterface protocol
|
|
//------------------------------------------------------------------
|
|
ConstString GetPluginName() override;
|
|
|
|
uint32_t GetPluginVersion() override;
|
|
|
|
ObjCRuntimeVersions GetRuntimeVersion() const override {
|
|
return ObjCRuntimeVersions::eAppleObjC_V2;
|
|
}
|
|
|
|
size_t GetByteOffsetForIvar(CompilerType &parent_qual_type,
|
|
const char *ivar_name) override;
|
|
|
|
void UpdateISAToDescriptorMapIfNeeded() override;
|
|
|
|
ConstString GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) override;
|
|
|
|
ClassDescriptorSP GetClassDescriptor(ValueObject &in_value) override;
|
|
|
|
ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;
|
|
|
|
DeclVendor *GetDeclVendor() override;
|
|
|
|
lldb::addr_t LookupRuntimeSymbol(const ConstString &name) override;
|
|
|
|
EncodingToTypeSP GetEncodingToType() override;
|
|
|
|
bool IsTaggedPointer(lldb::addr_t ptr) override;
|
|
|
|
TaggedPointerVendor *GetTaggedPointerVendor() override {
|
|
return m_tagged_pointer_vendor_ap.get();
|
|
}
|
|
|
|
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
|
|
lldb::addr_t &cf_false) override;
|
|
|
|
// none of these are valid ISAs - we use them to infer the type
|
|
// of tagged pointers - if we have something meaningful to say
|
|
// we report an actual type - otherwise, we just say tagged
|
|
// there is no connection between the values here and the tagged pointers map
|
|
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1;
|
|
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSAtom = 2;
|
|
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSNumber = 3;
|
|
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDateTS = 4;
|
|
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject =
|
|
5;
|
|
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
|
|
|
|
protected:
|
|
lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
|
|
bool catch_bp,
|
|
bool throw_bp) override;
|
|
|
|
private:
|
|
class HashTableSignature {
|
|
public:
|
|
HashTableSignature();
|
|
|
|
bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime,
|
|
RemoteNXMapTable &hash_table);
|
|
|
|
void UpdateSignature(const RemoteNXMapTable &hash_table);
|
|
|
|
protected:
|
|
uint32_t m_count;
|
|
uint32_t m_num_buckets;
|
|
lldb::addr_t m_buckets_ptr;
|
|
};
|
|
|
|
class NonPointerISACache {
|
|
public:
|
|
static NonPointerISACache *
|
|
CreateInstance(AppleObjCRuntimeV2 &runtime,
|
|
const lldb::ModuleSP &objc_module_sp);
|
|
|
|
ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa);
|
|
|
|
private:
|
|
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);
|
|
|
|
AppleObjCRuntimeV2 &m_runtime;
|
|
std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
|
|
lldb::ModuleWP m_objc_module_wp;
|
|
uint64_t m_objc_debug_isa_class_mask;
|
|
uint64_t m_objc_debug_isa_magic_mask;
|
|
uint64_t m_objc_debug_isa_magic_value;
|
|
|
|
uint64_t m_objc_debug_indexed_isa_magic_mask;
|
|
uint64_t m_objc_debug_indexed_isa_magic_value;
|
|
uint64_t m_objc_debug_indexed_isa_index_mask;
|
|
uint64_t m_objc_debug_indexed_isa_index_shift;
|
|
lldb::addr_t m_objc_indexed_classes;
|
|
|
|
std::vector<lldb::addr_t> m_indexed_isa_cache;
|
|
|
|
friend class AppleObjCRuntimeV2;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
|
|
};
|
|
|
|
class TaggedPointerVendorV2
|
|
: public ObjCLanguageRuntime::TaggedPointerVendor {
|
|
public:
|
|
~TaggedPointerVendorV2() override = default;
|
|
|
|
static TaggedPointerVendorV2 *
|
|
CreateInstance(AppleObjCRuntimeV2 &runtime,
|
|
const lldb::ModuleSP &objc_module_sp);
|
|
|
|
protected:
|
|
AppleObjCRuntimeV2 &m_runtime;
|
|
|
|
TaggedPointerVendorV2(AppleObjCRuntimeV2 &runtime)
|
|
: TaggedPointerVendor(), m_runtime(runtime) {}
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorV2);
|
|
};
|
|
|
|
class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2 {
|
|
public:
|
|
bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
|
|
|
|
ObjCLanguageRuntime::ClassDescriptorSP
|
|
GetClassDescriptor(lldb::addr_t ptr) override;
|
|
|
|
protected:
|
|
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);
|
|
|
|
typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
|
|
typedef Cache::iterator CacheIterator;
|
|
Cache m_cache;
|
|
uint64_t m_objc_debug_taggedpointer_mask;
|
|
uint32_t m_objc_debug_taggedpointer_slot_shift;
|
|
uint32_t m_objc_debug_taggedpointer_slot_mask;
|
|
uint32_t m_objc_debug_taggedpointer_payload_lshift;
|
|
uint32_t m_objc_debug_taggedpointer_payload_rshift;
|
|
lldb::addr_t m_objc_debug_taggedpointer_classes;
|
|
|
|
friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
|
|
};
|
|
|
|
class TaggedPointerVendorExtended
|
|
: public TaggedPointerVendorRuntimeAssisted {
|
|
public:
|
|
ObjCLanguageRuntime::ClassDescriptorSP
|
|
GetClassDescriptor(lldb::addr_t ptr) override;
|
|
|
|
protected:
|
|
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);
|
|
|
|
bool IsPossibleExtendedTaggedPointer(lldb::addr_t ptr);
|
|
|
|
typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
|
|
typedef Cache::iterator CacheIterator;
|
|
Cache m_ext_cache;
|
|
uint64_t m_objc_debug_taggedpointer_ext_mask;
|
|
uint32_t m_objc_debug_taggedpointer_ext_slot_shift;
|
|
uint32_t m_objc_debug_taggedpointer_ext_slot_mask;
|
|
uint32_t m_objc_debug_taggedpointer_ext_payload_lshift;
|
|
uint32_t m_objc_debug_taggedpointer_ext_payload_rshift;
|
|
lldb::addr_t m_objc_debug_taggedpointer_ext_classes;
|
|
|
|
friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorExtended);
|
|
};
|
|
|
|
class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 {
|
|
public:
|
|
bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
|
|
|
|
ObjCLanguageRuntime::ClassDescriptorSP
|
|
GetClassDescriptor(lldb::addr_t ptr) override;
|
|
|
|
protected:
|
|
TaggedPointerVendorLegacy(AppleObjCRuntimeV2 &runtime)
|
|
: TaggedPointerVendorV2(runtime) {}
|
|
|
|
friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
|
|
};
|
|
|
|
struct DescriptorMapUpdateResult {
|
|
bool m_update_ran;
|
|
uint32_t m_num_found;
|
|
|
|
DescriptorMapUpdateResult(bool ran, uint32_t found) {
|
|
m_update_ran = ran;
|
|
m_num_found = found;
|
|
}
|
|
|
|
static DescriptorMapUpdateResult Fail() { return {false, 0}; }
|
|
|
|
static DescriptorMapUpdateResult Success(uint32_t found) {
|
|
return {true, found};
|
|
}
|
|
};
|
|
|
|
AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);
|
|
|
|
ObjCISA GetPointerISA(ObjCISA isa);
|
|
|
|
lldb::addr_t GetISAHashTablePointer();
|
|
|
|
bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table);
|
|
|
|
DescriptorMapUpdateResult
|
|
UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
|
|
|
|
uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,
|
|
uint32_t num_class_infos);
|
|
|
|
DescriptorMapUpdateResult UpdateISAToDescriptorMapSharedCache();
|
|
|
|
enum class SharedCacheWarningReason {
|
|
eExpressionExecutionFailure,
|
|
eNotEnoughClassesRead
|
|
};
|
|
|
|
void WarnIfNoClassesCached(SharedCacheWarningReason reason);
|
|
|
|
lldb::addr_t GetSharedCacheReadOnlyAddress();
|
|
|
|
bool GetCFBooleanValuesIfNeeded();
|
|
|
|
friend class ClassDescriptorV2;
|
|
|
|
std::unique_ptr<UtilityFunction> m_get_class_info_code;
|
|
lldb::addr_t m_get_class_info_args;
|
|
std::mutex m_get_class_info_args_mutex;
|
|
|
|
std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
|
|
lldb::addr_t m_get_shared_cache_class_info_args;
|
|
std::mutex m_get_shared_cache_class_info_args_mutex;
|
|
|
|
std::unique_ptr<DeclVendor> m_decl_vendor_ap;
|
|
lldb::addr_t m_isa_hash_table_ptr;
|
|
HashTableSignature m_hash_signature;
|
|
bool m_has_object_getClass;
|
|
bool m_loaded_objc_opt;
|
|
std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
|
|
std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
|
|
EncodingToTypeSP m_encoding_to_type_sp;
|
|
bool m_noclasses_warning_emitted;
|
|
llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // liblldb_AppleObjCRuntimeV2_h_
|