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