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