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