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