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