blob: 034687bfe0164c2e0c166ebe9ddbbaa3a601ef2e [file] [log] [blame]
Enrico Granataf615b802013-02-15 23:38:37 +00001//===-- NSArray.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenko8d15f332015-10-20 01:10:59 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13#include "clang/AST/ASTContext.h"
14
15// Project includes
Enrico Granata170c3952015-09-14 22:18:32 +000016#include "Cocoa.h"
Enrico Granataf615b802013-02-15 23:38:37 +000017
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
Enrico Granataf615b802013-02-15 23:38:37 +000019#include "lldb/Core/DataBufferHeap.h"
20#include "lldb/Core/Error.h"
21#include "lldb/Core/Stream.h"
22#include "lldb/Core/ValueObject.h"
23#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000024#include "lldb/DataFormatters/FormattersHelpers.h"
Jim Ingham151c0322015-09-15 21:13:50 +000025#include "lldb/Expression/FunctionCaller.h"
Enrico Granataf615b802013-02-15 23:38:37 +000026#include "lldb/Host/Endian.h"
27#include "lldb/Symbol/ClangASTContext.h"
Enrico Granata675f49b2015-10-07 18:36:53 +000028#include "lldb/Target/Language.h"
Enrico Granataf615b802013-02-15 23:38:37 +000029#include "lldb/Target/ObjCLanguageRuntime.h"
30#include "lldb/Target/Target.h"
31
32using namespace lldb;
33using namespace lldb_private;
34using namespace lldb_private::formatters;
35
Kate Stoneb9c1b512016-09-06 20:57:50 +000036namespace lldb_private {
37namespace formatters {
38std::map<ConstString, CXXFunctionSummaryFormat::Callback> &
39NSArray_Additionals::GetAdditionalSummaries() {
40 static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
41 return g_map;
42}
Eugene Zelenko8d15f332015-10-20 01:10:59 +000043
Kate Stoneb9c1b512016-09-06 20:57:50 +000044std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> &
45NSArray_Additionals::GetAdditionalSynthetics() {
46 static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>
47 g_map;
48 return g_map;
49}
Eugene Zelenko8d15f332015-10-20 01:10:59 +000050
Kate Stoneb9c1b512016-09-06 20:57:50 +000051class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
52public:
53 NSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +000054
Kate Stoneb9c1b512016-09-06 20:57:50 +000055 ~NSArrayMSyntheticFrontEnd() override = default;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000056
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 size_t CalculateNumChildren() override;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000058
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 bool Update() override = 0;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 bool MightHaveChildren() override;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 size_t GetIndexOfChildWithName(const ConstString &name) override;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067protected:
68 virtual lldb::addr_t GetDataAddress() = 0;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000069
Kate Stoneb9c1b512016-09-06 20:57:50 +000070 virtual uint64_t GetUsedCount() = 0;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000071
Kate Stoneb9c1b512016-09-06 20:57:50 +000072 virtual uint64_t GetOffset() = 0;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000073
Kate Stoneb9c1b512016-09-06 20:57:50 +000074 virtual uint64_t GetSize() = 0;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000075
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 ExecutionContextRef m_exe_ctx_ref;
77 uint8_t m_ptr_size;
78 CompilerType m_id_type;
79};
Eugene Zelenko8d15f332015-10-20 01:10:59 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd {
82public:
83 NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +000084
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 ~NSArrayMSyntheticFrontEnd_109() override;
Enrico Granata936499a2016-02-29 21:06:50 +000086
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 bool Update() override;
88
89protected:
90 lldb::addr_t GetDataAddress() override;
91
92 uint64_t GetUsedCount() override;
93
94 uint64_t GetOffset() override;
95
96 uint64_t GetSize() override;
97
98private:
99 struct DataDescriptor_32 {
100 uint32_t _used;
101 uint32_t _priv1 : 2;
102 uint32_t _size : 30;
103 uint32_t _priv2 : 2;
104 uint32_t _offset : 30;
105 uint32_t _priv3;
106 uint32_t _data;
107 };
108
109 struct DataDescriptor_64 {
110 uint64_t _used;
111 uint64_t _priv1 : 2;
112 uint64_t _size : 62;
113 uint64_t _priv2 : 2;
114 uint64_t _offset : 62;
115 uint32_t _priv3;
116 uint64_t _data;
117 };
118
119 DataDescriptor_32 *m_data_32;
120 DataDescriptor_64 *m_data_64;
121};
122
123class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd {
124public:
125 NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp);
126
127 ~NSArrayMSyntheticFrontEnd_1010() override;
128
129 bool Update() override;
130
131protected:
132 lldb::addr_t GetDataAddress() override;
133
134 uint64_t GetUsedCount() override;
135
136 uint64_t GetOffset() override;
137
138 uint64_t GetSize() override;
139
140private:
141 struct DataDescriptor_32 {
142 uint32_t _used;
143 uint32_t _offset;
144 uint32_t _size : 28;
145 uint64_t _priv1 : 4;
146 uint32_t _priv2;
147 uint32_t _data;
148 };
149
150 struct DataDescriptor_64 {
151 uint64_t _used;
152 uint64_t _offset;
153 uint64_t _size : 60;
154 uint64_t _priv1 : 4;
155 uint32_t _priv2;
156 uint64_t _data;
157 };
158
159 DataDescriptor_32 *m_data_32;
160 DataDescriptor_64 *m_data_64;
161};
162
163class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
164public:
165 NSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
166
167 ~NSArrayISyntheticFrontEnd() override = default;
168
169 size_t CalculateNumChildren() override;
170
171 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
172
173 bool Update() override;
174
175 bool MightHaveChildren() override;
176
177 size_t GetIndexOfChildWithName(const ConstString &name) override;
178
179private:
180 ExecutionContextRef m_exe_ctx_ref;
181 uint8_t m_ptr_size;
182 uint64_t m_items;
183 lldb::addr_t m_data_ptr;
184 CompilerType m_id_type;
185};
186
187class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
188public:
189 NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
190
191 ~NSArray0SyntheticFrontEnd() override = default;
192
193 size_t CalculateNumChildren() override;
194
195 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
196
197 bool Update() override;
198
199 bool MightHaveChildren() override;
200
201 size_t GetIndexOfChildWithName(const ConstString &name) override;
202};
203
204class NSArray1SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
205public:
206 NSArray1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
207
208 ~NSArray1SyntheticFrontEnd() override = default;
209
210 size_t CalculateNumChildren() override;
211
212 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
213
214 bool Update() override;
215
216 bool MightHaveChildren() override;
217
218 size_t GetIndexOfChildWithName(const ConstString &name) override;
219};
220} // namespace formatters
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000221} // namespace lldb_private
Jason Molenda705b1802014-06-13 02:37:02 +0000222
Kate Stoneb9c1b512016-09-06 20:57:50 +0000223bool lldb_private::formatters::NSArraySummaryProvider(
224 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
225 static ConstString g_TypeHint("NSArray");
226
227 ProcessSP process_sp = valobj.GetProcessSP();
228 if (!process_sp)
229 return false;
230
231 ObjCLanguageRuntime *runtime =
232 (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
233 lldb::eLanguageTypeObjC);
234
235 if (!runtime)
236 return false;
237
238 ObjCLanguageRuntime::ClassDescriptorSP descriptor(
239 runtime->GetClassDescriptor(valobj));
240
241 if (!descriptor || !descriptor->IsValid())
242 return false;
243
244 uint32_t ptr_size = process_sp->GetAddressByteSize();
245
246 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
247
248 if (!valobj_addr)
249 return false;
250
251 uint64_t value = 0;
252
253 ConstString class_name(descriptor->GetClassName());
254
255 static const ConstString g_NSArrayI("__NSArrayI");
256 static const ConstString g_NSArrayM("__NSArrayM");
257 static const ConstString g_NSArray0("__NSArray0");
258 static const ConstString g_NSArray1("__NSSingleObjectArrayI");
259 static const ConstString g_NSArrayCF("__NSCFArray");
260
261 if (class_name.IsEmpty())
262 return false;
263
264 if (class_name == g_NSArrayI) {
265 Error error;
266 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
267 ptr_size, 0, error);
268 if (error.Fail())
269 return false;
270 } else if (class_name == g_NSArrayM) {
271 Error error;
272 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
273 ptr_size, 0, error);
274 if (error.Fail())
275 return false;
276 } else if (class_name == g_NSArray0) {
277 value = 0;
278 } else if (class_name == g_NSArray1) {
279 value = 1;
280 } else if (class_name == g_NSArrayCF) {
281 Error error;
282 value = process_sp->ReadUnsignedIntegerFromMemory(
283 valobj_addr + 2 * ptr_size, ptr_size, 0, error);
284 if (error.Fail())
285 return false;
286 } else {
287 auto &map(NSArray_Additionals::GetAdditionalSummaries());
288 auto iter = map.find(class_name), end = map.end();
289 if (iter != end)
290 return iter->second(valobj, stream, options);
Enrico Granataf615b802013-02-15 23:38:37 +0000291 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 return false;
293 }
294
295 std::string prefix, suffix;
296 if (Language *language = Language::FindPlugin(options.GetLanguage())) {
297 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
298 suffix)) {
299 prefix.clear();
300 suffix.clear();
Enrico Granatac28b3e82016-04-11 18:46:37 +0000301 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 }
303
304 stream.Printf("%s%" PRIu64 " %s%s%s", prefix.c_str(), value, "element",
305 value == 1 ? "" : "s", suffix.c_str());
306 return true;
Enrico Granataf615b802013-02-15 23:38:37 +0000307}
308
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd(
310 lldb::ValueObjectSP valobj_sp)
311 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
312 m_id_type() {
313 if (valobj_sp) {
314 clang::ASTContext *ast = valobj_sp->GetExecutionContextRef()
315 .GetTargetSP()
316 ->GetScratchClangASTContext()
317 ->getASTContext();
318 if (ast)
319 m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy);
320 if (valobj_sp->GetProcessSP())
321 m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
322 }
Enrico Granataf615b802013-02-15 23:38:37 +0000323}
324
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::
326 NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp)
327 : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr),
328 m_data_64(nullptr) {}
Jason Molenda705b1802014-06-13 02:37:02 +0000329
Kate Stoneb9c1b512016-09-06 20:57:50 +0000330lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::
331 NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp)
332 : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr),
333 m_data_64(nullptr) {}
Jason Molenda705b1802014-06-13 02:37:02 +0000334
Enrico Granataf615b802013-02-15 23:38:37 +0000335size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() {
337 return GetUsedCount();
Enrico Granataf615b802013-02-15 23:38:37 +0000338}
339
340lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex(
342 size_t idx) {
343 if (idx >= CalculateNumChildren())
344 return lldb::ValueObjectSP();
345 lldb::addr_t object_at_idx = GetDataAddress();
346 size_t pyhs_idx = idx;
347 pyhs_idx += GetOffset();
348 if (GetSize() <= pyhs_idx)
349 pyhs_idx -= GetSize();
350 object_at_idx += (pyhs_idx * m_ptr_size);
351 StreamString idx_name;
352 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
353 return CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx,
354 m_exe_ctx_ref, m_id_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000355}
356
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() {
358 ValueObjectSP valobj_sp = m_backend.GetSP();
359 m_ptr_size = 0;
360 delete m_data_32;
361 m_data_32 = nullptr;
362 delete m_data_64;
363 m_data_64 = nullptr;
364 if (!valobj_sp)
Jason Molenda705b1802014-06-13 02:37:02 +0000365 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000366 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
367 Error error;
368 error.Clear();
369 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
370 if (!process_sp)
Enrico Granataf615b802013-02-15 23:38:37 +0000371 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000372 m_ptr_size = process_sp->GetAddressByteSize();
373 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
374 if (m_ptr_size == 4) {
375 m_data_32 = new DataDescriptor_32();
376 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
377 error);
378 } else {
379 m_data_64 = new DataDescriptor_64();
380 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
381 error);
382 }
383 if (error.Fail())
Enrico Granataf615b802013-02-15 23:38:37 +0000384 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000385 return false;
Enrico Granataf615b802013-02-15 23:38:37 +0000386}
387
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() {
389 ValueObjectSP valobj_sp = m_backend.GetSP();
390 m_ptr_size = 0;
391 delete m_data_32;
392 m_data_32 = nullptr;
393 delete m_data_64;
394 m_data_64 = nullptr;
395 if (!valobj_sp)
396 return false;
397 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
398 Error error;
399 error.Clear();
400 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
401 if (!process_sp)
402 return false;
403 m_ptr_size = process_sp->GetAddressByteSize();
404 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
405 if (m_ptr_size == 4) {
406 m_data_32 = new DataDescriptor_32();
407 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
408 error);
409 } else {
410 m_data_64 = new DataDescriptor_64();
411 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
412 error);
413 }
414 if (error.Fail())
415 return false;
416 return false;
Enrico Granataf615b802013-02-15 23:38:37 +0000417}
418
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() {
420 return true;
Enrico Granatabbf1da32015-10-14 22:45:04 +0000421}
422
Enrico Granatabbf1da32015-10-14 22:45:04 +0000423size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName(
425 const ConstString &name) {
426 const char *item_name = name.GetCString();
427 uint32_t idx = ExtractIndexFromString(item_name);
428 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
Enrico Granatabbf1da32015-10-14 22:45:04 +0000429 return UINT32_MAX;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000430 return idx;
Enrico Granatabbf1da32015-10-14 22:45:04 +0000431}
432
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::
434 ~NSArrayMSyntheticFrontEnd_109() {
435 delete m_data_32;
436 m_data_32 = nullptr;
437 delete m_data_64;
438 m_data_64 = nullptr;
439}
440
441lldb::addr_t
442lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress() {
443 if (!m_data_32 && !m_data_64)
444 return LLDB_INVALID_ADDRESS;
445 return m_data_32 ? m_data_32->_data : m_data_64->_data;
446}
447
448uint64_t
449lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount() {
450 if (!m_data_32 && !m_data_64)
Enrico Granatabbf1da32015-10-14 22:45:04 +0000451 return 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000452 return m_data_32 ? m_data_32->_used : m_data_64->_used;
Enrico Granatabbf1da32015-10-14 22:45:04 +0000453}
454
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset() {
456 if (!m_data_32 && !m_data_64)
457 return 0;
458 return m_data_32 ? m_data_32->_offset : m_data_64->_offset;
Enrico Granatabbf1da32015-10-14 22:45:04 +0000459}
460
Kate Stoneb9c1b512016-09-06 20:57:50 +0000461uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize() {
462 if (!m_data_32 && !m_data_64)
463 return 0;
464 return m_data_32 ? m_data_32->_size : m_data_64->_size;
Enrico Granatabbf1da32015-10-14 22:45:04 +0000465}
466
Kate Stoneb9c1b512016-09-06 20:57:50 +0000467lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::
468 ~NSArrayMSyntheticFrontEnd_1010() {
469 delete m_data_32;
470 m_data_32 = nullptr;
471 delete m_data_64;
472 m_data_64 = nullptr;
Enrico Granatabbf1da32015-10-14 22:45:04 +0000473}
474
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475lldb::addr_t
476lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress() {
477 if (!m_data_32 && !m_data_64)
478 return LLDB_INVALID_ADDRESS;
479 return m_data_32 ? m_data_32->_data : m_data_64->_data;
480}
481
482uint64_t
483lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount() {
484 if (!m_data_32 && !m_data_64)
485 return 0;
486 return m_data_32 ? m_data_32->_used : m_data_64->_used;
487}
488
489uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset() {
490 if (!m_data_32 && !m_data_64)
491 return 0;
492 return m_data_32 ? m_data_32->_offset : m_data_64->_offset;
493}
494
495uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize() {
496 if (!m_data_32 && !m_data_64)
497 return 0;
498 return m_data_32 ? m_data_32->_size : m_data_64->_size;
499}
500
501lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd(
502 lldb::ValueObjectSP valobj_sp)
503 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
504 m_items(0), m_data_ptr(0) {
505 if (valobj_sp) {
506 CompilerType type = valobj_sp->GetCompilerType();
507 if (type) {
508 ClangASTContext *ast = valobj_sp->GetExecutionContextRef()
509 .GetTargetSP()
510 ->GetScratchClangASTContext();
511 if (ast)
512 m_id_type = CompilerType(ast->getASTContext(),
513 ast->getASTContext()->ObjCBuiltinIdTy);
514 }
515 }
Enrico Granata936499a2016-02-29 21:06:50 +0000516}
517
518size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName(
520 const ConstString &name) {
521 const char *item_name = name.GetCString();
522 uint32_t idx = ExtractIndexFromString(item_name);
523 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
Enrico Granata936499a2016-02-29 21:06:50 +0000524 return UINT32_MAX;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525 return idx;
Enrico Granata936499a2016-02-29 21:06:50 +0000526}
527
528size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000529lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren() {
530 return m_items;
Enrico Granata936499a2016-02-29 21:06:50 +0000531}
532
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() {
534 m_ptr_size = 0;
535 m_items = 0;
536 m_data_ptr = 0;
537 ValueObjectSP valobj_sp = m_backend.GetSP();
538 if (!valobj_sp)
Enrico Granata936499a2016-02-29 21:06:50 +0000539 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
541 Error error;
542 error.Clear();
543 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
544 if (!process_sp)
545 return false;
546 m_ptr_size = process_sp->GetAddressByteSize();
547 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
548 m_items = process_sp->ReadPointerFromMemory(data_location, error);
549 if (error.Fail())
550 return false;
551 m_data_ptr = data_location + m_ptr_size;
552 return false;
Enrico Granata936499a2016-02-29 21:06:50 +0000553}
554
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555bool lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren() {
556 return true;
Enrico Granata936499a2016-02-29 21:06:50 +0000557}
558
559lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000560lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex(
561 size_t idx) {
562 if (idx >= CalculateNumChildren())
Enrico Granata936499a2016-02-29 21:06:50 +0000563 return lldb::ValueObjectSP();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000564 lldb::addr_t object_at_idx = m_data_ptr;
565 object_at_idx += (idx * m_ptr_size);
566 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
567 if (!process_sp)
568 return lldb::ValueObjectSP();
569 Error error;
570 if (error.Fail())
571 return lldb::ValueObjectSP();
572 StreamString idx_name;
573 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
574 return CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx,
575 m_exe_ctx_ref, m_id_type);
Enrico Granata936499a2016-02-29 21:06:50 +0000576}
577
Kate Stoneb9c1b512016-09-06 20:57:50 +0000578lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd(
579 lldb::ValueObjectSP valobj_sp)
580 : SyntheticChildrenFrontEnd(*valobj_sp) {}
581
582size_t
583lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName(
584 const ConstString &name) {
585 return UINT32_MAX;
586}
587
588size_t
589lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren() {
590 return 0;
591}
592
593bool lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() {
594 return false;
595}
596
597bool lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren() {
598 return false;
599}
600
601lldb::ValueObjectSP
602lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex(
603 size_t idx) {
604 return lldb::ValueObjectSP();
605}
606
607lldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd(
608 lldb::ValueObjectSP valobj_sp)
609 : SyntheticChildrenFrontEnd(*valobj_sp.get()) {}
610
611size_t
612lldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName(
613 const ConstString &name) {
614 static const ConstString g_zero("[0]");
615
616 if (name == g_zero)
617 return 0;
618
619 return UINT32_MAX;
620}
621
622size_t
623lldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren() {
624 return 1;
625}
626
627bool lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() {
628 return false;
629}
630
631bool lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren() {
632 return true;
633}
634
635lldb::ValueObjectSP
636lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex(
637 size_t idx) {
638 static const ConstString g_zero("[0]");
639
640 if (idx == 0) {
641 CompilerType id_type(
642 m_backend.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
643 lldb::eBasicTypeObjCID));
644 return m_backend.GetSyntheticChildAtOffset(
645 m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero);
646 }
647 return lldb::ValueObjectSP();
648}
649
650SyntheticChildrenFrontEnd *
651lldb_private::formatters::NSArraySyntheticFrontEndCreator(
652 CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
653 if (!valobj_sp)
Enrico Granata2543d292016-02-12 07:50:15 +0000654 return nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000655
656 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
657 if (!process_sp)
658 return nullptr;
659 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
660 process_sp->GetObjCLanguageRuntime());
661 if (!runtime)
662 return nullptr;
663
664 CompilerType valobj_type(valobj_sp->GetCompilerType());
665 Flags flags(valobj_type.GetTypeInfo());
666
667 if (flags.IsClear(eTypeIsPointer)) {
668 Error error;
669 valobj_sp = valobj_sp->AddressOf(error);
670 if (error.Fail() || !valobj_sp)
671 return nullptr;
672 }
673
674 ObjCLanguageRuntime::ClassDescriptorSP descriptor(
675 runtime->GetClassDescriptor(*valobj_sp));
676
677 if (!descriptor || !descriptor->IsValid())
678 return nullptr;
679
680 ConstString class_name(descriptor->GetClassName());
681
682 static const ConstString g_NSArrayI("__NSArrayI");
683 static const ConstString g_NSArrayM("__NSArrayM");
684 static const ConstString g_NSArray0("__NSArray0");
685 static const ConstString g_NSArray1("__NSSingleObjectArrayI");
686
687 if (class_name.IsEmpty())
688 return nullptr;
689
690 if (class_name == g_NSArrayI) {
691 return (new NSArrayISyntheticFrontEnd(valobj_sp));
692 } else if (class_name == g_NSArray0) {
693 return (new NSArray0SyntheticFrontEnd(valobj_sp));
694 } else if (class_name == g_NSArray1) {
695 return (new NSArray1SyntheticFrontEnd(valobj_sp));
696 } else if (class_name == g_NSArrayM) {
697 if (runtime->GetFoundationVersion() >= 1100)
698 return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
699 else
700 return (new NSArrayMSyntheticFrontEnd_109(valobj_sp));
701 } else {
702 auto &map(NSArray_Additionals::GetAdditionalSynthetics());
703 auto iter = map.find(class_name), end = map.end();
704 if (iter != end)
705 return iter->second(synth, valobj_sp);
706 }
707
708 return nullptr;
Enrico Granataf615b802013-02-15 23:38:37 +0000709}