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