1 //===-- FormattersHelpers.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 // C Includes
11 
12 // C++ Includes
13 
14 // Other libraries and framework includes
15 
16 // Project includes
17 #include "lldb/DataFormatters/FormattersHelpers.h"
18 
19 #include "lldb/Core/ConstString.h"
20 #include "lldb/Core/RegularExpression.h"
21 #include "lldb/Target/StackFrame.h"
22 #include "lldb/Target/Thread.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 using namespace lldb_private::formatters;
27 
28 void
29 lldb_private::formatters::AddFormat (TypeCategoryImpl::SharedPointer category_sp,
30                                      lldb::Format format,
31                                      ConstString type_name,
32                                      TypeFormatImpl::Flags flags,
33                                      bool regex)
34 {
35     lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags));
36 
37     if (regex)
38         category_sp->GetRegexTypeFormatsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp);
39     else
40         category_sp->GetTypeFormatsContainer()->Add(type_name, format_sp);
41 }
42 
43 void
44 lldb_private::formatters::AddSummary(TypeCategoryImpl::SharedPointer category_sp,
45                                      TypeSummaryImplSP summary_sp,
46                                      ConstString type_name,
47                                      bool regex)
48 {
49     if (regex)
50         category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
51     else
52         category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
53 }
54 
55 void
56 lldb_private::formatters::AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
57                                            const char* string,
58                                            ConstString type_name,
59                                            TypeSummaryImpl::Flags flags,
60                                            bool regex)
61 {
62     lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags,
63                                                                string));
64 
65     if (regex)
66         category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
67     else
68         category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
69 }
70 
71 void
72 lldb_private::formatters::AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp,
73                                              ConstString type_name,
74                                              TypeSummaryImpl::Flags flags,
75                                              bool regex)
76 {
77     flags.SetShowMembersOneLiner(true);
78     lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, ""));
79 
80     if (regex)
81         category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
82     else
83         category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
84 }
85 
86 #ifndef LLDB_DISABLE_PYTHON
87 void
88 lldb_private::formatters::AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
89                                          CXXFunctionSummaryFormat::Callback funct,
90                                          const char* description,
91                                          ConstString type_name,
92                                          TypeSummaryImpl::Flags flags,
93                                          bool regex)
94 {
95     lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description));
96     if (regex)
97         category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
98     else
99         category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
100 }
101 
102 void
103 lldb_private::formatters::AddCXXSynthetic  (TypeCategoryImpl::SharedPointer category_sp,
104                                             CXXSyntheticChildren::CreateFrontEndCallback generator,
105                                             const char* description,
106                                             ConstString type_name,
107                                             ScriptedSyntheticChildren::Flags flags,
108                                             bool regex)
109 {
110     lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator));
111     if (regex)
112         category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp);
113     else
114         category_sp->GetTypeSyntheticsContainer()->Add(type_name,synth_sp);
115 }
116 
117 void
118 lldb_private::formatters::AddFilter  (TypeCategoryImpl::SharedPointer category_sp,
119                                       std::vector<std::string> children,
120                                       const char* description,
121                                       ConstString type_name,
122                                       ScriptedSyntheticChildren::Flags flags,
123                                       bool regex)
124 {
125     TypeFilterImplSP filter_sp(new TypeFilterImpl(flags));
126     for (auto child : children)
127         filter_sp->AddExpressionPath(child);
128     if (regex)
129         category_sp->GetRegexTypeFiltersContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), filter_sp);
130     else
131         category_sp->GetTypeFiltersContainer()->Add(type_name,filter_sp);
132 }
133 #endif
134 
135 StackFrame*
136 lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
137 {
138     StackFrame* frame = exe_ctx.GetFramePtr();
139     if (frame)
140         return frame;
141 
142     Process* process = exe_ctx.GetProcessPtr();
143     if (!process)
144         return nullptr;
145 
146     ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
147     if (thread_sp)
148         return thread_sp->GetSelectedFrame().get();
149     return nullptr;
150 }
151 
152 bool
153 lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
154                                                           const char* target_type,
155                                                           const char* selector,
156                                                           uint64_t &value)
157 {
158     if (!target_type || !*target_type)
159         return false;
160     if (!selector || !*selector)
161         return false;
162     StreamString expr;
163     expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
164     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
165     lldb::ValueObjectSP result_sp;
166     Target* target = exe_ctx.GetTargetPtr();
167     StackFrame* stack_frame = GetViableFrame(exe_ctx);
168     if (!target || !stack_frame)
169         return false;
170 
171     EvaluateExpressionOptions options;
172     options.SetCoerceToId(false);
173     options.SetUnwindOnError(true);
174     options.SetKeepInMemory(true);
175 
176     target->EvaluateExpression(expr.GetData(),
177                                stack_frame,
178                                result_sp,
179                                options);
180     if (!result_sp)
181         return false;
182     value = result_sp->GetValueAsUnsigned(0);
183     return true;
184 }
185 
186 bool
187 lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
188                                                             const char* target_type,
189                                                             const char* selector,
190                                                             Stream &stream)
191 {
192     if (!target_type || !*target_type)
193         return false;
194     if (!selector || !*selector)
195         return false;
196     StreamString expr;
197     expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
198     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
199     lldb::ValueObjectSP result_sp;
200     Target* target = exe_ctx.GetTargetPtr();
201     StackFrame* stack_frame = GetViableFrame(exe_ctx);
202     if (!target || !stack_frame)
203         return false;
204 
205     EvaluateExpressionOptions options;
206     options.SetCoerceToId(false);
207     options.SetUnwindOnError(true);
208     options.SetKeepInMemory(true);
209     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
210 
211     target->EvaluateExpression(expr.GetData(),
212                                stack_frame,
213                                result_sp,
214                                options);
215     if (!result_sp)
216         return false;
217     stream.Printf("%s",result_sp->GetSummaryAsCString());
218     return true;
219 }
220 
221 lldb::ValueObjectSP
222 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
223                                                 const char* return_type,
224                                                 const char* selector,
225                                                 uint64_t index)
226 {
227     lldb::ValueObjectSP valobj_sp;
228     if (!return_type || !*return_type)
229         return valobj_sp;
230     if (!selector || !*selector)
231         return valobj_sp;
232     StreamString expr_path_stream;
233     valobj.GetExpressionPath(expr_path_stream, false);
234     StreamString expr;
235     expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
236     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
237     lldb::ValueObjectSP result_sp;
238     Target* target = exe_ctx.GetTargetPtr();
239     StackFrame* stack_frame = GetViableFrame(exe_ctx);
240     if (!target || !stack_frame)
241         return valobj_sp;
242 
243     EvaluateExpressionOptions options;
244     options.SetCoerceToId(false);
245     options.SetUnwindOnError(true);
246     options.SetKeepInMemory(true);
247     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
248 
249     target->EvaluateExpression(expr.GetData(),
250                                stack_frame,
251                                valobj_sp,
252                                options);
253     return valobj_sp;
254 }
255 
256 lldb::ValueObjectSP
257 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
258                                                 const char* return_type,
259                                                 const char* selector,
260                                                 const char* key)
261 {
262     lldb::ValueObjectSP valobj_sp;
263     if (!return_type || !*return_type)
264         return valobj_sp;
265     if (!selector || !*selector)
266         return valobj_sp;
267     if (!key || !*key)
268         return valobj_sp;
269     StreamString expr_path_stream;
270     valobj.GetExpressionPath(expr_path_stream, false);
271     StreamString expr;
272     expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
273     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
274     lldb::ValueObjectSP result_sp;
275     Target* target = exe_ctx.GetTargetPtr();
276     StackFrame* stack_frame = GetViableFrame(exe_ctx);
277     if (!target || !stack_frame)
278         return valobj_sp;
279 
280     EvaluateExpressionOptions options;
281     options.SetCoerceToId(false);
282     options.SetUnwindOnError(true);
283     options.SetKeepInMemory(true);
284     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
285 
286     target->EvaluateExpression(expr.GetData(),
287                                stack_frame,
288                                valobj_sp,
289                                options);
290     return valobj_sp;
291 }
292 
293 size_t
294 lldb_private::formatters::ExtractIndexFromString (const char* item_name)
295 {
296     if (!item_name || !*item_name)
297         return UINT32_MAX;
298     if (*item_name != '[')
299         return UINT32_MAX;
300     item_name++;
301     char* endptr = NULL;
302     unsigned long int idx = ::strtoul(item_name, &endptr, 0);
303     if (idx == 0 && endptr == item_name)
304         return UINT32_MAX;
305     if (idx == ULONG_MAX)
306         return UINT32_MAX;
307     return idx;
308 }
309 
310 lldb::addr_t
311 lldb_private::formatters::GetArrayAddressOrPointerValue (ValueObject& valobj)
312 {
313     lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
314 
315     if (valobj.IsPointerType())
316         data_addr = valobj.GetValueAsUnsigned(0);
317     else if (valobj.IsArrayType())
318         data_addr = valobj.GetAddressOf();
319 
320     return data_addr;
321 }
322