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