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