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