1 //===-- ObjCLanguage.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 // C Includes 11 // C++ Includes 12 #include <mutex> 13 14 // Other libraries and framework includes 15 // Project includes 16 #include "ObjCLanguage.h" 17 18 #include "lldb/Core/PluginManager.h" 19 #include "lldb/Core/ValueObject.h" 20 #include "lldb/DataFormatters/DataVisualization.h" 21 #include "lldb/DataFormatters/FormattersHelpers.h" 22 #include "lldb/Symbol/ClangASTContext.h" 23 #include "lldb/Symbol/CompilerType.h" 24 #include "lldb/Target/ObjCLanguageRuntime.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Utility/ConstString.h" 27 #include "lldb/Utility/StreamString.h" 28 29 #include "llvm/Support/Threading.h" 30 31 #include "CF.h" 32 #include "Cocoa.h" 33 #include "CoreMedia.h" 34 #include "NSDictionary.h" 35 #include "NSSet.h" 36 #include "NSString.h" 37 38 using namespace lldb; 39 using namespace lldb_private; 40 using namespace lldb_private::formatters; 41 42 void ObjCLanguage::Initialize() { 43 PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C Language", 44 CreateInstance); 45 } 46 47 void ObjCLanguage::Terminate() { 48 PluginManager::UnregisterPlugin(CreateInstance); 49 } 50 51 lldb_private::ConstString ObjCLanguage::GetPluginNameStatic() { 52 static ConstString g_name("objc"); 53 return g_name; 54 } 55 56 //------------------------------------------------------------------ 57 // PluginInterface protocol 58 //------------------------------------------------------------------ 59 60 lldb_private::ConstString ObjCLanguage::GetPluginName() { 61 return GetPluginNameStatic(); 62 } 63 64 uint32_t ObjCLanguage::GetPluginVersion() { return 1; } 65 66 //------------------------------------------------------------------ 67 // Static Functions 68 //------------------------------------------------------------------ 69 70 Language *ObjCLanguage::CreateInstance(lldb::LanguageType language) { 71 switch (language) { 72 case lldb::eLanguageTypeObjC: 73 return new ObjCLanguage(); 74 default: 75 return nullptr; 76 } 77 } 78 79 void ObjCLanguage::MethodName::Clear() { 80 m_full.Clear(); 81 m_class.Clear(); 82 m_category.Clear(); 83 m_selector.Clear(); 84 m_type = eTypeUnspecified; 85 m_category_is_valid = false; 86 } 87 88 bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) { 89 Clear(); 90 if (name.empty()) 91 return IsValid(strict); 92 93 // If "strict" is true. then the method must be specified with a 94 // '+' or '-' at the beginning. If "strict" is false, then the '+' 95 // or '-' can be omitted 96 bool valid_prefix = false; 97 98 if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) { 99 valid_prefix = name[1] == '['; 100 if (name[0] == '+') 101 m_type = eTypeClassMethod; 102 else 103 m_type = eTypeInstanceMethod; 104 } else if (!strict) { 105 // "strict" is false, the name just needs to start with '[' 106 valid_prefix = name[0] == '['; 107 } 108 109 if (valid_prefix) { 110 int name_len = name.size(); 111 // Objective C methods must have at least: 112 // "-[" or "+[" prefix 113 // One character for a class name 114 // One character for the space between the class name 115 // One character for the method name 116 // "]" suffix 117 if (name_len >= (5 + (strict ? 1 : 0)) && name.back() == ']') { 118 m_full.SetString(name); 119 } 120 } 121 return IsValid(strict); 122 } 123 124 bool ObjCLanguage::MethodName::SetName(const char *name, bool strict) { 125 return SetName(llvm::StringRef(name), strict); 126 } 127 128 const ConstString &ObjCLanguage::MethodName::GetClassName() { 129 if (!m_class) { 130 if (IsValid(false)) { 131 const char *full = m_full.GetCString(); 132 const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 133 const char *paren_pos = strchr(class_start, '('); 134 if (paren_pos) { 135 m_class.SetCStringWithLength(class_start, paren_pos - class_start); 136 } else { 137 // No '(' was found in the full name, we can definitively say 138 // that our category was valid (and empty). 139 m_category_is_valid = true; 140 const char *space_pos = strchr(full, ' '); 141 if (space_pos) { 142 m_class.SetCStringWithLength(class_start, space_pos - class_start); 143 if (!m_class_category) { 144 // No category in name, so we can also fill in the m_class_category 145 m_class_category = m_class; 146 } 147 } 148 } 149 } 150 } 151 return m_class; 152 } 153 154 const ConstString &ObjCLanguage::MethodName::GetClassNameWithCategory() { 155 if (!m_class_category) { 156 if (IsValid(false)) { 157 const char *full = m_full.GetCString(); 158 const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 159 const char *space_pos = strchr(full, ' '); 160 if (space_pos) { 161 m_class_category.SetCStringWithLength(class_start, 162 space_pos - class_start); 163 // If m_class hasn't been filled in and the class with category doesn't 164 // contain a '(', then we can also fill in the m_class 165 if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) { 166 m_class = m_class_category; 167 // No '(' was found in the full name, we can definitively say 168 // that our category was valid (and empty). 169 m_category_is_valid = true; 170 } 171 } 172 } 173 } 174 return m_class_category; 175 } 176 177 const ConstString &ObjCLanguage::MethodName::GetSelector() { 178 if (!m_selector) { 179 if (IsValid(false)) { 180 const char *full = m_full.GetCString(); 181 const char *space_pos = strchr(full, ' '); 182 if (space_pos) { 183 ++space_pos; // skip the space 184 m_selector.SetCStringWithLength(space_pos, m_full.GetLength() - 185 (space_pos - full) - 1); 186 } 187 } 188 } 189 return m_selector; 190 } 191 192 const ConstString &ObjCLanguage::MethodName::GetCategory() { 193 if (!m_category_is_valid && !m_category) { 194 if (IsValid(false)) { 195 m_category_is_valid = true; 196 const char *full = m_full.GetCString(); 197 const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 198 const char *open_paren_pos = strchr(class_start, '('); 199 if (open_paren_pos) { 200 ++open_paren_pos; // Skip the open paren 201 const char *close_paren_pos = strchr(open_paren_pos, ')'); 202 if (close_paren_pos) 203 m_category.SetCStringWithLength(open_paren_pos, 204 close_paren_pos - open_paren_pos); 205 } 206 } 207 } 208 return m_category; 209 } 210 211 ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory( 212 bool empty_if_no_category) { 213 if (IsValid(false)) { 214 if (HasCategory()) { 215 StreamString strm; 216 if (m_type == eTypeClassMethod) 217 strm.PutChar('+'); 218 else if (m_type == eTypeInstanceMethod) 219 strm.PutChar('-'); 220 strm.Printf("[%s %s]", GetClassName().GetCString(), 221 GetSelector().GetCString()); 222 return ConstString(strm.GetString()); 223 } 224 225 if (!empty_if_no_category) { 226 // Just return the full name since it doesn't have a category 227 return GetFullName(); 228 } 229 } 230 return ConstString(); 231 } 232 233 size_t ObjCLanguage::MethodName::GetFullNames(std::vector<ConstString> &names, 234 bool append) { 235 if (!append) 236 names.clear(); 237 if (IsValid(false)) { 238 StreamString strm; 239 const bool is_class_method = m_type == eTypeClassMethod; 240 const bool is_instance_method = m_type == eTypeInstanceMethod; 241 const ConstString &category = GetCategory(); 242 if (is_class_method || is_instance_method) { 243 names.push_back(m_full); 244 if (category) { 245 strm.Printf("%c[%s %s]", is_class_method ? '+' : '-', 246 GetClassName().GetCString(), GetSelector().GetCString()); 247 names.emplace_back(strm.GetString()); 248 } 249 } else { 250 const ConstString &class_name = GetClassName(); 251 const ConstString &selector = GetSelector(); 252 strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString()); 253 names.emplace_back(strm.GetString()); 254 strm.Clear(); 255 strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString()); 256 names.emplace_back(strm.GetString()); 257 strm.Clear(); 258 if (category) { 259 strm.Printf("+[%s(%s) %s]", class_name.GetCString(), 260 category.GetCString(), selector.GetCString()); 261 names.emplace_back(strm.GetString()); 262 strm.Clear(); 263 strm.Printf("-[%s(%s) %s]", class_name.GetCString(), 264 category.GetCString(), selector.GetCString()); 265 names.emplace_back(strm.GetString()); 266 } 267 } 268 } 269 return names.size(); 270 } 271 272 static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { 273 if (!objc_category_sp) 274 return; 275 276 TypeSummaryImpl::Flags objc_flags; 277 objc_flags.SetCascades(false) 278 .SetSkipPointers(true) 279 .SetSkipReferences(true) 280 .SetDontShowChildren(true) 281 .SetDontShowValue(true) 282 .SetShowMembersOneLiner(false) 283 .SetHideItemNames(false); 284 285 lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat( 286 objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider, "")); 287 objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"), 288 ObjC_BOOL_summary); 289 objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"), 290 ObjC_BOOL_summary); 291 objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"), 292 ObjC_BOOL_summary); 293 294 #ifndef LLDB_DISABLE_PYTHON 295 // we need to skip pointers here since we are special casing a SEL* when 296 // retrieving its value 297 objc_flags.SetSkipPointers(true); 298 AddCXXSummary(objc_category_sp, 299 lldb_private::formatters::ObjCSELSummaryProvider<false>, 300 "SEL summary provider", ConstString("SEL"), objc_flags); 301 AddCXXSummary( 302 objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, 303 "SEL summary provider", ConstString("struct objc_selector"), objc_flags); 304 AddCXXSummary( 305 objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, 306 "SEL summary provider", ConstString("objc_selector"), objc_flags); 307 AddCXXSummary( 308 objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, 309 "SEL summary provider", ConstString("objc_selector *"), objc_flags); 310 AddCXXSummary(objc_category_sp, 311 lldb_private::formatters::ObjCSELSummaryProvider<true>, 312 "SEL summary provider", ConstString("SEL *"), objc_flags); 313 314 AddCXXSummary(objc_category_sp, 315 lldb_private::formatters::ObjCClassSummaryProvider, 316 "Class summary provider", ConstString("Class"), objc_flags); 317 318 SyntheticChildren::Flags class_synth_flags; 319 class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( 320 false); 321 322 AddCXXSynthetic(objc_category_sp, 323 lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, 324 "Class synthetic children", ConstString("Class"), 325 class_synth_flags); 326 #endif // LLDB_DISABLE_PYTHON 327 328 objc_flags.SetSkipPointers(false); 329 objc_flags.SetCascades(true); 330 objc_flags.SetSkipReferences(false); 331 332 AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}", 333 ConstString("__block_literal_generic"), objc_flags); 334 335 AddStringSummary(objc_category_sp, "${var.years} years, ${var.months} " 336 "months, ${var.days} days, ${var.hours} " 337 "hours, ${var.minutes} minutes " 338 "${var.seconds} seconds", 339 ConstString("CFGregorianUnits"), objc_flags); 340 AddStringSummary(objc_category_sp, 341 "location=${var.location} length=${var.length}", 342 ConstString("CFRange"), objc_flags); 343 344 AddStringSummary(objc_category_sp, 345 "location=${var.location}, length=${var.length}", 346 ConstString("NSRange"), objc_flags); 347 AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...", 348 ConstString("NSRectArray"), objc_flags); 349 350 AddOneLineSummary(objc_category_sp, ConstString("NSPoint"), objc_flags); 351 AddOneLineSummary(objc_category_sp, ConstString("NSSize"), objc_flags); 352 AddOneLineSummary(objc_category_sp, ConstString("NSRect"), objc_flags); 353 354 AddOneLineSummary(objc_category_sp, ConstString("CGSize"), objc_flags); 355 AddOneLineSummary(objc_category_sp, ConstString("CGPoint"), objc_flags); 356 AddOneLineSummary(objc_category_sp, ConstString("CGRect"), objc_flags); 357 358 AddStringSummary(objc_category_sp, 359 "red=${var.red} green=${var.green} blue=${var.blue}", 360 ConstString("RGBColor"), objc_flags); 361 AddStringSummary( 362 objc_category_sp, 363 "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", 364 ConstString("Rect"), objc_flags); 365 AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}", 366 ConstString("Point"), objc_flags); 367 AddStringSummary(objc_category_sp, 368 "${var.month}/${var.day}/${var.year} ${var.hour} " 369 ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}", 370 ConstString("DateTimeRect *"), objc_flags); 371 AddStringSummary(objc_category_sp, "${var.ld.month}/${var.ld.day}/" 372 "${var.ld.year} ${var.ld.hour} " 373 ":${var.ld.minute} :${var.ld.second} " 374 "dayOfWeek:${var.ld.dayOfWeek}", 375 ConstString("LongDateRect"), objc_flags); 376 AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})", 377 ConstString("HIPoint"), objc_flags); 378 AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}", 379 ConstString("HIRect"), objc_flags); 380 381 TypeSummaryImpl::Flags appkit_flags; 382 appkit_flags.SetCascades(true) 383 .SetSkipPointers(false) 384 .SetSkipReferences(false) 385 .SetDontShowChildren(true) 386 .SetDontShowValue(false) 387 .SetShowMembersOneLiner(false) 388 .SetHideItemNames(false); 389 390 appkit_flags.SetDontShowChildren(false); 391 392 #ifndef LLDB_DISABLE_PYTHON 393 AddCXXSummary( 394 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 395 "NSArray summary provider", ConstString("NSArray"), appkit_flags); 396 AddCXXSummary( 397 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 398 "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags); 399 AddCXXSummary( 400 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 401 "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags); 402 AddCXXSummary( 403 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 404 "NSArray summary provider", ConstString("__NSArray0"), appkit_flags); 405 AddCXXSummary(objc_category_sp, 406 lldb_private::formatters::NSArraySummaryProvider, 407 "NSArray summary provider", 408 ConstString("__NSSingleObjectArrayI"), appkit_flags); 409 AddCXXSummary( 410 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 411 "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags); 412 AddCXXSummary( 413 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 414 "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags); 415 AddCXXSummary( 416 objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, 417 "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags); 418 AddCXXSummary(objc_category_sp, 419 lldb_private::formatters::NSArraySummaryProvider, 420 "NSArray summary provider", ConstString("CFMutableArrayRef"), 421 appkit_flags); 422 423 AddCXXSummary(objc_category_sp, 424 lldb_private::formatters::NSDictionarySummaryProvider<false>, 425 "NSDictionary summary provider", ConstString("NSDictionary"), 426 appkit_flags); 427 AddCXXSummary(objc_category_sp, 428 lldb_private::formatters::NSDictionarySummaryProvider<false>, 429 "NSDictionary summary provider", 430 ConstString("NSMutableDictionary"), appkit_flags); 431 AddCXXSummary(objc_category_sp, 432 lldb_private::formatters::NSDictionarySummaryProvider<false>, 433 "NSDictionary summary provider", 434 ConstString("__NSCFDictionary"), appkit_flags); 435 AddCXXSummary(objc_category_sp, 436 lldb_private::formatters::NSDictionarySummaryProvider<false>, 437 "NSDictionary summary provider", ConstString("__NSDictionaryI"), 438 appkit_flags); 439 AddCXXSummary(objc_category_sp, 440 lldb_private::formatters::NSDictionarySummaryProvider<false>, 441 "NSDictionary summary provider", 442 ConstString("__NSSingleEntryDictionaryI"), appkit_flags); 443 AddCXXSummary(objc_category_sp, 444 lldb_private::formatters::NSDictionarySummaryProvider<false>, 445 "NSDictionary summary provider", ConstString("__NSDictionaryM"), 446 appkit_flags); 447 AddCXXSummary(objc_category_sp, 448 lldb_private::formatters::NSDictionarySummaryProvider<true>, 449 "NSDictionary summary provider", ConstString("CFDictionaryRef"), 450 appkit_flags); 451 AddCXXSummary(objc_category_sp, 452 lldb_private::formatters::NSDictionarySummaryProvider<true>, 453 "NSDictionary summary provider", 454 ConstString("CFMutableDictionaryRef"), appkit_flags); 455 456 AddCXXSummary(objc_category_sp, 457 lldb_private::formatters::NSSetSummaryProvider<false>, 458 "NSSet summary", ConstString("NSSet"), appkit_flags); 459 AddCXXSummary( 460 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 461 "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); 462 AddCXXSummary(objc_category_sp, 463 lldb_private::formatters::NSSetSummaryProvider<true>, 464 "CFSetRef summary", ConstString("CFSetRef"), appkit_flags); 465 AddCXXSummary( 466 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, 467 "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags); 468 AddCXXSummary(objc_category_sp, 469 lldb_private::formatters::NSSetSummaryProvider<false>, 470 "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags); 471 AddCXXSummary(objc_category_sp, 472 lldb_private::formatters::NSSetSummaryProvider<false>, 473 "__NSSetI summary", ConstString("__NSSetI"), appkit_flags); 474 AddCXXSummary(objc_category_sp, 475 lldb_private::formatters::NSSetSummaryProvider<false>, 476 "__NSSetM summary", ConstString("__NSSetM"), appkit_flags); 477 AddCXXSummary( 478 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 479 "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags); 480 AddCXXSummary( 481 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 482 "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); 483 AddCXXSummary( 484 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 485 "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags); 486 AddCXXSummary( 487 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 488 "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags); 489 AddCXXSummary( 490 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, 491 "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags); 492 493 AddCXXSummary( 494 objc_category_sp, lldb_private::formatters::NSError_SummaryProvider, 495 "NSError summary provider", ConstString("NSError"), appkit_flags); 496 AddCXXSummary( 497 objc_category_sp, lldb_private::formatters::NSException_SummaryProvider, 498 "NSException summary provider", ConstString("NSException"), appkit_flags); 499 500 // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", 501 // ConstString("$_lldb_typegen_nspair"), appkit_flags); 502 503 appkit_flags.SetDontShowChildren(true); 504 505 AddCXXSynthetic(objc_category_sp, 506 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 507 "NSArray synthetic children", ConstString("__NSArrayM"), 508 ScriptedSyntheticChildren::Flags()); 509 AddCXXSynthetic(objc_category_sp, 510 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 511 "NSArray synthetic children", ConstString("__NSArrayI"), 512 ScriptedSyntheticChildren::Flags()); 513 AddCXXSynthetic(objc_category_sp, 514 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 515 "NSArray synthetic children", ConstString("__NSArray0"), 516 ScriptedSyntheticChildren::Flags()); 517 AddCXXSynthetic(objc_category_sp, 518 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 519 "NSArray synthetic children", 520 ConstString("__NSSingleObjectArrayI"), 521 ScriptedSyntheticChildren::Flags()); 522 AddCXXSynthetic(objc_category_sp, 523 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 524 "NSArray synthetic children", ConstString("NSArray"), 525 ScriptedSyntheticChildren::Flags()); 526 AddCXXSynthetic(objc_category_sp, 527 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 528 "NSArray synthetic children", ConstString("NSMutableArray"), 529 ScriptedSyntheticChildren::Flags()); 530 AddCXXSynthetic(objc_category_sp, 531 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 532 "NSArray synthetic children", ConstString("__NSCFArray"), 533 ScriptedSyntheticChildren::Flags()); 534 AddCXXSynthetic(objc_category_sp, 535 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 536 "NSArray synthetic children", 537 ConstString("CFMutableArrayRef"), 538 ScriptedSyntheticChildren::Flags()); 539 AddCXXSynthetic(objc_category_sp, 540 lldb_private::formatters::NSArraySyntheticFrontEndCreator, 541 "NSArray synthetic children", ConstString("CFArrayRef"), 542 ScriptedSyntheticChildren::Flags()); 543 544 AddCXXSynthetic( 545 objc_category_sp, 546 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 547 "NSDictionary synthetic children", ConstString("__NSDictionaryM"), 548 ScriptedSyntheticChildren::Flags()); 549 AddCXXSynthetic( 550 objc_category_sp, 551 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 552 "NSDictionary synthetic children", ConstString("__NSDictionaryI"), 553 ScriptedSyntheticChildren::Flags()); 554 AddCXXSynthetic( 555 objc_category_sp, 556 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 557 "NSDictionary synthetic children", 558 ConstString("__NSSingleEntryDictionaryI"), 559 ScriptedSyntheticChildren::Flags()); 560 AddCXXSynthetic( 561 objc_category_sp, 562 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 563 "NSDictionary synthetic children", ConstString("__NSCFDictionary"), 564 ScriptedSyntheticChildren::Flags()); 565 AddCXXSynthetic( 566 objc_category_sp, 567 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 568 "NSDictionary synthetic children", ConstString("NSDictionary"), 569 ScriptedSyntheticChildren::Flags()); 570 AddCXXSynthetic( 571 objc_category_sp, 572 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 573 "NSDictionary synthetic children", ConstString("NSMutableDictionary"), 574 ScriptedSyntheticChildren::Flags()); 575 AddCXXSynthetic( 576 objc_category_sp, 577 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 578 "NSDictionary synthetic children", ConstString("CFDictionaryRef"), 579 ScriptedSyntheticChildren::Flags()); 580 AddCXXSynthetic( 581 objc_category_sp, 582 lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, 583 "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), 584 ScriptedSyntheticChildren::Flags()); 585 586 AddCXXSynthetic(objc_category_sp, 587 lldb_private::formatters::NSErrorSyntheticFrontEndCreator, 588 "NSError synthetic children", ConstString("NSError"), 589 ScriptedSyntheticChildren::Flags()); 590 AddCXXSynthetic(objc_category_sp, 591 lldb_private::formatters::NSExceptionSyntheticFrontEndCreator, 592 "NSException synthetic children", ConstString("NSException"), 593 ScriptedSyntheticChildren::Flags()); 594 595 AddCXXSynthetic(objc_category_sp, 596 lldb_private::formatters::NSSetSyntheticFrontEndCreator, 597 "NSSet synthetic children", ConstString("NSSet"), 598 ScriptedSyntheticChildren::Flags()); 599 AddCXXSynthetic(objc_category_sp, 600 lldb_private::formatters::NSSetSyntheticFrontEndCreator, 601 "__NSSetI synthetic children", ConstString("__NSSetI"), 602 ScriptedSyntheticChildren::Flags()); 603 AddCXXSynthetic(objc_category_sp, 604 lldb_private::formatters::NSSetSyntheticFrontEndCreator, 605 "__NSSetM synthetic children", ConstString("__NSSetM"), 606 ScriptedSyntheticChildren::Flags()); 607 AddCXXSynthetic( 608 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 609 "NSMutableSet synthetic children", ConstString("NSMutableSet"), 610 ScriptedSyntheticChildren::Flags()); 611 AddCXXSynthetic( 612 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 613 "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), 614 ScriptedSyntheticChildren::Flags()); 615 AddCXXSynthetic( 616 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 617 "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), 618 ScriptedSyntheticChildren::Flags()); 619 AddCXXSynthetic( 620 objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, 621 "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), 622 ScriptedSyntheticChildren::Flags()); 623 624 AddCXXSynthetic(objc_category_sp, 625 lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, 626 "NSIndexPath synthetic children", ConstString("NSIndexPath"), 627 ScriptedSyntheticChildren::Flags()); 628 629 AddCXXSummary( 630 objc_category_sp, lldb_private::formatters::CFBagSummaryProvider, 631 "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); 632 AddCXXSummary(objc_category_sp, 633 lldb_private::formatters::CFBagSummaryProvider, 634 "CFBag summary provider", ConstString("__CFBag"), appkit_flags); 635 AddCXXSummary(objc_category_sp, 636 lldb_private::formatters::CFBagSummaryProvider, 637 "CFBag summary provider", ConstString("const struct __CFBag"), 638 appkit_flags); 639 AddCXXSummary( 640 objc_category_sp, lldb_private::formatters::CFBagSummaryProvider, 641 "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags); 642 643 AddCXXSummary(objc_category_sp, 644 lldb_private::formatters::CFBinaryHeapSummaryProvider, 645 "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), 646 appkit_flags); 647 AddCXXSummary(objc_category_sp, 648 lldb_private::formatters::CFBinaryHeapSummaryProvider, 649 "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), 650 appkit_flags); 651 652 AddCXXSummary( 653 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 654 "NSString summary provider", ConstString("NSString"), appkit_flags); 655 AddCXXSummary( 656 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 657 "NSString summary provider", ConstString("CFStringRef"), appkit_flags); 658 AddCXXSummary( 659 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 660 "NSString summary provider", ConstString("__CFString"), appkit_flags); 661 AddCXXSummary(objc_category_sp, 662 lldb_private::formatters::NSStringSummaryProvider, 663 "NSString summary provider", ConstString("CFMutableStringRef"), 664 appkit_flags); 665 AddCXXSummary(objc_category_sp, 666 lldb_private::formatters::NSStringSummaryProvider, 667 "NSString summary provider", ConstString("NSMutableString"), 668 appkit_flags); 669 AddCXXSummary(objc_category_sp, 670 lldb_private::formatters::NSStringSummaryProvider, 671 "NSString summary provider", 672 ConstString("__NSCFConstantString"), appkit_flags); 673 AddCXXSummary( 674 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 675 "NSString summary provider", ConstString("__NSCFString"), appkit_flags); 676 AddCXXSummary(objc_category_sp, 677 lldb_private::formatters::NSStringSummaryProvider, 678 "NSString summary provider", ConstString("NSCFConstantString"), 679 appkit_flags); 680 AddCXXSummary( 681 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 682 "NSString summary provider", ConstString("NSCFString"), appkit_flags); 683 AddCXXSummary( 684 objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, 685 "NSString summary provider", ConstString("NSPathStore2"), appkit_flags); 686 AddCXXSummary(objc_category_sp, 687 lldb_private::formatters::NSStringSummaryProvider, 688 "NSString summary provider", 689 ConstString("NSTaggedPointerString"), appkit_flags); 690 691 AddCXXSummary(objc_category_sp, 692 lldb_private::formatters::NSAttributedStringSummaryProvider, 693 "NSAttributedString summary provider", 694 ConstString("NSAttributedString"), appkit_flags); 695 AddCXXSummary( 696 objc_category_sp, 697 lldb_private::formatters::NSMutableAttributedStringSummaryProvider, 698 "NSMutableAttributedString summary provider", 699 ConstString("NSMutableAttributedString"), appkit_flags); 700 AddCXXSummary( 701 objc_category_sp, 702 lldb_private::formatters::NSMutableAttributedStringSummaryProvider, 703 "NSMutableAttributedString summary provider", 704 ConstString("NSConcreteMutableAttributedString"), appkit_flags); 705 706 AddCXXSummary( 707 objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, 708 "NSBundle summary provider", ConstString("NSBundle"), appkit_flags); 709 710 AddCXXSummary(objc_category_sp, 711 lldb_private::formatters::NSDataSummaryProvider<false>, 712 "NSData summary provider", ConstString("NSData"), appkit_flags); 713 AddCXXSummary( 714 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 715 "NSData summary provider", ConstString("_NSInlineData"), appkit_flags); 716 AddCXXSummary( 717 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 718 "NSData summary provider", ConstString("NSConcreteData"), appkit_flags); 719 AddCXXSummary(objc_category_sp, 720 lldb_private::formatters::NSDataSummaryProvider<false>, 721 "NSData summary provider", ConstString("NSConcreteMutableData"), 722 appkit_flags); 723 AddCXXSummary( 724 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 725 "NSData summary provider", ConstString("NSMutableData"), appkit_flags); 726 AddCXXSummary( 727 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, 728 "NSData summary provider", ConstString("__NSCFData"), appkit_flags); 729 AddCXXSummary( 730 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, 731 "NSData summary provider", ConstString("CFDataRef"), appkit_flags); 732 AddCXXSummary( 733 objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, 734 "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags); 735 736 AddCXXSummary( 737 objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, 738 "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags); 739 740 AddCXXSummary(objc_category_sp, 741 lldb_private::formatters::NSNotificationSummaryProvider, 742 "NSNotification summary provider", 743 ConstString("NSNotification"), appkit_flags); 744 AddCXXSummary(objc_category_sp, 745 lldb_private::formatters::NSNotificationSummaryProvider, 746 "NSNotification summary provider", 747 ConstString("NSConcreteNotification"), appkit_flags); 748 749 AddCXXSummary( 750 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 751 "NSNumber summary provider", ConstString("NSNumber"), appkit_flags); 752 AddCXXSummary( 753 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 754 "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags); 755 AddCXXSummary( 756 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 757 "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags); 758 AddCXXSummary( 759 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 760 "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags); 761 AddCXXSummary( 762 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 763 "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags); 764 AddCXXSummary( 765 objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, 766 "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags); 767 768 AddCXXSummary(objc_category_sp, 769 lldb_private::formatters::NSURLSummaryProvider, 770 "NSURL summary provider", ConstString("NSURL"), appkit_flags); 771 AddCXXSummary( 772 objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, 773 "NSURL summary provider", ConstString("CFURLRef"), appkit_flags); 774 775 AddCXXSummary(objc_category_sp, 776 lldb_private::formatters::NSDateSummaryProvider, 777 "NSDate summary provider", ConstString("NSDate"), appkit_flags); 778 AddCXXSummary( 779 objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, 780 "NSDate summary provider", ConstString("__NSDate"), appkit_flags); 781 AddCXXSummary( 782 objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, 783 "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags); 784 AddCXXSummary( 785 objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, 786 "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags); 787 788 AddCXXSummary( 789 objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, 790 "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags); 791 AddCXXSummary(objc_category_sp, 792 lldb_private::formatters::NSTimeZoneSummaryProvider, 793 "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), 794 appkit_flags); 795 AddCXXSummary( 796 objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, 797 "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags); 798 799 // CFAbsoluteTime is actually a double rather than a pointer to an object 800 // we do not care about the numeric value, since it is probably meaningless to 801 // users 802 appkit_flags.SetDontShowValue(true); 803 AddCXXSummary(objc_category_sp, 804 lldb_private::formatters::CFAbsoluteTimeSummaryProvider, 805 "CFAbsoluteTime summary provider", 806 ConstString("CFAbsoluteTime"), appkit_flags); 807 appkit_flags.SetDontShowValue(false); 808 809 AddCXXSummary( 810 objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, 811 "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags); 812 AddCXXSummary(objc_category_sp, 813 lldb_private::formatters::NSIndexSetSummaryProvider, 814 "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), 815 appkit_flags); 816 817 AddStringSummary(objc_category_sp, 818 "@\"${var.month%d}/${var.day%d}/${var.year%d} " 819 "${var.hour%d}:${var.minute%d}:${var.second}\"", 820 ConstString("CFGregorianDate"), appkit_flags); 821 822 AddCXXSummary(objc_category_sp, 823 lldb_private::formatters::CFBitVectorSummaryProvider, 824 "CFBitVector summary provider", ConstString("CFBitVectorRef"), 825 appkit_flags); 826 AddCXXSummary(objc_category_sp, 827 lldb_private::formatters::CFBitVectorSummaryProvider, 828 "CFBitVector summary provider", 829 ConstString("CFMutableBitVectorRef"), appkit_flags); 830 AddCXXSummary(objc_category_sp, 831 lldb_private::formatters::CFBitVectorSummaryProvider, 832 "CFBitVector summary provider", ConstString("__CFBitVector"), 833 appkit_flags); 834 AddCXXSummary(objc_category_sp, 835 lldb_private::formatters::CFBitVectorSummaryProvider, 836 "CFBitVector summary provider", 837 ConstString("__CFMutableBitVector"), appkit_flags); 838 #endif // LLDB_DISABLE_PYTHON 839 } 840 841 static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) { 842 if (!objc_category_sp) 843 return; 844 845 TypeSummaryImpl::Flags cm_flags; 846 cm_flags.SetCascades(true) 847 .SetDontShowChildren(false) 848 .SetDontShowValue(false) 849 .SetHideItemNames(false) 850 .SetShowMembersOneLiner(false) 851 .SetSkipPointers(false) 852 .SetSkipReferences(false); 853 854 #ifndef LLDB_DISABLE_PYTHON 855 AddCXXSummary(objc_category_sp, 856 lldb_private::formatters::CMTimeSummaryProvider, 857 "CMTime summary provider", ConstString("CMTime"), cm_flags); 858 #endif // LLDB_DISABLE_PYTHON 859 } 860 861 lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() { 862 static llvm::once_flag g_initialize; 863 static TypeCategoryImplSP g_category; 864 865 llvm::call_once(g_initialize, [this]() -> void { 866 DataVisualization::Categories::GetCategory(GetPluginName(), g_category); 867 if (g_category) { 868 LoadCoreMediaFormatters(g_category); 869 LoadObjCFormatters(g_category); 870 } 871 }); 872 return g_category; 873 } 874 875 std::vector<ConstString> 876 ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, 877 lldb::DynamicValueType use_dynamic) { 878 std::vector<ConstString> result; 879 880 if (use_dynamic == lldb::eNoDynamicValues) 881 return result; 882 883 CompilerType compiler_type(valobj.GetCompilerType()); 884 885 const bool check_cpp = false; 886 const bool check_objc = true; 887 bool canBeObjCDynamic = 888 compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc); 889 890 if (canBeObjCDynamic) { 891 do { 892 lldb::ProcessSP process_sp = valobj.GetProcessSP(); 893 if (!process_sp) 894 break; 895 ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); 896 if (runtime == nullptr) 897 break; 898 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp( 899 runtime->GetClassDescriptor(valobj)); 900 if (!objc_class_sp) 901 break; 902 if (ConstString name = objc_class_sp->GetClassName()) 903 result.push_back(name); 904 } while (false); 905 } 906 907 return result; 908 } 909 910 std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() { 911 class ObjCScavengerResult : public Language::TypeScavenger::Result { 912 public: 913 ObjCScavengerResult(CompilerType type) 914 : Language::TypeScavenger::Result(), m_compiler_type(type) {} 915 916 bool IsValid() override { return m_compiler_type.IsValid(); } 917 918 bool DumpToStream(Stream &stream, bool print_help_if_available) override { 919 if (IsValid()) { 920 m_compiler_type.DumpTypeDescription(&stream); 921 stream.EOL(); 922 return true; 923 } 924 return false; 925 } 926 927 private: 928 CompilerType m_compiler_type; 929 }; 930 931 class ObjCRuntimeScavenger : public Language::TypeScavenger { 932 protected: 933 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 934 ResultSet &results) override { 935 bool result = false; 936 937 Process *process = exe_scope->CalculateProcess().get(); 938 if (process) { 939 const bool create_on_demand = false; 940 auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand); 941 if (objc_runtime) { 942 auto decl_vendor = objc_runtime->GetDeclVendor(); 943 if (decl_vendor) { 944 std::vector<clang::NamedDecl *> decls; 945 ConstString name(key); 946 decl_vendor->FindDecls(name, true, UINT32_MAX, decls); 947 for (auto decl : decls) { 948 if (decl) { 949 if (CompilerType candidate = 950 ClangASTContext::GetTypeForDecl(decl)) { 951 result = true; 952 std::unique_ptr<Language::TypeScavenger::Result> result( 953 new ObjCScavengerResult(candidate)); 954 results.insert(std::move(result)); 955 } 956 } 957 } 958 } 959 } 960 } 961 962 return result; 963 } 964 965 friend class lldb_private::ObjCLanguage; 966 }; 967 968 class ObjCModulesScavenger : public Language::TypeScavenger { 969 protected: 970 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 971 ResultSet &results) override { 972 bool result = false; 973 974 Target *target = exe_scope->CalculateTarget().get(); 975 if (target) { 976 if (auto clang_modules_decl_vendor = 977 target->GetClangModulesDeclVendor()) { 978 std::vector<clang::NamedDecl *> decls; 979 ConstString key_cs(key); 980 981 if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX, 982 decls) > 0 && 983 !decls.empty()) { 984 CompilerType module_type = 985 ClangASTContext::GetTypeForDecl(decls.front()); 986 result = true; 987 std::unique_ptr<Language::TypeScavenger::Result> result( 988 new ObjCScavengerResult(module_type)); 989 results.insert(std::move(result)); 990 } 991 } 992 } 993 994 return result; 995 } 996 997 friend class lldb_private::ObjCLanguage; 998 }; 999 1000 class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger { 1001 public: 1002 virtual CompilerType AdjustForInclusion(CompilerType &candidate) override { 1003 LanguageType lang_type(candidate.GetMinimumLanguage()); 1004 if (!Language::LanguageIsObjC(lang_type)) 1005 return CompilerType(); 1006 if (candidate.IsTypedefType()) 1007 return candidate.GetTypedefedType(); 1008 return candidate; 1009 } 1010 }; 1011 1012 return std::unique_ptr<TypeScavenger>( 1013 new Language::EitherTypeScavenger<ObjCModulesScavenger, 1014 ObjCRuntimeScavenger, 1015 ObjCDebugInfoScavenger>()); 1016 } 1017 1018 bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj, 1019 ConstString type_hint, 1020 std::string &prefix, 1021 std::string &suffix) { 1022 static ConstString g_CFBag("CFBag"); 1023 static ConstString g_CFBinaryHeap("CFBinaryHeap"); 1024 1025 static ConstString g_NSNumberChar("NSNumber:char"); 1026 static ConstString g_NSNumberShort("NSNumber:short"); 1027 static ConstString g_NSNumberInt("NSNumber:int"); 1028 static ConstString g_NSNumberLong("NSNumber:long"); 1029 static ConstString g_NSNumberFloat("NSNumber:float"); 1030 static ConstString g_NSNumberDouble("NSNumber:double"); 1031 1032 static ConstString g_NSData("NSData"); 1033 static ConstString g_NSArray("NSArray"); 1034 static ConstString g_NSString("NSString"); 1035 static ConstString g_NSStringStar("NSString*"); 1036 1037 if (type_hint.IsEmpty()) 1038 return false; 1039 1040 prefix.clear(); 1041 suffix.clear(); 1042 1043 if (type_hint == g_CFBag || type_hint == g_CFBinaryHeap) { 1044 prefix = "@"; 1045 return true; 1046 } 1047 1048 if (type_hint == g_NSNumberChar) { 1049 prefix = "(char)"; 1050 return true; 1051 } 1052 if (type_hint == g_NSNumberShort) { 1053 prefix = "(short)"; 1054 return true; 1055 } 1056 if (type_hint == g_NSNumberInt) { 1057 prefix = "(int)"; 1058 return true; 1059 } 1060 if (type_hint == g_NSNumberLong) { 1061 prefix = "(long)"; 1062 return true; 1063 } 1064 if (type_hint == g_NSNumberFloat) { 1065 prefix = "(float)"; 1066 return true; 1067 } 1068 if (type_hint == g_NSNumberDouble) { 1069 prefix = "(double)"; 1070 return true; 1071 } 1072 1073 if (type_hint == g_NSData || type_hint == g_NSArray) { 1074 prefix = "@\""; 1075 suffix = "\""; 1076 return true; 1077 } 1078 1079 if (type_hint == g_NSString || type_hint == g_NSStringStar) { 1080 prefix = "@"; 1081 return true; 1082 } 1083 1084 return false; 1085 } 1086 1087 bool ObjCLanguage::IsNilReference(ValueObject &valobj) { 1088 const uint32_t mask = eTypeIsObjC | eTypeIsPointer; 1089 bool isObjCpointer = 1090 (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask); 1091 if (!isObjCpointer) 1092 return false; 1093 bool canReadValue = true; 1094 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0; 1095 return canReadValue && isZero; 1096 } 1097