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                                                             lldb::LanguageType lang_type)
192 {
193     if (!target_type || !*target_type)
194         return false;
195     if (!selector || !*selector)
196         return false;
197     StreamString expr;
198     expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
199     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
200     lldb::ValueObjectSP result_sp;
201     Target* target = exe_ctx.GetTargetPtr();
202     StackFrame* stack_frame = GetViableFrame(exe_ctx);
203     if (!target || !stack_frame)
204         return false;
205 
206     EvaluateExpressionOptions options;
207     options.SetCoerceToId(false);
208     options.SetUnwindOnError(true);
209     options.SetKeepInMemory(true);
210     options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
211     options.SetResultIsInternal(true);
212     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
213 
214     target->EvaluateExpression(expr.GetData(),
215                                stack_frame,
216                                result_sp,
217                                options);
218     if (!result_sp)
219         return false;
220     stream.Printf("%s",result_sp->GetSummaryAsCString(lang_type));
221     return true;
222 }
223 
224 lldb::ValueObjectSP
225 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
226                                                 const char* return_type,
227                                                 const char* selector,
228                                                 uint64_t index)
229 {
230     lldb::ValueObjectSP valobj_sp;
231     if (!return_type || !*return_type)
232         return valobj_sp;
233     if (!selector || !*selector)
234         return valobj_sp;
235     StreamString expr_path_stream;
236     valobj.GetExpressionPath(expr_path_stream, false);
237     StreamString expr;
238     expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
239     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
240     lldb::ValueObjectSP result_sp;
241     Target* target = exe_ctx.GetTargetPtr();
242     StackFrame* stack_frame = GetViableFrame(exe_ctx);
243     if (!target || !stack_frame)
244         return valobj_sp;
245 
246     EvaluateExpressionOptions options;
247     options.SetCoerceToId(false);
248     options.SetUnwindOnError(true);
249     options.SetKeepInMemory(true);
250     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
251 
252     target->EvaluateExpression(expr.GetData(),
253                                stack_frame,
254                                valobj_sp,
255                                options);
256     return valobj_sp;
257 }
258 
259 lldb::ValueObjectSP
260 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
261                                                 const char* return_type,
262                                                 const char* selector,
263                                                 const char* key)
264 {
265     lldb::ValueObjectSP valobj_sp;
266     if (!return_type || !*return_type)
267         return valobj_sp;
268     if (!selector || !*selector)
269         return valobj_sp;
270     if (!key || !*key)
271         return valobj_sp;
272     StreamString expr_path_stream;
273     valobj.GetExpressionPath(expr_path_stream, false);
274     StreamString expr;
275     expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
276     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
277     lldb::ValueObjectSP result_sp;
278     Target* target = exe_ctx.GetTargetPtr();
279     StackFrame* stack_frame = GetViableFrame(exe_ctx);
280     if (!target || !stack_frame)
281         return valobj_sp;
282 
283     EvaluateExpressionOptions options;
284     options.SetCoerceToId(false);
285     options.SetUnwindOnError(true);
286     options.SetKeepInMemory(true);
287     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
288 
289     target->EvaluateExpression(expr.GetData(),
290                                stack_frame,
291                                valobj_sp,
292                                options);
293     return valobj_sp;
294 }
295 
296 size_t
297 lldb_private::formatters::ExtractIndexFromString (const char* item_name)
298 {
299     if (!item_name || !*item_name)
300         return UINT32_MAX;
301     if (*item_name != '[')
302         return UINT32_MAX;
303     item_name++;
304     char* endptr = NULL;
305     unsigned long int idx = ::strtoul(item_name, &endptr, 0);
306     if (idx == 0 && endptr == item_name)
307         return UINT32_MAX;
308     if (idx == ULONG_MAX)
309         return UINT32_MAX;
310     return idx;
311 }
312 
313 lldb::addr_t
314 lldb_private::formatters::GetArrayAddressOrPointerValue (ValueObject& valobj)
315 {
316     lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
317 
318     if (valobj.IsPointerType())
319         data_addr = valobj.GetValueAsUnsigned(0);
320     else if (valobj.IsArrayType())
321         data_addr = valobj.GetAddressOf();
322 
323     return data_addr;
324 }
325