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