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 Thread *thread = exe_ctx.GetThreadPtr(); 144 if (thread) 145 return thread->GetSelectedFrame().get(); 146 147 Process* process = exe_ctx.GetProcessPtr(); 148 if (!process) 149 return nullptr; 150 151 thread = process->GetThreadList().GetSelectedThread().get(); 152 if (thread) 153 return thread->GetSelectedFrame().get(); 154 155 return nullptr; 156 } 157 158 bool 159 lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj, 160 const char* target_type, 161 const char* selector, 162 uint64_t &value) 163 { 164 if (!target_type || !*target_type) 165 return false; 166 if (!selector || !*selector) 167 return false; 168 StreamString expr; 169 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); 170 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 171 lldb::ValueObjectSP result_sp; 172 Target* target = exe_ctx.GetTargetPtr(); 173 StackFrame* stack_frame = GetViableFrame(exe_ctx); 174 if (!target || !stack_frame) 175 return false; 176 177 EvaluateExpressionOptions options; 178 options.SetCoerceToId(false); 179 options.SetUnwindOnError(true); 180 options.SetKeepInMemory(true); 181 options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); 182 options.SetResultIsInternal(true); 183 options.SetUseDynamic(lldb::eDynamicCanRunTarget); 184 185 target->EvaluateExpression(expr.GetData(), 186 stack_frame, 187 result_sp, 188 options); 189 if (!result_sp) 190 return false; 191 value = result_sp->GetValueAsUnsigned(0); 192 return true; 193 } 194 195 bool 196 lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj, 197 const char* target_type, 198 const char* selector, 199 Stream &stream, 200 lldb::LanguageType lang_type) 201 { 202 if (!target_type || !*target_type) 203 return false; 204 if (!selector || !*selector) 205 return false; 206 StreamString expr; 207 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); 208 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 209 lldb::ValueObjectSP result_sp; 210 Target* target = exe_ctx.GetTargetPtr(); 211 StackFrame* stack_frame = GetViableFrame(exe_ctx); 212 if (!target || !stack_frame) 213 return false; 214 215 EvaluateExpressionOptions options; 216 options.SetCoerceToId(false); 217 options.SetUnwindOnError(true); 218 options.SetKeepInMemory(true); 219 options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); 220 options.SetResultIsInternal(true); 221 options.SetUseDynamic(lldb::eDynamicCanRunTarget); 222 223 target->EvaluateExpression(expr.GetData(), 224 stack_frame, 225 result_sp, 226 options); 227 if (!result_sp) 228 return false; 229 stream.Printf("%s",result_sp->GetSummaryAsCString(lang_type)); 230 return true; 231 } 232 233 lldb::ValueObjectSP 234 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, 235 const char* return_type, 236 const char* selector, 237 uint64_t index) 238 { 239 lldb::ValueObjectSP valobj_sp; 240 if (!return_type || !*return_type) 241 return valobj_sp; 242 if (!selector || !*selector) 243 return valobj_sp; 244 StreamString expr; 245 const char *colon = ""; 246 llvm::StringRef selector_sr(selector); 247 if (selector_sr.back() != ':') 248 colon = ":"; 249 expr.Printf("(%s)[(id)0x%" PRIx64 " %s%s%" PRId64 "]",return_type,valobj.GetPointerValue(),selector,colon,index); 250 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 251 lldb::ValueObjectSP result_sp; 252 Target* target = exe_ctx.GetTargetPtr(); 253 StackFrame* stack_frame = GetViableFrame(exe_ctx); 254 if (!target || !stack_frame) 255 return valobj_sp; 256 257 EvaluateExpressionOptions options; 258 options.SetCoerceToId(false); 259 options.SetUnwindOnError(true); 260 options.SetKeepInMemory(true); 261 options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); 262 options.SetResultIsInternal(true); 263 options.SetUseDynamic(lldb::eDynamicCanRunTarget); 264 265 target->EvaluateExpression(expr.GetData(), 266 stack_frame, 267 valobj_sp, 268 options); 269 return valobj_sp; 270 } 271 272 lldb::ValueObjectSP 273 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, 274 const char* return_type, 275 const char* selector, 276 const char* key) 277 { 278 lldb::ValueObjectSP valobj_sp; 279 if (!return_type || !*return_type) 280 return valobj_sp; 281 if (!selector || !*selector) 282 return valobj_sp; 283 if (!key || !*key) 284 return valobj_sp; 285 StreamString expr; 286 const char *colon = ""; 287 llvm::StringRef selector_sr(selector); 288 if (selector_sr.back() != ':') 289 colon = ":"; 290 expr.Printf("(%s)[(id)0x%" PRIx64 " %s%s%s]",return_type,valobj.GetPointerValue(),selector,colon,key); 291 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 292 lldb::ValueObjectSP result_sp; 293 Target* target = exe_ctx.GetTargetPtr(); 294 StackFrame* stack_frame = GetViableFrame(exe_ctx); 295 if (!target || !stack_frame) 296 return valobj_sp; 297 298 EvaluateExpressionOptions options; 299 options.SetCoerceToId(false); 300 options.SetUnwindOnError(true); 301 options.SetKeepInMemory(true); 302 options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); 303 options.SetResultIsInternal(true); 304 options.SetUseDynamic(lldb::eDynamicCanRunTarget); 305 306 target->EvaluateExpression(expr.GetData(), 307 stack_frame, 308 valobj_sp, 309 options); 310 return valobj_sp; 311 } 312 313 size_t 314 lldb_private::formatters::ExtractIndexFromString (const char* item_name) 315 { 316 if (!item_name || !*item_name) 317 return UINT32_MAX; 318 if (*item_name != '[') 319 return UINT32_MAX; 320 item_name++; 321 char* endptr = NULL; 322 unsigned long int idx = ::strtoul(item_name, &endptr, 0); 323 if (idx == 0 && endptr == item_name) 324 return UINT32_MAX; 325 if (idx == ULONG_MAX) 326 return UINT32_MAX; 327 return idx; 328 } 329 330 lldb::addr_t 331 lldb_private::formatters::GetArrayAddressOrPointerValue (ValueObject& valobj) 332 { 333 lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; 334 335 if (valobj.IsPointerType()) 336 data_addr = valobj.GetValueAsUnsigned(0); 337 else if (valobj.IsArrayType()) 338 data_addr = valobj.GetAddressOf(); 339 340 return data_addr; 341 } 342