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