1 //===-- FormatEntity.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 #include "llvm/ADT/StringRef.h" 11 12 #include "lldb/Core/FormatEntity.h" 13 14 #include "lldb/Core/Address.h" 15 #include "lldb/Core/Debugger.h" 16 #include "lldb/Core/Module.h" 17 #include "lldb/Core/Stream.h" 18 #include "lldb/Core/StreamString.h" 19 #include "lldb/Core/ValueObject.h" 20 #include "lldb/Core/ValueObjectVariable.h" 21 #include "lldb/DataFormatters/DataVisualization.h" 22 #include "lldb/DataFormatters/FormatManager.h" 23 #include "lldb/Host/FileSpec.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Symbol/Block.h" 26 #include "lldb/Symbol/CompileUnit.h" 27 #include "lldb/Symbol/Function.h" 28 #include "lldb/Symbol/LineEntry.h" 29 #include "lldb/Symbol/Symbol.h" 30 #include "lldb/Symbol/VariableList.h" 31 #include "lldb/Target/ExecutionContext.h" 32 #include "lldb/Target/Process.h" 33 #include "lldb/Target/RegisterContext.h" 34 #include "lldb/Target/SectionLoadList.h" 35 #include "lldb/Target/StackFrame.h" 36 #include "lldb/Target/StopInfo.h" 37 #include "lldb/Target/Target.h" 38 #include "lldb/Target/Thread.h" 39 #include "lldb/Utility/AnsiTerminal.h" 40 41 using namespace lldb; 42 using namespace lldb_private; 43 44 45 enum FileKind 46 { 47 FileError = 0, 48 Basename, 49 Dirname, 50 Fullpath 51 }; 52 53 #define ENTRY(n,t,f) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,0,NULL, false} 54 #define ENTRY_VALUE(n,t,f,v) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, v,0,NULL, false} 55 #define ENTRY_CHILDREN(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, false} 56 #define ENTRY_CHILDREN_KEEP_SEP(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, true} 57 #define ENTRY_STRING(n,s) { n, s, FormatEntity::Entry::Type::InsertString, FormatEntity::Entry::FormatType::None, 0,0, NULL, false} 58 static FormatEntity::Entry::Definition g_string_entry[] = 59 { 60 ENTRY("*", ParentString, None) 61 }; 62 63 static FormatEntity::Entry::Definition g_addr_entries[] = 64 { 65 ENTRY ("load", AddressLoad , UInt64), 66 ENTRY ("file", AddressFile , UInt64), 67 ENTRY ("load", AddressLoadOrFile, UInt64), 68 }; 69 70 static FormatEntity::Entry::Definition g_file_child_entries[] = 71 { 72 ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename), 73 ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname), 74 ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath) 75 }; 76 77 static FormatEntity::Entry::Definition g_frame_child_entries[] = 78 { 79 80 ENTRY ("index", FrameIndex , UInt32), 81 ENTRY ("pc" , FrameRegisterPC , UInt64), 82 ENTRY ("fp" , FrameRegisterFP , UInt64), 83 ENTRY ("sp" , FrameRegisterSP , UInt64), 84 ENTRY ("flags", FrameRegisterFlags, UInt64), 85 ENTRY_CHILDREN ("reg", FrameRegisterByName, UInt64, g_string_entry), 86 }; 87 88 static FormatEntity::Entry::Definition g_function_child_entries[] = 89 { 90 ENTRY ("id" , FunctionID , UInt64), 91 ENTRY ("name" , FunctionName , CString), 92 ENTRY ("name-without-args" , FunctionNameNoArgs , CString), 93 ENTRY ("name-with-args" , FunctionNameWithArgs , CString), 94 ENTRY ("addr-offset" , FunctionAddrOffset , UInt64), 95 ENTRY ("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, UInt64), 96 ENTRY ("line-offset" , FunctionLineOffset , UInt64), 97 ENTRY ("pc-offset" , FunctionPCOffset , UInt64) 98 }; 99 100 static FormatEntity::Entry::Definition g_line_child_entries[] = 101 { 102 ENTRY_CHILDREN("file", LineEntryFile , None , g_file_child_entries), 103 ENTRY("number" , LineEntryLineNumber , UInt32), 104 ENTRY("start-addr" , LineEntryStartAddress, UInt64), 105 ENTRY("end-addr" , LineEntryEndAddress , UInt64), 106 }; 107 108 static FormatEntity::Entry::Definition g_module_child_entries[] = 109 { 110 ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), 111 }; 112 113 static FormatEntity::Entry::Definition g_process_child_entries[] = 114 { 115 ENTRY ( "id" , ProcessID , UInt64 ), 116 ENTRY_VALUE ( "name" , ProcessFile , CString , FileKind::Basename), 117 ENTRY_CHILDREN ( "file" , ProcessFile , None , g_file_child_entries), 118 }; 119 120 static FormatEntity::Entry::Definition g_svar_child_entries[] = 121 { 122 ENTRY ( "*" , ParentString , None) 123 }; 124 125 static FormatEntity::Entry::Definition g_var_child_entries[] = 126 { 127 ENTRY ( "*" , ParentString , None) 128 }; 129 130 static FormatEntity::Entry::Definition g_thread_child_entries[] = 131 { 132 ENTRY ( "id" , ThreadID , UInt64 ), 133 ENTRY ( "protocol_id" , ThreadProtocolID , UInt64 ), 134 ENTRY ( "index" , ThreadIndexID , UInt32 ), 135 ENTRY_CHILDREN ( "info" , ThreadInfo , None , g_string_entry), 136 ENTRY ( "queue" , ThreadQueue , CString ), 137 ENTRY ( "name" , ThreadName , CString ), 138 ENTRY ( "stop-reason" , ThreadStopReason , CString ), 139 ENTRY ( "return-value" , ThreadReturnValue , CString ), 140 ENTRY ( "completed-expression", ThreadCompletedExpression , CString ), 141 }; 142 143 static FormatEntity::Entry::Definition g_target_child_entries[] = 144 { 145 ENTRY ( "arch" , TargetArch , CString ), 146 }; 147 148 #define _TO_STR2(_val) #_val 149 #define _TO_STR(_val) _TO_STR2(_val) 150 151 static FormatEntity::Entry::Definition g_ansi_fg_entries[] = 152 { 153 ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), 154 ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), 155 ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), 156 ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), 157 ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), 158 ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), 159 ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), 160 ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), 161 }; 162 163 static FormatEntity::Entry::Definition g_ansi_bg_entries[] = 164 { 165 ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), 166 ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), 167 ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), 168 ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), 169 ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), 170 ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), 171 ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), 172 ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), 173 }; 174 175 static FormatEntity::Entry::Definition g_ansi_entries[] = 176 { 177 ENTRY_CHILDREN ( "fg" , Invalid , None , g_ansi_fg_entries), 178 ENTRY_CHILDREN ( "bg" , Invalid , None , g_ansi_bg_entries), 179 ENTRY_STRING ( "normal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), 180 ENTRY_STRING ( "bold" , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), 181 ENTRY_STRING ( "faint" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), 182 ENTRY_STRING ( "italic" , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), 183 ENTRY_STRING ( "underline" , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), 184 ENTRY_STRING ( "slow-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), 185 ENTRY_STRING ( "fast-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), 186 ENTRY_STRING ( "negative" , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), 187 ENTRY_STRING ( "conceal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), 188 ENTRY_STRING ( "crossed-out" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), 189 190 }; 191 192 static FormatEntity::Entry::Definition g_script_child_entries[] = 193 { 194 ENTRY ( "frame" , ScriptFrame , None), 195 ENTRY ( "process" , ScriptProcess , None), 196 ENTRY ( "target" , ScriptTarget , None), 197 ENTRY ( "thread" , ScriptThread , None), 198 ENTRY ( "var" , ScriptVariable , None), 199 ENTRY ( "svar" , ScriptVariableSynthetic , None), 200 ENTRY ( "thread" , ScriptThread , None), 201 }; 202 203 static FormatEntity::Entry::Definition g_top_level_entries[] = 204 { 205 ENTRY_CHILDREN ("addr" , AddressLoadOrFile , UInt64 , g_addr_entries), 206 ENTRY ("addr-file-or-load" , AddressLoadOrFile , UInt64 ), 207 ENTRY_CHILDREN ("ansi" , Invalid , None , g_ansi_entries), 208 ENTRY ("current-pc-arrow" , CurrentPCArrow , CString ), 209 ENTRY_CHILDREN ("file" , File , CString , g_file_child_entries), 210 ENTRY_CHILDREN ("frame" , Invalid , None , g_frame_child_entries), 211 ENTRY_CHILDREN ("function" , Invalid , None , g_function_child_entries), 212 ENTRY_CHILDREN ("line" , Invalid , None , g_line_child_entries), 213 ENTRY_CHILDREN ("module" , Invalid , None , g_module_child_entries), 214 ENTRY_CHILDREN ("process" , Invalid , None , g_process_child_entries), 215 ENTRY_CHILDREN ("script" , Invalid , None , g_script_child_entries), 216 ENTRY_CHILDREN_KEEP_SEP ("svar" , VariableSynthetic , None , g_svar_child_entries), 217 ENTRY_CHILDREN ("thread" , Invalid , None , g_thread_child_entries), 218 ENTRY_CHILDREN ("target" , Invalid , None , g_target_child_entries), 219 ENTRY_CHILDREN_KEEP_SEP ("var" , Variable , None , g_var_child_entries), 220 }; 221 222 static FormatEntity::Entry::Definition g_root = ENTRY_CHILDREN ("<root>", Root, None, g_top_level_entries); 223 224 225 FormatEntity::Entry::Entry (llvm::StringRef s) : 226 string (s.data(), s.size()), 227 printf_format (), 228 children (), 229 definition (NULL), 230 type (Type::String), 231 fmt (lldb::eFormatDefault), 232 number (0), 233 deref (false) 234 { 235 } 236 237 FormatEntity::Entry::Entry (char ch) : 238 string (1, ch), 239 printf_format (), 240 children (), 241 definition (NULL), 242 type (Type::String), 243 fmt (lldb::eFormatDefault), 244 number (0), 245 deref (false) 246 { 247 } 248 249 void 250 FormatEntity::Entry::AppendChar (char ch) 251 { 252 if (children.empty() || children.back().type != Entry::Type::String) 253 children.push_back(Entry(ch)); 254 else 255 children.back().string.append(1, ch); 256 } 257 258 void 259 FormatEntity::Entry::AppendText (const llvm::StringRef &s) 260 { 261 if (children.empty() || children.back().type != Entry::Type::String) 262 children.push_back(Entry(s)); 263 else 264 children.back().string.append(s.data(), s.size()); 265 } 266 267 void 268 FormatEntity::Entry::AppendText (const char *cstr) 269 { 270 return AppendText (llvm::StringRef(cstr)); 271 } 272 273 274 Error 275 FormatEntity::Parse (const llvm::StringRef &format_str, Entry &entry) 276 { 277 entry.Clear(); 278 entry.type = Entry::Type::Root; 279 llvm::StringRef modifiable_format (format_str); 280 return ParseInternal (modifiable_format, entry, 0); 281 } 282 283 #define ENUM_TO_CSTR(eee) case FormatEntity::Entry::Type::eee: return #eee 284 285 const char * 286 FormatEntity::Entry::TypeToCString (Type t) 287 { 288 switch (t) 289 { 290 ENUM_TO_CSTR(Invalid); 291 ENUM_TO_CSTR(ParentNumber); 292 ENUM_TO_CSTR(ParentString); 293 ENUM_TO_CSTR(InsertString); 294 ENUM_TO_CSTR(Root); 295 ENUM_TO_CSTR(String); 296 ENUM_TO_CSTR(Scope); 297 ENUM_TO_CSTR(Variable); 298 ENUM_TO_CSTR(VariableSynthetic); 299 ENUM_TO_CSTR(ScriptVariable); 300 ENUM_TO_CSTR(ScriptVariableSynthetic); 301 ENUM_TO_CSTR(AddressLoad); 302 ENUM_TO_CSTR(AddressFile); 303 ENUM_TO_CSTR(AddressLoadOrFile); 304 ENUM_TO_CSTR(ProcessID); 305 ENUM_TO_CSTR(ProcessFile); 306 ENUM_TO_CSTR(ScriptProcess); 307 ENUM_TO_CSTR(ThreadID); 308 ENUM_TO_CSTR(ThreadProtocolID); 309 ENUM_TO_CSTR(ThreadIndexID); 310 ENUM_TO_CSTR(ThreadName); 311 ENUM_TO_CSTR(ThreadQueue); 312 ENUM_TO_CSTR(ThreadStopReason); 313 ENUM_TO_CSTR(ThreadReturnValue); 314 ENUM_TO_CSTR(ThreadCompletedExpression); 315 ENUM_TO_CSTR(ScriptThread); 316 ENUM_TO_CSTR(ThreadInfo); 317 ENUM_TO_CSTR(TargetArch); 318 ENUM_TO_CSTR(ScriptTarget); 319 ENUM_TO_CSTR(ModuleFile); 320 ENUM_TO_CSTR(File); 321 ENUM_TO_CSTR(FrameIndex); 322 ENUM_TO_CSTR(FrameRegisterPC); 323 ENUM_TO_CSTR(FrameRegisterSP); 324 ENUM_TO_CSTR(FrameRegisterFP); 325 ENUM_TO_CSTR(FrameRegisterFlags); 326 ENUM_TO_CSTR(FrameRegisterByName); 327 ENUM_TO_CSTR(ScriptFrame); 328 ENUM_TO_CSTR(FunctionID); 329 ENUM_TO_CSTR(FunctionDidChange); 330 ENUM_TO_CSTR(FunctionInitialFunction); 331 ENUM_TO_CSTR(FunctionName); 332 ENUM_TO_CSTR(FunctionNameWithArgs); 333 ENUM_TO_CSTR(FunctionNameNoArgs); 334 ENUM_TO_CSTR(FunctionAddrOffset); 335 ENUM_TO_CSTR(FunctionAddrOffsetConcrete); 336 ENUM_TO_CSTR(FunctionLineOffset); 337 ENUM_TO_CSTR(FunctionPCOffset); 338 ENUM_TO_CSTR(LineEntryFile); 339 ENUM_TO_CSTR(LineEntryLineNumber); 340 ENUM_TO_CSTR(LineEntryStartAddress); 341 ENUM_TO_CSTR(LineEntryEndAddress); 342 ENUM_TO_CSTR(CurrentPCArrow); 343 } 344 return "???"; 345 } 346 347 #undef ENUM_TO_CSTR 348 349 void 350 FormatEntity::Entry::Dump (Stream &s, int depth) const 351 { 352 s.Printf ("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); 353 if (fmt != eFormatDefault) 354 s.Printf ("lldb-format = %s, ", FormatManager::GetFormatAsCString (fmt)); 355 if (!string.empty()) 356 s.Printf ("string = \"%s\"", string.c_str()); 357 if (!printf_format.empty()) 358 s.Printf ("printf_format = \"%s\"", printf_format.c_str()); 359 if (number != 0) 360 s.Printf ("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); 361 if (deref) 362 s.Printf ("deref = true, "); 363 s.EOL(); 364 for (const auto &child : children) 365 { 366 child.Dump(s, depth + 1); 367 } 368 } 369 370 371 template <typename T> 372 static bool RunScriptFormatKeyword(Stream &s, 373 const SymbolContext *sc, 374 const ExecutionContext *exe_ctx, 375 T t, 376 const char *script_function_name) 377 { 378 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 379 380 if (target) 381 { 382 ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 383 if (script_interpreter) 384 { 385 Error error; 386 std::string script_output; 387 388 if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, script_output, error) && error.Success()) 389 { 390 s.Printf("%s", script_output.c_str()); 391 return true; 392 } 393 else 394 { 395 s.Printf("<error: %s>",error.AsCString()); 396 } 397 } 398 } 399 return false; 400 } 401 402 static bool 403 DumpAddress (Stream &s, 404 const SymbolContext *sc, 405 const ExecutionContext *exe_ctx, 406 const Address &addr, 407 bool print_file_addr_or_load_addr) 408 { 409 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 410 addr_t vaddr = LLDB_INVALID_ADDRESS; 411 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 412 vaddr = addr.GetLoadAddress (target); 413 if (vaddr == LLDB_INVALID_ADDRESS) 414 vaddr = addr.GetFileAddress (); 415 416 if (vaddr != LLDB_INVALID_ADDRESS) 417 { 418 int addr_width = 0; 419 if (exe_ctx && target) 420 { 421 addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 422 } 423 if (addr_width == 0) 424 addr_width = 16; 425 if (print_file_addr_or_load_addr) 426 { 427 ExecutionContextScope *exe_scope = NULL; 428 if (exe_ctx) 429 exe_scope = exe_ctx->GetBestExecutionContextScope(); 430 addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); 431 } 432 else 433 { 434 s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 435 } 436 return true; 437 } 438 return false; 439 } 440 441 static bool 442 DumpAddressOffsetFromFunction (Stream &s, 443 const SymbolContext *sc, 444 const ExecutionContext *exe_ctx, 445 const Address &format_addr, 446 bool concrete_only, 447 bool no_padding) 448 { 449 if (format_addr.IsValid()) 450 { 451 Address func_addr; 452 453 if (sc) 454 { 455 if (sc->function) 456 { 457 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 458 if (sc->block && !concrete_only) 459 { 460 // Check to make sure we aren't in an inline 461 // function. If we are, use the inline block 462 // range that contains "format_addr" since 463 // blocks can be discontiguous. 464 Block *inline_block = sc->block->GetContainingInlinedBlock (); 465 AddressRange inline_range; 466 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 467 func_addr = inline_range.GetBaseAddress(); 468 } 469 } 470 else if (sc->symbol && sc->symbol->ValueIsAddress()) 471 func_addr = sc->symbol->GetAddress(); 472 } 473 474 if (func_addr.IsValid()) 475 { 476 const char *addr_offset_padding = no_padding ? "" : " "; 477 478 if (func_addr.GetSection() == format_addr.GetSection()) 479 { 480 addr_t func_file_addr = func_addr.GetFileAddress(); 481 addr_t addr_file_addr = format_addr.GetFileAddress(); 482 if (addr_file_addr > func_file_addr) 483 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); 484 else if (addr_file_addr < func_file_addr) 485 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); 486 return true; 487 } 488 else 489 { 490 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 491 if (target) 492 { 493 addr_t func_load_addr = func_addr.GetLoadAddress (target); 494 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 495 if (addr_load_addr > func_load_addr) 496 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); 497 else if (addr_load_addr < func_load_addr) 498 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); 499 return true; 500 } 501 } 502 } 503 } 504 return false; 505 } 506 507 static bool 508 ScanBracketedRange (llvm::StringRef subpath, 509 size_t& close_bracket_index, 510 const char*& var_name_final_if_array_range, 511 int64_t& index_lower, 512 int64_t& index_higher) 513 { 514 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 515 close_bracket_index = llvm::StringRef::npos; 516 const size_t open_bracket_index = subpath.find('['); 517 if (open_bracket_index == llvm::StringRef::npos) 518 { 519 if (log) 520 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 521 return false; 522 } 523 524 close_bracket_index = subpath.find(']', open_bracket_index + 1); 525 526 if (close_bracket_index == llvm::StringRef::npos) 527 { 528 if (log) 529 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 530 return false; 531 } 532 else 533 { 534 var_name_final_if_array_range = subpath.data() + open_bracket_index; 535 536 if (close_bracket_index - open_bracket_index == 1) 537 { 538 if (log) 539 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 540 index_lower = 0; 541 } 542 else 543 { 544 const size_t separator_index = subpath.find('-', open_bracket_index + 1); 545 546 if (separator_index == llvm::StringRef::npos) 547 { 548 const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 549 index_lower = ::strtoul (index_lower_cstr, NULL, 0); 550 index_higher = index_lower; 551 if (log) 552 log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", index_lower); 553 } 554 else 555 { 556 const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; 557 const char *index_higher_cstr = subpath.data() + separator_index + 1; 558 index_lower = ::strtoul (index_lower_cstr, NULL, 0); 559 index_higher = ::strtoul (index_higher_cstr, NULL, 0); 560 if (log) 561 log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", index_lower, index_higher); 562 } 563 if (index_lower > index_higher && index_higher > 0) 564 { 565 if (log) 566 log->Printf("[ScanBracketedRange] swapping indices"); 567 const int64_t temp = index_lower; 568 index_lower = index_higher; 569 index_higher = temp; 570 } 571 } 572 } 573 return true; 574 } 575 576 static bool 577 DumpFile (Stream &s, const FileSpec &file, FileKind file_kind) 578 { 579 switch (file_kind) 580 { 581 case FileKind::FileError: 582 break; 583 584 case FileKind::Basename: 585 if (file.GetFilename()) 586 { 587 s << file.GetFilename(); 588 return true; 589 } 590 break; 591 592 case FileKind::Dirname: 593 if (file.GetDirectory()) 594 { 595 s << file.GetDirectory(); 596 return true; 597 } 598 break; 599 600 case FileKind::Fullpath: 601 if (file) 602 { 603 s << file; 604 return true; 605 } 606 break; 607 } 608 return false; 609 } 610 611 static bool 612 DumpRegister (Stream &s, 613 StackFrame *frame, 614 RegisterKind reg_kind, 615 uint32_t reg_num, 616 Format format) 617 618 { 619 if (frame) 620 { 621 RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 622 623 if (reg_ctx) 624 { 625 const uint32_t lldb_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 626 if (lldb_reg_num != LLDB_INVALID_REGNUM) 627 { 628 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (lldb_reg_num); 629 if (reg_info) 630 { 631 RegisterValue reg_value; 632 if (reg_ctx->ReadRegister (reg_info, reg_value)) 633 { 634 reg_value.Dump(&s, reg_info, false, false, format); 635 return true; 636 } 637 } 638 } 639 } 640 } 641 return false; 642 } 643 644 645 static ValueObjectSP 646 ExpandIndexedExpression (ValueObject* valobj, 647 size_t index, 648 StackFrame* frame, 649 bool deref_pointer) 650 { 651 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 652 const char* ptr_deref_format = "[%d]"; 653 std::string ptr_deref_buffer(10,0); 654 ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); 655 if (log) 656 log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); 657 const char* first_unparsed; 658 ValueObject::GetValueForExpressionPathOptions options; 659 ValueObject::ExpressionPathEndResultType final_value_type; 660 ValueObject::ExpressionPathScanEndReason reason_to_stop; 661 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 662 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), 663 &first_unparsed, 664 &reason_to_stop, 665 &final_value_type, 666 options, 667 &what_next); 668 if (!item) 669 { 670 if (log) 671 log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 672 " final_value_type %d", 673 first_unparsed, reason_to_stop, final_value_type); 674 } 675 else 676 { 677 if (log) 678 log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 679 " final_value_type %d", 680 first_unparsed, reason_to_stop, final_value_type); 681 } 682 return item; 683 } 684 685 static char 686 ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style) 687 { 688 switch (style) 689 { 690 case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: return '@'; 691 case ValueObject::eValueObjectRepresentationStyleValue: return 'V'; 692 case ValueObject::eValueObjectRepresentationStyleLocation: return 'L'; 693 case ValueObject::eValueObjectRepresentationStyleSummary: return 'S'; 694 case ValueObject::eValueObjectRepresentationStyleChildrenCount: return '#'; 695 case ValueObject::eValueObjectRepresentationStyleType: return 'T'; 696 case ValueObject::eValueObjectRepresentationStyleName: return 'N'; 697 case ValueObject::eValueObjectRepresentationStyleExpressionPath: return '>'; 698 } 699 return '\0'; 700 } 701 702 static bool 703 DumpValue (Stream &s, 704 const SymbolContext *sc, 705 const ExecutionContext *exe_ctx, 706 const FormatEntity::Entry &entry, 707 ValueObject *valobj) 708 { 709 if (valobj == NULL) 710 return false; 711 712 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 713 Format custom_format = eFormatInvalid; 714 ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary; 715 716 bool do_deref_pointer = entry.deref; 717 bool is_script = false; 718 switch (entry.type) 719 { 720 case FormatEntity::Entry::Type::ScriptVariable: 721 is_script = true; 722 break; 723 724 case FormatEntity::Entry::Type::Variable: 725 custom_format = entry.fmt; 726 val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 727 break; 728 729 case FormatEntity::Entry::Type::ScriptVariableSynthetic: 730 is_script = true; 731 // Fall through 732 case FormatEntity::Entry::Type::VariableSynthetic: 733 custom_format = entry.fmt; 734 val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; 735 if (!valobj->IsSynthetic()) 736 { 737 valobj = valobj->GetSyntheticValue().get(); 738 if (valobj == nullptr) 739 return false; 740 } 741 break; 742 743 default: 744 return false; 745 } 746 747 if (valobj == NULL) 748 return false; 749 750 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 751 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 752 ValueObject::GetValueForExpressionPathOptions options; 753 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 754 ValueObject* target = NULL; 755 const char* var_name_final_if_array_range = NULL; 756 size_t close_bracket_index = llvm::StringRef::npos; 757 int64_t index_lower = -1; 758 int64_t index_higher = -1; 759 bool is_array_range = false; 760 const char* first_unparsed; 761 bool was_plain_var = false; 762 bool was_var_format = false; 763 bool was_var_indexed = false; 764 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 765 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 766 767 if (is_script) 768 { 769 return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string.c_str()); 770 } 771 772 llvm::StringRef subpath (entry.string); 773 // simplest case ${var}, just print valobj's value 774 if (entry.string.empty()) 775 { 776 if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue) 777 was_plain_var = true; 778 else 779 was_var_format = true; 780 target = valobj; 781 } 782 else // this is ${var.something} or multiple .something nested 783 { 784 if (entry.string[0] == '[') 785 was_var_indexed = true; 786 ScanBracketedRange (subpath, 787 close_bracket_index, 788 var_name_final_if_array_range, 789 index_lower, 790 index_higher); 791 792 Error error; 793 794 const std::string &expr_path = entry.string; 795 796 if (log) 797 log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); 798 799 target = valobj->GetValueForExpressionPath(expr_path.c_str(), 800 &first_unparsed, 801 &reason_to_stop, 802 &final_value_type, 803 options, 804 &what_next).get(); 805 806 if (!target) 807 { 808 if (log) 809 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 810 " final_value_type %d", 811 first_unparsed, reason_to_stop, final_value_type); 812 return false; 813 } 814 else 815 { 816 if (log) 817 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 818 " final_value_type %d", 819 first_unparsed, reason_to_stop, final_value_type); 820 target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); 821 } 822 } 823 824 825 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 826 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 827 828 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 829 830 if (do_deref_pointer && !is_array_range) 831 { 832 // I have not deref-ed yet, let's do it 833 // this happens when we are not going through GetValueForVariableExpressionPath 834 // to get to the target ValueObject 835 Error error; 836 target = target->Dereference(error).get(); 837 if (error.Fail()) 838 { 839 if (log) 840 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 841 return false; 842 } 843 do_deref_pointer = false; 844 } 845 846 if (!target) 847 { 848 if (log) 849 log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); 850 return false; 851 } 852 853 // we do not want to use the summary for a bitfield of type T:n 854 // if we were originally dealing with just a T - that would get 855 // us into an endless recursion 856 if (target->IsBitfield() && was_var_indexed) 857 { 858 // TODO: check for a (T:n)-specific summary - we should still obey that 859 StreamString bitfield_name; 860 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 861 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 862 if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp)) 863 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 864 } 865 866 // TODO use flags for these 867 const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); 868 bool is_array = (type_info_flags & eTypeIsArray) != 0; 869 bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; 870 bool is_aggregate = target->GetClangType().IsAggregateType(); 871 872 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 873 { 874 StreamString str_temp; 875 if (log) 876 log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 877 878 if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) 879 { 880 // try to use the special cases 881 bool success = target->DumpPrintableRepresentation(str_temp, 882 val_obj_display, 883 custom_format); 884 if (log) 885 log->Printf("[Debugger::FormatPrompt] special cases did%s match", success ? "" : "n't"); 886 887 // should not happen 888 if (success) 889 s << str_temp.GetData(); 890 return true; 891 } 892 else 893 { 894 if (was_plain_var) // if ${var} 895 { 896 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 897 } 898 else if (is_pointer) // if pointer, value is the address stored 899 { 900 target->DumpPrintableRepresentation (s, 901 val_obj_display, 902 custom_format, 903 ValueObject::ePrintableRepresentationSpecialCasesDisable); 904 } 905 return true; 906 } 907 } 908 909 // if directly trying to print ${var}, and this is an aggregate, display a nice 910 // type @ location message 911 if (is_aggregate && was_plain_var) 912 { 913 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 914 return true; 915 } 916 917 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 918 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 919 { 920 s << "<invalid use of aggregate type>"; 921 return true; 922 } 923 924 if (!is_array_range) 925 { 926 if (log) 927 log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 928 return target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 929 } 930 else 931 { 932 if (log) 933 log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 934 if (!is_array && !is_pointer) 935 return false; 936 if (log) 937 log->Printf("[Debugger::FormatPrompt] handle as array"); 938 llvm::StringRef special_directions; 939 if (close_bracket_index != llvm::StringRef::npos && subpath.size() > close_bracket_index) 940 { 941 ConstString additional_data (subpath.drop_front(close_bracket_index+1)); 942 StreamString special_directions_stream; 943 special_directions_stream.Printf("${%svar%s", 944 do_deref_pointer ? "*" : "", 945 additional_data.GetCString()); 946 947 if (entry.fmt != eFormatDefault) 948 { 949 const char format_char = FormatManager::GetFormatAsFormatChar(entry.fmt); 950 if (format_char != '\0') 951 special_directions_stream.Printf("%%%c", format_char); 952 else 953 { 954 const char *format_cstr = FormatManager::GetFormatAsCString(entry.fmt); 955 special_directions_stream.Printf("%%%s", format_cstr); 956 } 957 } 958 else if (entry.number != 0) 959 { 960 const char style_char = ConvertValueObjectStyleToChar ((ValueObject::ValueObjectRepresentationStyle)entry.number); 961 if (style_char) 962 special_directions_stream.Printf("%%%c", style_char); 963 } 964 special_directions_stream.PutChar('}'); 965 special_directions = llvm::StringRef(special_directions_stream.GetString()); 966 } 967 968 // let us display items index_lower thru index_higher of this array 969 s.PutChar('['); 970 971 if (index_higher < 0) 972 index_higher = valobj->GetNumChildren() - 1; 973 974 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 975 976 bool success = true; 977 for (int64_t index = index_lower;index<=index_higher; ++index) 978 { 979 ValueObject* item = ExpandIndexedExpression (target, 980 index, 981 exe_ctx->GetFramePtr(), 982 false).get(); 983 984 if (!item) 985 { 986 if (log) 987 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index); 988 } 989 else 990 { 991 if (log) 992 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions.data() ? special_directions.data() : ""); 993 } 994 995 if (special_directions.empty()) 996 { 997 success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 998 } 999 else 1000 { 1001 success &= FormatEntity::FormatStringRef(special_directions, s, sc, exe_ctx, NULL, item, false, false); 1002 } 1003 1004 if (--max_num_children == 0) 1005 { 1006 s.PutCString(", ..."); 1007 break; 1008 } 1009 1010 if (index < index_higher) 1011 s.PutChar(','); 1012 } 1013 s.PutChar(']'); 1014 return success; 1015 } 1016 1017 } 1018 1019 static bool 1020 DumpRegister (Stream &s, 1021 StackFrame *frame, 1022 const char *reg_name, 1023 Format format) 1024 1025 { 1026 if (frame) 1027 { 1028 RegisterContext *reg_ctx = frame->GetRegisterContext().get(); 1029 1030 if (reg_ctx) 1031 { 1032 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 1033 if (reg_info) 1034 { 1035 RegisterValue reg_value; 1036 if (reg_ctx->ReadRegister (reg_info, reg_value)) 1037 { 1038 reg_value.Dump(&s, reg_info, false, false, format); 1039 return true; 1040 } 1041 } 1042 } 1043 } 1044 return false; 1045 } 1046 1047 static bool 1048 FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry, 1049 const StructuredData::ObjectSP &thread_info_dictionary, 1050 const SymbolContext *sc, 1051 const ExecutionContext *exe_ctx, 1052 Stream &s) 1053 { 1054 llvm::StringRef path(entry.string); 1055 1056 StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); 1057 1058 if (value.get()) 1059 { 1060 if (value->GetType() == StructuredData::Type::eTypeInteger) 1061 { 1062 const char *token_format = "0x%4.4" PRIx64; 1063 if (!entry.printf_format.empty()) 1064 token_format = entry.printf_format.c_str(); 1065 s.Printf(token_format, value->GetAsInteger()->GetValue()); 1066 return true; 1067 } 1068 else if (value->GetType() == StructuredData::Type::eTypeFloat) 1069 { 1070 s.Printf ("%f", value->GetAsFloat()->GetValue()); 1071 return true; 1072 } 1073 else if (value->GetType() == StructuredData::Type::eTypeString) 1074 { 1075 s.Printf("%s", value->GetAsString()->GetValue().c_str()); 1076 return true; 1077 } 1078 else if (value->GetType() == StructuredData::Type::eTypeArray) 1079 { 1080 if (value->GetAsArray()->GetSize() > 0) 1081 { 1082 s.Printf ("%zu", value->GetAsArray()->GetSize()); 1083 return true; 1084 } 1085 } 1086 else if (value->GetType() == StructuredData::Type::eTypeDictionary) 1087 { 1088 s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); 1089 return true; 1090 } 1091 } 1092 1093 return false; 1094 } 1095 1096 1097 static inline bool 1098 IsToken(const char *var_name_begin, const char *var) 1099 { 1100 return (::strncmp (var_name_begin, var, strlen(var)) == 0); 1101 } 1102 1103 bool 1104 FormatEntity::FormatStringRef (const llvm::StringRef &format_str, 1105 Stream &s, 1106 const SymbolContext *sc, 1107 const ExecutionContext *exe_ctx, 1108 const Address *addr, 1109 ValueObject* valobj, 1110 bool function_changed, 1111 bool initial_function) 1112 { 1113 if (!format_str.empty()) 1114 { 1115 FormatEntity::Entry root; 1116 Error error = FormatEntity::Parse(format_str, root); 1117 if (error.Success()) 1118 { 1119 return FormatEntity::Format (root, 1120 s, 1121 sc, 1122 exe_ctx, 1123 addr, 1124 valobj, 1125 function_changed, 1126 initial_function); 1127 } 1128 } 1129 return false; 1130 1131 } 1132 bool 1133 FormatEntity::FormatCString (const char *format, 1134 Stream &s, 1135 const SymbolContext *sc, 1136 const ExecutionContext *exe_ctx, 1137 const Address *addr, 1138 ValueObject* valobj, 1139 bool function_changed, 1140 bool initial_function) 1141 { 1142 if (format && format[0]) 1143 { 1144 FormatEntity::Entry root; 1145 llvm::StringRef format_str(format); 1146 Error error = FormatEntity::Parse(format_str, root); 1147 if (error.Success()) 1148 { 1149 return FormatEntity::Format (root, 1150 s, 1151 sc, 1152 exe_ctx, 1153 addr, 1154 valobj, 1155 function_changed, 1156 initial_function); 1157 } 1158 } 1159 return false; 1160 } 1161 1162 bool 1163 FormatEntity::Format (const Entry &entry, 1164 Stream &s, 1165 const SymbolContext *sc, 1166 const ExecutionContext *exe_ctx, 1167 const Address *addr, 1168 ValueObject* valobj, 1169 bool function_changed, 1170 bool initial_function) 1171 { 1172 switch (entry.type) 1173 { 1174 case Entry::Type::Invalid: 1175 case Entry::Type::ParentNumber: // Only used for FormatEntity::Entry::Definition encoding 1176 case Entry::Type::ParentString: // Only used for FormatEntity::Entry::Definition encoding 1177 case Entry::Type::InsertString: // Only used for FormatEntity::Entry::Definition encoding 1178 return false; 1179 1180 case Entry::Type::Root: 1181 for (const auto &child : entry.children) 1182 { 1183 if (Format (child, 1184 s, 1185 sc, 1186 exe_ctx, 1187 addr, 1188 valobj, 1189 function_changed, 1190 initial_function) == false) 1191 { 1192 return false; // If any item of root fails, then the formatting fails 1193 } 1194 } 1195 return true; // Only return true if all items succeeded 1196 1197 case Entry::Type::String: 1198 s.PutCString(entry.string.c_str()); 1199 return true; 1200 1201 case Entry::Type::Scope: 1202 { 1203 StreamString scope_stream; 1204 bool success = false; 1205 for (const auto &child : entry.children) 1206 { 1207 success = Format (child, scope_stream, sc, exe_ctx, addr, valobj, function_changed, initial_function); 1208 if (!success) 1209 break; 1210 } 1211 // Only if all items in a scope succeed, then do we 1212 // print the output into the main stream 1213 if (success) 1214 s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); 1215 } 1216 return true; // Scopes always successfully print themselves 1217 1218 case Entry::Type::Variable: 1219 case Entry::Type::VariableSynthetic: 1220 case Entry::Type::ScriptVariable: 1221 case Entry::Type::ScriptVariableSynthetic: 1222 if (DumpValue(s, sc, exe_ctx, entry, valobj)) 1223 return true; 1224 return false; 1225 1226 case Entry::Type::AddressFile: 1227 case Entry::Type::AddressLoad: 1228 case Entry::Type::AddressLoadOrFile: 1229 if (addr && addr->IsValid() && DumpAddress(s, sc, exe_ctx, *addr, entry.type == Entry::Type::AddressLoadOrFile)) 1230 return true; 1231 return false; 1232 1233 case Entry::Type::ProcessID: 1234 if (exe_ctx) 1235 { 1236 Process *process = exe_ctx->GetProcessPtr(); 1237 if (process) 1238 { 1239 const char *format = "%" PRIu64; 1240 if (!entry.printf_format.empty()) 1241 format = entry.printf_format.c_str(); 1242 s.Printf(format, process->GetID()); 1243 return true; 1244 } 1245 } 1246 return false; 1247 1248 case Entry::Type::ProcessFile: 1249 if (exe_ctx) 1250 { 1251 Process *process = exe_ctx->GetProcessPtr(); 1252 if (process) 1253 { 1254 Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1255 if (exe_module) 1256 { 1257 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) 1258 return true; 1259 } 1260 } 1261 } 1262 return false; 1263 1264 case Entry::Type::ScriptProcess: 1265 if (exe_ctx) 1266 { 1267 Process *process = exe_ctx->GetProcessPtr(); 1268 if (process) 1269 return RunScriptFormatKeyword (s, sc, exe_ctx, process, entry.string.c_str()); 1270 } 1271 return false; 1272 1273 1274 case Entry::Type::ThreadID: 1275 if (exe_ctx) 1276 { 1277 Thread *thread = exe_ctx->GetThreadPtr(); 1278 if (thread) 1279 { 1280 const char *format = "0x%4.4" PRIx64; 1281 if (!entry.printf_format.empty()) 1282 { 1283 // Watch for the special "tid" format... 1284 if (entry.printf_format == "tid") 1285 { 1286 bool handled = false; 1287 Target &target = thread->GetProcess()->GetTarget(); 1288 ArchSpec arch (target.GetArchitecture ()); 1289 llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; 1290 if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) 1291 { 1292 handled = true; 1293 format = "%" PRIu64; 1294 } 1295 } 1296 else 1297 { 1298 format = entry.printf_format.c_str(); 1299 } 1300 } 1301 s.Printf(format, thread->GetID()); 1302 return true; 1303 } 1304 } 1305 return false; 1306 1307 case Entry::Type::ThreadProtocolID: 1308 if (exe_ctx) 1309 { 1310 Thread *thread = exe_ctx->GetThreadPtr(); 1311 if (thread) 1312 { 1313 const char *format = "0x%4.4" PRIx64; 1314 if (!entry.printf_format.empty()) 1315 format = entry.printf_format.c_str(); 1316 s.Printf(format, thread->GetProtocolID()); 1317 return true; 1318 } 1319 } 1320 return false; 1321 1322 case Entry::Type::ThreadIndexID: 1323 if (exe_ctx) 1324 { 1325 Thread *thread = exe_ctx->GetThreadPtr(); 1326 if (thread) 1327 { 1328 const char *format = "%" PRIu32; 1329 if (!entry.printf_format.empty()) 1330 format = entry.printf_format.c_str(); 1331 s.Printf(format, thread->GetIndexID()); 1332 return true; 1333 } 1334 } 1335 return false; 1336 1337 case Entry::Type::ThreadName: 1338 if (exe_ctx) 1339 { 1340 Thread *thread = exe_ctx->GetThreadPtr(); 1341 if (thread) 1342 { 1343 const char *cstr = thread->GetName(); 1344 if (cstr && cstr[0]) 1345 { 1346 s.PutCString(cstr); 1347 return true; 1348 } 1349 } 1350 } 1351 return false; 1352 1353 case Entry::Type::ThreadQueue: 1354 if (exe_ctx) 1355 { 1356 Thread *thread = exe_ctx->GetThreadPtr(); 1357 if (thread) 1358 { 1359 const char *cstr = thread->GetQueueName(); 1360 if (cstr && cstr[0]) 1361 { 1362 s.PutCString(cstr); 1363 return true; 1364 } 1365 } 1366 } 1367 return false; 1368 1369 case Entry::Type::ThreadStopReason: 1370 if (exe_ctx) 1371 { 1372 Thread *thread = exe_ctx->GetThreadPtr(); 1373 if (thread) 1374 { 1375 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1376 if (stop_info_sp && stop_info_sp->IsValid()) 1377 { 1378 const char *cstr = stop_info_sp->GetDescription(); 1379 if (cstr && cstr[0]) 1380 { 1381 s.PutCString(cstr); 1382 return true; 1383 } 1384 } 1385 } 1386 } 1387 return false; 1388 1389 case Entry::Type::ThreadReturnValue: 1390 if (exe_ctx) 1391 { 1392 Thread *thread = exe_ctx->GetThreadPtr(); 1393 if (thread) 1394 { 1395 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1396 if (stop_info_sp && stop_info_sp->IsValid()) 1397 { 1398 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 1399 if (return_valobj_sp) 1400 { 1401 return_valobj_sp->Dump(s); 1402 return true; 1403 } 1404 } 1405 } 1406 } 1407 return false; 1408 1409 case Entry::Type::ThreadCompletedExpression: 1410 if (exe_ctx) 1411 { 1412 Thread *thread = exe_ctx->GetThreadPtr(); 1413 if (thread) 1414 { 1415 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1416 if (stop_info_sp && stop_info_sp->IsValid()) 1417 { 1418 ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); 1419 if (expression_var_sp && expression_var_sp->GetValueObject()) 1420 { 1421 expression_var_sp->GetValueObject()->Dump(s); 1422 return true; 1423 } 1424 } 1425 } 1426 } 1427 return false; 1428 1429 case Entry::Type::ScriptThread: 1430 if (exe_ctx) 1431 { 1432 Thread *thread = exe_ctx->GetThreadPtr(); 1433 if (thread) 1434 return RunScriptFormatKeyword (s, sc, exe_ctx, thread, entry.string.c_str()); 1435 } 1436 return false; 1437 1438 case Entry::Type::ThreadInfo: 1439 if (exe_ctx) 1440 { 1441 Thread *thread = exe_ctx->GetThreadPtr(); 1442 if (thread) 1443 { 1444 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); 1445 if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) 1446 { 1447 if (FormatThreadExtendedInfoRecurse (entry, object_sp, sc, exe_ctx, s)) 1448 return true; 1449 } 1450 } 1451 } 1452 return false; 1453 1454 case Entry::Type::TargetArch: 1455 if (exe_ctx) 1456 { 1457 Target *target = exe_ctx->GetTargetPtr(); 1458 if (target) 1459 { 1460 const ArchSpec &arch = target->GetArchitecture (); 1461 if (arch.IsValid()) 1462 { 1463 s.PutCString (arch.GetArchitectureName()); 1464 return true; 1465 } 1466 } 1467 } 1468 return false; 1469 1470 case Entry::Type::ScriptTarget: 1471 if (exe_ctx) 1472 { 1473 Target *target = exe_ctx->GetTargetPtr(); 1474 if (target) 1475 return RunScriptFormatKeyword (s, sc, exe_ctx, target, entry.string.c_str()); 1476 } 1477 return false; 1478 1479 case Entry::Type::ModuleFile: 1480 if (sc) 1481 { 1482 Module *module = sc->module_sp.get(); 1483 if (module) 1484 { 1485 if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) 1486 return true; 1487 } 1488 } 1489 return false; 1490 1491 case Entry::Type::File: 1492 if (sc) 1493 { 1494 CompileUnit *cu = sc->comp_unit; 1495 if (cu) 1496 { 1497 // CompileUnit is a FileSpec 1498 if (DumpFile(s, *cu, (FileKind)entry.number)) 1499 return true; 1500 } 1501 } 1502 return false; 1503 1504 case Entry::Type::FrameIndex: 1505 if (exe_ctx) 1506 { 1507 StackFrame *frame = exe_ctx->GetFramePtr(); 1508 if (frame) 1509 { 1510 const char *format = "%" PRIu32; 1511 if (!entry.printf_format.empty()) 1512 format = entry.printf_format.c_str(); 1513 s.Printf(format, frame->GetFrameIndex()); 1514 return true; 1515 } 1516 } 1517 return false; 1518 1519 case Entry::Type::FrameRegisterPC: 1520 if (exe_ctx) 1521 { 1522 StackFrame *frame = exe_ctx->GetFramePtr(); 1523 if (frame) 1524 { 1525 const Address &pc_addr = frame->GetFrameCodeAddress(); 1526 if (pc_addr.IsValid()) 1527 { 1528 if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) 1529 return true; 1530 } 1531 } 1532 } 1533 return false; 1534 1535 case Entry::Type::FrameRegisterSP: 1536 if (exe_ctx) 1537 { 1538 StackFrame *frame = exe_ctx->GetFramePtr(); 1539 if (frame) 1540 { 1541 if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (lldb::Format)entry.number)) 1542 return true; 1543 } 1544 } 1545 return false; 1546 1547 case Entry::Type::FrameRegisterFP: 1548 if (exe_ctx) 1549 { 1550 StackFrame *frame = exe_ctx->GetFramePtr(); 1551 if (frame) 1552 { 1553 if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, (lldb::Format)entry.number)) 1554 return true; 1555 } 1556 } 1557 return false; 1558 1559 case Entry::Type::FrameRegisterFlags: 1560 if (exe_ctx) 1561 { 1562 StackFrame *frame = exe_ctx->GetFramePtr(); 1563 if (frame) 1564 { 1565 if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) 1566 return true; 1567 } 1568 } 1569 return false; 1570 1571 1572 case Entry::Type::FrameRegisterByName: 1573 if (exe_ctx) 1574 { 1575 StackFrame *frame = exe_ctx->GetFramePtr(); 1576 if (frame) 1577 { 1578 if (DumpRegister (s, frame, entry.string.c_str(), (lldb::Format)entry.number)) 1579 return true; 1580 } 1581 } 1582 return false; 1583 1584 case Entry::Type::ScriptFrame: 1585 if (exe_ctx) 1586 { 1587 StackFrame *frame = exe_ctx->GetFramePtr(); 1588 if (frame) 1589 return RunScriptFormatKeyword (s, sc, exe_ctx, frame, entry.string.c_str()); 1590 } 1591 return false; 1592 1593 case Entry::Type::FunctionID: 1594 if (sc) 1595 { 1596 if (sc->function) 1597 { 1598 s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 1599 return true; 1600 } 1601 else if (sc->symbol) 1602 { 1603 s.Printf("symbol[%u]", sc->symbol->GetID()); 1604 return true; 1605 } 1606 } 1607 return false; 1608 1609 case Entry::Type::FunctionDidChange: 1610 return function_changed; 1611 1612 case Entry::Type::FunctionInitialFunction: 1613 return initial_function; 1614 1615 case Entry::Type::FunctionName: 1616 { 1617 const char *name = NULL; 1618 if (sc->function) 1619 name = sc->function->GetName().AsCString (NULL); 1620 else if (sc->symbol) 1621 name = sc->symbol->GetName().AsCString (NULL); 1622 if (name) 1623 { 1624 s.PutCString(name); 1625 1626 if (sc->block) 1627 { 1628 Block *inline_block = sc->block->GetContainingInlinedBlock (); 1629 if (inline_block) 1630 { 1631 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 1632 if (inline_info) 1633 { 1634 s.PutCString(" [inlined] "); 1635 inline_info->GetName().Dump(&s); 1636 } 1637 } 1638 } 1639 return true; 1640 } 1641 } 1642 return false; 1643 1644 case Entry::Type::FunctionNameNoArgs: 1645 { 1646 ConstString name; 1647 if (sc->function) 1648 name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 1649 else if (sc->symbol) 1650 name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); 1651 if (name) 1652 { 1653 s.PutCString(name.GetCString()); 1654 return true; 1655 } 1656 } 1657 return false; 1658 1659 case Entry::Type::FunctionNameWithArgs: 1660 { 1661 // Print the function name with arguments in it 1662 if (sc->function) 1663 { 1664 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 1665 const char *cstr = sc->function->GetName().AsCString (NULL); 1666 if (cstr) 1667 { 1668 const InlineFunctionInfo *inline_info = NULL; 1669 VariableListSP variable_list_sp; 1670 bool get_function_vars = true; 1671 if (sc->block) 1672 { 1673 Block *inline_block = sc->block->GetContainingInlinedBlock (); 1674 1675 if (inline_block) 1676 { 1677 get_function_vars = false; 1678 inline_info = sc->block->GetInlinedFunctionInfo(); 1679 if (inline_info) 1680 variable_list_sp = inline_block->GetBlockVariableList (true); 1681 } 1682 } 1683 1684 if (get_function_vars) 1685 { 1686 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 1687 } 1688 1689 if (inline_info) 1690 { 1691 s.PutCString (cstr); 1692 s.PutCString (" [inlined] "); 1693 cstr = inline_info->GetName().GetCString(); 1694 } 1695 1696 VariableList args; 1697 if (variable_list_sp) 1698 variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); 1699 if (args.GetSize() > 0) 1700 { 1701 const char *open_paren = strchr (cstr, '('); 1702 const char *close_paren = nullptr; 1703 const char *generic = strchr(cstr, '<'); 1704 // if before the arguments list begins there is a template sign 1705 // then scan to the end of the generic args before you try to find 1706 // the arguments list 1707 if (generic && open_paren && generic < open_paren) 1708 { 1709 int generic_depth = 1; 1710 ++generic; 1711 for (; 1712 *generic && generic_depth > 0; 1713 generic++) 1714 { 1715 if (*generic == '<') 1716 generic_depth++; 1717 if (*generic == '>') 1718 generic_depth--; 1719 } 1720 if (*generic) 1721 open_paren = strchr(generic, '('); 1722 else 1723 open_paren = nullptr; 1724 } 1725 if (open_paren) 1726 { 1727 if (IsToken (open_paren, "(anonymous namespace)")) 1728 { 1729 open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); 1730 if (open_paren) 1731 close_paren = strchr (open_paren, ')'); 1732 } 1733 else 1734 close_paren = strchr (open_paren, ')'); 1735 } 1736 1737 if (open_paren) 1738 s.Write(cstr, open_paren - cstr + 1); 1739 else 1740 { 1741 s.PutCString (cstr); 1742 s.PutChar ('('); 1743 } 1744 const size_t num_args = args.GetSize(); 1745 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 1746 { 1747 std::string buffer; 1748 1749 VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 1750 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 1751 const char *var_representation = nullptr; 1752 const char *var_name = var_value_sp->GetName().GetCString(); 1753 if (var_value_sp->GetClangType().IsAggregateType() && 1754 DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) 1755 { 1756 static StringSummaryFormat format(TypeSummaryImpl::Flags() 1757 .SetHideItemNames(false) 1758 .SetShowMembersOneLiner(true), 1759 ""); 1760 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); 1761 var_representation = buffer.c_str(); 1762 } 1763 else 1764 var_representation = var_value_sp->GetValueAsCString(); 1765 if (arg_idx > 0) 1766 s.PutCString (", "); 1767 if (var_value_sp->GetError().Success()) 1768 { 1769 if (var_representation) 1770 s.Printf ("%s=%s", var_name, var_representation); 1771 else 1772 s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); 1773 } 1774 else 1775 s.Printf ("%s=<unavailable>", var_name); 1776 } 1777 1778 if (close_paren) 1779 s.PutCString (close_paren); 1780 else 1781 s.PutChar(')'); 1782 1783 } 1784 else 1785 { 1786 s.PutCString(cstr); 1787 } 1788 return true; 1789 } 1790 } 1791 else if (sc->symbol) 1792 { 1793 const char *cstr = sc->symbol->GetName().AsCString (NULL); 1794 if (cstr) 1795 { 1796 s.PutCString(cstr); 1797 return true; 1798 } 1799 } 1800 } 1801 return false; 1802 1803 case Entry::Type::FunctionAddrOffset: 1804 if (addr) 1805 { 1806 if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, false, false)) 1807 return true; 1808 } 1809 return false; 1810 1811 case Entry::Type::FunctionAddrOffsetConcrete: 1812 if (addr) 1813 { 1814 if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, true, true)) 1815 return true; 1816 } 1817 return false; 1818 1819 case Entry::Type::FunctionLineOffset: 1820 if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false)) 1821 return true; 1822 return false; 1823 1824 case Entry::Type::FunctionPCOffset: 1825 if (exe_ctx) 1826 { 1827 StackFrame *frame = exe_ctx->GetFramePtr(); 1828 if (frame) 1829 { 1830 if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, frame->GetFrameCodeAddress(), false, false)) 1831 return true; 1832 } 1833 } 1834 return false; 1835 1836 case Entry::Type::LineEntryFile: 1837 if (sc && sc->line_entry.IsValid()) 1838 { 1839 Module *module = sc->module_sp.get(); 1840 if (module) 1841 { 1842 if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) 1843 return true; 1844 } 1845 } 1846 return false; 1847 1848 case Entry::Type::LineEntryLineNumber: 1849 if (sc && sc->line_entry.IsValid()) 1850 { 1851 const char *format = "%" PRIu32; 1852 if (!entry.printf_format.empty()) 1853 format = entry.printf_format.c_str(); 1854 s.Printf(format, sc->line_entry.line); 1855 return true; 1856 } 1857 return false; 1858 1859 case Entry::Type::LineEntryStartAddress: 1860 case Entry::Type::LineEntryEndAddress: 1861 if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) 1862 { 1863 Address addr = sc->line_entry.range.GetBaseAddress(); 1864 1865 if (entry.type == Entry::Type::LineEntryEndAddress) 1866 addr.Slide(sc->line_entry.range.GetByteSize()); 1867 if (DumpAddress(s, sc, exe_ctx, addr, false)) 1868 return true; 1869 } 1870 return false; 1871 1872 case Entry::Type::CurrentPCArrow: 1873 if (addr && exe_ctx && exe_ctx->GetFramePtr()) 1874 { 1875 RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); 1876 if (reg_ctx.get()) 1877 { 1878 addr_t pc_loadaddr = reg_ctx->GetPC(); 1879 if (pc_loadaddr != LLDB_INVALID_ADDRESS) 1880 { 1881 Address pc; 1882 pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); 1883 if (pc == *addr) 1884 { 1885 s.Printf ("-> "); 1886 return true; 1887 } 1888 } 1889 } 1890 s.Printf(" "); 1891 return true; 1892 } 1893 return false; 1894 } 1895 return false; 1896 } 1897 1898 static bool 1899 DumpCommaSeparatedChildEntryNames (Stream &s, const FormatEntity::Entry::Definition *parent) 1900 { 1901 if (parent->children) 1902 { 1903 const size_t n = parent->num_children; 1904 for (size_t i=0; i<n; ++i) 1905 { 1906 if (i > 0) 1907 s.PutCString(", "); 1908 s.Printf ("\"%s\"", parent->children[i].name); 1909 } 1910 return true; 1911 } 1912 return false; 1913 } 1914 1915 1916 static Error 1917 ParseEntry (const llvm::StringRef &format_str, 1918 const FormatEntity::Entry::Definition *parent, 1919 FormatEntity::Entry &entry) 1920 { 1921 Error error; 1922 1923 const size_t sep_pos = format_str.find_first_of(".[:"); 1924 const char sep_char = (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; 1925 llvm::StringRef key = format_str.substr(0, sep_pos); 1926 1927 const size_t n = parent->num_children; 1928 for (size_t i=0; i<n; ++i) 1929 { 1930 const FormatEntity::Entry::Definition *entry_def = parent->children + i; 1931 if (key.equals(entry_def->name) || entry_def->name[0] == '*') 1932 { 1933 llvm::StringRef value; 1934 if (sep_char) 1935 value = format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); 1936 switch (entry_def->type) 1937 { 1938 case FormatEntity::Entry::Type::ParentString: 1939 entry.string = std::move(format_str.str()); 1940 return error; // Success 1941 1942 case FormatEntity::Entry::Type::ParentNumber: 1943 entry.number = entry_def->data; 1944 return error; // Success 1945 1946 case FormatEntity::Entry::Type::InsertString: 1947 entry.type = entry_def->type; 1948 entry.string = entry_def->string; 1949 return error; // Success 1950 1951 default: 1952 entry.type = entry_def->type; 1953 break; 1954 } 1955 1956 if (value.empty()) 1957 { 1958 if (entry_def->type == FormatEntity::Entry::Type::Invalid) 1959 { 1960 if (entry_def->children) 1961 { 1962 StreamString error_strm; 1963 error_strm.Printf("'%s' can't be specified on its own, you must access one of its children: ", entry_def->name); 1964 DumpCommaSeparatedChildEntryNames (error_strm, entry_def); 1965 error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); 1966 } 1967 else if (sep_char == ':') 1968 { 1969 // Any value whose separator is a with a ':' means this value has a string argument 1970 // that needs to be stored in the entry (like "${script.var:}"). 1971 // In this case the string value is the empty string which is ok. 1972 } 1973 else 1974 { 1975 error.SetErrorStringWithFormat("%s", "invalid entry definitions"); 1976 } 1977 } 1978 } 1979 else 1980 { 1981 if (entry_def->children) 1982 { 1983 error = ParseEntry (value, entry_def, entry); 1984 } 1985 else if (sep_char == ':') 1986 { 1987 // Any value whose separator is a with a ':' means this value has a string argument 1988 // that needs to be stored in the entry (like "${script.var:modulename.function}") 1989 entry.string = std::move(value.str()); 1990 } 1991 else 1992 { 1993 error.SetErrorStringWithFormat("'%s' followed by '%s' but it has no children", 1994 key.str().c_str(), 1995 value.str().c_str()); 1996 } 1997 } 1998 return error; 1999 } 2000 } 2001 StreamString error_strm; 2002 if (parent->type == FormatEntity::Entry::Type::Root) 2003 error_strm.Printf("invalid top level item '%s'. Valid top level items are: ", key.str().c_str()); 2004 else 2005 error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", key.str().c_str(), parent->name); 2006 DumpCommaSeparatedChildEntryNames (error_strm, parent); 2007 error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); 2008 return error; 2009 } 2010 2011 2012 static const FormatEntity::Entry::Definition * 2013 FindEntry (const llvm::StringRef &format_str, const FormatEntity::Entry::Definition *parent, llvm::StringRef &remainder) 2014 { 2015 Error error; 2016 2017 std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); 2018 const size_t n = parent->num_children; 2019 for (size_t i=0; i<n; ++i) 2020 { 2021 const FormatEntity::Entry::Definition *entry_def = parent->children + i; 2022 if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') 2023 { 2024 if (p.second.empty()) 2025 { 2026 if (format_str.back() == '.') 2027 remainder = format_str.drop_front(format_str.size() - 1); 2028 else 2029 remainder = llvm::StringRef(); // Exact match 2030 return entry_def; 2031 } 2032 else 2033 { 2034 if (entry_def->children) 2035 { 2036 return FindEntry (p.second, entry_def, remainder); 2037 } 2038 else 2039 { 2040 remainder = p.second; 2041 return entry_def; 2042 } 2043 } 2044 } 2045 } 2046 remainder = format_str; 2047 return parent; 2048 } 2049 2050 Error 2051 FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth) 2052 { 2053 Error error; 2054 while (!format.empty() && error.Success()) 2055 { 2056 const size_t non_special_chars = format.find_first_of("${}\\"); 2057 2058 if (non_special_chars == llvm::StringRef::npos) 2059 { 2060 // No special characters, just string bytes so add them and we are done 2061 parent_entry.AppendText(format); 2062 return error; 2063 } 2064 2065 if (non_special_chars > 0) 2066 { 2067 // We have a special character, so add all characters before these as a plain string 2068 parent_entry.AppendText(format.substr(0,non_special_chars)); 2069 format = format.drop_front(non_special_chars); 2070 } 2071 2072 switch (format[0]) 2073 { 2074 case '\0': 2075 return error; 2076 2077 case '{': 2078 { 2079 format = format.drop_front(); // Skip the '{' 2080 Entry scope_entry(Entry::Type::Scope); 2081 error = FormatEntity::ParseInternal (format, scope_entry, depth+1); 2082 if (error.Fail()) 2083 return error; 2084 parent_entry.AppendEntry(std::move(scope_entry)); 2085 } 2086 break; 2087 2088 case '}': 2089 if (depth == 0) 2090 error.SetErrorString("unmatched '}' character"); 2091 else 2092 format = format.drop_front(); // Skip the '}' as we are at the end of the scope 2093 return error; 2094 2095 case '\\': 2096 { 2097 format = format.drop_front(); // Skip the '\' character 2098 if (format.empty()) 2099 { 2100 error.SetErrorString("'\\' character was not followed by another character"); 2101 return error; 2102 } 2103 2104 const char desens_char = format[0]; 2105 format = format.drop_front(); // Skip the desensitized char character 2106 switch (desens_char) 2107 { 2108 case 'a': parent_entry.AppendChar('\a'); break; 2109 case 'b': parent_entry.AppendChar('\b'); break; 2110 case 'f': parent_entry.AppendChar('\f'); break; 2111 case 'n': parent_entry.AppendChar('\n'); break; 2112 case 'r': parent_entry.AppendChar('\r'); break; 2113 case 't': parent_entry.AppendChar('\t'); break; 2114 case 'v': parent_entry.AppendChar('\v'); break; 2115 case '\'': parent_entry.AppendChar('\''); break; 2116 case '\\': parent_entry.AppendChar('\\'); break; 2117 case '0': 2118 // 1 to 3 octal chars 2119 { 2120 // Make a string that can hold onto the initial zero char, 2121 // up to 3 octal digits, and a terminating NULL. 2122 char oct_str[5] = { 0, 0, 0, 0, 0 }; 2123 2124 int i; 2125 for (i=0; (format[i] >= '0' && format[i] <= '7') && i<4; ++i) 2126 oct_str[i] = format[i]; 2127 2128 // We don't want to consume the last octal character since 2129 // the main for loop will do this for us, so we advance p by 2130 // one less than i (even if i is zero) 2131 format = format.drop_front(i); 2132 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 2133 if (octal_value <= UINT8_MAX) 2134 { 2135 parent_entry.AppendChar((char)octal_value); 2136 } 2137 else 2138 { 2139 error.SetErrorString("octal number is larger than a single byte"); 2140 return error; 2141 } 2142 } 2143 break; 2144 2145 case 'x': 2146 // hex number in the format 2147 if (isxdigit(format[0])) 2148 { 2149 // Make a string that can hold onto two hex chars plus a 2150 // NULL terminator 2151 char hex_str[3] = { 0,0,0 }; 2152 hex_str[0] = format[0]; 2153 2154 format = format.drop_front(); 2155 2156 if (isxdigit(format[0])) 2157 { 2158 hex_str[1] = format[0]; 2159 format = format.drop_front(); 2160 } 2161 2162 unsigned long hex_value = strtoul (hex_str, NULL, 16); 2163 if (hex_value <= UINT8_MAX) 2164 { 2165 parent_entry.AppendChar((char)hex_value); 2166 } 2167 else 2168 { 2169 error.SetErrorString("hex number is larger than a single byte"); 2170 return error; 2171 } 2172 } 2173 else 2174 { 2175 parent_entry.AppendChar(desens_char); 2176 } 2177 break; 2178 2179 default: 2180 // Just desensitize any other character by just printing what 2181 // came after the '\' 2182 parent_entry.AppendChar(desens_char); 2183 break; 2184 } 2185 } 2186 break; 2187 2188 case '$': 2189 if (format.size() == 1) 2190 { 2191 // '$' at the end of a format string, just print the '$' 2192 parent_entry.AppendText("$"); 2193 } 2194 else 2195 { 2196 format = format.drop_front(); // Skip the '$' 2197 2198 if (format[0] == '{') 2199 { 2200 format = format.drop_front(); // Skip the '{' 2201 2202 llvm::StringRef variable, variable_format; 2203 error = FormatEntity::ExtractVariableInfo (format, variable, variable_format); 2204 if (error.Fail()) 2205 return error; 2206 bool verify_is_thread_id = false; 2207 Entry entry; 2208 if (!variable_format.empty()) 2209 { 2210 entry.printf_format = std::move(variable_format.str()); 2211 2212 // If the format contains a '%' we are going to assume this is 2213 // a printf style format. So if you want to format your thread ID 2214 // using "0x%llx" you can use: 2215 // ${thread.id%0x%llx} 2216 // 2217 // If there is no '%' in the format, then it is assumed to be a 2218 // LLDB format name, or one of the extended formats specified in 2219 // the switch statement below. 2220 2221 if (entry.printf_format.find('%') == std::string::npos) 2222 { 2223 bool clear_printf = false; 2224 2225 if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(), 2226 false, 2227 entry.fmt)) 2228 { 2229 // We have an LLDB format, so clear the printf format 2230 clear_printf = true; 2231 } 2232 else if (entry.printf_format.size() == 1) 2233 { 2234 switch (entry.printf_format[0]) 2235 { 2236 case '@': // if this is an @ sign, print ObjC description 2237 entry.number = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 2238 clear_printf = true; 2239 break; 2240 case 'V': // if this is a V, print the value using the default format 2241 entry.number = ValueObject::eValueObjectRepresentationStyleValue; 2242 clear_printf = true; 2243 break; 2244 case 'L': // if this is an L, print the location of the value 2245 entry.number = ValueObject::eValueObjectRepresentationStyleLocation; 2246 clear_printf = true; 2247 break; 2248 case 'S': // if this is an S, print the summary after all 2249 entry.number = ValueObject::eValueObjectRepresentationStyleSummary; 2250 clear_printf = true; 2251 break; 2252 case '#': // if this is a '#', print the number of children 2253 entry.number = ValueObject::eValueObjectRepresentationStyleChildrenCount; 2254 clear_printf = true; 2255 break; 2256 case 'T': // if this is a 'T', print the type 2257 entry.number = ValueObject::eValueObjectRepresentationStyleType; 2258 clear_printf = true; 2259 break; 2260 case 'N': // if this is a 'N', print the name 2261 entry.number = ValueObject::eValueObjectRepresentationStyleName; 2262 clear_printf = true; 2263 break; 2264 case '>': // if this is a '>', print the expression path 2265 entry.number = ValueObject::eValueObjectRepresentationStyleExpressionPath; 2266 clear_printf = true; 2267 break; 2268 default: 2269 error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str()); 2270 return error; 2271 } 2272 } 2273 else if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(), 2274 true, 2275 entry.fmt)) 2276 { 2277 clear_printf = true; 2278 } 2279 else if (entry.printf_format == "tid") 2280 { 2281 verify_is_thread_id = true; 2282 } 2283 else 2284 { 2285 error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str()); 2286 return error; 2287 } 2288 2289 // Our format string turned out to not be a printf style format 2290 // so lets clear the string 2291 if (clear_printf) 2292 entry.printf_format.clear(); 2293 } 2294 } 2295 2296 // Check for dereferences 2297 if (variable[0] == '*') 2298 { 2299 entry.deref = true; 2300 variable = variable.drop_front(); 2301 } 2302 2303 error = ParseEntry (variable, &g_root, entry); 2304 if (error.Fail()) 2305 return error; 2306 2307 if (verify_is_thread_id) 2308 { 2309 if (entry.type != Entry::Type::ThreadID && 2310 entry.type != Entry::Type::ThreadProtocolID) 2311 { 2312 error.SetErrorString("the 'tid' format can only be used on ${thread.id} and ${thread.protocol_id}"); 2313 } 2314 } 2315 2316 switch (entry.type) 2317 { 2318 case Entry::Type::Variable: 2319 case Entry::Type::VariableSynthetic: 2320 if (entry.number == 0) 2321 { 2322 if (entry.string.empty()) 2323 entry.number = ValueObject::eValueObjectRepresentationStyleValue; 2324 else 2325 entry.number = ValueObject::eValueObjectRepresentationStyleSummary; 2326 } 2327 break; 2328 default: 2329 // Make sure someone didn't try to dereference anything but ${var} or ${svar} 2330 if (entry.deref) 2331 { 2332 error.SetErrorStringWithFormat("${%s} can't be dereferenced, only ${var} and ${svar} can.", variable.str().c_str()); 2333 return error; 2334 } 2335 } 2336 // Check if this entry just wants to insert a constant string 2337 // value into the parent_entry, if so, insert the string with 2338 // AppendText, else append the entry to the parent_entry. 2339 if (entry.type == Entry::Type::InsertString) 2340 parent_entry.AppendText(entry.string.c_str()); 2341 else 2342 parent_entry.AppendEntry(std::move(entry)); 2343 } 2344 } 2345 break; 2346 } 2347 } 2348 return error; 2349 } 2350 2351 2352 Error 2353 FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format) 2354 { 2355 Error error; 2356 variable_name = llvm::StringRef(); 2357 variable_format = llvm::StringRef(); 2358 2359 const size_t paren_pos = format_str.find_first_of('}'); 2360 if (paren_pos != llvm::StringRef::npos) 2361 { 2362 const size_t percent_pos = format_str.find_first_of('%'); 2363 if (percent_pos < paren_pos) 2364 { 2365 if (percent_pos > 0) 2366 { 2367 if (percent_pos > 1) 2368 variable_name = format_str.substr(0, percent_pos); 2369 variable_format = format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); 2370 } 2371 } 2372 else 2373 { 2374 variable_name = format_str.substr(0, paren_pos); 2375 } 2376 // Strip off elements and the formatting and the trailing '}' 2377 format_str = format_str.substr(paren_pos + 1); 2378 } 2379 else 2380 { 2381 error.SetErrorStringWithFormat("missing terminating '}' character for '${%s'", format_str.str().c_str()); 2382 } 2383 return error; 2384 } 2385 2386 bool 2387 FormatEntity::FormatFileSpec (const FileSpec &file_spec, Stream &s, llvm::StringRef variable_name, llvm::StringRef variable_format) 2388 { 2389 if (variable_name.empty() || variable_name.equals(".fullpath")) 2390 { 2391 file_spec.Dump(&s); 2392 return true; 2393 } 2394 else if (variable_name.equals(".basename")) 2395 { 2396 s.PutCString(file_spec.GetFilename().AsCString("")); 2397 return true; 2398 } 2399 else if (variable_name.equals(".dirname")) 2400 { 2401 s.PutCString(file_spec.GetFilename().AsCString("")); 2402 return true; 2403 } 2404 return false; 2405 } 2406 2407 static std::string 2408 MakeMatch (const llvm::StringRef &prefix, const char *suffix) 2409 { 2410 std::string match(prefix.str()); 2411 match.append(suffix); 2412 return std::move(match); 2413 } 2414 2415 static void 2416 AddMatches (const FormatEntity::Entry::Definition *def, 2417 const llvm::StringRef &prefix, 2418 const llvm::StringRef &match_prefix, 2419 StringList &matches) 2420 { 2421 const size_t n = def->num_children; 2422 if (n > 0) 2423 { 2424 for (size_t i=0; i<n; ++i) 2425 { 2426 std::string match = std::move(prefix.str()); 2427 if (match_prefix.empty()) 2428 matches.AppendString(MakeMatch (prefix, def->children[i].name)); 2429 else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0) 2430 matches.AppendString(MakeMatch (prefix, def->children[i].name + match_prefix.size())); 2431 } 2432 } 2433 } 2434 size_t 2435 FormatEntity::AutoComplete (const char *s, 2436 int match_start_point, 2437 int max_return_elements, 2438 bool &word_complete, 2439 StringList &matches) 2440 { 2441 word_complete = false; 2442 llvm::StringRef str(s + match_start_point); 2443 matches.Clear(); 2444 2445 const size_t dollar_pos = str.rfind('$'); 2446 if (dollar_pos != llvm::StringRef::npos) 2447 { 2448 // Hitting TAB after $ at the end of the string add a "{" 2449 if (dollar_pos == str.size() - 1) 2450 { 2451 std::string match = std::move(str.str()); 2452 match.append("{"); 2453 matches.AppendString(std::move(match)); 2454 } 2455 else if (str[dollar_pos + 1] == '{') 2456 { 2457 const size_t close_pos = str.find('}', dollar_pos + 2); 2458 if (close_pos == llvm::StringRef::npos) 2459 { 2460 const size_t format_pos = str.find('%', dollar_pos + 2); 2461 if (format_pos == llvm::StringRef::npos) 2462 { 2463 llvm::StringRef partial_variable (str.substr(dollar_pos + 2)); 2464 if (partial_variable.empty()) 2465 { 2466 // Suggest all top level entites as we are just past "${" 2467 AddMatches(&g_root, str, llvm::StringRef(), matches); 2468 } 2469 else 2470 { 2471 // We have a partially specified variable, find it 2472 llvm::StringRef remainder; 2473 const FormatEntity::Entry::Definition* entry_def = FindEntry (partial_variable, &g_root, remainder); 2474 if (entry_def) 2475 { 2476 const size_t n = entry_def->num_children; 2477 2478 if (remainder.empty()) 2479 { 2480 // Exact match 2481 if (n > 0) 2482 { 2483 // "${thread.info" <TAB> 2484 matches.AppendString(std::move(MakeMatch (str, "."))); 2485 } 2486 else 2487 { 2488 // "${thread.id" <TAB> 2489 matches.AppendString(std::move(MakeMatch (str, "}"))); 2490 word_complete = true; 2491 } 2492 } 2493 else if (remainder.equals(".")) 2494 { 2495 // "${thread." <TAB> 2496 AddMatches(entry_def, str, llvm::StringRef(), matches); 2497 } 2498 else 2499 { 2500 // We have a partial match 2501 // "${thre" <TAB> 2502 AddMatches(entry_def, str, remainder, matches); 2503 } 2504 } 2505 } 2506 } 2507 } 2508 } 2509 } 2510 return matches.GetSize(); 2511 } 2512