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