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 "lldb/lldb-python.h" 11 12 #include "lldb/DataFormatters/CXXFormatterFunctions.h" 13 14 #include "lldb/Core/DataBufferHeap.h" 15 #include "lldb/Core/Debugger.h" 16 #include "lldb/Core/Error.h" 17 #include "lldb/Core/Stream.h" 18 #include "lldb/Core/ValueObject.h" 19 #include "lldb/Core/ValueObjectConstResult.h" 20 #include "lldb/Host/Endian.h" 21 #include "lldb/Symbol/ClangASTContext.h" 22 #include "lldb/Target/ObjCLanguageRuntime.h" 23 #include "lldb/Target/Target.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 using namespace lldb_private::formatters; 28 29 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 30 SyntheticChildrenFrontEnd(*valobj_sp.get()), 31 m_exe_ctx_ref(), 32 m_count(0), 33 m_base_data_address(0), 34 m_options() 35 { 36 if (valobj_sp) 37 Update(); 38 m_options.SetCoerceToId(false) 39 .SetUnwindOnError(true) 40 .SetKeepInMemory(true) 41 .SetUseDynamic(lldb::eDynamicCanRunTarget); 42 } 43 44 size_t 45 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren () 46 { 47 return m_count; 48 } 49 50 lldb::ValueObjectSP 51 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) 52 { 53 if (idx >= m_count) 54 return ValueObjectSP(); 55 if (m_base_data_address == 0 || m_count == 0) 56 return ValueObjectSP(); 57 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index 58 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index 59 lldb::addr_t byte_location = m_base_data_address + byte_idx; 60 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); 61 if (!process_sp) 62 return ValueObjectSP(); 63 uint8_t byte = 0; 64 uint8_t mask = 0; 65 Error err; 66 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); 67 if (err.Fail() || bytes_read == 0) 68 return ValueObjectSP(); 69 switch (bit_index) 70 { 71 case 0: 72 mask = 1; break; 73 case 1: 74 mask = 2; break; 75 case 2: 76 mask = 4; break; 77 case 3: 78 mask = 8; break; 79 case 4: 80 mask = 16; break; 81 case 5: 82 mask = 32; break; 83 case 6: 84 mask = 64; break; 85 case 7: 86 mask = 128; break; 87 default: 88 return ValueObjectSP(); 89 } 90 bool bit_set = ((byte & mask) != 0); 91 Target& target(process_sp->GetTarget()); 92 ValueObjectSP retval_sp; 93 if (bit_set) 94 target.EvaluateExpression("(bool)true", NULL, retval_sp); 95 else 96 target.EvaluateExpression("(bool)false", NULL, retval_sp); 97 StreamString name; name.Printf("[%zu]",idx); 98 if (retval_sp) 99 retval_sp->SetName(ConstString(name.GetData())); 100 return retval_sp; 101 } 102 103 /*(std::__1::vector<std::__1::allocator<bool> >) vBool = { 104 __begin_ = 0x00000001001000e0 105 __size_ = 56 106 __cap_alloc_ = { 107 std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = { 108 __first_ = 1 109 } 110 } 111 }*/ 112 113 bool 114 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() 115 { 116 ValueObjectSP valobj_sp = m_backend.GetSP(); 117 if (!valobj_sp) 118 return false; 119 if (!valobj_sp) 120 return false; 121 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 122 ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true)); 123 if (!size_sp) 124 return false; 125 m_count = size_sp->GetValueAsUnsigned(0); 126 if (!m_count) 127 return true; 128 ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true)); 129 if (!begin_sp) 130 { 131 m_count = 0; 132 return false; 133 } 134 m_base_data_address = begin_sp->GetValueAsUnsigned(0); 135 if (!m_base_data_address) 136 { 137 m_count = 0; 138 return false; 139 } 140 return false; 141 } 142 143 bool 144 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren () 145 { 146 return true; 147 } 148 149 size_t 150 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 151 { 152 if (!m_count || !m_base_data_address) 153 return UINT32_MAX; 154 const char* item_name = name.GetCString(); 155 uint32_t idx = ExtractIndexFromString(item_name); 156 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 157 return UINT32_MAX; 158 return idx; 159 } 160 161 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () 162 {} 163 164 SyntheticChildrenFrontEnd* 165 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 166 { 167 if (!valobj_sp) 168 return NULL; 169 return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); 170 } 171 172 /* 173 (lldb) fr var ibeg --raw --ptr-depth 1 174 (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 = { 175 __i_ = { 176 __ptr_ = 0x0000000100103870 { 177 std::__1::__tree_node_base<void *> = { 178 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = { 179 __left_ = 0x0000000000000000 180 } 181 __right_ = 0x0000000000000000 182 __parent_ = 0x00000001001038b0 183 __is_black_ = true 184 } 185 __value_ = { 186 first = 0 187 second = { std::string } 188 */ 189 190 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 191 SyntheticChildrenFrontEnd(*valobj_sp.get()), 192 m_pair_ptr() 193 { 194 if (valobj_sp) 195 Update(); 196 } 197 198 bool 199 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() 200 { 201 ValueObjectSP valobj_sp = m_backend.GetSP(); 202 if (!valobj_sp) 203 return false; 204 205 TargetSP target_sp(valobj_sp->GetTargetSP()); 206 207 if (!target_sp) 208 return false; 209 210 if (!valobj_sp) 211 return false; 212 213 // this must be a ValueObject* because it is a child of the ValueObject we are producing children for 214 // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator) 215 // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory 216 m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_", 217 NULL, 218 NULL, 219 NULL, 220 ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().DontAllowSyntheticChildren(), 221 NULL).get(); 222 223 return false; 224 } 225 226 size_t 227 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren () 228 { 229 return 2; 230 } 231 232 lldb::ValueObjectSP 233 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 234 { 235 if (!m_pair_ptr) 236 return lldb::ValueObjectSP(); 237 return m_pair_ptr->GetChildAtIndex(idx, true); 238 } 239 240 bool 241 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren () 242 { 243 return true; 244 } 245 246 size_t 247 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 248 { 249 if (name == ConstString("first")) 250 return 0; 251 if (name == ConstString("second")) 252 return 1; 253 return UINT32_MAX; 254 } 255 256 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd () 257 { 258 // this will be deleted when its parent dies (since it's a child object) 259 //delete m_pair_ptr; 260 } 261 262 SyntheticChildrenFrontEnd* 263 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 264 { 265 if (!valobj_sp) 266 return NULL; 267 return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)); 268 } 269 270 /* 271 (lldb) fr var ibeg --raw --ptr-depth 1 -T 272 (std::__1::__wrap_iter<int *>) ibeg = { 273 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 { 274 (int) *__i = 1 275 } 276 } 277 */ 278 279 SyntheticChildrenFrontEnd* 280 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 281 { 282 static ConstString g_item_name; 283 if (!g_item_name) 284 g_item_name.SetCString("__i"); 285 if (!valobj_sp) 286 return NULL; 287 return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); 288 } 289 290 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 291 SyntheticChildrenFrontEnd(*valobj_sp.get()), 292 m_cntrl(NULL), 293 m_count_sp(), 294 m_weak_count_sp(), 295 m_ptr_size(0), 296 m_byte_order(lldb::eByteOrderInvalid) 297 { 298 if (valobj_sp) 299 Update(); 300 } 301 302 size_t 303 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren () 304 { 305 return (m_cntrl ? 1 : 0); 306 } 307 308 lldb::ValueObjectSP 309 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx) 310 { 311 if (!m_cntrl) 312 return lldb::ValueObjectSP(); 313 314 ValueObjectSP valobj_sp = m_backend.GetSP(); 315 if (!valobj_sp) 316 return lldb::ValueObjectSP(); 317 318 if (idx == 0) 319 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true); 320 321 if (idx > 2) 322 return lldb::ValueObjectSP(); 323 324 if (idx == 1) 325 { 326 if (!m_count_sp) 327 { 328 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true)); 329 if (!shared_owners_sp) 330 return lldb::ValueObjectSP(); 331 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0); 332 DataExtractor data(&count, 8, m_byte_order, m_ptr_size); 333 m_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType()); 334 } 335 return m_count_sp; 336 } 337 else /* if (idx == 2) */ 338 { 339 if (!m_weak_count_sp) 340 { 341 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true)); 342 if (!shared_weak_owners_sp) 343 return lldb::ValueObjectSP(); 344 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0); 345 DataExtractor data(&count, 8, m_byte_order, m_ptr_size); 346 m_weak_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType()); 347 } 348 return m_weak_count_sp; 349 } 350 } 351 352 bool 353 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() 354 { 355 m_count_sp.reset(); 356 m_weak_count_sp.reset(); 357 m_cntrl = NULL; 358 359 ValueObjectSP valobj_sp = m_backend.GetSP(); 360 if (!valobj_sp) 361 return false; 362 363 TargetSP target_sp(valobj_sp->GetTargetSP()); 364 if (!target_sp) 365 return false; 366 367 m_byte_order = target_sp->GetArchitecture().GetByteOrder(); 368 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize(); 369 370 lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true)); 371 372 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency 373 return false; 374 } 375 376 bool 377 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren () 378 { 379 return true; 380 } 381 382 size_t 383 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 384 { 385 if (name == ConstString("__ptr_")) 386 return 0; 387 if (name == ConstString("count")) 388 return 1; 389 if (name == ConstString("weak_count")) 390 return 2; 391 return UINT32_MAX; 392 } 393 394 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd () 395 {} 396 397 SyntheticChildrenFrontEnd* 398 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 399 { 400 if (!valobj_sp) 401 return NULL; 402 return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)); 403 } 404 405 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 406 SyntheticChildrenFrontEnd(*valobj_sp.get()), 407 m_start(NULL), 408 m_finish(NULL), 409 m_element_type(), 410 m_element_size(0), 411 m_children() 412 { 413 if (valobj_sp) 414 Update(); 415 } 416 417 size_t 418 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () 419 { 420 if (!m_start || !m_finish) 421 return 0; 422 uint64_t start_val = m_start->GetValueAsUnsigned(0); 423 uint64_t finish_val = m_finish->GetValueAsUnsigned(0); 424 425 if (start_val == 0 || finish_val == 0) 426 return 0; 427 428 if (start_val >= finish_val) 429 return 0; 430 431 size_t num_children = (finish_val - start_val); 432 if (num_children % m_element_size) 433 return 0; 434 return num_children/m_element_size; 435 } 436 437 lldb::ValueObjectSP 438 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 439 { 440 if (!m_start || !m_finish) 441 return lldb::ValueObjectSP(); 442 443 auto cached = m_children.find(idx); 444 if (cached != m_children.end()) 445 return cached->second; 446 447 uint64_t offset = idx * m_element_size; 448 offset = offset + m_start->GetValueAsUnsigned(0); 449 StreamString name; 450 name.Printf("[%zu]",idx); 451 ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); 452 m_children[idx] = child_sp; 453 return child_sp; 454 } 455 456 bool 457 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() 458 { 459 m_start = m_finish = NULL; 460 m_children.clear(); 461 ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); 462 if (!data_type_finder_sp) 463 return false; 464 data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); 465 if (!data_type_finder_sp) 466 return false; 467 m_element_type = data_type_finder_sp->GetClangType().GetPointeeType(); 468 m_element_size = m_element_type.GetByteSize(); 469 470 if (m_element_size > 0) 471 { 472 // store raw pointers or end up with a circular dependency 473 m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get(); 474 m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get(); 475 } 476 return false; 477 } 478 479 bool 480 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () 481 { 482 return true; 483 } 484 485 size_t 486 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 487 { 488 if (!m_start || !m_finish) 489 return UINT32_MAX; 490 return ExtractIndexFromString(name.GetCString()); 491 } 492 493 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd () 494 { 495 // these need to stay around because they are child objects who will follow their parent's life cycle 496 // delete m_start; 497 // delete m_finish; 498 } 499 500 SyntheticChildrenFrontEnd* 501 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 502 { 503 if (!valobj_sp) 504 return NULL; 505 return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); 506 } 507 508 bool 509 lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream) 510 { 511 if (valobj.IsPointerType()) 512 { 513 uint64_t value = valobj.GetValueAsUnsigned(0); 514 if (!value) 515 return false; 516 stream.Printf("0x%016" PRIx64 " ", value); 517 } 518 return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj); 519 } 520