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