NSSet.cpp revision 32d7ee3d2969211e104a27fcfcd636f249b26559
1//===-- NSSet.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 10#include "lldb/DataFormatters/CXXFormatterFunctions.h" 11 12#include "lldb/Core/DataBufferHeap.h" 13#include "lldb/Core/Error.h" 14#include "lldb/Core/Stream.h" 15#include "lldb/Core/ValueObject.h" 16#include "lldb/Core/ValueObjectConstResult.h" 17#include "lldb/Host/Endian.h" 18#include "lldb/Symbol/ClangASTContext.h" 19#include "lldb/Target/ObjCLanguageRuntime.h" 20#include "lldb/Target/Target.h" 21 22using namespace lldb; 23using namespace lldb_private; 24using namespace lldb_private::formatters; 25 26template<bool cf_style> 27bool 28lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream) 29{ 30 ProcessSP process_sp = valobj.GetProcessSP(); 31 if (!process_sp) 32 return false; 33 34 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 35 36 if (!runtime) 37 return false; 38 39 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 40 41 if (!descriptor.get() || !descriptor->IsValid()) 42 return false; 43 44 uint32_t ptr_size = process_sp->GetAddressByteSize(); 45 bool is_64bit = (ptr_size == 8); 46 47 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 48 49 if (!valobj_addr) 50 return false; 51 52 uint64_t value = 0; 53 54 const char* class_name = descriptor->GetClassName().GetCString(); 55 56 if (!class_name || !*class_name) 57 return false; 58 59 if (!strcmp(class_name,"__NSSetI")) 60 { 61 Error error; 62 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 63 if (error.Fail()) 64 return false; 65 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 66 } 67 else if (!strcmp(class_name,"__NSSetM")) 68 { 69 Error error; 70 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 71 if (error.Fail()) 72 return false; 73 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 74 } 75 else if (!strcmp(class_name,"__NSCFSet")) 76 { 77 Error error; 78 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), ptr_size, 0, error); 79 if (error.Fail()) 80 return false; 81 if (is_64bit) 82 value &= ~0x1fff000000000000UL; 83 } 84 else if (!strcmp(class_name,"NSCountedSet")) 85 { 86 Error error; 87 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 88 if (error.Fail()) 89 return false; 90 value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), ptr_size, 0, error); 91 if (error.Fail()) 92 return false; 93 if (is_64bit) 94 value &= ~0x1fff000000000000UL; 95 } 96 else 97 { 98 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) 99 return false; 100 } 101 102 stream.Printf("%s%" PRIu64 " %s%s", 103 (cf_style ? "@\"" : ""), 104 value, 105 (cf_style ? (value == 1 ? "value" : "values") : (value == 1 ? "object" : "objects")), 106 (cf_style ? "\"" : "")); 107 return true; 108} 109 110SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 111{ 112 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); 113 if (!process_sp) 114 return NULL; 115 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 116 if (!runtime) 117 return NULL; 118 119 if (!valobj_sp->IsPointerType()) 120 { 121 Error error; 122 valobj_sp = valobj_sp->AddressOf(error); 123 if (error.Fail() || !valobj_sp) 124 return NULL; 125 } 126 127 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); 128 129 if (!descriptor.get() || !descriptor->IsValid()) 130 return NULL; 131 132 const char* class_name = descriptor->GetClassName().GetCString(); 133 134 if (!class_name || !*class_name) 135 return NULL; 136 137 if (!strcmp(class_name,"__NSSetI")) 138 { 139 return (new NSSetISyntheticFrontEnd(valobj_sp)); 140 } 141 else if (!strcmp(class_name,"__NSSetM")) 142 { 143 return (new NSSetMSyntheticFrontEnd(valobj_sp)); 144 } 145 else 146 { 147 return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL; 148 } 149} 150 151lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 152SyntheticChildrenFrontEnd(*valobj_sp.get()), 153m_exe_ctx_ref(), 154m_ptr_size(8), 155m_data_32(NULL), 156m_data_64(NULL) 157{ 158 if (valobj_sp) 159 Update(); 160} 161 162lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd () 163{ 164 delete m_data_32; 165 m_data_32 = NULL; 166 delete m_data_64; 167 m_data_64 = NULL; 168} 169 170size_t 171lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 172{ 173 const char* item_name = name.GetCString(); 174 uint32_t idx = ExtractIndexFromString(item_name); 175 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 176 return UINT32_MAX; 177 return idx; 178} 179 180size_t 181lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren () 182{ 183 if (!m_data_32 && !m_data_64) 184 return 0; 185 return (m_data_32 ? m_data_32->_used : m_data_64->_used); 186} 187 188bool 189lldb_private::formatters::NSSetISyntheticFrontEnd::Update() 190{ 191 m_children.clear(); 192 delete m_data_32; 193 m_data_32 = NULL; 194 delete m_data_64; 195 m_data_64 = NULL; 196 m_ptr_size = 0; 197 ValueObjectSP valobj_sp = m_backend.GetSP(); 198 if (!valobj_sp) 199 return false; 200 if (!valobj_sp) 201 return false; 202 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 203 Error error; 204 if (valobj_sp->IsPointerType()) 205 { 206 valobj_sp = valobj_sp->Dereference(error); 207 if (error.Fail() || !valobj_sp) 208 return false; 209 } 210 error.Clear(); 211 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 212 if (!process_sp) 213 return false; 214 m_ptr_size = process_sp->GetAddressByteSize(); 215 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; 216 if (m_ptr_size == 4) 217 { 218 m_data_32 = new DataDescriptor_32(); 219 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 220 } 221 else 222 { 223 m_data_64 = new DataDescriptor_64(); 224 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 225 } 226 if (error.Fail()) 227 return false; 228 m_data_ptr = data_location + m_ptr_size; 229 return false; 230} 231 232bool 233lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren () 234{ 235 return true; 236} 237 238lldb::ValueObjectSP 239lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx) 240{ 241 uint32_t num_children = CalculateNumChildren(); 242 243 if (idx >= num_children) 244 return lldb::ValueObjectSP(); 245 246 if (m_children.empty()) 247 { 248 // do the scan phase 249 lldb::addr_t obj_at_idx = 0; 250 251 uint32_t tries = 0; 252 uint32_t test_idx = 0; 253 254 while(tries < num_children) 255 { 256 obj_at_idx = m_data_ptr + (test_idx * m_ptr_size); 257 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 258 if (!process_sp) 259 return lldb::ValueObjectSP(); 260 Error error; 261 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 262 if (error.Fail()) 263 return lldb::ValueObjectSP(); 264 265 test_idx++; 266 267 if (!obj_at_idx) 268 continue; 269 tries++; 270 271 SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()}; 272 273 m_children.push_back(descriptor); 274 } 275 } 276 277 if (idx >= m_children.size()) // should never happen 278 return lldb::ValueObjectSP(); 279 280 SetItemDescriptor &set_item = m_children[idx]; 281 if (!set_item.valobj_sp) 282 { 283 // make the new ValueObject 284 StreamString expr; 285 expr.Printf("(id)%" PRIu64,set_item.item_ptr); 286 StreamString idx_name; 287 idx_name.Printf("[%zu]",idx); 288 set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref); 289 } 290 return set_item.valobj_sp; 291} 292 293lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 294SyntheticChildrenFrontEnd(*valobj_sp.get()), 295m_exe_ctx_ref(), 296m_ptr_size(8), 297m_data_32(NULL), 298m_data_64(NULL) 299{ 300 if (valobj_sp) 301 Update (); 302} 303 304lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd () 305{ 306 delete m_data_32; 307 m_data_32 = NULL; 308 delete m_data_64; 309 m_data_64 = NULL; 310} 311 312size_t 313lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 314{ 315 const char* item_name = name.GetCString(); 316 uint32_t idx = ExtractIndexFromString(item_name); 317 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 318 return UINT32_MAX; 319 return idx; 320} 321 322size_t 323lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren () 324{ 325 if (!m_data_32 && !m_data_64) 326 return 0; 327 return (m_data_32 ? m_data_32->_used : m_data_64->_used); 328} 329 330bool 331lldb_private::formatters::NSSetMSyntheticFrontEnd::Update() 332{ 333 m_children.clear(); 334 ValueObjectSP valobj_sp = m_backend.GetSP(); 335 m_ptr_size = 0; 336 delete m_data_32; 337 m_data_32 = NULL; 338 delete m_data_64; 339 m_data_64 = NULL; 340 if (!valobj_sp) 341 return false; 342 if (!valobj_sp) 343 return false; 344 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 345 Error error; 346 if (valobj_sp->IsPointerType()) 347 { 348 valobj_sp = valobj_sp->Dereference(error); 349 if (error.Fail() || !valobj_sp) 350 return false; 351 } 352 error.Clear(); 353 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 354 if (!process_sp) 355 return false; 356 m_ptr_size = process_sp->GetAddressByteSize(); 357 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; 358 if (m_ptr_size == 4) 359 { 360 m_data_32 = new DataDescriptor_32(); 361 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 362 } 363 else 364 { 365 m_data_64 = new DataDescriptor_64(); 366 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 367 } 368 if (error.Fail()) 369 return false; 370 return false; 371} 372 373bool 374lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren () 375{ 376 return true; 377} 378 379lldb::ValueObjectSP 380lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx) 381{ 382 lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 383 384 uint32_t num_children = CalculateNumChildren(); 385 386 if (idx >= num_children) 387 return lldb::ValueObjectSP(); 388 389 if (m_children.empty()) 390 { 391 // do the scan phase 392 lldb::addr_t obj_at_idx = 0; 393 394 uint32_t tries = 0; 395 uint32_t test_idx = 0; 396 397 while(tries < num_children) 398 { 399 obj_at_idx = m_objs_addr + (test_idx * m_ptr_size); 400 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 401 if (!process_sp) 402 return lldb::ValueObjectSP(); 403 Error error; 404 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 405 if (error.Fail()) 406 return lldb::ValueObjectSP(); 407 408 test_idx++; 409 410 if (!obj_at_idx) 411 continue; 412 tries++; 413 414 SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()}; 415 416 m_children.push_back(descriptor); 417 } 418 } 419 420 if (idx >= m_children.size()) // should never happen 421 return lldb::ValueObjectSP(); 422 423 SetItemDescriptor &set_item = m_children[idx]; 424 if (!set_item.valobj_sp) 425 { 426 // make the new ValueObject 427 StreamString expr; 428 expr.Printf("(id)%" PRIu64,set_item.item_ptr); 429 StreamString idx_name; 430 idx_name.Printf("[%zu]",idx); 431 set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref); 432 } 433 return set_item.valobj_sp; 434} 435 436template bool 437lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream); 438 439template bool 440lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream); 441