LLDB  mainline
NSIndexPath.cpp
Go to the documentation of this file.
1 //===-- NSIndexPath.cpp ---------------------------------------------------===//
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 #include "Cocoa.h"
10 
12 #include "lldb/Core/ValueObject.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
18 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::formatters;
23 
24 static constexpr size_t PACKED_INDEX_SHIFT_64(size_t i) {
25  return (60 - (13 * (4 - i)));
26 }
27 
28 static constexpr size_t PACKED_INDEX_SHIFT_32(size_t i) {
29  return (32 - (13 * (2 - i)));
30 }
31 
33 public:
34  NSIndexPathSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
35  : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_descriptor_sp(nullptr),
36  m_impl(), m_ptr_size(0), m_uint_star_type() {
37  m_ptr_size =
38  m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
39  }
40 
41  ~NSIndexPathSyntheticFrontEnd() override = default;
42 
43  size_t CalculateNumChildren() override { return m_impl.GetNumIndexes(); }
44 
45  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
46  return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
47  }
48 
49  bool Update() override {
50  m_impl.Clear();
51 
52  TypeSystem *type_system = m_backend.GetCompilerType().GetTypeSystem();
53  if (!type_system)
54  return false;
55 
56  TypeSystemClang *ast = ScratchTypeSystemClang::GetForTarget(
57  *m_backend.GetExecutionContextRef().GetTargetSP());
58  if (!ast)
59  return false;
60 
61  m_uint_star_type = ast->GetPointerSizedIntType(false);
62 
63  static ConstString g__indexes("_indexes");
64  static ConstString g__length("_length");
65 
66  ProcessSP process_sp = m_backend.GetProcessSP();
67  if (!process_sp)
68  return false;
69 
70  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
71 
72  if (!runtime)
73  return false;
74 
76  runtime->GetClassDescriptor(m_backend));
77 
78  if (!descriptor.get() || !descriptor->IsValid())
79  return false;
80 
81  uint64_t info_bits(0), value_bits(0), payload(0);
82 
83  if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) {
84  m_impl.m_inlined.SetIndexes(payload, *process_sp);
85  m_impl.m_mode = Mode::Inlined;
86  } else {
89 
90  bool has_indexes(false), has_length(false);
91 
92  for (size_t x = 0; x < descriptor->GetNumIVars(); x++) {
93  const auto &ivar = descriptor->GetIVarAtIndex(x);
94  if (ivar.m_name == g__indexes) {
95  _indexes_id = ivar;
96  has_indexes = true;
97  } else if (ivar.m_name == g__length) {
98  _length_id = ivar;
99  has_length = true;
100  }
101 
102  if (has_length && has_indexes)
103  break;
104  }
105 
106  if (has_length && has_indexes) {
107  m_impl.m_outsourced.m_indexes =
108  m_backend
109  .GetSyntheticChildAtOffset(_indexes_id.m_offset,
110  m_uint_star_type.GetPointerType(),
111  true)
112  .get();
113  ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(
114  _length_id.m_offset, m_uint_star_type, true));
115  if (length_sp) {
116  m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
117  if (m_impl.m_outsourced.m_indexes)
118  m_impl.m_mode = Mode::Outsourced;
119  }
120  }
121  }
122  return false;
123  }
124 
125  bool MightHaveChildren() override { return m_impl.m_mode != Mode::Invalid; }
126 
127  size_t GetIndexOfChildWithName(ConstString name) override {
128  const char *item_name = name.GetCString();
129  uint32_t idx = ExtractIndexFromString(item_name);
130  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
131  return UINT32_MAX;
132  return idx;
133  }
134 
135  lldb::ValueObjectSP GetSyntheticValue() override { return nullptr; }
136 
137 protected:
139 
140  enum class Mode { Inlined, Outsourced, Invalid };
141 
142  struct Impl {
143  size_t GetNumIndexes() {
144  switch (m_mode) {
145  case Mode::Inlined:
146  return m_inlined.GetNumIndexes();
147  case Mode::Outsourced:
148  return m_outsourced.m_count;
149  default:
150  return 0;
151  }
152  }
153 
154  lldb::ValueObjectSP GetIndexAtIndex(size_t idx,
155  const CompilerType &desired_type) {
156  if (idx >= GetNumIndexes())
157  return nullptr;
158  switch (m_mode) {
159  default:
160  return nullptr;
161  case Mode::Inlined:
162  return m_inlined.GetIndexAtIndex(idx, desired_type);
163  case Mode::Outsourced:
164  return m_outsourced.GetIndexAtIndex(idx);
165  }
166  }
167 
168  struct InlinedIndexes {
169  public:
170  void SetIndexes(uint64_t value, Process &p) {
171  m_indexes = value;
172  _lengthForInlinePayload(p.GetAddressByteSize());
173  m_process = &p;
174  }
175 
176  size_t GetNumIndexes() { return m_count; }
177 
178  lldb::ValueObjectSP GetIndexAtIndex(size_t idx,
179  const CompilerType &desired_type) {
180  if (!m_process)
181  return nullptr;
182 
183  std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
184  if (!value.second)
185  return nullptr;
186 
187  Value v;
188  if (m_ptr_size == 8) {
189  Scalar scalar((unsigned long long)value.first);
190  v = Value(scalar);
191  } else {
192  Scalar scalar((unsigned int)value.first);
193  v = Value(scalar);
194  }
195 
196  v.SetCompilerType(desired_type);
197 
198  StreamString idx_name;
199  idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
200 
201  return ValueObjectConstResult::Create(
202  m_process, v, ConstString(idx_name.GetString()));
203  }
204 
205  void Clear() {
206  m_indexes = 0;
207  m_count = 0;
208  m_ptr_size = 0;
209  m_process = nullptr;
210  }
211 
213 
214  private:
215  uint64_t m_indexes = 0;
216  size_t m_count = 0;
217  uint32_t m_ptr_size = 0;
218  Process *m_process = nullptr;
219 
220  // cfr. Foundation for the details of this code
222  m_ptr_size = ptr_size;
223  if (m_ptr_size == 8)
224  m_count = ((m_indexes >> 3) & 0x7);
225  else
226  m_count = ((m_indexes >> 3) & 0x3);
227  return m_count;
228  }
229 
230  std::pair<uint64_t, bool> _indexAtPositionForInlinePayload(size_t pos) {
231  static const uint64_t PACKED_INDEX_MASK = ((1 << 13) - 1);
232  if (m_ptr_size == 8) {
233  switch (pos) {
234  case 3:
235  case 2:
236  case 1:
237  case 0:
238  return {(m_indexes >> PACKED_INDEX_SHIFT_64(pos)) &
239  PACKED_INDEX_MASK,
240  true};
241  default:
242  return {0, false};
243  }
244  } else {
245  switch (pos) {
246  case 0:
247  case 1:
248  return {(m_indexes >> PACKED_INDEX_SHIFT_32(pos)) &
249  PACKED_INDEX_MASK,
250  true};
251  default:
252  return {0, false};
253  }
254  }
255  return {0, false};
256  }
257  };
258 
260  lldb::ValueObjectSP GetIndexAtIndex(size_t idx) {
261  if (m_indexes) {
262  ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
263  return index_sp;
264  }
265  return nullptr;
266  }
267 
268  void Clear() {
269  m_indexes = nullptr;
270  m_count = 0;
271  }
272 
274 
275  ValueObject *m_indexes = nullptr;
276  size_t m_count = 0;
277  };
278 
279  union {
280  struct InlinedIndexes m_inlined;
281  struct OutsourcedIndexes m_outsourced;
282  };
283 
284  void Clear() {
285  m_mode = Mode::Invalid;
286  m_inlined.Clear();
287  m_outsourced.Clear();
288  }
289 
290  Impl() {}
291 
292  Mode m_mode = Mode::Invalid;
293  } m_impl;
294 
297 };
298 
299 namespace lldb_private {
300 namespace formatters {
301 
304  lldb::ValueObjectSP valobj_sp) {
305  if (valobj_sp)
306  return new NSIndexPathSyntheticFrontEnd(valobj_sp);
307  return nullptr;
308 }
309 
310 } // namespace formatters
311 } // namespace lldb_private
lldb_private::CompilerContextKind::Invalid
@ Invalid
lldb_private::ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor::m_offset
int32_t m_offset
Definition: ObjCLanguageRuntime.h:131
NSIndexPathSyntheticFrontEnd::Impl::Clear
void Clear()
Definition: NSIndexPath.cpp:284
PACKED_INDEX_SHIFT_64
static constexpr size_t PACKED_INDEX_SHIFT_64(size_t i)
Definition: NSIndexPath.cpp:24
lldb_private::ObjCLanguageRuntime
Definition: ObjCLanguageRuntime.h:34
lldb_private::Value
Definition: Value.h:38
lldb_private::ObjCLanguageRuntime::ClassDescriptorSP
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
Definition: ObjCLanguageRuntime.h:44
lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator
SyntheticChildrenFrontEnd * NSIndexPathSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSIndexPath.cpp:303
lldb_private::Scalar
Definition: Scalar.h:34
lldb_private::Process
Definition: Process.h:341
CalculateNumChildren
static size_t CalculateNumChildren(CompilerType container_type, CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope=nullptr)
Definition: VectorType.cpp:169
lldb_private::SyntheticChildrenFrontEnd
Definition: TypeSynthetic.h:27
NSIndexPathSyntheticFrontEnd::m_ptr_size
uint32_t m_ptr_size
Definition: NSIndexPath.cpp:295
NSIndexPathSyntheticFrontEnd::GetIndexOfChildWithName
size_t GetIndexOfChildWithName(ConstString name) override
Definition: NSIndexPath.cpp:127
NSIndexPathSyntheticFrontEnd::GetSyntheticValue
lldb::ValueObjectSP GetSyntheticValue() override
Definition: NSIndexPath.cpp:135
NSIndexPathSyntheticFrontEnd::Impl::Impl
Impl()
Definition: NSIndexPath.cpp:290
arm64_dwarf::x3
@ x3
Definition: ARM64_DWARF_Registers.h:20
NSIndexPathSyntheticFrontEnd::Impl::OutsourcedIndexes
Definition: NSIndexPath.cpp:259
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
Process.h
NSIndexPathSyntheticFrontEnd::Mode
Mode
Definition: NSIndexPath.cpp:140
lldb_private::Value::SetCompilerType
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:254
Target.h
NSIndexPathSyntheticFrontEnd::Impl::GetIndexAtIndex
lldb::ValueObjectSP GetIndexAtIndex(size_t idx, const CompilerType &desired_type)
Definition: NSIndexPath.cpp:154
NSIndexPathSyntheticFrontEnd::m_descriptor_sp
ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp
Definition: NSIndexPath.cpp:138
TypeSystemClang.h
NSIndexPathSyntheticFrontEnd::Update
bool Update() override
Definition: NSIndexPath.cpp:49
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::GetIndexAtIndex
lldb::ValueObjectSP GetIndexAtIndex(size_t idx, const CompilerType &desired_type)
Definition: NSIndexPath.cpp:178
lldb_private::ObjCLanguageRuntime::GetClassDescriptor
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
Definition: ObjCLanguageRuntime.cpp:235
lldb_private::Process::GetAddressByteSize
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3317
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::StreamString
Definition: StreamString.h:23
NSIndexPathSyntheticFrontEnd::Impl::OutsourcedIndexes::Clear
void Clear()
Definition: NSIndexPath.cpp:268
NSIndexPathSyntheticFrontEnd::MightHaveChildren
bool MightHaveChildren() override
Definition: NSIndexPath.cpp:125
ValueObject.h
NSIndexPathSyntheticFrontEnd::Impl::OutsourcedIndexes::OutsourcedIndexes
OutsourcedIndexes()
Definition: NSIndexPath.cpp:273
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::_lengthForInlinePayload
size_t _lengthForInlinePayload(uint32_t ptr_size)
Definition: NSIndexPath.cpp:221
ValueObjectConstResult.h
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::_indexAtPositionForInlinePayload
std::pair< uint64_t, bool > _indexAtPositionForInlinePayload(size_t pos)
Definition: NSIndexPath.cpp:230
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes
Definition: NSIndexPath.cpp:168
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::InlinedIndexes
InlinedIndexes()
Definition: NSIndexPath.cpp:212
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::Clear
void Clear()
Definition: NSIndexPath.cpp:205
NSIndexPathSyntheticFrontEnd::GetChildAtIndex
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: NSIndexPath.cpp:45
lldb_private::ValueObject
ValueObject:
Definition: ValueObject.h:105
uint32_t
TypeSynthetic.h
NSIndexPathSyntheticFrontEnd::CalculateNumChildren
size_t CalculateNumChildren() override
Definition: NSIndexPath.cpp:43
PACKED_INDEX_SHIFT_32
static constexpr size_t PACKED_INDEX_SHIFT_32(size_t i)
Definition: NSIndexPath.cpp:28
NSIndexPathSyntheticFrontEnd
Definition: NSIndexPath.cpp:32
arm64_dwarf::x7
@ x7
Definition: ARM64_DWARF_Registers.h:24
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:31
ObjCLanguageRuntime.h
lldb_private::ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor
Definition: ObjCLanguageRuntime.h:127
lldb_private::ConstString::GetCString
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
NSIndexPathSyntheticFrontEnd::NSIndexPathSyntheticFrontEnd
NSIndexPathSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: NSIndexPath.cpp:34
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::GetNumIndexes
size_t GetNumIndexes()
Definition: NSIndexPath.cpp:176
lldb_private::formatters
Definition: CXXFunctionPointer.h:15
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
NSIndexPathSyntheticFrontEnd::Impl::GetNumIndexes
size_t GetNumIndexes()
Definition: NSIndexPath.cpp:143
lldb_private::TypeSystem
Interface for representing a type system.
Definition: TypeSystem.h:71
lldb_private::TypeSystemClang
A TypeSystem implementation based on Clang.
Definition: TypeSystemClang.h:106
NSIndexPathSyntheticFrontEnd::m_uint_star_type
CompilerType m_uint_star_type
Definition: NSIndexPath.cpp:296
NSIndexPathSyntheticFrontEnd::Impl
Definition: NSIndexPath.cpp:142
NSIndexPathSyntheticFrontEnd::Impl::OutsourcedIndexes::GetIndexAtIndex
lldb::ValueObjectSP GetIndexAtIndex(size_t idx)
Definition: NSIndexPath.cpp:260
Cocoa.h
lldb_private::CXXSyntheticChildren
Definition: TypeSynthetic.h:358
NSIndexPathSyntheticFrontEnd::Impl::InlinedIndexes::SetIndexes
void SetIndexes(uint64_t value, Process &p)
Definition: NSIndexPath.cpp:170
FormattersHelpers.h
lldb_private::TypeSystemClang::GetPointerSizedIntType
CompilerType GetPointerSizedIntType(bool is_signed)
Definition: TypeSystemClang.cpp:2380
lldb
Definition: SBAddress.h:15
lldb_private::formatters::ExtractIndexFromString
size_t ExtractIndexFromString(const char *item_name)
Definition: FormattersHelpers.cpp:119