brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.8 KiB · b99bda2 Raw
490 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H10#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H11 12#include <map>13#include <memory>14#include <mutex>15#include <optional>16 17#include "AppleObjCRuntime.h"18#include "lldb/lldb-private.h"19 20#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"21 22#include "llvm/ADT/BitVector.h"23#include "llvm/ADT/SmallSet.h"24 25class RemoteNXMapTable;26 27namespace lldb_private {28 29class AppleObjCRuntimeV2 : public AppleObjCRuntime {30public:31  ~AppleObjCRuntimeV2() override = default;32 33  static void Initialize();34 35  static void Terminate();36 37  static lldb_private::LanguageRuntime *38  CreateInstance(Process *process, lldb::LanguageType language);39 40  static llvm::StringRef GetPluginNameStatic() { return "apple-objc-v2"; }41 42  LanguageRuntime *GetPreferredLanguageRuntime(ValueObject &in_value) override;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 54  bool GetDynamicTypeAndAddress(ValueObject &in_value,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 65  ObjCRuntimeVersions GetRuntimeVersion() const override {66    return ObjCRuntimeVersions::eAppleObjC_V2;67  }68 69  size_t GetByteOffsetForIvar(CompilerType &parent_ast_type,70                              const char *ivar_name) override;71 72  void UpdateISAToDescriptorMapIfNeeded() override;73 74  ClassDescriptorSP GetClassDescriptor(ValueObject &valobj) override;75 76  ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;77 78  DeclVendor *GetDeclVendor() override;79 80  lldb::addr_t LookupRuntimeSymbol(ConstString name) override;81 82  EncodingToTypeSP GetEncodingToType() override;83 84  bool IsTaggedPointer(lldb::addr_t ptr) override;85 86  TaggedPointerVendor *GetTaggedPointerVendor() override {87    return m_tagged_pointer_vendor_up.get();88  }89 90  lldb::addr_t GetTaggedPointerObfuscator();91 92  /// Returns the base address for relative method list selector strings.93  lldb::addr_t GetRelativeSelectorBaseAddr() {94    return m_relative_selector_base;95  }96 97  void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {98    m_relative_selector_base = relative_selector_base;99  }100 101  void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,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 110  StructuredData::ObjectSP GetLanguageSpecificData(SymbolContext sc) override;111 112protected:113  lldb::BreakpointResolverSP114  CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,115                          bool throw_bp) override;116 117private:118  class HashTableSignature {119  public:120    HashTableSignature();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;130    lldb::addr_t m_buckets_ptr = 0;131  };132 133  class NonPointerISACache {134  public:135    static NonPointerISACache *136    CreateInstance(AppleObjCRuntimeV2 &runtime,137                   const lldb::ModuleSP &objc_module_sp);138 139    ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa);140 141  private:142    NonPointerISACache(AppleObjCRuntimeV2 &runtime,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 155    AppleObjCRuntimeV2 &m_runtime;156    std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache;157    lldb::ModuleWP m_objc_module_wp;158    uint64_t m_objc_debug_isa_class_mask;159    uint64_t m_objc_debug_isa_magic_mask;160    uint64_t m_objc_debug_isa_magic_value;161 162    uint64_t m_objc_debug_indexed_isa_magic_mask;163    uint64_t m_objc_debug_indexed_isa_magic_value;164    uint64_t m_objc_debug_indexed_isa_index_mask;165    uint64_t m_objc_debug_indexed_isa_index_shift;166    lldb::addr_t m_objc_indexed_classes;167 168    std::vector<lldb::addr_t> m_indexed_isa_cache;169 170    friend class AppleObjCRuntimeV2;171 172    NonPointerISACache(const NonPointerISACache &) = delete;173    const NonPointerISACache &operator=(const NonPointerISACache &) = delete;174  };175 176  class TaggedPointerVendorV2177      : public ObjCLanguageRuntime::TaggedPointerVendor {178  public:179    ~TaggedPointerVendorV2() override = default;180 181    static TaggedPointerVendorV2 *182    CreateInstance(AppleObjCRuntimeV2 &runtime,183                   const lldb::ModuleSP &objc_module_sp);184 185  protected:186    AppleObjCRuntimeV2 &m_runtime;187 188    TaggedPointerVendorV2(AppleObjCRuntimeV2 &runtime)189        : TaggedPointerVendor(), m_runtime(runtime) {}190 191  private:192    TaggedPointerVendorV2(const TaggedPointerVendorV2 &) = delete;193    const TaggedPointerVendorV2 &194    operator=(const TaggedPointerVendorV2 &) = delete;195  };196 197  class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2 {198  public:199    bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;200 201    ObjCLanguageRuntime::ClassDescriptorSP202    GetClassDescriptor(lldb::addr_t ptr) override;203 204  protected:205    TaggedPointerVendorRuntimeAssisted(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;215    Cache m_cache;216    uint64_t m_objc_debug_taggedpointer_mask;217    uint32_t m_objc_debug_taggedpointer_slot_shift;218    uint32_t m_objc_debug_taggedpointer_slot_mask;219    uint32_t m_objc_debug_taggedpointer_payload_lshift;220    uint32_t m_objc_debug_taggedpointer_payload_rshift;221    lldb::addr_t m_objc_debug_taggedpointer_classes;222 223    friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;224 225    TaggedPointerVendorRuntimeAssisted(226        const TaggedPointerVendorRuntimeAssisted &) = delete;227    const TaggedPointerVendorRuntimeAssisted &228    operator=(const TaggedPointerVendorRuntimeAssisted &) = delete;229  };230 231  class TaggedPointerVendorExtended232      : public TaggedPointerVendorRuntimeAssisted {233  public:234    ObjCLanguageRuntime::ClassDescriptorSP235    GetClassDescriptor(lldb::addr_t ptr) override;236 237  protected:238    TaggedPointerVendorExtended(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 252    bool IsPossibleExtendedTaggedPointer(lldb::addr_t ptr);253 254    typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;255    typedef Cache::iterator CacheIterator;256    Cache m_ext_cache;257    uint64_t m_objc_debug_taggedpointer_ext_mask;258    uint32_t m_objc_debug_taggedpointer_ext_slot_shift;259    uint32_t m_objc_debug_taggedpointer_ext_slot_mask;260    uint32_t m_objc_debug_taggedpointer_ext_payload_lshift;261    uint32_t m_objc_debug_taggedpointer_ext_payload_rshift;262    lldb::addr_t m_objc_debug_taggedpointer_ext_classes;263 264    friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;265 266    TaggedPointerVendorExtended(const TaggedPointerVendorExtended &) = delete;267    const TaggedPointerVendorExtended &268    operator=(const TaggedPointerVendorExtended &) = delete;269  };270 271  class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 {272  public:273    bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;274 275    ObjCLanguageRuntime::ClassDescriptorSP276    GetClassDescriptor(lldb::addr_t ptr) override;277 278  protected:279    TaggedPointerVendorLegacy(AppleObjCRuntimeV2 &runtime)280        : TaggedPointerVendorV2(runtime) {}281 282    friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;283 284    TaggedPointerVendorLegacy(const TaggedPointerVendorLegacy &) = delete;285    const TaggedPointerVendorLegacy &286    operator=(const TaggedPointerVendorLegacy &) = delete;287  };288 289  struct DescriptorMapUpdateResult {290    bool m_update_ran;291    bool m_retry_update;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.312  class ClassInfoExtractor {313  public:314    ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {}315    std::mutex &GetMutex() { return m_mutex; }316 317  protected:318    /// The lifetime of this object is tied to that of the runtime.319    AppleObjCRuntimeV2 &m_runtime;320    std::mutex m_mutex;321  };322 323  /// We can read the class info from the Objective-C runtime using324  /// gdb_objc_realized_classes, objc_copyRealizedClassList or325  /// objc_getRealizedClassList_trylock. The RealizedClassList variants are326  /// preferred because they include lazily named classes, but they are not327  /// always available or safe to call.328  ///329  /// We potentially need more than one helper for the same process, because we330  /// may need to use gdb_objc_realized_classes until dyld is initialized and331  /// then switch over to objc_copyRealizedClassList or332  /// objc_getRealizedClassList_trylock for lazily named classes.333  class DynamicClassInfoExtractor : public ClassInfoExtractor {334  public:335    DynamicClassInfoExtractor(AppleObjCRuntimeV2 &runtime)336        : ClassInfoExtractor(runtime) {}337 338    DescriptorMapUpdateResult339    UpdateISAToDescriptorMap(RemoteNXMapTable &hash_table);340 341  private:342    enum Helper {343      gdb_objc_realized_classes,344      objc_copyRealizedClassList,345      objc_getRealizedClassList_trylock346    };347 348    /// Compute which helper to use. If dyld is not yet fully initialized we349    /// must use gdb_objc_realized_classes. Otherwise, we prefer350    /// objc_getRealizedClassList_trylock and objc_copyRealizedClassList351    /// respectively, depending on availability.352    Helper ComputeHelper(ExecutionContext &exe_ctx) const;353 354    UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx,355                                                 Helper helper);356    lldb::addr_t &GetClassInfoArgs(Helper helper);357 358    std::unique_ptr<UtilityFunction>359    GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, Helper helper,360                                    std::string code, std::string name);361 362    struct UtilityFunctionHelper {363      std::unique_ptr<UtilityFunction> utility_function;364      lldb::addr_t args = LLDB_INVALID_ADDRESS;365    };366 367    UtilityFunctionHelper m_gdb_objc_realized_classes_helper;368    UtilityFunctionHelper m_objc_copyRealizedClassList_helper;369    UtilityFunctionHelper m_objc_getRealizedClassList_trylock_helper;370  };371 372  /// Abstraction to read the Objective-C class info from the shared cache.373  class SharedCacheClassInfoExtractor : public ClassInfoExtractor {374  public:375    SharedCacheClassInfoExtractor(AppleObjCRuntimeV2 &runtime)376        : ClassInfoExtractor(runtime) {}377 378    DescriptorMapUpdateResult UpdateISAToDescriptorMap();379 380  private:381    UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx);382 383    std::unique_ptr<UtilityFunction>384    GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx);385 386    std::unique_ptr<UtilityFunction> m_utility_function;387    lldb::addr_t m_args = LLDB_INVALID_ADDRESS;388  };389 390  class SharedCacheImageHeaders {391  public:392    static std::unique_ptr<SharedCacheImageHeaders>393    CreateSharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime);394 395    void SetNeedsUpdate() { m_needs_update = true; }396 397    bool IsImageLoaded(uint16_t image_index);398 399    uint64_t GetVersion();400 401  private:402    SharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime,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 410    AppleObjCRuntimeV2 &m_runtime;411    lldb::addr_t m_headerInfoRWs_ptr;412    llvm::BitVector m_loaded_images;413    uint64_t m_version;414    uint32_t m_count;415    uint32_t m_entsize;416    bool m_needs_update;417  };418 419  AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);420 421  ObjCISA GetPointerISA(ObjCISA isa);422 423  lldb::addr_t GetISAHashTablePointer();424 425  using ValueObjectSet = llvm::SmallPtrSet<ValueObject *, 8>;426  ClassDescriptorSP GetClassDescriptorImpl(ValueObject &valobj,427                                           ValueObjectSet &seen);428 429  /// Update the generation count of realized classes. This is not an exact430  /// count but rather a value that is incremented when new classes are realized431  /// or destroyed. Unlike the count in gdb_objc_realized_classes, it will432  /// change when lazily named classes get realized.433  bool RealizedClassGenerationCountChanged();434 435  uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,436                               uint32_t num_class_infos);437 438  enum class SharedCacheWarningReason {439    eExpressionUnableToRun,440    eExpressionExecutionFailure,441    eNotEnoughClassesRead442  };443 444  void WarnIfNoClassesCached(SharedCacheWarningReason reason);445  void WarnIfNoExpandedSharedCache();446 447  lldb::addr_t GetSharedCacheReadOnlyAddress();448  lldb::addr_t GetSharedCacheBaseAddress();449 450  bool GetCFBooleanValuesIfNeeded();451 452  bool HasSymbol(ConstString Name);453 454  NonPointerISACache *GetNonPointerIsaCache() {455    if (!m_non_pointer_isa_cache_up)456      m_non_pointer_isa_cache_up.reset(457          NonPointerISACache::CreateInstance(*this, m_objc_module_sp));458    return m_non_pointer_isa_cache_up.get();459  }460 461  friend class ClassDescriptorV2;462 463  lldb::ModuleSP m_objc_module_sp;464 465  DynamicClassInfoExtractor m_dynamic_class_info_extractor;466  SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor;467 468  std::unique_ptr<DeclVendor> m_decl_vendor_up;469  lldb::addr_t m_tagged_pointer_obfuscator;470  lldb::addr_t m_isa_hash_table_ptr;471  lldb::addr_t m_relative_selector_base;472  HashTableSignature m_hash_signature;473  bool m_has_object_getClass;474  bool m_has_objc_copyRealizedClassList;475  bool m_has_objc_getRealizedClassList_trylock;476  bool m_loaded_objc_opt;477  std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up;478  std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up;479  EncodingToTypeSP m_encoding_to_type_sp;480  std::once_flag m_no_classes_cached_warning;481  std::once_flag m_no_expanded_cache_warning;482  std::optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;483  uint64_t m_realized_class_generation_count;484  std::unique_ptr<SharedCacheImageHeaders> m_shared_cache_image_headers_up;485};486 487} // namespace lldb_private488 489#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H490