1 //===-- LibStdcpp.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 "LibStdcpp.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/DataBufferHeap.h" 17 #include "lldb/Core/Error.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Core/ValueObject.h" 20 #include "lldb/Core/ValueObjectConstResult.h" 21 #include "lldb/DataFormatters/StringPrinter.h" 22 #include "lldb/DataFormatters/VectorIterator.h" 23 #include "lldb/Host/Endian.h" 24 #include "lldb/Symbol/ClangASTContext.h" 25 #include "lldb/Target/Target.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 using namespace lldb_private::formatters; 30 31 namespace 32 { 33 34 class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd 35 { 36 /* 37 (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = { 38 (_Base_ptr) _M_node = 0x0000000100103910 { 39 (std::_Rb_tree_color) _M_color = _S_black 40 (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 41 (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 42 (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 43 } 44 } 45 */ 46 47 public: 48 explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 49 50 size_t 51 CalculateNumChildren() override; 52 53 lldb::ValueObjectSP 54 GetChildAtIndex(size_t idx) override; 55 56 bool 57 Update() override; 58 59 bool 60 MightHaveChildren() override; 61 62 size_t 63 GetIndexOfChildWithName (const ConstString &name) override; 64 65 private: 66 ExecutionContextRef m_exe_ctx_ref; 67 lldb::addr_t m_pair_address; 68 CompilerType m_pair_type; 69 lldb::ValueObjectSP m_pair_sp; 70 }; 71 72 class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd 73 { 74 public: 75 explicit LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 76 77 size_t 78 CalculateNumChildren() override; 79 80 lldb::ValueObjectSP 81 GetChildAtIndex(size_t idx) override; 82 83 bool 84 Update() override; 85 86 bool 87 MightHaveChildren() override; 88 89 size_t 90 GetIndexOfChildWithName(const ConstString &name) override; 91 }; 92 93 } // end of anonymous namespace 94 95 LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 96 SyntheticChildrenFrontEnd(*valobj_sp), 97 m_exe_ctx_ref(), 98 m_pair_address(0), 99 m_pair_type(), 100 m_pair_sp() 101 { 102 if (valobj_sp) 103 Update(); 104 } 105 106 bool 107 LibstdcppMapIteratorSyntheticFrontEnd::Update() 108 { 109 ValueObjectSP valobj_sp = m_backend.GetSP(); 110 if (!valobj_sp) 111 return false; 112 113 TargetSP target_sp(valobj_sp->GetTargetSP()); 114 115 if (!target_sp) 116 return false; 117 118 bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8); 119 120 if (!valobj_sp) 121 return false; 122 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 123 124 ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true)); 125 if (!_M_node_sp) 126 return false; 127 128 m_pair_address = _M_node_sp->GetValueAsUnsigned(0); 129 if (m_pair_address == 0) 130 return false; 131 132 m_pair_address += (is_64bit ? 32 : 16); 133 134 CompilerType my_type(valobj_sp->GetCompilerType()); 135 if (my_type.GetNumTemplateArguments() >= 1) 136 { 137 TemplateArgumentKind kind; 138 CompilerType pair_type = my_type.GetTemplateArgument(0, kind); 139 if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion) 140 return false; 141 m_pair_type = pair_type; 142 } 143 else 144 return false; 145 146 return true; 147 } 148 149 size_t 150 LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren () 151 { 152 return 2; 153 } 154 155 lldb::ValueObjectSP 156 LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 157 { 158 if (m_pair_address != 0 && m_pair_type) 159 { 160 if (!m_pair_sp) 161 m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type); 162 if (m_pair_sp) 163 return m_pair_sp->GetChildAtIndex(idx, true); 164 } 165 return lldb::ValueObjectSP(); 166 } 167 168 bool 169 LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren () 170 { 171 return true; 172 } 173 174 size_t 175 LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 176 { 177 if (name == ConstString("first")) 178 return 0; 179 if (name == ConstString("second")) 180 return 1; 181 return UINT32_MAX; 182 } 183 184 SyntheticChildrenFrontEnd* 185 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 186 { 187 return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp) : nullptr); 188 } 189 190 /* 191 (lldb) fr var ibeg --ptr-depth 1 192 (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = { 193 _M_current = 0x00000001001037a0 { 194 *_M_current = 1 195 } 196 } 197 */ 198 199 SyntheticChildrenFrontEnd* 200 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 201 { 202 static ConstString g_item_name; 203 if (!g_item_name) 204 g_item_name.SetCString("_M_current"); 205 return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name) : nullptr); 206 } 207 208 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, 209 ConstString item_name) : 210 SyntheticChildrenFrontEnd(*valobj_sp), 211 m_exe_ctx_ref(), 212 m_item_name(item_name), 213 m_item_sp() 214 { 215 if (valobj_sp) 216 Update(); 217 } 218 219 bool 220 VectorIteratorSyntheticFrontEnd::Update() 221 { 222 m_item_sp.reset(); 223 224 ValueObjectSP valobj_sp = m_backend.GetSP(); 225 if (!valobj_sp) 226 return false; 227 228 if (!valobj_sp) 229 return false; 230 231 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true)); 232 if (!item_ptr) 233 return false; 234 if (item_ptr->GetValueAsUnsigned(0) == 0) 235 return false; 236 Error err; 237 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 238 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType()); 239 if (err.Fail()) 240 m_item_sp.reset(); 241 return false; 242 } 243 244 size_t 245 VectorIteratorSyntheticFrontEnd::CalculateNumChildren() 246 { 247 return 1; 248 } 249 250 lldb::ValueObjectSP 251 VectorIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) 252 { 253 if (idx == 0) 254 return m_item_sp; 255 return lldb::ValueObjectSP(); 256 } 257 258 bool 259 VectorIteratorSyntheticFrontEnd::MightHaveChildren() 260 { 261 return true; 262 } 263 264 size_t 265 VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) 266 { 267 if (name == ConstString("item")) 268 return 0; 269 return UINT32_MAX; 270 } 271 272 bool 273 lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 274 { 275 const bool scalar_is_load_addr = true; 276 AddressType addr_type; 277 lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type); 278 if (addr_of_string != LLDB_INVALID_ADDRESS) 279 { 280 switch (addr_type) 281 { 282 case eAddressTypeLoad: 283 { 284 ProcessSP process_sp(valobj.GetProcessSP()); 285 if (!process_sp) 286 return false; 287 288 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 289 Error error; 290 lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error); 291 if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS) 292 return false; 293 options.SetLocation(addr_of_data); 294 options.SetProcessSP(process_sp); 295 options.SetStream(&stream); 296 options.SetNeedsZeroTermination(false); 297 options.SetBinaryZeroIsTerminator(true); 298 lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error); 299 if (error.Fail()) 300 return false; 301 options.SetSourceSize(size_of_data); 302 303 if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options)) 304 { 305 stream.Printf("Summary Unavailable"); 306 return true; 307 } 308 else 309 return true; 310 } 311 break; 312 case eAddressTypeHost: 313 break; 314 case eAddressTypeInvalid: 315 case eAddressTypeFile: 316 break; 317 } 318 } 319 return false; 320 } 321 322 bool 323 lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 324 { 325 const bool scalar_is_load_addr = true; 326 AddressType addr_type; 327 lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type); 328 if (addr_of_string != LLDB_INVALID_ADDRESS) 329 { 330 switch (addr_type) 331 { 332 case eAddressTypeLoad: 333 { 334 ProcessSP process_sp(valobj.GetProcessSP()); 335 if (!process_sp) 336 return false; 337 338 CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 339 340 if (!wchar_compiler_type) 341 return false; 342 343 const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here 344 345 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 346 Error error; 347 lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error); 348 if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS) 349 return false; 350 options.SetLocation(addr_of_data); 351 options.SetProcessSP(process_sp); 352 options.SetStream(&stream); 353 options.SetNeedsZeroTermination(false); 354 options.SetBinaryZeroIsTerminator(false); 355 lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error); 356 if (error.Fail()) 357 return false; 358 options.SetSourceSize(size_of_data); 359 options.SetPrefixToken("L"); 360 361 switch (wchar_size) 362 { 363 case 8: 364 return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options); 365 case 16: 366 return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options); 367 case 32: 368 return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options); 369 default: 370 stream.Printf("size for wchar_t is not valid"); 371 return true; 372 } 373 return true; 374 } 375 break; 376 case eAddressTypeHost: 377 break; 378 case eAddressTypeInvalid: 379 case eAddressTypeFile: 380 break; 381 } 382 } 383 return false; 384 } 385 386 LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 387 : SyntheticChildrenFrontEnd(*valobj_sp) 388 { 389 if (valobj_sp) 390 Update(); 391 } 392 393 size_t 394 LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() 395 { 396 return 1; 397 } 398 399 lldb::ValueObjectSP 400 LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) 401 { 402 ValueObjectSP valobj_sp = m_backend.GetSP(); 403 if (!valobj_sp) 404 return lldb::ValueObjectSP(); 405 406 if (idx == 0) 407 return valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true); 408 else 409 return lldb::ValueObjectSP(); 410 } 411 412 bool 413 LibStdcppSharedPtrSyntheticFrontEnd::Update() 414 { 415 return false; 416 } 417 418 bool 419 LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() 420 { 421 return true; 422 } 423 424 size_t 425 LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) 426 { 427 if (name == ConstString("_M_ptr")) 428 return 0; 429 return UINT32_MAX; 430 } 431 432 SyntheticChildrenFrontEnd * 433 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, 434 lldb::ValueObjectSP valobj_sp) 435 { 436 return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp) : nullptr); 437 } 438 439 bool 440 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream, 441 const TypeSummaryOptions &options) 442 { 443 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); 444 if (!valobj_sp) 445 return false; 446 447 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true)); 448 if (!ptr_sp) 449 return false; 450 451 ValueObjectSP usecount_sp( 452 valobj_sp->GetChildAtNamePath({ConstString("_M_refcount"), ConstString("_M_pi"), ConstString("_M_use_count")})); 453 if (!usecount_sp) 454 return false; 455 456 if (ptr_sp->GetValueAsUnsigned(0) == 0 || usecount_sp->GetValueAsUnsigned(0) == 0) 457 { 458 stream.Printf("nullptr"); 459 return true; 460 } 461 462 Error error; 463 ValueObjectSP pointee_sp = ptr_sp->Dereference(error); 464 if (pointee_sp && error.Success()) 465 { 466 if (pointee_sp->DumpPrintableRepresentation(stream, ValueObject::eValueObjectRepresentationStyleSummary, 467 lldb::eFormatInvalid, 468 ValueObject::ePrintableRepresentationSpecialCasesDisable, false)) 469 { 470 return true; 471 } 472 } 473 474 stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); 475 return true; 476 } 477