1 // Copyright 2013 ARM Limited 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND ANY 17 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, 20 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 22 // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifdef USE_SIMULATOR 28 29 #include "a64/debugger-a64.h" 30 31 namespace vixl { 32 33 // List of commands supported by the debugger. 34 #define DEBUG_COMMAND_LIST(C) \ 35 C(HelpCommand) \ 36 C(ContinueCommand) \ 37 C(StepCommand) \ 38 C(DisasmCommand) \ 39 C(PrintCommand) \ 40 C(ExamineCommand) 41 42 // Debugger command lines are broken up in token of different type to make 43 // processing easier later on. 44 class Token { 45 public: 46 virtual ~Token() {} 47 48 // Token type. 49 virtual bool IsRegister() const { return false; } 50 virtual bool IsFPRegister() const { return false; } 51 virtual bool IsIdentifier() const { return false; } 52 virtual bool IsAddress() const { return false; } 53 virtual bool IsInteger() const { return false; } 54 virtual bool IsFormat() const { return false; } 55 virtual bool IsUnknown() const { return false; } 56 // Token properties. 57 virtual bool CanAddressMemory() const { return false; } 58 virtual uint8_t* ToAddress(Debugger* debugger) const; 59 virtual void Print(FILE* out = stdout) const = 0; 60 61 static Token* Tokenize(const char* arg); 62 }; 63 64 // Tokens often hold one value. 65 template<typename T> class ValueToken : public Token { 66 public: 67 explicit ValueToken(T value) : value_(value) {} 68 ValueToken() {} 69 70 T value() const { return value_; } 71 72 protected: 73 T value_; 74 }; 75 76 // Integer registers (X or W) and their aliases. 77 // Format: wn or xn with 0 <= n < 32 or a name in the aliases list. 78 class RegisterToken : public ValueToken<const Register> { 79 public: 80 explicit RegisterToken(const Register reg) 81 : ValueToken<const Register>(reg) {} 82 83 virtual bool IsRegister() const { return true; } 84 virtual bool CanAddressMemory() const { return value().Is64Bits(); } 85 virtual uint8_t* ToAddress(Debugger* debugger) const; 86 virtual void Print(FILE* out = stdout) const ; 87 const char* Name() const; 88 89 static Token* Tokenize(const char* arg); 90 static RegisterToken* Cast(Token* tok) { 91 VIXL_ASSERT(tok->IsRegister()); 92 return reinterpret_cast<RegisterToken*>(tok); 93 } 94 95 private: 96 static const int kMaxAliasNumber = 4; 97 static const char* kXAliases[kNumberOfRegisters][kMaxAliasNumber]; 98 static const char* kWAliases[kNumberOfRegisters][kMaxAliasNumber]; 99 }; 100 101 // Floating point registers (D or S). 102 // Format: sn or dn with 0 <= n < 32. 103 class FPRegisterToken : public ValueToken<const FPRegister> { 104 public: 105 explicit FPRegisterToken(const FPRegister fpreg) 106 : ValueToken<const FPRegister>(fpreg) {} 107 108 virtual bool IsFPRegister() const { return true; } 109 virtual void Print(FILE* out = stdout) const ; 110 111 static Token* Tokenize(const char* arg); 112 static FPRegisterToken* Cast(Token* tok) { 113 VIXL_ASSERT(tok->IsFPRegister()); 114 return reinterpret_cast<FPRegisterToken*>(tok); 115 } 116 }; 117 118 119 // Non-register identifiers. 120 // Format: Alphanumeric string starting with a letter. 121 class IdentifierToken : public ValueToken<char*> { 122 public: 123 explicit IdentifierToken(const char* name) { 124 int size = strlen(name) + 1; 125 value_ = new char[size]; 126 strncpy(value_, name, size); 127 } 128 virtual ~IdentifierToken() { delete[] value_; } 129 130 virtual bool IsIdentifier() const { return true; } 131 virtual bool CanAddressMemory() const { return strcmp(value(), "pc") == 0; } 132 virtual uint8_t* ToAddress(Debugger* debugger) const; 133 virtual void Print(FILE* out = stdout) const; 134 135 static Token* Tokenize(const char* arg); 136 static IdentifierToken* Cast(Token* tok) { 137 VIXL_ASSERT(tok->IsIdentifier()); 138 return reinterpret_cast<IdentifierToken*>(tok); 139 } 140 }; 141 142 // 64-bit address literal. 143 // Format: 0x... with up to 16 hexadecimal digits. 144 class AddressToken : public ValueToken<uint8_t*> { 145 public: 146 explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {} 147 148 virtual bool IsAddress() const { return true; } 149 virtual bool CanAddressMemory() const { return true; } 150 virtual uint8_t* ToAddress(Debugger* debugger) const; 151 virtual void Print(FILE* out = stdout) const ; 152 153 static Token* Tokenize(const char* arg); 154 static AddressToken* Cast(Token* tok) { 155 VIXL_ASSERT(tok->IsAddress()); 156 return reinterpret_cast<AddressToken*>(tok); 157 } 158 }; 159 160 161 // 64-bit decimal integer literal. 162 // Format: n. 163 class IntegerToken : public ValueToken<int64_t> { 164 public: 165 explicit IntegerToken(int value) : ValueToken<int64_t>(value) {} 166 167 virtual bool IsInteger() const { return true; } 168 virtual void Print(FILE* out = stdout) const; 169 170 static Token* Tokenize(const char* arg); 171 static IntegerToken* Cast(Token* tok) { 172 VIXL_ASSERT(tok->IsInteger()); 173 return reinterpret_cast<IntegerToken*>(tok); 174 } 175 }; 176 177 // Literal describing how to print a chunk of data (up to 64 bits). 178 // Format: .ln 179 // where l (letter) is one of 180 // * x: hexadecimal 181 // * s: signed integer 182 // * u: unsigned integer 183 // * f: floating point 184 // * i: instruction 185 // and n (size) is one of 8, 16, 32 and 64. n should be omitted for 186 // instructions. 187 class FormatToken : public Token { 188 public: 189 FormatToken() {} 190 191 virtual bool IsFormat() const { return true; } 192 virtual int SizeOf() const = 0; 193 virtual char type_code() const = 0; 194 virtual void PrintData(void* data, FILE* out = stdout) const = 0; 195 virtual void Print(FILE* out = stdout) const = 0; 196 197 static Token* Tokenize(const char* arg); 198 static FormatToken* Cast(Token* tok) { 199 VIXL_ASSERT(tok->IsFormat()); 200 return reinterpret_cast<FormatToken*>(tok); 201 } 202 }; 203 204 205 template<typename T> class Format : public FormatToken { 206 public: 207 Format(const char* fmt, char type_code) : fmt_(fmt), type_code_(type_code) {} 208 209 virtual int SizeOf() const { return sizeof(T); } 210 virtual char type_code() const { return type_code_; } 211 virtual void PrintData(void* data, FILE* out = stdout) const { 212 T value; 213 memcpy(&value, data, sizeof(value)); 214 fprintf(out, fmt_, value); 215 } 216 virtual void Print(FILE* out = stdout) const; 217 218 private: 219 const char* fmt_; 220 char type_code_; 221 }; 222 223 // Tokens which don't fit any of the above. 224 class UnknownToken : public Token { 225 public: 226 explicit UnknownToken(const char* arg) { 227 int size = strlen(arg) + 1; 228 unknown_ = new char[size]; 229 strncpy(unknown_, arg, size); 230 } 231 virtual ~UnknownToken() { delete[] unknown_; } 232 233 virtual bool IsUnknown() const { return true; } 234 virtual void Print(FILE* out = stdout) const; 235 236 private: 237 char* unknown_; 238 }; 239 240 241 // All debugger commands must subclass DebugCommand and implement Run, Print 242 // and Build. Commands must also define kHelp and kAliases. 243 class DebugCommand { 244 public: 245 explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {} 246 DebugCommand() : name_(NULL) {} 247 virtual ~DebugCommand() { delete name_; } 248 249 const char* name() { return name_->value(); } 250 // Run the command on the given debugger. The command returns true if 251 // execution should move to the next instruction. 252 virtual bool Run(Debugger * debugger) = 0; 253 virtual void Print(FILE* out = stdout); 254 255 static bool Match(const char* name, const char** aliases); 256 static DebugCommand* Parse(char* line); 257 static void PrintHelp(const char** aliases, 258 const char* args, 259 const char* help); 260 261 private: 262 IdentifierToken* name_; 263 }; 264 265 // For all commands below see their respective kHelp and kAliases in 266 // debugger-a64.cc 267 class HelpCommand : public DebugCommand { 268 public: 269 explicit HelpCommand(Token* name) : DebugCommand(name) {} 270 271 virtual bool Run(Debugger* debugger); 272 273 static DebugCommand* Build(std::vector<Token*> args); 274 275 static const char* kHelp; 276 static const char* kAliases[]; 277 static const char* kArguments; 278 }; 279 280 281 class ContinueCommand : public DebugCommand { 282 public: 283 explicit ContinueCommand(Token* name) : DebugCommand(name) {} 284 285 virtual bool Run(Debugger* debugger); 286 287 static DebugCommand* Build(std::vector<Token*> args); 288 289 static const char* kHelp; 290 static const char* kAliases[]; 291 static const char* kArguments; 292 }; 293 294 295 class StepCommand : public DebugCommand { 296 public: 297 StepCommand(Token* name, IntegerToken* count) 298 : DebugCommand(name), count_(count) {} 299 virtual ~StepCommand() { delete count_; } 300 301 int64_t count() { return count_->value(); } 302 virtual bool Run(Debugger* debugger); 303 virtual void Print(FILE* out = stdout); 304 305 static DebugCommand* Build(std::vector<Token*> args); 306 307 static const char* kHelp; 308 static const char* kAliases[]; 309 static const char* kArguments; 310 311 private: 312 IntegerToken* count_; 313 }; 314 315 class DisasmCommand : public DebugCommand { 316 public: 317 static DebugCommand* Build(std::vector<Token*> args); 318 319 static const char* kHelp; 320 static const char* kAliases[]; 321 static const char* kArguments; 322 }; 323 324 325 class PrintCommand : public DebugCommand { 326 public: 327 PrintCommand(Token* name, Token* target, FormatToken* format) 328 : DebugCommand(name), target_(target), format_(format) {} 329 virtual ~PrintCommand() { 330 delete target_; 331 delete format_; 332 } 333 334 Token* target() { return target_; } 335 FormatToken* format() { return format_; } 336 virtual bool Run(Debugger* debugger); 337 virtual void Print(FILE* out = stdout); 338 339 static DebugCommand* Build(std::vector<Token*> args); 340 341 static const char* kHelp; 342 static const char* kAliases[]; 343 static const char* kArguments; 344 345 private: 346 Token* target_; 347 FormatToken* format_; 348 }; 349 350 class ExamineCommand : public DebugCommand { 351 public: 352 ExamineCommand(Token* name, 353 Token* target, 354 FormatToken* format, 355 IntegerToken* count) 356 : DebugCommand(name), target_(target), format_(format), count_(count) {} 357 virtual ~ExamineCommand() { 358 delete target_; 359 delete format_; 360 delete count_; 361 } 362 363 Token* target() { return target_; } 364 FormatToken* format() { return format_; } 365 IntegerToken* count() { return count_; } 366 virtual bool Run(Debugger* debugger); 367 virtual void Print(FILE* out = stdout); 368 369 static DebugCommand* Build(std::vector<Token*> args); 370 371 static const char* kHelp; 372 static const char* kAliases[]; 373 static const char* kArguments; 374 375 private: 376 Token* target_; 377 FormatToken* format_; 378 IntegerToken* count_; 379 }; 380 381 // Commands which name does not match any of the known commnand. 382 class UnknownCommand : public DebugCommand { 383 public: 384 explicit UnknownCommand(std::vector<Token*> args) : args_(args) {} 385 virtual ~UnknownCommand(); 386 387 virtual bool Run(Debugger* debugger); 388 389 private: 390 std::vector<Token*> args_; 391 }; 392 393 // Commands which name match a known command but the syntax is invalid. 394 class InvalidCommand : public DebugCommand { 395 public: 396 InvalidCommand(std::vector<Token*> args, int index, const char* cause) 397 : args_(args), index_(index), cause_(cause) {} 398 virtual ~InvalidCommand(); 399 400 virtual bool Run(Debugger* debugger); 401 402 private: 403 std::vector<Token*> args_; 404 int index_; 405 const char* cause_; 406 }; 407 408 const char* HelpCommand::kAliases[] = { "help", NULL }; 409 const char* HelpCommand::kArguments = NULL; 410 const char* HelpCommand::kHelp = " Print this help."; 411 412 const char* ContinueCommand::kAliases[] = { "continue", "c", NULL }; 413 const char* ContinueCommand::kArguments = NULL; 414 const char* ContinueCommand::kHelp = " Resume execution."; 415 416 const char* StepCommand::kAliases[] = { "stepi", "si", NULL }; 417 const char* StepCommand::kArguments = "[n = 1]"; 418 const char* StepCommand::kHelp = " Execute n next instruction(s)."; 419 420 const char* DisasmCommand::kAliases[] = { "disasm", "di", NULL }; 421 const char* DisasmCommand::kArguments = "[n = 10]"; 422 const char* DisasmCommand::kHelp = 423 " Disassemble n instruction(s) at pc.\n" 424 " This command is equivalent to x pc.i [n = 10]." 425 ; 426 427 const char* PrintCommand::kAliases[] = { "print", "p", NULL }; 428 const char* PrintCommand::kArguments = "<entity>[.format]"; 429 const char* PrintCommand::kHelp = 430 " Print the given entity according to the given format.\n" 431 " The format parameter only affects individual registers; it is ignored\n" 432 " for other entities.\n" 433 " <entity> can be one of the following:\n" 434 " * A register name (such as x0, s1, ...).\n" 435 " * 'regs', to print all integer (W and X) registers.\n" 436 " * 'fpregs' to print all floating-point (S and D) registers.\n" 437 " * 'sysregs' to print all system registers (including NZCV).\n" 438 " * 'pc' to print the current program counter.\n" 439 ; 440 441 const char* ExamineCommand::kAliases[] = { "m", "mem", "x", NULL }; 442 const char* ExamineCommand::kArguments = "<addr>[.format] [n = 10]"; 443 const char* ExamineCommand::kHelp = 444 " Examine memory. Print n items of memory at address <addr> according to\n" 445 " the given [.format].\n" 446 " Addr can be an immediate address, a register name or pc.\n" 447 " Format is made of a type letter: 'x' (hexadecimal), 's' (signed), 'u'\n" 448 " (unsigned), 'f' (floating point), i (instruction) and a size in bits\n" 449 " when appropriate (8, 16, 32, 64)\n" 450 " E.g 'x sp.x64' will print 10 64-bit words from the stack in\n" 451 " hexadecimal format." 452 ; 453 454 const char* RegisterToken::kXAliases[kNumberOfRegisters][kMaxAliasNumber] = { 455 { "x0", NULL }, 456 { "x1", NULL }, 457 { "x2", NULL }, 458 { "x3", NULL }, 459 { "x4", NULL }, 460 { "x5", NULL }, 461 { "x6", NULL }, 462 { "x7", NULL }, 463 { "x8", NULL }, 464 { "x9", NULL }, 465 { "x10", NULL }, 466 { "x11", NULL }, 467 { "x12", NULL }, 468 { "x13", NULL }, 469 { "x14", NULL }, 470 { "x15", NULL }, 471 { "ip0", "x16", NULL }, 472 { "ip1", "x17", NULL }, 473 { "x18", "pr", NULL }, 474 { "x19", NULL }, 475 { "x20", NULL }, 476 { "x21", NULL }, 477 { "x22", NULL }, 478 { "x23", NULL }, 479 { "x24", NULL }, 480 { "x25", NULL }, 481 { "x26", NULL }, 482 { "x27", NULL }, 483 { "x28", NULL }, 484 { "fp", "x29", NULL }, 485 { "lr", "x30", NULL }, 486 { "sp", NULL} 487 }; 488 489 const char* RegisterToken::kWAliases[kNumberOfRegisters][kMaxAliasNumber] = { 490 { "w0", NULL }, 491 { "w1", NULL }, 492 { "w2", NULL }, 493 { "w3", NULL }, 494 { "w4", NULL }, 495 { "w5", NULL }, 496 { "w6", NULL }, 497 { "w7", NULL }, 498 { "w8", NULL }, 499 { "w9", NULL }, 500 { "w10", NULL }, 501 { "w11", NULL }, 502 { "w12", NULL }, 503 { "w13", NULL }, 504 { "w14", NULL }, 505 { "w15", NULL }, 506 { "w16", NULL }, 507 { "w17", NULL }, 508 { "w18", NULL }, 509 { "w19", NULL }, 510 { "w20", NULL }, 511 { "w21", NULL }, 512 { "w22", NULL }, 513 { "w23", NULL }, 514 { "w24", NULL }, 515 { "w25", NULL }, 516 { "w26", NULL }, 517 { "w27", NULL }, 518 { "w28", NULL }, 519 { "w29", NULL }, 520 { "w30", NULL }, 521 { "wsp", NULL } 522 }; 523 524 525 Debugger::Debugger(Decoder* decoder, FILE* stream) 526 : Simulator(decoder, stream), 527 log_parameters_(0), 528 debug_parameters_(0), 529 pending_request_(false), 530 steps_(0), 531 last_command_(NULL) { 532 disasm_ = new PrintDisassembler(stdout); 533 printer_ = new Decoder(); 534 printer_->AppendVisitor(disasm_); 535 } 536 537 538 void Debugger::Run() { 539 pc_modified_ = false; 540 while (pc_ != kEndOfSimAddress) { 541 if (pending_request()) { 542 LogProcessorState(); 543 RunDebuggerShell(); 544 } 545 546 ExecuteInstruction(); 547 } 548 } 549 550 551 void Debugger::PrintInstructions(void* address, int64_t count) { 552 if (count == 0) { 553 return; 554 } 555 556 Instruction* from = Instruction::Cast(address); 557 if (count < 0) { 558 count = -count; 559 from -= (count - 1) * kInstructionSize; 560 } 561 Instruction* to = from + count * kInstructionSize; 562 563 for (Instruction* current = from; 564 current < to; 565 current = current->NextInstruction()) { 566 printer_->Decode(current); 567 } 568 } 569 570 571 void Debugger::PrintMemory(const uint8_t* address, 572 const FormatToken* format, 573 int64_t count) { 574 if (count == 0) { 575 return; 576 } 577 578 const uint8_t* from = address; 579 int size = format->SizeOf(); 580 if (count < 0) { 581 count = -count; 582 from -= (count - 1) * size; 583 } 584 const uint8_t* to = from + count * size; 585 586 for (const uint8_t* current = from; current < to; current += size) { 587 if (((current - from) % 8) == 0) { 588 printf("\n%p: ", current); 589 } 590 591 uint64_t data = MemoryRead(current, size); 592 format->PrintData(&data); 593 printf(" "); 594 } 595 printf("\n\n"); 596 } 597 598 599 void Debugger::PrintRegister(const Register& target_reg, 600 const char* name, 601 const FormatToken* format) { 602 const uint64_t reg_size = target_reg.SizeInBits(); 603 const uint64_t format_size = format->SizeOf() * 8; 604 const uint64_t count = reg_size / format_size; 605 const uint64_t mask = UINT64_C(0xffffffffffffffff) >> (64 - format_size); 606 const uint64_t reg_value = reg<uint64_t>(reg_size, 607 target_reg.code(), 608 Reg31IsStackPointer); 609 VIXL_ASSERT(count > 0); 610 611 printf("%s = ", name); 612 for (uint64_t i = 1; i <= count; i++) { 613 uint64_t data = reg_value >> (reg_size - (i * format_size)); 614 data &= mask; 615 format->PrintData(&data); 616 printf(" "); 617 } 618 printf("\n"); 619 } 620 621 622 void Debugger::PrintFPRegister(const FPRegister& target_fpreg, 623 const FormatToken* format) { 624 const uint64_t fpreg_size = target_fpreg.SizeInBits(); 625 const uint64_t format_size = format->SizeOf() * 8; 626 const uint64_t count = fpreg_size / format_size; 627 const uint64_t mask = UINT64_C(0xffffffffffffffff) >> (64 - format_size); 628 const uint64_t fpreg_value = fpreg<uint64_t>(fpreg_size, 629 target_fpreg.code()); 630 VIXL_ASSERT(count > 0); 631 632 if (target_fpreg.Is32Bits()) { 633 printf("s%u = ", target_fpreg.code()); 634 } else { 635 printf("d%u = ", target_fpreg.code()); 636 } 637 for (uint64_t i = 1; i <= count; i++) { 638 uint64_t data = fpreg_value >> (fpreg_size - (i * format_size)); 639 data &= mask; 640 format->PrintData(&data); 641 printf(" "); 642 } 643 printf("\n"); 644 } 645 646 647 void Debugger::VisitException(Instruction* instr) { 648 switch (instr->Mask(ExceptionMask)) { 649 case BRK: 650 DoBreakpoint(instr); 651 return; 652 case HLT: 653 switch (instr->ImmException()) { 654 case kUnreachableOpcode: 655 DoUnreachable(instr); 656 return; 657 case kTraceOpcode: 658 DoTrace(instr); 659 return; 660 case kLogOpcode: 661 DoLog(instr); 662 return; 663 } 664 // Fall through 665 default: Simulator::VisitException(instr); 666 } 667 } 668 669 670 void Debugger::LogSystemRegisters() { 671 if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters(); 672 } 673 674 675 void Debugger::LogRegisters() { 676 if (log_parameters_ & LOG_REGS) PrintRegisters(); 677 } 678 679 680 void Debugger::LogFPRegisters() { 681 if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters(); 682 } 683 684 685 void Debugger::LogProcessorState() { 686 LogSystemRegisters(); 687 LogRegisters(); 688 LogFPRegisters(); 689 } 690 691 692 // Read a command. A command will be at most kMaxDebugShellLine char long and 693 // ends with '\n\0'. 694 // TODO: Should this be a utility function? 695 char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) { 696 int fgets_calls = 0; 697 char* end = NULL; 698 699 printf("%s", prompt); 700 fflush(stdout); 701 702 do { 703 if (fgets(buffer, length, stdin) == NULL) { 704 printf(" ** Error while reading command. **\n"); 705 return NULL; 706 } 707 708 fgets_calls++; 709 end = strchr(buffer, '\n'); 710 } while (end == NULL); 711 712 if (fgets_calls != 1) { 713 printf(" ** Command too long. **\n"); 714 return NULL; 715 } 716 717 // Remove the newline from the end of the command. 718 VIXL_ASSERT(end[1] == '\0'); 719 VIXL_ASSERT((end - buffer) < (length - 1)); 720 end[0] = '\0'; 721 722 return buffer; 723 } 724 725 726 void Debugger::RunDebuggerShell() { 727 if (IsDebuggerRunning()) { 728 if (steps_ > 0) { 729 // Finish stepping first. 730 --steps_; 731 return; 732 } 733 734 printf("Next: "); 735 PrintInstructions(pc()); 736 bool done = false; 737 while (!done) { 738 char buffer[kMaxDebugShellLine]; 739 char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine); 740 741 if (line == NULL) continue; // An error occurred. 742 743 DebugCommand* command = DebugCommand::Parse(line); 744 if (command != NULL) { 745 last_command_ = command; 746 } 747 748 if (last_command_ != NULL) { 749 done = last_command_->Run(this); 750 } else { 751 printf("No previous command to run!\n"); 752 } 753 } 754 755 if ((debug_parameters_ & DBG_BREAK) != 0) { 756 // The break request has now been handled, move to next instruction. 757 debug_parameters_ &= ~DBG_BREAK; 758 increment_pc(); 759 } 760 } 761 } 762 763 764 void Debugger::DoBreakpoint(Instruction* instr) { 765 VIXL_ASSERT(instr->Mask(ExceptionMask) == BRK); 766 767 printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<void*>(instr)); 768 set_debug_parameters(debug_parameters() | DBG_BREAK | DBG_ACTIVE); 769 // Make the shell point to the brk instruction. 770 set_pc(instr); 771 } 772 773 774 void Debugger::DoUnreachable(Instruction* instr) { 775 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && 776 (instr->ImmException() == kUnreachableOpcode)); 777 778 fprintf(stream_, "Hit UNREACHABLE marker at pc=%p.\n", 779 reinterpret_cast<void*>(instr)); 780 abort(); 781 } 782 783 784 void Debugger::DoTrace(Instruction* instr) { 785 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && 786 (instr->ImmException() == kTraceOpcode)); 787 788 // Read the arguments encoded inline in the instruction stream. 789 uint32_t parameters; 790 uint32_t command; 791 792 VIXL_STATIC_ASSERT(sizeof(*instr) == 1); 793 memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters)); 794 memcpy(&command, instr + kTraceCommandOffset, sizeof(command)); 795 796 switch (command) { 797 case TRACE_ENABLE: 798 set_log_parameters(log_parameters() | parameters); 799 break; 800 case TRACE_DISABLE: 801 set_log_parameters(log_parameters() & ~parameters); 802 break; 803 default: 804 VIXL_UNREACHABLE(); 805 } 806 807 set_pc(instr->InstructionAtOffset(kTraceLength)); 808 } 809 810 811 void Debugger::DoLog(Instruction* instr) { 812 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && 813 (instr->ImmException() == kLogOpcode)); 814 815 // Read the arguments encoded inline in the instruction stream. 816 uint32_t parameters; 817 818 VIXL_STATIC_ASSERT(sizeof(*instr) == 1); 819 memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters)); 820 821 // We don't support a one-shot LOG_DISASM. 822 VIXL_ASSERT((parameters & LOG_DISASM) == 0); 823 // Print the requested information. 824 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true); 825 if (parameters & LOG_REGS) PrintRegisters(true); 826 if (parameters & LOG_FP_REGS) PrintFPRegisters(true); 827 828 set_pc(instr->InstructionAtOffset(kLogLength)); 829 } 830 831 832 static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) { 833 char* endptr = NULL; 834 errno = 0; // Reset errors. 835 uint64_t parsed = strtoul(line, &endptr, base); 836 837 if (errno == ERANGE) { 838 // Overflow. 839 return false; 840 } 841 842 if (endptr == line) { 843 // No digits were parsed. 844 return false; 845 } 846 847 if (*endptr != '\0') { 848 // Non-digit characters present at the end. 849 return false; 850 } 851 852 *value = parsed; 853 return true; 854 } 855 856 857 static bool StringToInt64(int64_t* value, const char* line, int base = 10) { 858 char* endptr = NULL; 859 errno = 0; // Reset errors. 860 int64_t parsed = strtol(line, &endptr, base); 861 862 if (errno == ERANGE) { 863 // Overflow, undeflow. 864 return false; 865 } 866 867 if (endptr == line) { 868 // No digits were parsed. 869 return false; 870 } 871 872 if (*endptr != '\0') { 873 // Non-digit characters present at the end. 874 return false; 875 } 876 877 *value = parsed; 878 return true; 879 } 880 881 882 uint8_t* Token::ToAddress(Debugger* debugger) const { 883 USE(debugger); 884 VIXL_UNREACHABLE(); 885 return NULL; 886 } 887 888 889 Token* Token::Tokenize(const char* arg) { 890 if ((arg == NULL) || (*arg == '\0')) { 891 return NULL; 892 } 893 894 // The order is important. For example Identifier::Tokenize would consider 895 // any register to be a valid identifier. 896 897 Token* token = RegisterToken::Tokenize(arg); 898 if (token != NULL) { 899 return token; 900 } 901 902 token = FPRegisterToken::Tokenize(arg); 903 if (token != NULL) { 904 return token; 905 } 906 907 token = IdentifierToken::Tokenize(arg); 908 if (token != NULL) { 909 return token; 910 } 911 912 token = AddressToken::Tokenize(arg); 913 if (token != NULL) { 914 return token; 915 } 916 917 token = IntegerToken::Tokenize(arg); 918 if (token != NULL) { 919 return token; 920 } 921 922 return new UnknownToken(arg); 923 } 924 925 926 uint8_t* RegisterToken::ToAddress(Debugger* debugger) const { 927 VIXL_ASSERT(CanAddressMemory()); 928 uint64_t reg_value = debugger->xreg(value().code(), Reg31IsStackPointer); 929 uint8_t* address = NULL; 930 memcpy(&address, ®_value, sizeof(address)); 931 return address; 932 } 933 934 935 void RegisterToken::Print(FILE* out) const { 936 VIXL_ASSERT(value().IsValid()); 937 fprintf(out, "[Register %s]", Name()); 938 } 939 940 941 const char* RegisterToken::Name() const { 942 if (value().Is32Bits()) { 943 return kWAliases[value().code()][0]; 944 } else { 945 return kXAliases[value().code()][0]; 946 } 947 } 948 949 950 Token* RegisterToken::Tokenize(const char* arg) { 951 for (unsigned i = 0; i < kNumberOfRegisters; i++) { 952 // Is it a X register or alias? 953 for (const char** current = kXAliases[i]; *current != NULL; current++) { 954 if (strcmp(arg, *current) == 0) { 955 return new RegisterToken(Register::XRegFromCode(i)); 956 } 957 } 958 959 // Is it a W register or alias? 960 for (const char** current = kWAliases[i]; *current != NULL; current++) { 961 if (strcmp(arg, *current) == 0) { 962 return new RegisterToken(Register::WRegFromCode(i)); 963 } 964 } 965 } 966 967 return NULL; 968 } 969 970 971 void FPRegisterToken::Print(FILE* out) const { 972 VIXL_ASSERT(value().IsValid()); 973 char prefix = value().Is32Bits() ? 's' : 'd'; 974 fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().code()); 975 } 976 977 978 Token* FPRegisterToken::Tokenize(const char* arg) { 979 if (strlen(arg) < 2) { 980 return NULL; 981 } 982 983 switch (*arg) { 984 case 's': 985 case 'd': 986 const char* cursor = arg + 1; 987 uint64_t code = 0; 988 if (!StringToUInt64(&code, cursor)) { 989 return NULL; 990 } 991 992 if (code > kNumberOfFPRegisters) { 993 return NULL; 994 } 995 996 FPRegister fpreg = NoFPReg; 997 switch (*arg) { 998 case 's': fpreg = FPRegister::SRegFromCode(code); break; 999 case 'd': fpreg = FPRegister::DRegFromCode(code); break; 1000 default: VIXL_UNREACHABLE(); 1001 } 1002 1003 return new FPRegisterToken(fpreg); 1004 } 1005 1006 return NULL; 1007 } 1008 1009 1010 uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const { 1011 VIXL_ASSERT(CanAddressMemory()); 1012 Instruction* pc_value = debugger->pc(); 1013 uint8_t* address = NULL; 1014 memcpy(&address, &pc_value, sizeof(address)); 1015 return address; 1016 } 1017 1018 void IdentifierToken::Print(FILE* out) const { 1019 fprintf(out, "[Identifier %s]", value()); 1020 } 1021 1022 1023 Token* IdentifierToken::Tokenize(const char* arg) { 1024 if (!isalpha(arg[0])) { 1025 return NULL; 1026 } 1027 1028 const char* cursor = arg + 1; 1029 while ((*cursor != '\0') && isalnum(*cursor)) { 1030 ++cursor; 1031 } 1032 1033 if (*cursor == '\0') { 1034 return new IdentifierToken(arg); 1035 } 1036 1037 return NULL; 1038 } 1039 1040 1041 uint8_t* AddressToken::ToAddress(Debugger* debugger) const { 1042 USE(debugger); 1043 return value(); 1044 } 1045 1046 1047 void AddressToken::Print(FILE* out) const { 1048 fprintf(out, "[Address %p]", value()); 1049 } 1050 1051 1052 Token* AddressToken::Tokenize(const char* arg) { 1053 if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) { 1054 return NULL; 1055 } 1056 1057 uint64_t ptr = 0; 1058 if (!StringToUInt64(&ptr, arg, 16)) { 1059 return NULL; 1060 } 1061 1062 uint8_t* address = reinterpret_cast<uint8_t*>(ptr); 1063 return new AddressToken(address); 1064 } 1065 1066 1067 void IntegerToken::Print(FILE* out) const { 1068 fprintf(out, "[Integer %" PRId64 "]", value()); 1069 } 1070 1071 1072 Token* IntegerToken::Tokenize(const char* arg) { 1073 int64_t value = 0; 1074 if (!StringToInt64(&value, arg)) { 1075 return NULL; 1076 } 1077 1078 return new IntegerToken(value); 1079 } 1080 1081 1082 Token* FormatToken::Tokenize(const char* arg) { 1083 int length = strlen(arg); 1084 switch (arg[0]) { 1085 case 'x': 1086 case 's': 1087 case 'u': 1088 case 'f': 1089 if (length == 1) return NULL; 1090 break; 1091 case 'i': 1092 if (length == 1) return new Format<uint32_t>("%08" PRIx32, 'i'); 1093 default: return NULL; 1094 } 1095 1096 char* endptr = NULL; 1097 errno = 0; // Reset errors. 1098 uint64_t count = strtoul(arg + 1, &endptr, 10); 1099 1100 if (errno != 0) { 1101 // Overflow, etc. 1102 return NULL; 1103 } 1104 1105 if (endptr == arg) { 1106 // No digits were parsed. 1107 return NULL; 1108 } 1109 1110 if (*endptr != '\0') { 1111 // There are unexpected (non-digit) characters after the number. 1112 return NULL; 1113 } 1114 1115 switch (arg[0]) { 1116 case 'x': 1117 switch (count) { 1118 case 8: return new Format<uint8_t>("%02" PRIx8, 'x'); 1119 case 16: return new Format<uint16_t>("%04" PRIx16, 'x'); 1120 case 32: return new Format<uint32_t>("%08" PRIx32, 'x'); 1121 case 64: return new Format<uint64_t>("%016" PRIx64, 'x'); 1122 default: return NULL; 1123 } 1124 case 's': 1125 switch (count) { 1126 case 8: return new Format<int8_t>("%4" PRId8, 's'); 1127 case 16: return new Format<int16_t>("%6" PRId16, 's'); 1128 case 32: return new Format<int32_t>("%11" PRId32, 's'); 1129 case 64: return new Format<int64_t>("%20" PRId64, 's'); 1130 default: return NULL; 1131 } 1132 case 'u': 1133 switch (count) { 1134 case 8: return new Format<uint8_t>("%3" PRIu8, 'u'); 1135 case 16: return new Format<uint16_t>("%5" PRIu16, 'u'); 1136 case 32: return new Format<uint32_t>("%10" PRIu32, 'u'); 1137 case 64: return new Format<uint64_t>("%20" PRIu64, 'u'); 1138 default: return NULL; 1139 } 1140 case 'f': 1141 switch (count) { 1142 case 32: return new Format<float>("%13g", 'f'); 1143 case 64: return new Format<double>("%13g", 'f'); 1144 default: return NULL; 1145 } 1146 default: 1147 VIXL_UNREACHABLE(); 1148 return NULL; 1149 } 1150 } 1151 1152 1153 template<typename T> 1154 void Format<T>::Print(FILE* out) const { 1155 unsigned size = sizeof(T) * 8; 1156 fprintf(out, "[Format %c%u - %s]", type_code_, size, fmt_); 1157 } 1158 1159 1160 void UnknownToken::Print(FILE* out) const { 1161 fprintf(out, "[Unknown %s]", unknown_); 1162 } 1163 1164 1165 void DebugCommand::Print(FILE* out) { 1166 fprintf(out, "%s", name()); 1167 } 1168 1169 1170 bool DebugCommand::Match(const char* name, const char** aliases) { 1171 for (const char** current = aliases; *current != NULL; current++) { 1172 if (strcmp(name, *current) == 0) { 1173 return true; 1174 } 1175 } 1176 1177 return false; 1178 } 1179 1180 1181 DebugCommand* DebugCommand::Parse(char* line) { 1182 std::vector<Token*> args; 1183 1184 for (char* chunk = strtok(line, " \t"); 1185 chunk != NULL; 1186 chunk = strtok(NULL, " \t")) { 1187 char* dot = strchr(chunk, '.'); 1188 if (dot != NULL) { 1189 // 'Token.format'. 1190 Token* format = FormatToken::Tokenize(dot + 1); 1191 if (format != NULL) { 1192 *dot = '\0'; 1193 args.push_back(Token::Tokenize(chunk)); 1194 args.push_back(format); 1195 } else { 1196 // Error while parsing the format, push the UnknownToken so an error 1197 // can be accurately reported. 1198 args.push_back(Token::Tokenize(chunk)); 1199 } 1200 } else { 1201 args.push_back(Token::Tokenize(chunk)); 1202 } 1203 } 1204 1205 if (args.size() == 0) { 1206 return NULL; 1207 } 1208 1209 if (!args[0]->IsIdentifier()) { 1210 return new InvalidCommand(args, 0, "command name is not valid"); 1211 } 1212 1213 const char* name = IdentifierToken::Cast(args[0])->value(); 1214 #define RETURN_IF_MATCH(Command) \ 1215 if (Match(name, Command::kAliases)) { \ 1216 return Command::Build(args); \ 1217 } 1218 DEBUG_COMMAND_LIST(RETURN_IF_MATCH); 1219 #undef RETURN_IF_MATCH 1220 1221 return new UnknownCommand(args); 1222 } 1223 1224 1225 void DebugCommand::PrintHelp(const char** aliases, 1226 const char* args, 1227 const char* help) { 1228 VIXL_ASSERT(aliases[0] != NULL); 1229 VIXL_ASSERT(help != NULL); 1230 1231 printf("\n----\n\n"); 1232 for (const char** current = aliases; *current != NULL; current++) { 1233 if (args != NULL) { 1234 printf("%s %s\n", *current, args); 1235 } else { 1236 printf("%s\n", *current); 1237 } 1238 } 1239 printf("\n%s\n", help); 1240 } 1241 1242 1243 bool HelpCommand::Run(Debugger* debugger) { 1244 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1245 USE(debugger); 1246 1247 #define PRINT_HELP(Command) \ 1248 DebugCommand::PrintHelp(Command::kAliases, \ 1249 Command::kArguments, \ 1250 Command::kHelp); 1251 DEBUG_COMMAND_LIST(PRINT_HELP); 1252 #undef PRINT_HELP 1253 printf("\n----\n\n"); 1254 1255 return false; 1256 } 1257 1258 1259 DebugCommand* HelpCommand::Build(std::vector<Token*> args) { 1260 if (args.size() != 1) { 1261 return new InvalidCommand(args, -1, "too many arguments"); 1262 } 1263 1264 return new HelpCommand(args[0]); 1265 } 1266 1267 1268 bool ContinueCommand::Run(Debugger* debugger) { 1269 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1270 1271 debugger->set_debug_parameters(debugger->debug_parameters() & ~DBG_ACTIVE); 1272 return true; 1273 } 1274 1275 1276 DebugCommand* ContinueCommand::Build(std::vector<Token*> args) { 1277 if (args.size() != 1) { 1278 return new InvalidCommand(args, -1, "too many arguments"); 1279 } 1280 1281 return new ContinueCommand(args[0]); 1282 } 1283 1284 1285 bool StepCommand::Run(Debugger* debugger) { 1286 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1287 1288 int64_t steps = count(); 1289 if (steps < 0) { 1290 printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps); 1291 } else if (steps > 1) { 1292 debugger->set_steps(steps - 1); 1293 } 1294 1295 return true; 1296 } 1297 1298 1299 void StepCommand::Print(FILE* out) { 1300 fprintf(out, "%s %" PRId64 "", name(), count()); 1301 } 1302 1303 1304 DebugCommand* StepCommand::Build(std::vector<Token*> args) { 1305 IntegerToken* count = NULL; 1306 switch (args.size()) { 1307 case 1: { // step [1] 1308 count = new IntegerToken(1); 1309 break; 1310 } 1311 case 2: { // step n 1312 Token* first = args[1]; 1313 if (!first->IsInteger()) { 1314 return new InvalidCommand(args, 1, "expects int"); 1315 } 1316 count = IntegerToken::Cast(first); 1317 break; 1318 } 1319 default: 1320 return new InvalidCommand(args, -1, "too many arguments"); 1321 } 1322 1323 return new StepCommand(args[0], count); 1324 } 1325 1326 1327 DebugCommand* DisasmCommand::Build(std::vector<Token*> args) { 1328 IntegerToken* count = NULL; 1329 switch (args.size()) { 1330 case 1: { // disasm [10] 1331 count = new IntegerToken(10); 1332 break; 1333 } 1334 case 2: { // disasm n 1335 Token* first = args[1]; 1336 if (!first->IsInteger()) { 1337 return new InvalidCommand(args, 1, "expects int"); 1338 } 1339 1340 count = IntegerToken::Cast(first); 1341 break; 1342 } 1343 default: 1344 return new InvalidCommand(args, -1, "too many arguments"); 1345 } 1346 1347 Token* target = new IdentifierToken("pc"); 1348 FormatToken* format = new Format<uint32_t>("%08" PRIx32, 'i'); 1349 return new ExamineCommand(args[0], target, format, count); 1350 } 1351 1352 1353 void PrintCommand::Print(FILE* out) { 1354 fprintf(out, "%s ", name()); 1355 target()->Print(out); 1356 if (format() != NULL) format()->Print(out); 1357 } 1358 1359 1360 bool PrintCommand::Run(Debugger* debugger) { 1361 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1362 1363 Token* tok = target(); 1364 if (tok->IsIdentifier()) { 1365 char* identifier = IdentifierToken::Cast(tok)->value(); 1366 if (strcmp(identifier, "regs") == 0) { 1367 debugger->PrintRegisters(true); 1368 } else if (strcmp(identifier, "fpregs") == 0) { 1369 debugger->PrintFPRegisters(true); 1370 } else if (strcmp(identifier, "sysregs") == 0) { 1371 debugger->PrintSystemRegisters(true); 1372 } else if (strcmp(identifier, "pc") == 0) { 1373 printf("pc = %16p\n", reinterpret_cast<void*>(debugger->pc())); 1374 } else { 1375 printf(" ** Unknown identifier to print: %s **\n", identifier); 1376 } 1377 1378 return false; 1379 } 1380 1381 FormatToken* format_tok = format(); 1382 VIXL_ASSERT(format_tok != NULL); 1383 if (format_tok->type_code() == 'i') { 1384 // TODO(all): Add support for instruction disassembly. 1385 printf(" ** unsupported format: instructions **\n"); 1386 return false; 1387 } 1388 1389 if (tok->IsRegister()) { 1390 RegisterToken* reg_tok = RegisterToken::Cast(tok); 1391 Register reg = reg_tok->value(); 1392 debugger->PrintRegister(reg, reg_tok->Name(), format_tok); 1393 return false; 1394 } 1395 1396 if (tok->IsFPRegister()) { 1397 FPRegister fpreg = FPRegisterToken::Cast(tok)->value(); 1398 debugger->PrintFPRegister(fpreg, format_tok); 1399 return false; 1400 } 1401 1402 VIXL_UNREACHABLE(); 1403 return false; 1404 } 1405 1406 1407 DebugCommand* PrintCommand::Build(std::vector<Token*> args) { 1408 if (args.size() < 2) { 1409 return new InvalidCommand(args, -1, "too few arguments"); 1410 } 1411 1412 Token* target = args[1]; 1413 if (!target->IsRegister() && 1414 !target->IsFPRegister() && 1415 !target->IsIdentifier()) { 1416 return new InvalidCommand(args, 1, "expects reg or identifier"); 1417 } 1418 1419 FormatToken* format = NULL; 1420 int target_size = 0; 1421 if (target->IsRegister()) { 1422 Register reg = RegisterToken::Cast(target)->value(); 1423 target_size = reg.SizeInBytes(); 1424 } else if (target->IsFPRegister()) { 1425 FPRegister fpreg = FPRegisterToken::Cast(target)->value(); 1426 target_size = fpreg.SizeInBytes(); 1427 } 1428 // If the target is an identifier there must be no format. This is checked 1429 // in the switch statement below. 1430 1431 switch (args.size()) { 1432 case 2: { 1433 if (target->IsRegister()) { 1434 switch (target_size) { 1435 case 4: format = new Format<uint32_t>("%08" PRIx32, 'x'); break; 1436 case 8: format = new Format<uint64_t>("%016" PRIx64, 'x'); break; 1437 default: VIXL_UNREACHABLE(); 1438 } 1439 } else if (target->IsFPRegister()) { 1440 switch (target_size) { 1441 case 4: format = new Format<float>("%8g", 'f'); break; 1442 case 8: format = new Format<double>("%8g", 'f'); break; 1443 default: VIXL_UNREACHABLE(); 1444 } 1445 } 1446 break; 1447 } 1448 case 3: { 1449 if (target->IsIdentifier()) { 1450 return new InvalidCommand(args, 2, 1451 "format is only allowed with registers"); 1452 } 1453 1454 Token* second = args[2]; 1455 if (!second->IsFormat()) { 1456 return new InvalidCommand(args, 2, "expects format"); 1457 } 1458 format = FormatToken::Cast(second); 1459 1460 if (format->SizeOf() > target_size) { 1461 return new InvalidCommand(args, 2, "format too wide"); 1462 } 1463 1464 break; 1465 } 1466 default: 1467 return new InvalidCommand(args, -1, "too many arguments"); 1468 } 1469 1470 return new PrintCommand(args[0], target, format); 1471 } 1472 1473 1474 bool ExamineCommand::Run(Debugger* debugger) { 1475 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1476 1477 uint8_t* address = target()->ToAddress(debugger); 1478 int64_t amount = count()->value(); 1479 if (format()->type_code() == 'i') { 1480 debugger->PrintInstructions(address, amount); 1481 } else { 1482 debugger->PrintMemory(address, format(), amount); 1483 } 1484 1485 return false; 1486 } 1487 1488 1489 void ExamineCommand::Print(FILE* out) { 1490 fprintf(out, "%s ", name()); 1491 format()->Print(out); 1492 target()->Print(out); 1493 } 1494 1495 1496 DebugCommand* ExamineCommand::Build(std::vector<Token*> args) { 1497 if (args.size() < 2) { 1498 return new InvalidCommand(args, -1, "too few arguments"); 1499 } 1500 1501 Token* target = args[1]; 1502 if (!target->CanAddressMemory()) { 1503 return new InvalidCommand(args, 1, "expects address"); 1504 } 1505 1506 FormatToken* format = NULL; 1507 IntegerToken* count = NULL; 1508 1509 switch (args.size()) { 1510 case 2: { // mem addr[.x64] [10] 1511 format = new Format<uint64_t>("%016" PRIx64, 'x'); 1512 count = new IntegerToken(10); 1513 break; 1514 } 1515 case 3: { // mem addr.format [10] 1516 // mem addr[.x64] n 1517 Token* second = args[2]; 1518 if (second->IsFormat()) { 1519 format = FormatToken::Cast(second); 1520 count = new IntegerToken(10); 1521 break; 1522 } else if (second->IsInteger()) { 1523 format = new Format<uint64_t>("%016" PRIx64, 'x'); 1524 count = IntegerToken::Cast(second); 1525 } else { 1526 return new InvalidCommand(args, 2, "expects format or integer"); 1527 } 1528 VIXL_UNREACHABLE(); 1529 break; 1530 } 1531 case 4: { // mem addr.format n 1532 Token* second = args[2]; 1533 Token* third = args[3]; 1534 if (!second->IsFormat() || !third->IsInteger()) { 1535 return new InvalidCommand(args, -1, "expects addr[.format] [n]"); 1536 } 1537 format = FormatToken::Cast(second); 1538 count = IntegerToken::Cast(third); 1539 break; 1540 } 1541 default: 1542 return new InvalidCommand(args, -1, "too many arguments"); 1543 } 1544 1545 return new ExamineCommand(args[0], target, format, count); 1546 } 1547 1548 1549 UnknownCommand::~UnknownCommand() { 1550 const int size = args_.size(); 1551 for (int i = 0; i < size; ++i) { 1552 delete args_[i]; 1553 } 1554 } 1555 1556 1557 bool UnknownCommand::Run(Debugger* debugger) { 1558 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1559 USE(debugger); 1560 1561 printf(" ** Unknown Command:"); 1562 const int size = args_.size(); 1563 for (int i = 0; i < size; ++i) { 1564 printf(" "); 1565 args_[i]->Print(stdout); 1566 } 1567 printf(" **\n"); 1568 1569 return false; 1570 } 1571 1572 1573 InvalidCommand::~InvalidCommand() { 1574 const int size = args_.size(); 1575 for (int i = 0; i < size; ++i) { 1576 delete args_[i]; 1577 } 1578 } 1579 1580 1581 bool InvalidCommand::Run(Debugger* debugger) { 1582 VIXL_ASSERT(debugger->IsDebuggerRunning()); 1583 USE(debugger); 1584 1585 printf(" ** Invalid Command:"); 1586 const int size = args_.size(); 1587 for (int i = 0; i < size; ++i) { 1588 printf(" "); 1589 if (i == index_) { 1590 printf(">>"); 1591 args_[i]->Print(stdout); 1592 printf("<<"); 1593 } else { 1594 args_[i]->Print(stdout); 1595 } 1596 } 1597 printf(" **\n"); 1598 printf(" ** %s\n", cause_); 1599 1600 return false; 1601 } 1602 1603 } // namespace vixl 1604 1605 #endif // USE_SIMULATOR 1606