LibCxx.cpp revision 269024
1119610Sache//===-- LibCxx.cpp ----------------------------------------------*- C++ -*-===// 2119610Sache// 3119610Sache// The LLVM Compiler Infrastructure 4119610Sache// 5119610Sache// This file is distributed under the University of Illinois Open Source 6119610Sache// License. See LICENSE.TXT for details. 7119610Sache// 8119610Sache//===----------------------------------------------------------------------===// 9119610Sache 10119610Sache#include "lldb/lldb-python.h" 11119610Sache 12119610Sache#include "lldb/DataFormatters/CXXFormatterFunctions.h" 13119610Sache 14119610Sache#include "lldb/Core/DataBufferHeap.h" 15119610Sache#include "lldb/Core/Debugger.h" 16119610Sache#include "lldb/Core/Error.h" 17119610Sache#include "lldb/Core/Stream.h" 18119610Sache#include "lldb/Core/ValueObject.h" 19119610Sache#include "lldb/Core/ValueObjectConstResult.h" 20119610Sache#include "lldb/Host/Endian.h" 2175406Sache#include "lldb/Symbol/ClangASTContext.h" 2275406Sache#include "lldb/Target/ObjCLanguageRuntime.h" 2375406Sache#include "lldb/Target/Target.h" 2475406Sache 2575406Sacheusing namespace lldb; 2675406Sacheusing namespace lldb_private; 2775406Sacheusing namespace lldb_private::formatters; 2875406Sache 29157184Sachebool 30157184Sachelldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream) 3175406Sache{ 3275406Sache ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); 3375406Sache if (!valobj_sp) 3421308Sache return false; 3521308Sache ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)); 36136644Sache ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_owners_")} )); 3721308Sache ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_weak_owners_")} )); 3821308Sache 39136644Sache if (!ptr_sp) 4021308Sache return false; 4121308Sache 4221308Sache if (ptr_sp->GetValueAsUnsigned(0) == 0) 4321308Sache { 4421308Sache stream.Printf("nullptr"); 4521308Sache return true; 4621308Sache } 4721308Sache else 48136644Sache { 49136644Sache bool print_pointee = false; 50136644Sache Error error; 51136644Sache ValueObjectSP pointee_sp = ptr_sp->Dereference(error); 52136644Sache if (pointee_sp && error.Success()) 5321308Sache { 5421308Sache if (pointee_sp->DumpPrintableRepresentation(stream, 55136644Sache ValueObject::eValueObjectRepresentationStyleSummary, 5621308Sache lldb::eFormatInvalid, 5721308Sache ValueObject::ePrintableRepresentationSpecialCasesDisable, 58136644Sache false)) 59136644Sache print_pointee = true; 60136644Sache } 6121308Sache if (!print_pointee) 62136644Sache stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); 6321308Sache } 64136644Sache 65136644Sache if (count_sp) 66136644Sache stream.Printf(" strong=%" PRIu64, 1+count_sp->GetValueAsUnsigned(0)); 6721308Sache 68136644Sache if (weakcount_sp) 69136644Sache stream.Printf(" weak=%" PRIu64, 1+weakcount_sp->GetValueAsUnsigned(0)); 70136644Sache 71136644Sache return true; 72136644Sache} 7321308Sache 74136644Sachelldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 75136644SacheSyntheticChildrenFrontEnd(*valobj_sp.get()), 76136644Sachem_bool_type(), 77136644Sachem_exe_ctx_ref(), 7821308Sachem_count(0), 7921308Sachem_base_data_address(0), 80136644Sachem_children() 8121308Sache{ 82136644Sache if (valobj_sp) 8321308Sache { 84136644Sache Update(); 8521308Sache m_bool_type = valobj_sp->GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeBool); 86136644Sache } 87136644Sache} 88136644Sache 89136644Sachesize_t 90136644Sachelldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren () 9121308Sache{ 92136644Sache return m_count; 93136644Sache} 94136644Sache 95136644Sachelldb::ValueObjectSP 96136644Sachelldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) 97136644Sache{ 98136644Sache auto iter = m_children.find(idx), 99136644Sache end = m_children.end(); 100136644Sache if (iter != end) 101136644Sache return iter->second; 102136644Sache if (idx >= m_count) 103136644Sache return ValueObjectSP(); 10421308Sache if (m_base_data_address == 0 || m_count == 0) 105136644Sache return ValueObjectSP(); 106136644Sache if (!m_bool_type) 107136644Sache return ValueObjectSP(); 108136644Sache size_t byte_idx = (idx >> 3); // divide by 8 to get byte index 109136644Sache size_t bit_index = (idx & 7); // efficient idx % 8 for bit index 110136644Sache lldb::addr_t byte_location = m_base_data_address + byte_idx; 111136644Sache ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); 112136644Sache if (!process_sp) 113136644Sache return ValueObjectSP(); 114136644Sache uint8_t byte = 0; 115136644Sache uint8_t mask = 0; 116136644Sache Error err; 117136644Sache size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); 118136644Sache if (err.Fail() || bytes_read == 0) 119136644Sache return ValueObjectSP(); 120136644Sache switch (bit_index) 121136644Sache { 122136644Sache case 0: 12321308Sache mask = 1; break; 12421308Sache case 1: 125 mask = 2; break; 126 case 2: 127 mask = 4; break; 128 case 3: 129 mask = 8; break; 130 case 4: 131 mask = 16; break; 132 case 5: 133 mask = 32; break; 134 case 6: 135 mask = 64; break; 136 case 7: 137 mask = 128; break; 138 default: 139 return ValueObjectSP(); 140 } 141 bool bit_set = ((byte & mask) != 0); 142 ValueObjectSP retval_sp; 143 DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(),0)); 144 if (bit_set && buffer_sp && buffer_sp->GetBytes()) 145 *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true 146 StreamString name; name.Printf("[%zu]",idx); 147 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); 148 retval_sp = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_exe_ctx_ref, m_bool_type); 149 if (retval_sp) 150 m_children[idx] = retval_sp; 151 return retval_sp; 152} 153 154/*(std::__1::vector<std::__1::allocator<bool> >) vBool = { 155 __begin_ = 0x00000001001000e0 156 __size_ = 56 157 __cap_alloc_ = { 158 std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = { 159 __first_ = 1 160 } 161 } 162 }*/ 163 164bool 165lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() 166{ 167 m_children.clear(); 168 ValueObjectSP valobj_sp = m_backend.GetSP(); 169 if (!valobj_sp) 170 return false; 171 if (!valobj_sp) 172 return false; 173 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 174 ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true)); 175 if (!size_sp) 176 return false; 177 m_count = size_sp->GetValueAsUnsigned(0); 178 if (!m_count) 179 return true; 180 ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true)); 181 if (!begin_sp) 182 { 183 m_count = 0; 184 return false; 185 } 186 m_base_data_address = begin_sp->GetValueAsUnsigned(0); 187 if (!m_base_data_address) 188 { 189 m_count = 0; 190 return false; 191 } 192 return false; 193} 194 195bool 196lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren () 197{ 198 return true; 199} 200 201size_t 202lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 203{ 204 if (!m_count || !m_base_data_address) 205 return UINT32_MAX; 206 const char* item_name = name.GetCString(); 207 uint32_t idx = ExtractIndexFromString(item_name); 208 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 209 return UINT32_MAX; 210 return idx; 211} 212 213lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () 214{} 215 216SyntheticChildrenFrontEnd* 217lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 218{ 219 if (!valobj_sp) 220 return NULL; 221 return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); 222} 223 224/* 225 (lldb) fr var ibeg --raw --ptr-depth 1 226 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = { 227 __i_ = { 228 __ptr_ = 0x0000000100103870 { 229 std::__1::__tree_node_base<void *> = { 230 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = { 231 __left_ = 0x0000000000000000 232 } 233 __right_ = 0x0000000000000000 234 __parent_ = 0x00000001001038b0 235 __is_black_ = true 236 } 237 __value_ = { 238 first = 0 239 second = { std::string } 240 */ 241 242lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 243SyntheticChildrenFrontEnd(*valobj_sp.get()), 244m_pair_ptr() 245{ 246 if (valobj_sp) 247 Update(); 248} 249 250bool 251lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() 252{ 253 ValueObjectSP valobj_sp = m_backend.GetSP(); 254 if (!valobj_sp) 255 return false; 256 257 TargetSP target_sp(valobj_sp->GetTargetSP()); 258 259 if (!target_sp) 260 return false; 261 262 if (!valobj_sp) 263 return false; 264 265 // this must be a ValueObject* because it is a child of the ValueObject we are producing children for 266 // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator) 267 // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory 268 m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_", 269 NULL, 270 NULL, 271 NULL, 272 ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().DontAllowSyntheticChildren(), 273 NULL).get(); 274 275 return false; 276} 277 278size_t 279lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren () 280{ 281 return 2; 282} 283 284lldb::ValueObjectSP 285lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 286{ 287 if (!m_pair_ptr) 288 return lldb::ValueObjectSP(); 289 return m_pair_ptr->GetChildAtIndex(idx, true); 290} 291 292bool 293lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren () 294{ 295 return true; 296} 297 298size_t 299lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 300{ 301 if (name == ConstString("first")) 302 return 0; 303 if (name == ConstString("second")) 304 return 1; 305 return UINT32_MAX; 306} 307 308lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd () 309{ 310 // this will be deleted when its parent dies (since it's a child object) 311 //delete m_pair_ptr; 312} 313 314SyntheticChildrenFrontEnd* 315lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 316{ 317 if (!valobj_sp) 318 return NULL; 319 return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)); 320} 321 322/* 323 (lldb) fr var ibeg --raw --ptr-depth 1 -T 324 (std::__1::__wrap_iter<int *>) ibeg = { 325 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 { 326 (int) *__i = 1 327 } 328 } 329*/ 330 331SyntheticChildrenFrontEnd* 332lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 333{ 334 static ConstString g_item_name; 335 if (!g_item_name) 336 g_item_name.SetCString("__i"); 337 if (!valobj_sp) 338 return NULL; 339 return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); 340} 341 342lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 343SyntheticChildrenFrontEnd(*valobj_sp.get()), 344m_cntrl(NULL), 345m_count_sp(), 346m_weak_count_sp(), 347m_ptr_size(0), 348m_byte_order(lldb::eByteOrderInvalid) 349{ 350 if (valobj_sp) 351 Update(); 352} 353 354size_t 355lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren () 356{ 357 return (m_cntrl ? 1 : 0); 358} 359 360lldb::ValueObjectSP 361lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx) 362{ 363 if (!m_cntrl) 364 return lldb::ValueObjectSP(); 365 366 ValueObjectSP valobj_sp = m_backend.GetSP(); 367 if (!valobj_sp) 368 return lldb::ValueObjectSP(); 369 370 if (idx == 0) 371 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true); 372 373 if (idx > 2) 374 return lldb::ValueObjectSP(); 375 376 if (idx == 1) 377 { 378 if (!m_count_sp) 379 { 380 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true)); 381 if (!shared_owners_sp) 382 return lldb::ValueObjectSP(); 383 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0); 384 DataExtractor data(&count, 8, m_byte_order, m_ptr_size); 385 m_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType()); 386 } 387 return m_count_sp; 388 } 389 else /* if (idx == 2) */ 390 { 391 if (!m_weak_count_sp) 392 { 393 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true)); 394 if (!shared_weak_owners_sp) 395 return lldb::ValueObjectSP(); 396 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0); 397 DataExtractor data(&count, 8, m_byte_order, m_ptr_size); 398 m_weak_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType()); 399 } 400 return m_weak_count_sp; 401 } 402} 403 404bool 405lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() 406{ 407 m_count_sp.reset(); 408 m_weak_count_sp.reset(); 409 m_cntrl = NULL; 410 411 ValueObjectSP valobj_sp = m_backend.GetSP(); 412 if (!valobj_sp) 413 return false; 414 415 TargetSP target_sp(valobj_sp->GetTargetSP()); 416 if (!target_sp) 417 return false; 418 419 m_byte_order = target_sp->GetArchitecture().GetByteOrder(); 420 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize(); 421 422 lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true)); 423 424 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency 425 return false; 426} 427 428bool 429lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren () 430{ 431 return true; 432} 433 434size_t 435lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 436{ 437 if (name == ConstString("__ptr_")) 438 return 0; 439 if (name == ConstString("count")) 440 return 1; 441 if (name == ConstString("weak_count")) 442 return 2; 443 return UINT32_MAX; 444} 445 446lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd () 447{} 448 449SyntheticChildrenFrontEnd* 450lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 451{ 452 if (!valobj_sp) 453 return NULL; 454 return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)); 455} 456 457lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 458 SyntheticChildrenFrontEnd(*valobj_sp.get()), 459 m_start(NULL), 460 m_finish(NULL), 461 m_element_type(), 462 m_element_size(0), 463 m_children() 464{ 465 if (valobj_sp) 466 Update(); 467} 468 469size_t 470lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () 471{ 472 if (!m_start || !m_finish) 473 return 0; 474 uint64_t start_val = m_start->GetValueAsUnsigned(0); 475 uint64_t finish_val = m_finish->GetValueAsUnsigned(0); 476 477 if (start_val == 0 || finish_val == 0) 478 return 0; 479 480 if (start_val >= finish_val) 481 return 0; 482 483 size_t num_children = (finish_val - start_val); 484 if (num_children % m_element_size) 485 return 0; 486 return num_children/m_element_size; 487} 488 489lldb::ValueObjectSP 490lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 491{ 492 if (!m_start || !m_finish) 493 return lldb::ValueObjectSP(); 494 495 auto cached = m_children.find(idx); 496 if (cached != m_children.end()) 497 return cached->second; 498 499 uint64_t offset = idx * m_element_size; 500 offset = offset + m_start->GetValueAsUnsigned(0); 501 StreamString name; 502 name.Printf("[%zu]",idx); 503 ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); 504 m_children[idx] = child_sp; 505 return child_sp; 506} 507 508bool 509lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() 510{ 511 m_start = m_finish = NULL; 512 m_children.clear(); 513 ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); 514 if (!data_type_finder_sp) 515 return false; 516 data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); 517 if (!data_type_finder_sp) 518 return false; 519 m_element_type = data_type_finder_sp->GetClangType().GetPointeeType(); 520 m_element_size = m_element_type.GetByteSize(); 521 522 if (m_element_size > 0) 523 { 524 // store raw pointers or end up with a circular dependency 525 m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get(); 526 m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get(); 527 } 528 return false; 529} 530 531bool 532lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () 533{ 534 return true; 535} 536 537size_t 538lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 539{ 540 if (!m_start || !m_finish) 541 return UINT32_MAX; 542 return ExtractIndexFromString(name.GetCString()); 543} 544 545lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd () 546{ 547 // these need to stay around because they are child objects who will follow their parent's life cycle 548 // delete m_start; 549 // delete m_finish; 550} 551 552SyntheticChildrenFrontEnd* 553lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 554{ 555 if (!valobj_sp) 556 return NULL; 557 return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); 558} 559 560bool 561lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream) 562{ 563 if (valobj.IsPointerType()) 564 { 565 uint64_t value = valobj.GetValueAsUnsigned(0); 566 if (!value) 567 return false; 568 stream.Printf("0x%016" PRIx64 " ", value); 569 } 570 return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj); 571} 572