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