brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.7 KiB · 0fff9af Raw
403 lines · c
1//===-- AppleObjCClassDescriptorV2.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_APPLEOBJCCLASSDESCRIPTORV2_H10#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCCLASSDESCRIPTORV2_H11 12#include <mutex>13 14#include "AppleObjCRuntimeV2.h"15#include "lldb/lldb-enumerations.h"16#include "lldb/lldb-private.h"17 18#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"19 20namespace lldb_private {21 22class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor {23public:24  friend class lldb_private::AppleObjCRuntimeV2;25 26  ~ClassDescriptorV2() override = default;27 28  ConstString GetClassName() override;29 30  ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override;31 32  ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override;33 34  bool IsValid() override {35    return true; // any Objective-C v2 runtime class descriptor we vend is valid36  }37 38  lldb::LanguageType GetImplementationLanguage() const override;39 40  // a custom descriptor is used for tagged pointers41  bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,42                            uint64_t *value_bits = nullptr,43                            uint64_t *payload = nullptr) override {44    return false;45  }46 47  bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,48                                  int64_t *value_bits = nullptr,49                                  uint64_t *payload = nullptr) override {50    return false;51  }52 53  uint64_t GetInstanceSize() override;54 55  ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; }56 57  bool Describe(58      std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,59      std::function<bool(const char *, const char *)> const60          &instance_method_func,61      std::function<bool(const char *, const char *)> const &class_method_func,62      std::function<bool(const char *, const char *, lldb::addr_t,63                         uint64_t)> const &ivar_func) const override;64 65  size_t GetNumIVars() override {66    GetIVarInformation();67    return m_ivars_storage.size();68  }69 70  iVarDescriptor GetIVarAtIndex(size_t idx) override {71    if (idx >= GetNumIVars())72      return iVarDescriptor();73    return m_ivars_storage[idx];74  }75 76protected:77  void GetIVarInformation();78 79private:80  static const uint32_t RW_REALIZED = (1u << 31);81 82  struct objc_class_t {83    ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass.84    ObjCLanguageRuntime::ObjCISA m_superclass = 0;85    lldb::addr_t m_cache_ptr = 0;86    lldb::addr_t m_vtable_ptr = 0;87    lldb::addr_t m_data_ptr = 0;88    uint8_t m_flags = 0;89 90    objc_class_t() = default;91 92    void Clear() {93      m_isa = 0;94      m_superclass = 0;95      m_cache_ptr = 0;96      m_vtable_ptr = 0;97      m_data_ptr = 0;98      m_flags = 0;99    }100 101    bool Read(Process *process, lldb::addr_t addr);102  };103 104  struct class_ro_t {105    uint32_t m_flags;106    uint32_t m_instanceStart;107    uint32_t m_instanceSize;108    uint32_t m_reserved;109 110    lldb::addr_t m_ivarLayout_ptr;111    lldb::addr_t m_name_ptr;112    lldb::addr_t m_baseMethods_ptr;113    lldb::addr_t m_baseProtocols_ptr;114    lldb::addr_t m_ivars_ptr;115 116    lldb::addr_t m_weakIvarLayout_ptr;117    lldb::addr_t m_baseProperties_ptr;118 119    std::string m_name;120 121    bool Read(Process *process, lldb::addr_t addr);122  };123 124  struct class_rw_t {125    uint32_t m_flags;126    uint32_t m_version;127 128    lldb::addr_t m_ro_ptr;129    union {130      lldb::addr_t m_method_list_ptr;131      lldb::addr_t m_method_lists_ptr;132    };133    lldb::addr_t m_properties_ptr;134    lldb::addr_t m_protocols_ptr;135 136    ObjCLanguageRuntime::ObjCISA m_firstSubclass;137    ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;138 139    bool Read(Process *process, lldb::addr_t addr);140  };141 142  struct method_list_t {143    uint16_t m_entsize;144    bool m_is_small;145    bool m_has_direct_selector;146    bool m_has_relative_types;147    uint32_t m_count;148    lldb::addr_t m_first_ptr;149 150    bool Read(Process *process, lldb::addr_t addr);151  };152 153  std::optional<method_list_t>154  GetMethodList(Process *process, lldb::addr_t method_list_ptr) const;155 156  struct method_t {157    lldb::addr_t m_name_ptr;158    lldb::addr_t m_types_ptr;159    lldb::addr_t m_imp_ptr;160 161    std::string m_name;162    std::string m_types;163 164    static size_t GetSize(Process *process, bool is_small) {165      size_t field_size;166      if (is_small)167        field_size = 4; // uint32_t relative indirect fields168      else169        field_size = process->GetAddressByteSize();170 171      return field_size    // SEL name;172             + field_size  // const char *types;173             + field_size; // IMP imp;174    }175 176    bool Read(DataExtractor &extractor, Process *process, lldb::addr_t addr,177              lldb::addr_t relative_string_base_addr, bool is_small,178              bool has_direct_sel, bool has_relative_types);179  };180 181  llvm::SmallVector<method_t, 0>182  ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses,183              lldb::addr_t relative_string_base_addr, bool is_small,184              bool has_direct_sel, bool has_relative_types) const;185 186  struct ivar_list_t {187    uint32_t m_entsize;188    uint32_t m_count;189    lldb::addr_t m_first_ptr;190 191    bool Read(Process *process, lldb::addr_t addr);192  };193 194  struct ivar_t {195    lldb::addr_t m_offset_ptr;196    lldb::addr_t m_name_ptr;197    lldb::addr_t m_type_ptr;198    uint32_t m_alignment;199    uint32_t m_size;200 201    std::string m_name;202    std::string m_type;203 204    static size_t GetSize(Process *process) {205      size_t ptr_size = process->GetAddressByteSize();206 207      return ptr_size            // uintptr_t *offset;208             + ptr_size          // const char *name;209             + ptr_size          // const char *type;210             + sizeof(uint32_t)  // uint32_t alignment;211             + sizeof(uint32_t); // uint32_t size;212    }213 214    bool Read(Process *process, lldb::addr_t addr);215  };216 217  struct relative_list_entry_t {218    uint16_t m_image_index;219    int64_t m_list_offset;220 221    bool Read(Process *process, lldb::addr_t addr);222  };223 224  struct relative_list_list_t {225    uint32_t m_entsize;226    uint32_t m_count;227    lldb::addr_t m_first_ptr;228 229    bool Read(Process *process, lldb::addr_t addr);230  };231 232  class iVarsStorage {233  public:234    iVarsStorage();235 236    size_t size();237 238    iVarDescriptor &operator[](size_t idx);239 240    void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);241 242  private:243    bool m_filled = false;244    std::vector<iVarDescriptor> m_ivars;245    std::recursive_mutex m_mutex;246  };247 248  // The constructor should only be invoked by the runtime as it builds its249  // caches250  // or populates them.  A ClassDescriptorV2 should only ever exist in a cache.251  ClassDescriptorV2(AppleObjCRuntimeV2 &runtime,252                    ObjCLanguageRuntime::ObjCISA isa, const char *name)253      : m_runtime(runtime), m_objc_class_ptr(isa), m_name(name),254        m_ivars_storage(), m_image_to_method_lists(), m_last_version_updated() {255  }256 257  bool Read_objc_class(Process *process,258                       std::unique_ptr<objc_class_t> &objc_class) const;259 260  bool Read_class_row(Process *process, const objc_class_t &objc_class,261                      std::unique_ptr<class_ro_t> &class_ro,262                      std::unique_ptr<class_rw_t> &class_rw) const;263 264  bool ProcessMethodList(std::function<bool(const char *, const char *)> const265                             &instance_method_func,266                         method_list_t &method_list) const;267 268  bool ProcessRelativeMethodLists(269      std::function<bool(const char *, const char *)> const270          &instance_method_func,271      lldb::addr_t relative_method_list_ptr) const;272 273  AppleObjCRuntimeV2274      &m_runtime; // The runtime, so we can read information lazily.275  lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t.  (I.e.,276                                 // objects of this class type have this as277                                 // their ISA)278  ConstString m_name;            // May be NULL279  iVarsStorage m_ivars_storage;280 281  mutable std::map<uint16_t, std::vector<method_list_t>>282      m_image_to_method_lists;283  mutable std::optional<uint64_t> m_last_version_updated;284};285 286// tagged pointer descriptor287class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor {288public:289  ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {290    m_name = class_name;291    if (!m_name) {292      m_valid = false;293      return;294    }295    m_valid = true;296    m_payload = payload;297    m_info_bits = (m_payload & 0xF0ULL) >> 4;298    m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;299  }300 301  ClassDescriptorV2Tagged(302      ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,303      uint64_t u_payload, int64_t s_payload) {304    if (!actual_class_sp) {305      m_valid = false;306      return;307    }308    m_name = actual_class_sp->GetClassName();309    if (!m_name) {310      m_valid = false;311      return;312    }313    m_valid = true;314    m_payload = u_payload;315    m_info_bits = (m_payload & 0x0FULL);316    m_value_bits = (m_payload & ~0x0FULL) >> 4;317    m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;318  }319 320  ~ClassDescriptorV2Tagged() override = default;321 322  ConstString GetClassName() override { return m_name; }323 324  ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override {325    // tagged pointers can represent a class that has a superclass, but since326    // that information is not327    // stored in the object itself, we would have to query the runtime to328    // discover the hierarchy329    // for the time being, we skip this step in the interest of static discovery330    return ObjCLanguageRuntime::ClassDescriptorSP();331  }332 333  ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override {334    return ObjCLanguageRuntime::ClassDescriptorSP();335  }336 337  bool IsValid() override { return m_valid; }338 339  bool IsKVO() override {340    return false; // tagged pointers are not KVO'ed341  }342 343  bool IsCFType() override {344    return false; // tagged pointers are not CF objects345  }346 347  bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,348                            uint64_t *value_bits = nullptr,349                            uint64_t *payload = nullptr) override {350    if (info_bits)351      *info_bits = GetInfoBits();352    if (value_bits)353      *value_bits = GetValueBits();354    if (payload)355      *payload = GetPayload();356    return true;357  }358 359  bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,360                                  int64_t *value_bits = nullptr,361                                  uint64_t *payload = nullptr) override {362    if (info_bits)363      *info_bits = GetInfoBits();364    if (value_bits)365      *value_bits = GetValueBitsSigned();366    if (payload)367      *payload = GetPayload();368    return true;369  }370 371  uint64_t GetInstanceSize() override {372    return (IsValid() ? m_pointer_size : 0);373  }374 375  ObjCLanguageRuntime::ObjCISA GetISA() override {376    return 0; // tagged pointers have no ISA377  }378 379  // these calls are not part of any formal tagged pointers specification380  virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }381 382  virtual int64_t GetValueBitsSigned() {383    return (IsValid() ? m_value_bits_signed : 0);384  }385 386  virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }387 388  virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }389 390private:391  ConstString m_name;392  uint8_t m_pointer_size = 0;393  bool m_valid = false;394  uint64_t m_info_bits = 0;395  uint64_t m_value_bits = 0;396  int64_t m_value_bits_signed = 0;397  uint64_t m_payload = 0;398};399 400} // namespace lldb_private401 402#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCCLASSDESCRIPTORV2_H403