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