Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
Line
Count
Source (jump to first uncovered line)
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCCLASSDESCRIPTORV2_H
10
#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCCLASSDESCRIPTORV2_H
11
12
#include <mutex>
13
14
#include "AppleObjCRuntimeV2.h"
15
#include "lldb/lldb-private.h"
16
17
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
18
19
namespace lldb_private {
20
21
class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor {
22
public:
23
  friend class lldb_private::AppleObjCRuntimeV2;
24
25
97.5M
  ~ClassDescriptorV2() override = default;
26
27
  ConstString GetClassName() override;
28
29
  ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override;
30
31
  ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override;
32
33
3.65k
  bool IsValid() override {
34
3.65k
    return true; // any Objective-C v2 runtime class descriptor we vend is valid
35
3.65k
  }
36
37
  // a custom descriptor is used for tagged pointers
38
  bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
39
                            uint64_t *value_bits = nullptr,
40
36
                            uint64_t *payload = nullptr) override {
41
36
    return false;
42
36
  }
43
44
  bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
45
                                  int64_t *value_bits = nullptr,
46
156
                                  uint64_t *payload = nullptr) override {
47
156
    return false;
48
156
  }
49
50
  uint64_t GetInstanceSize() override;
51
52
0
  ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; }
53
54
  bool Describe(
55
      std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
56
      std::function<bool(const char *, const char *)> const
57
          &instance_method_func,
58
      std::function<bool(const char *, const char *)> const &class_method_func,
59
      std::function<bool(const char *, const char *, lldb::addr_t,
60
                         uint64_t)> const &ivar_func) const override;
61
62
636
  size_t GetNumIVars() override {
63
636
    GetIVarInformation();
64
636
    return m_ivars_storage.size();
65
636
  }
66
67
261
  iVarDescriptor GetIVarAtIndex(size_t idx) override {
68
261
    if (idx >= GetNumIVars())
69
0
      return iVarDescriptor();
70
261
    return m_ivars_storage[idx];
71
261
  }
72
73
protected:
74
  void GetIVarInformation();
75
76
private:
77
  static const uint32_t RW_REALIZED = (1 << 31);
78
79
  struct objc_class_t {
80
    ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass.
81
    ObjCLanguageRuntime::ObjCISA m_superclass = 0;
82
    lldb::addr_t m_cache_ptr = 0;
83
    lldb::addr_t m_vtable_ptr = 0;
84
    lldb::addr_t m_data_ptr = 0;
85
    uint8_t m_flags = 0;
86
87
2.81k
    objc_class_t() = default;
88
89
0
    void Clear() {
90
0
      m_isa = 0;
91
0
      m_superclass = 0;
92
0
      m_cache_ptr = 0;
93
0
      m_vtable_ptr = 0;
94
0
      m_data_ptr = 0;
95
0
      m_flags = 0;
96
0
    }
97
98
    bool Read(Process *process, lldb::addr_t addr);
99
  };
100
101
  struct class_ro_t {
102
    uint32_t m_flags;
103
    uint32_t m_instanceStart;
104
    uint32_t m_instanceSize;
105
    uint32_t m_reserved;
106
107
    lldb::addr_t m_ivarLayout_ptr;
108
    lldb::addr_t m_name_ptr;
109
    lldb::addr_t m_baseMethods_ptr;
110
    lldb::addr_t m_baseProtocols_ptr;
111
    lldb::addr_t m_ivars_ptr;
112
113
    lldb::addr_t m_weakIvarLayout_ptr;
114
    lldb::addr_t m_baseProperties_ptr;
115
116
    std::string m_name;
117
118
    bool Read(Process *process, lldb::addr_t addr);
119
  };
120
121
  struct class_rw_t {
122
    uint32_t m_flags;
123
    uint32_t m_version;
124
125
    lldb::addr_t m_ro_ptr;
126
    union {
127
      lldb::addr_t m_method_list_ptr;
128
      lldb::addr_t m_method_lists_ptr;
129
    };
130
    lldb::addr_t m_properties_ptr;
131
    lldb::addr_t m_protocols_ptr;
132
133
    ObjCLanguageRuntime::ObjCISA m_firstSubclass;
134
    ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
135
136
    bool Read(Process *process, lldb::addr_t addr);
137
  };
138
139
  struct method_list_t {
140
    uint16_t m_entsize;
141
    bool m_is_small;
142
    bool m_has_direct_selector;
143
    uint32_t m_count;
144
    lldb::addr_t m_first_ptr;
145
146
    bool Read(Process *process, lldb::addr_t addr);
147
  };
148
149
  struct method_t {
150
    lldb::addr_t m_name_ptr;
151
    lldb::addr_t m_types_ptr;
152
    lldb::addr_t m_imp_ptr;
153
154
    std::string m_name;
155
    std::string m_types;
156
157
25.0k
    static size_t GetSize(Process *process, bool is_small) {
158
25.0k
      size_t field_size;
159
25.0k
      if (is_small)
160
0
        field_size = 4; // uint32_t relative indirect fields
161
25.0k
      else
162
25.0k
        field_size = process->GetAddressByteSize();
163
164
25.0k
      return field_size    // SEL name;
165
25.0k
             + field_size  // const char *types;
166
25.0k
             + field_size; // IMP imp;
167
25.0k
    }
168
169
    bool Read(Process *process, lldb::addr_t addr,
170
              lldb::addr_t relative_method_lists_base_addr, bool, bool);
171
  };
172
173
  struct ivar_list_t {
174
    uint32_t m_entsize;
175
    uint32_t m_count;
176
    lldb::addr_t m_first_ptr;
177
178
    bool Read(Process *process, lldb::addr_t addr);
179
  };
180
181
  struct ivar_t {
182
    lldb::addr_t m_offset_ptr;
183
    lldb::addr_t m_name_ptr;
184
    lldb::addr_t m_type_ptr;
185
    uint32_t m_alignment;
186
    uint32_t m_size;
187
188
    std::string m_name;
189
    std::string m_type;
190
191
992
    static size_t GetSize(Process *process) {
192
992
      size_t ptr_size = process->GetAddressByteSize();
193
194
992
      return ptr_size            // uintptr_t *offset;
195
992
             + ptr_size          // const char *name;
196
992
             + ptr_size          // const char *type;
197
992
             + sizeof(uint32_t)  // uint32_t alignment;
198
992
             + sizeof(uint32_t); // uint32_t size;
199
992
    }
200
201
    bool Read(Process *process, lldb::addr_t addr);
202
  };
203
204
  class iVarsStorage {
205
  public:
206
    iVarsStorage();
207
208
    size_t size();
209
210
    iVarDescriptor &operator[](size_t idx);
211
212
    void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
213
214
  private:
215
    bool m_filled = false;
216
    std::vector<iVarDescriptor> m_ivars;
217
    std::recursive_mutex m_mutex;
218
  };
219
220
  // The constructor should only be invoked by the runtime as it builds its
221
  // caches
222
  // or populates them.  A ClassDescriptorV2 should only ever exist in a cache.
223
  ClassDescriptorV2(AppleObjCRuntimeV2 &runtime,
224
                    ObjCLanguageRuntime::ObjCISA isa, const char *name)
225
      : m_runtime(runtime), m_objc_class_ptr(isa), m_name(name),
226
97.5M
        m_ivars_storage() {}
227
228
  bool Read_objc_class(Process *process,
229
                       std::unique_ptr<objc_class_t> &objc_class) const;
230
231
  bool Read_class_row(Process *process, const objc_class_t &objc_class,
232
                      std::unique_ptr<class_ro_t> &class_ro,
233
                      std::unique_ptr<class_rw_t> &class_rw) const;
234
235
  AppleObjCRuntimeV2
236
      &m_runtime; // The runtime, so we can read information lazily.
237
  lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t.  (I.e.,
238
                                 // objects of this class type have this as
239
                                 // their ISA)
240
  ConstString m_name;            // May be NULL
241
  iVarsStorage m_ivars_storage;
242
};
243
244
// tagged pointer descriptor
245
class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor {
246
public:
247
0
  ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {
248
0
    m_name = class_name;
249
0
    if (!m_name) {
250
0
      m_valid = false;
251
0
      return;
252
0
    }
253
0
    m_valid = true;
254
0
    m_payload = payload;
255
0
    m_info_bits = (m_payload & 0xF0ULL) >> 4;
256
0
    m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
257
0
  }
258
259
  ClassDescriptorV2Tagged(
260
      ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
261
1.24k
      uint64_t u_payload, int64_t s_payload) {
262
1.24k
    if (!actual_class_sp) {
263
0
      m_valid = false;
264
0
      return;
265
0
    }
266
1.24k
    m_name = actual_class_sp->GetClassName();
267
1.24k
    if (!m_name) {
268
0
      m_valid = false;
269
0
      return;
270
0
    }
271
1.24k
    m_valid = true;
272
1.24k
    m_payload = u_payload;
273
1.24k
    m_info_bits = (m_payload & 0x0FULL);
274
1.24k
    m_value_bits = (m_payload & ~0x0FULL) >> 4;
275
1.24k
    m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;
276
1.24k
  }
277
278
1.24k
  ~ClassDescriptorV2Tagged() override = default;
279
280
1.17k
  ConstString GetClassName() override { return m_name; }
281
282
35
  ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override {
283
    // tagged pointers can represent a class that has a superclass, but since
284
    // that information is not
285
    // stored in the object itself, we would have to query the runtime to
286
    // discover the hierarchy
287
    // for the time being, we skip this step in the interest of static discovery
288
35
    return ObjCLanguageRuntime::ClassDescriptorSP();
289
35
  }
290
291
0
  ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override {
292
0
    return ObjCLanguageRuntime::ClassDescriptorSP();
293
0
  }
294
295
1.81k
  bool IsValid() override { return m_valid; }
296
297
224
  bool IsKVO() override {
298
224
    return false; // tagged pointers are not KVO'ed
299
224
  }
300
301
0
  bool IsCFType() override {
302
0
    return false; // tagged pointers are not CF objects
303
0
  }
304
305
  bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
306
                            uint64_t *value_bits = nullptr,
307
228
                            uint64_t *payload = nullptr) override {
308
228
    if (info_bits)
309
195
      *info_bits = GetInfoBits();
310
228
    if (value_bits)
311
195
      *value_bits = GetValueBits();
312
228
    if (payload)
313
24
      *payload = GetPayload();
314
228
    return true;
315
228
  }
316
317
  bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
318
                                  int64_t *value_bits = nullptr,
319
397
                                  uint64_t *payload = nullptr) override {
320
397
    if (info_bits)
321
397
      *info_bits = GetInfoBits();
322
397
    if (value_bits)
323
397
      *value_bits = GetValueBitsSigned();
324
397
    if (payload)
325
0
      *payload = GetPayload();
326
397
    return true;
327
397
  }
328
329
0
  uint64_t GetInstanceSize() override {
330
0
    return (IsValid() ? m_pointer_size : 0);
331
0
  }
332
333
0
  ObjCLanguageRuntime::ObjCISA GetISA() override {
334
0
    return 0; // tagged pointers have no ISA
335
0
  }
336
337
  // these calls are not part of any formal tagged pointers specification
338
195
  virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 
00
); }
339
340
397
  virtual int64_t GetValueBitsSigned() {
341
397
    return (IsValid() ? m_value_bits_signed : 
00
);
342
397
  }
343
344
592
  virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 
00
); }
345
346
24
  virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 
00
); }
347
348
private:
349
  ConstString m_name;
350
  uint8_t m_pointer_size;
351
  bool m_valid;
352
  uint64_t m_info_bits;
353
  uint64_t m_value_bits;
354
  int64_t m_value_bits_signed;
355
  uint64_t m_payload;
356
};
357
358
} // namespace lldb_private
359
360
#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCCLASSDESCRIPTORV2_H