1 //===-- LibCxx.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 "LibCxx.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Debugger.h" 17 #include "lldb/Core/FormatEntity.h" 18 #include "lldb/Core/ValueObject.h" 19 #include "lldb/Core/ValueObjectConstResult.h" 20 #include "lldb/DataFormatters/FormattersHelpers.h" 21 #include "lldb/DataFormatters/StringPrinter.h" 22 #include "lldb/DataFormatters/TypeSummary.h" 23 #include "lldb/DataFormatters/VectorIterator.h" 24 #include "lldb/Symbol/ClangASTContext.h" 25 #include "lldb/Target/ProcessStructReader.h" 26 #include "lldb/Target/Target.h" 27 #include "lldb/Utility/DataBufferHeap.h" 28 #include "lldb/Utility/Endian.h" 29 #include "lldb/Utility/Status.h" 30 #include "lldb/Utility/Stream.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 using namespace lldb_private::formatters; 35 36 bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider( 37 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 38 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); 39 if (!valobj_sp) 40 return false; 41 ValueObjectSP ptr_sp( 42 valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)); 43 ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( 44 {ConstString("__cntrl_"), ConstString("__shared_owners_")})); 45 ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( 46 {ConstString("__cntrl_"), ConstString("__shared_weak_owners_")})); 47 48 if (!ptr_sp) 49 return false; 50 51 if (ptr_sp->GetValueAsUnsigned(0) == 0) { 52 stream.Printf("nullptr"); 53 return true; 54 } else { 55 bool print_pointee = false; 56 Status error; 57 ValueObjectSP pointee_sp = ptr_sp->Dereference(error); 58 if (pointee_sp && error.Success()) { 59 if (pointee_sp->DumpPrintableRepresentation( 60 stream, ValueObject::eValueObjectRepresentationStyleSummary, 61 lldb::eFormatInvalid, 62 ValueObject::PrintableRepresentationSpecialCases::eDisable, 63 false)) 64 print_pointee = true; 65 } 66 if (!print_pointee) 67 stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); 68 } 69 70 if (count_sp) 71 stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0)); 72 73 if (weakcount_sp) 74 stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0)); 75 76 return true; 77 } 78 79 /* 80 (lldb) fr var ibeg --raw --ptr-depth 1 81 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, 82 std::__1::basic_string<char, std::__1::char_traits<char>, 83 std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, 84 std::__1::basic_string<char, std::__1::char_traits<char>, 85 std::__1::allocator<char> > >, void *> *, long> >) ibeg = { 86 __i_ = { 87 __ptr_ = 0x0000000100103870 { 88 std::__1::__tree_node_base<void *> = { 89 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = { 90 __left_ = 0x0000000000000000 91 } 92 __right_ = 0x0000000000000000 93 __parent_ = 0x00000001001038b0 94 __is_black_ = true 95 } 96 __value_ = { 97 first = 0 98 second = { std::string } 99 */ 100 101 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd:: 102 LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 103 : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() { 104 if (valobj_sp) 105 Update(); 106 } 107 108 bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() { 109 m_pair_sp.reset(); 110 m_pair_ptr = nullptr; 111 112 ValueObjectSP valobj_sp = m_backend.GetSP(); 113 if (!valobj_sp) 114 return false; 115 116 TargetSP target_sp(valobj_sp->GetTargetSP()); 117 118 if (!target_sp) 119 return false; 120 121 if (!valobj_sp) 122 return false; 123 124 static ConstString g___i_("__i_"); 125 126 // this must be a ValueObject* because it is a child of the ValueObject we are 127 // producing children for 128 // it if were a ValueObjectSP, we would end up with a loop (iterator -> 129 // synthetic -> child -> parent == iterator) 130 // and that would in turn leak memory by never allowing the ValueObjects to 131 // die and free their memory 132 m_pair_ptr = valobj_sp 133 ->GetValueForExpressionPath( 134 ".__i_.__ptr_->__value_", nullptr, nullptr, 135 ValueObject::GetValueForExpressionPathOptions() 136 .DontCheckDotVsArrowSyntax() 137 .SetSyntheticChildrenTraversal( 138 ValueObject::GetValueForExpressionPathOptions:: 139 SyntheticChildrenTraversal::None), 140 nullptr) 141 .get(); 142 143 if (!m_pair_ptr) { 144 m_pair_ptr = valobj_sp 145 ->GetValueForExpressionPath( 146 ".__i_.__ptr_", nullptr, nullptr, 147 ValueObject::GetValueForExpressionPathOptions() 148 .DontCheckDotVsArrowSyntax() 149 .SetSyntheticChildrenTraversal( 150 ValueObject::GetValueForExpressionPathOptions:: 151 SyntheticChildrenTraversal::None), 152 nullptr) 153 .get(); 154 if (m_pair_ptr) { 155 auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true)); 156 lldb::TemplateArgumentKind kind; 157 if (!__i_) { 158 m_pair_ptr = nullptr; 159 return false; 160 } 161 CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind)); 162 std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr; 163 pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr); 164 if (!pair_type) { 165 m_pair_ptr = nullptr; 166 return false; 167 } 168 169 auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS)); 170 m_pair_ptr = nullptr; 171 if (addr && addr!=LLDB_INVALID_ADDRESS) { 172 ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem()); 173 if (!ast_ctx) 174 return false; 175 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), { 176 {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()}, 177 {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()}, 178 {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()}, 179 {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)}, 180 {"payload",pair_type} 181 }); 182 DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0)); 183 ProcessSP process_sp(target_sp->GetProcessSP()); 184 Status error; 185 process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error); 186 if (error.Fail()) 187 return false; 188 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); 189 auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type); 190 if (pair_sp) 191 m_pair_sp = pair_sp->GetChildAtIndex(4,true); 192 } 193 } 194 } 195 196 return false; 197 } 198 199 size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd:: 200 CalculateNumChildren() { 201 return 2; 202 } 203 204 lldb::ValueObjectSP 205 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex( 206 size_t idx) { 207 if (m_pair_ptr) 208 return m_pair_ptr->GetChildAtIndex(idx, true); 209 if (m_pair_sp) 210 return m_pair_sp->GetChildAtIndex(idx, true); 211 return lldb::ValueObjectSP(); 212 } 213 214 bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd:: 215 MightHaveChildren() { 216 return true; 217 } 218 219 size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd:: 220 GetIndexOfChildWithName(const ConstString &name) { 221 if (name == ConstString("first")) 222 return 0; 223 if (name == ConstString("second")) 224 return 1; 225 return UINT32_MAX; 226 } 227 228 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd:: 229 ~LibCxxMapIteratorSyntheticFrontEnd() { 230 // this will be deleted when its parent dies (since it's a child object) 231 // delete m_pair_ptr; 232 } 233 234 SyntheticChildrenFrontEnd * 235 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator( 236 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 237 return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp) 238 : nullptr); 239 } 240 241 /* 242 (lldb) fr var ibeg --raw --ptr-depth 1 -T 243 (std::__1::__wrap_iter<int *>) ibeg = { 244 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 { 245 (int) *__i = 1 246 } 247 } 248 */ 249 250 SyntheticChildrenFrontEnd * 251 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator( 252 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 253 static ConstString g_item_name; 254 if (!g_item_name) 255 g_item_name.SetCString("__i"); 256 return (valobj_sp 257 ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name) 258 : nullptr); 259 } 260 261 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: 262 LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 263 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(), 264 m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) { 265 if (valobj_sp) 266 Update(); 267 } 268 269 size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: 270 CalculateNumChildren() { 271 return (m_cntrl ? 1 : 0); 272 } 273 274 lldb::ValueObjectSP 275 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex( 276 size_t idx) { 277 if (!m_cntrl) 278 return lldb::ValueObjectSP(); 279 280 ValueObjectSP valobj_sp = m_backend.GetSP(); 281 if (!valobj_sp) 282 return lldb::ValueObjectSP(); 283 284 if (idx == 0) 285 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true); 286 287 if (idx > 2) 288 return lldb::ValueObjectSP(); 289 290 if (idx == 1) { 291 if (!m_count_sp) { 292 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName( 293 ConstString("__shared_owners_"), true)); 294 if (!shared_owners_sp) 295 return lldb::ValueObjectSP(); 296 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0); 297 DataExtractor data(&count, 8, m_byte_order, m_ptr_size); 298 m_count_sp = CreateValueObjectFromData( 299 "count", data, valobj_sp->GetExecutionContextRef(), 300 shared_owners_sp->GetCompilerType()); 301 } 302 return m_count_sp; 303 } else /* if (idx == 2) */ 304 { 305 if (!m_weak_count_sp) { 306 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName( 307 ConstString("__shared_weak_owners_"), true)); 308 if (!shared_weak_owners_sp) 309 return lldb::ValueObjectSP(); 310 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0); 311 DataExtractor data(&count, 8, m_byte_order, m_ptr_size); 312 m_weak_count_sp = CreateValueObjectFromData( 313 "count", data, valobj_sp->GetExecutionContextRef(), 314 shared_weak_owners_sp->GetCompilerType()); 315 } 316 return m_weak_count_sp; 317 } 318 } 319 320 bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() { 321 m_count_sp.reset(); 322 m_weak_count_sp.reset(); 323 m_cntrl = nullptr; 324 325 ValueObjectSP valobj_sp = m_backend.GetSP(); 326 if (!valobj_sp) 327 return false; 328 329 TargetSP target_sp(valobj_sp->GetTargetSP()); 330 if (!target_sp) 331 return false; 332 333 m_byte_order = target_sp->GetArchitecture().GetByteOrder(); 334 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize(); 335 336 lldb::ValueObjectSP cntrl_sp( 337 valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true)); 338 339 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular 340 // dependency 341 return false; 342 } 343 344 bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: 345 MightHaveChildren() { 346 return true; 347 } 348 349 size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: 350 GetIndexOfChildWithName(const ConstString &name) { 351 if (name == ConstString("__ptr_")) 352 return 0; 353 if (name == ConstString("count")) 354 return 1; 355 if (name == ConstString("weak_count")) 356 return 2; 357 return UINT32_MAX; 358 } 359 360 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: 361 ~LibcxxSharedPtrSyntheticFrontEnd() = default; 362 363 SyntheticChildrenFrontEnd * 364 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator( 365 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 366 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp) 367 : nullptr); 368 } 369 370 bool lldb_private::formatters::LibcxxContainerSummaryProvider( 371 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 372 if (valobj.IsPointerType()) { 373 uint64_t value = valobj.GetValueAsUnsigned(0); 374 if (!value) 375 return false; 376 stream.Printf("0x%016" PRIx64 " ", value); 377 } 378 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr, 379 nullptr, nullptr, &valobj, false, false); 380 } 381 382 // the field layout in a libc++ string (cap, side, data or data, size, cap) 383 enum LibcxxStringLayoutMode { 384 eLibcxxStringLayoutModeCSD = 0, 385 eLibcxxStringLayoutModeDSC = 1, 386 eLibcxxStringLayoutModeInvalid = 0xffff 387 }; 388 389 // this function abstracts away the layout and mode details of a libc++ string 390 // and returns the address of the data and the size ready for callers to consume 391 static bool ExtractLibcxxStringInfo(ValueObject &valobj, 392 ValueObjectSP &location_sp, 393 uint64_t &size) { 394 ValueObjectSP D(valobj.GetChildAtIndexPath({0, 0, 0, 0})); 395 if (!D) 396 return false; 397 398 ValueObjectSP layout_decider( 399 D->GetChildAtIndexPath(llvm::ArrayRef<size_t>({0, 0}))); 400 401 // this child should exist 402 if (!layout_decider) 403 return false; 404 405 ConstString g_data_name("__data_"); 406 ConstString g_size_name("__size_"); 407 bool short_mode = false; // this means the string is in short-mode and the 408 // data is stored inline 409 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) 410 ? eLibcxxStringLayoutModeDSC 411 : eLibcxxStringLayoutModeCSD; 412 uint64_t size_mode_value = 0; 413 414 if (layout == eLibcxxStringLayoutModeDSC) { 415 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 1, 0})); 416 if (!size_mode) 417 return false; 418 419 if (size_mode->GetName() != g_size_name) { 420 // we are hitting the padding structure, move along 421 size_mode = D->GetChildAtIndexPath({1, 1, 1}); 422 if (!size_mode) 423 return false; 424 } 425 426 size_mode_value = (size_mode->GetValueAsUnsigned(0)); 427 short_mode = ((size_mode_value & 0x80) == 0); 428 } else { 429 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 0, 0})); 430 if (!size_mode) 431 return false; 432 433 size_mode_value = (size_mode->GetValueAsUnsigned(0)); 434 short_mode = ((size_mode_value & 1) == 0); 435 } 436 437 if (short_mode) { 438 ValueObjectSP s(D->GetChildAtIndex(1, true)); 439 if (!s) 440 return false; 441 location_sp = s->GetChildAtIndex( 442 (layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); 443 size = (layout == eLibcxxStringLayoutModeDSC) 444 ? size_mode_value 445 : ((size_mode_value >> 1) % 256); 446 return (location_sp.get() != nullptr); 447 } else { 448 ValueObjectSP l(D->GetChildAtIndex(0, true)); 449 if (!l) 450 return false; 451 // we can use the layout_decider object as the data pointer 452 location_sp = (layout == eLibcxxStringLayoutModeDSC) 453 ? layout_decider 454 : l->GetChildAtIndex(2, true); 455 ValueObjectSP size_vo(l->GetChildAtIndex(1, true)); 456 if (!size_vo || !location_sp) 457 return false; 458 size = size_vo->GetValueAsUnsigned(0); 459 return true; 460 } 461 } 462 463 bool lldb_private::formatters::LibcxxWStringSummaryProvider( 464 ValueObject &valobj, Stream &stream, 465 const TypeSummaryOptions &summary_options) { 466 uint64_t size = 0; 467 ValueObjectSP location_sp; 468 if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) 469 return false; 470 if (size == 0) { 471 stream.Printf("L\"\""); 472 return true; 473 } 474 if (!location_sp) 475 return false; 476 477 DataExtractor extractor; 478 479 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 480 481 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) { 482 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary(); 483 if (size > max_size) { 484 size = max_size; 485 options.SetIsTruncated(true); 486 } 487 } 488 location_sp->GetPointeeData(extractor, 0, size); 489 490 // std::wstring::size() is measured in 'characters', not bytes 491 auto wchar_t_size = valobj.GetTargetSP() 492 ->GetScratchClangASTContext() 493 ->GetBasicType(lldb::eBasicTypeWChar) 494 .GetByteSize(nullptr); 495 496 options.SetData(extractor); 497 options.SetStream(&stream); 498 options.SetPrefixToken("L"); 499 options.SetQuote('"'); 500 options.SetSourceSize(size); 501 options.SetBinaryZeroIsTerminator(false); 502 503 switch (wchar_t_size) { 504 case 1: 505 StringPrinter::ReadBufferAndDumpToStream< 506 lldb_private::formatters::StringPrinter::StringElementType::UTF8>( 507 options); 508 break; 509 510 case 2: 511 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream< 512 lldb_private::formatters::StringPrinter::StringElementType::UTF16>( 513 options); 514 break; 515 516 case 4: 517 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream< 518 lldb_private::formatters::StringPrinter::StringElementType::UTF32>( 519 options); 520 break; 521 522 default: 523 stream.Printf("size for wchar_t is not valid"); 524 return true; 525 } 526 527 return true; 528 } 529 530 bool lldb_private::formatters::LibcxxStringSummaryProvider( 531 ValueObject &valobj, Stream &stream, 532 const TypeSummaryOptions &summary_options) { 533 uint64_t size = 0; 534 ValueObjectSP location_sp; 535 536 if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) 537 return false; 538 539 if (size == 0) { 540 stream.Printf("\"\""); 541 return true; 542 } 543 544 if (!location_sp) 545 return false; 546 547 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 548 549 DataExtractor extractor; 550 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) { 551 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary(); 552 if (size > max_size) { 553 size = max_size; 554 options.SetIsTruncated(true); 555 } 556 } 557 location_sp->GetPointeeData(extractor, 0, size); 558 559 options.SetData(extractor); 560 options.SetStream(&stream); 561 options.SetPrefixToken(nullptr); 562 options.SetQuote('"'); 563 options.SetSourceSize(size); 564 options.SetBinaryZeroIsTerminator(false); 565 StringPrinter::ReadBufferAndDumpToStream< 566 StringPrinter::StringElementType::ASCII>(options); 567 568 return true; 569 } 570 571 class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd { 572 public: 573 LibcxxFunctionFrontEnd(ValueObject &backend) 574 : SyntheticValueProviderFrontEnd(backend) {} 575 576 lldb::ValueObjectSP GetSyntheticValue() override { 577 static ConstString g___f_("__f_"); 578 return m_backend.GetChildMemberWithName(g___f_, true); 579 } 580 }; 581 582 SyntheticChildrenFrontEnd * 583 lldb_private::formatters::LibcxxFunctionFrontEndCreator( 584 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 585 if (valobj_sp) 586 return new LibcxxFunctionFrontEnd(*valobj_sp); 587 return nullptr; 588 } 589