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