blob: 979ca6e4504490e521646dbaa12216dce294a47e [file] [log] [blame]
Eugene Zelenkobbd16812016-02-29 19:41:30 +00001//===-- LibStdcpp.cpp -------------------------------------------*- C++ -*-===//
Enrico Granataea2bc0f2013-02-21 19:57:10 +00002//
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
Enrico Granata33e97e62015-09-04 21:01:18 +000010#include "LibStdcpp.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000011
Eugene Zelenkobbd16812016-02-29 19:41:30 +000012// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Enrico Granataea2bc0f2013-02-21 19:57:10 +000016#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"
Todd Fiala82ffb8e2015-10-22 00:23:38 +000021#include "lldb/DataFormatters/StringPrinter.h"
Enrico Granata419d7912015-09-04 00:33:51 +000022#include "lldb/DataFormatters/VectorIterator.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000023#include "lldb/Host/Endian.h"
24#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000025#include "lldb/Target/Target.h"
26
27using namespace lldb;
28using namespace lldb_private;
29using namespace lldb_private::formatters;
30
Kate Stoneb9c1b512016-09-06 20:57:50 +000031namespace {
Tamas Berghammer9c6c8e92016-07-06 09:50:00 +000032
Kate Stoneb9c1b512016-09-06 20:57:50 +000033class 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 */
Eugene Zelenkobbd16812016-02-29 19:41:30 +000045
Tamas Berghammer9c6c8e92016-07-06 09:50:00 +000046public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000047 explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
Eugene Zelenkobbd16812016-02-29 19:41:30 +000048
Kate Stoneb9c1b512016-09-06 20:57:50 +000049 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
Enrico Granata419d7912015-09-04 00:33:51 +000059private:
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 ExecutionContextRef m_exe_ctx_ref;
61 lldb::addr_t m_pair_address;
62 CompilerType m_pair_type;
63 lldb::ValueObjectSP m_pair_sp;
Enrico Granata419d7912015-09-04 00:33:51 +000064};
65
Tamas Berghammer9c6c8e92016-07-06 09:50:00 +000066} // end of anonymous namespace
Enrico Granataea2bc0f2013-02-21 19:57:10 +000067
Kate Stoneb9c1b512016-09-06 20:57:50 +000068LibstdcppMapIteratorSyntheticFrontEnd::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();
Enrico Granataea2bc0f2013-02-21 19:57:10 +000074}
75
Kate Stoneb9c1b512016-09-06 20:57:50 +000076bool 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;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000116}
117
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118size_t LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren() {
119 return 2;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000120}
121
122lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123LibstdcppMapIteratorSyntheticFrontEnd::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();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000132}
133
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134bool LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
135
136size_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;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000143}
144
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145SyntheticChildrenFrontEnd *
146lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator(
147 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
148 return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)
149 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000150}
151
152/*
153 (lldb) fr var ibeg --ptr-depth 1
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >)
155 ibeg = {
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000156 _M_current = 0x00000001001037a0 {
157 *_M_current = 1
158 }
159 }
160 */
161
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162SyntheticChildrenFrontEnd *
163lldb_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);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000171}
Enrico Granatad87cc312015-09-03 01:29:42 +0000172
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173lldb_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();
Enrico Granatad87cc312015-09-03 01:29:42 +0000180}
181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182bool VectorIteratorSyntheticFrontEnd::Update() {
183 m_item_sp.reset();
184
185 ValueObjectSP valobj_sp = m_backend.GetSP();
186 if (!valobj_sp)
Enrico Granatad87cc312015-09-03 01:29:42 +0000187 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188
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;
Enrico Granatad87cc312015-09-03 01:29:42 +0000205}
206
Kate Stoneb9c1b512016-09-06 20:57:50 +0000207size_t VectorIteratorSyntheticFrontEnd::CalculateNumChildren() { return 1; }
Enrico Granatad87cc312015-09-03 01:29:42 +0000208
209lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210VectorIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
211 if (idx == 0)
212 return m_item_sp;
213 return lldb::ValueObjectSP();
214}
215
216bool VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
217
218size_t VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
219 const ConstString &name) {
220 if (name == ConstString("item"))
221 return 0;
222 return UINT32_MAX;
223}
224
225bool 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
273bool 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}