1 // Copyright 2014, 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 "vixl/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:
~Token()46 virtual ~Token() {}
47
48 // Token type.
IsRegister() const49 virtual bool IsRegister() const { return false; }
IsFPRegister() const50 virtual bool IsFPRegister() const { return false; }
IsIdentifier() const51 virtual bool IsIdentifier() const { return false; }
IsAddress() const52 virtual bool IsAddress() const { return false; }
IsInteger() const53 virtual bool IsInteger() const { return false; }
IsFormat() const54 virtual bool IsFormat() const { return false; }
IsUnknown() const55 virtual bool IsUnknown() const { return false; }
56 // Token properties.
CanAddressMemory() const57 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:
ValueToken(T value)67 explicit ValueToken(T value) : value_(value) {}
ValueToken()68 ValueToken() {}
69
value() const70 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:
RegisterToken(const Register reg)80 explicit RegisterToken(const Register reg)
81 : ValueToken<const Register>(reg) {}
82
IsRegister() const83 virtual bool IsRegister() const { return true; }
CanAddressMemory() const84 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);
Cast(Token * tok)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:
FPRegisterToken(const FPRegister fpreg)105 explicit FPRegisterToken(const FPRegister fpreg)
106 : ValueToken<const FPRegister>(fpreg) {}
107
IsFPRegister() const108 virtual bool IsFPRegister() const { return true; }
109 virtual void Print(FILE* out = stdout) const ;
110
111 static Token* Tokenize(const char* arg);
Cast(Token * tok)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:
IdentifierToken(const char * name)123 explicit IdentifierToken(const char* name) {
124 int size = strlen(name) + 1;
125 value_ = new char[size];
126 strncpy(value_, name, size);
127 }
~IdentifierToken()128 virtual ~IdentifierToken() { delete[] value_; }
129
IsIdentifier() const130 virtual bool IsIdentifier() const { return true; }
CanAddressMemory() const131 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);
Cast(Token * tok)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:
AddressToken(uint8_t * address)146 explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {}
147
IsAddress() const148 virtual bool IsAddress() const { return true; }
CanAddressMemory() const149 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);
Cast(Token * tok)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:
IntegerToken(int value)165 explicit IntegerToken(int value) : ValueToken<int64_t>(value) {}
166
IsInteger() const167 virtual bool IsInteger() const { return true; }
168 virtual void Print(FILE* out = stdout) const;
169
170 static Token* Tokenize(const char* arg);
Cast(Token * tok)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:
FormatToken()189 FormatToken() {}
190
IsFormat() const191 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);
Cast(Token * tok)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:
Format(const char * fmt,char type_code)207 Format(const char* fmt, char type_code) : fmt_(fmt), type_code_(type_code) {}
208
SizeOf() const209 virtual int SizeOf() const { return sizeof(T); }
type_code() const210 virtual char type_code() const { return type_code_; }
PrintData(void * data,FILE * out=stdout) const211 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:
UnknownToken(const char * arg)226 explicit UnknownToken(const char* arg) {
227 int size = strlen(arg) + 1;
228 unknown_ = new char[size];
229 strncpy(unknown_, arg, size);
230 }
~UnknownToken()231 virtual ~UnknownToken() { delete[] unknown_; }
232
IsUnknown() const233 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:
DebugCommand(Token * name)245 explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {}
DebugCommand()246 DebugCommand() : name_(NULL) {}
~DebugCommand()247 virtual ~DebugCommand() { delete name_; }
248
name()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:
HelpCommand(Token * name)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:
ContinueCommand(Token * name)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:
StepCommand(Token * name,IntegerToken * count)297 StepCommand(Token* name, IntegerToken* count)
298 : DebugCommand(name), count_(count) {}
~StepCommand()299 virtual ~StepCommand() { delete count_; }
300
count()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:
PrintCommand(Token * name,Token * target,FormatToken * format)327 PrintCommand(Token* name, Token* target, FormatToken* format)
328 : DebugCommand(name), target_(target), format_(format) {}
~PrintCommand()329 virtual ~PrintCommand() {
330 delete target_;
331 delete format_;
332 }
333
target()334 Token* target() { return target_; }
format()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:
ExamineCommand(Token * name,Token * target,FormatToken * format,IntegerToken * count)352 ExamineCommand(Token* name,
353 Token* target,
354 FormatToken* format,
355 IntegerToken* count)
356 : DebugCommand(name), target_(target), format_(format), count_(count) {}
~ExamineCommand()357 virtual ~ExamineCommand() {
358 delete target_;
359 delete format_;
360 delete count_;
361 }
362
target()363 Token* target() { return target_; }
format()364 FormatToken* format() { return format_; }
count()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:
UnknownCommand(std::vector<Token * > args)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:
InvalidCommand(std::vector<Token * > args,int index,const char * cause)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
Debugger(Decoder * decoder,FILE * stream)525 Debugger::Debugger(Decoder* decoder, FILE* stream)
526 : Simulator(decoder, stream),
527 debug_parameters_(DBG_INACTIVE),
528 pending_request_(false),
529 steps_(0),
530 last_command_(NULL) {
531 disasm_ = new PrintDisassembler(stdout);
532 printer_ = new Decoder();
533 printer_->AppendVisitor(disasm_);
534 }
535
~Debugger()536 Debugger::~Debugger() {
537 delete disasm_;
538 delete printer_;
539 }
540
541
Run()542 void Debugger::Run() {
543 pc_modified_ = false;
544 while (pc_ != kEndOfSimAddress) {
545 if (pending_request()) RunDebuggerShell();
546 ExecuteInstruction();
547 LogAllWrittenRegisters();
548 }
549 }
550
551
PrintInstructions(const void * address,int64_t count)552 void Debugger::PrintInstructions(const void* address, int64_t count) {
553 if (count == 0) {
554 return;
555 }
556
557 const Instruction* from = Instruction::CastConst(address);
558 if (count < 0) {
559 count = -count;
560 from -= (count - 1) * kInstructionSize;
561 }
562 const Instruction* to = from + count * kInstructionSize;
563
564 for (const Instruction* current = from;
565 current < to;
566 current = current->NextInstruction()) {
567 printer_->Decode(current);
568 }
569 }
570
571
PrintMemory(const uint8_t * address,const FormatToken * format,int64_t count)572 void Debugger::PrintMemory(const uint8_t* address,
573 const FormatToken* format,
574 int64_t count) {
575 if (count == 0) {
576 return;
577 }
578
579 const uint8_t* from = address;
580 int size = format->SizeOf();
581 if (count < 0) {
582 count = -count;
583 from -= (count - 1) * size;
584 }
585 const uint8_t* to = from + count * size;
586
587 for (const uint8_t* current = from; current < to; current += size) {
588 if (((current - from) % 8) == 0) {
589 printf("\n%p: ", current);
590 }
591
592 uint64_t data = Memory::Read<uint64_t>(current);
593 format->PrintData(&data);
594 printf(" ");
595 }
596 printf("\n\n");
597 }
598
599
PrintRegister(const Register & target_reg,const char * name,const FormatToken * format)600 void Debugger::PrintRegister(const Register& target_reg,
601 const char* name,
602 const FormatToken* format) {
603 const uint64_t reg_size = target_reg.size();
604 const uint64_t format_size = format->SizeOf() * 8;
605 const uint64_t count = reg_size / format_size;
606 const uint64_t mask = 0xffffffffffffffff >> (64 - format_size);
607 const uint64_t reg_value = reg<uint64_t>(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 // TODO(all): fix this for vector registers.
PrintFPRegister(const FPRegister & target_fpreg,const FormatToken * format)623 void Debugger::PrintFPRegister(const FPRegister& target_fpreg,
624 const FormatToken* format) {
625 const uint64_t fpreg_size = target_fpreg.size();
626 const uint64_t format_size = format->SizeOf() * 8;
627 const uint64_t count = fpreg_size / format_size;
628 const uint64_t mask = 0xffffffffffffffff >> (64 - format_size);
629 const uint64_t fpreg_value = vreg<uint64_t>(fpreg_size,
630 target_fpreg.code());
631 VIXL_ASSERT(count > 0);
632
633 if (target_fpreg.Is32Bits()) {
634 printf("s%u = ", target_fpreg.code());
635 } else {
636 printf("d%u = ", target_fpreg.code());
637 }
638 for (uint64_t i = 1; i <= count; i++) {
639 uint64_t data = fpreg_value >> (fpreg_size - (i * format_size));
640 data &= mask;
641 format->PrintData(&data);
642 printf(" ");
643 }
644 printf("\n");
645 }
646
647
VisitException(const Instruction * instr)648 void Debugger::VisitException(const Instruction* instr) {
649 switch (instr->Mask(ExceptionMask)) {
650 case BRK:
651 DoBreakpoint(instr);
652 return;
653 case HLT:
654 VIXL_FALLTHROUGH();
655 default: Simulator::VisitException(instr);
656 }
657 }
658
659
660 // Read a command. A command will be at most kMaxDebugShellLine char long and
661 // ends with '\n\0'.
662 // TODO: Should this be a utility function?
ReadCommandLine(const char * prompt,char * buffer,int length)663 char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) {
664 int fgets_calls = 0;
665 char* end = NULL;
666
667 printf("%s", prompt);
668 fflush(stdout);
669
670 do {
671 if (fgets(buffer, length, stdin) == NULL) {
672 printf(" ** Error while reading command. **\n");
673 return NULL;
674 }
675
676 fgets_calls++;
677 end = strchr(buffer, '\n');
678 } while (end == NULL);
679
680 if (fgets_calls != 1) {
681 printf(" ** Command too long. **\n");
682 return NULL;
683 }
684
685 // Remove the newline from the end of the command.
686 VIXL_ASSERT(end[1] == '\0');
687 VIXL_ASSERT((end - buffer) < (length - 1));
688 end[0] = '\0';
689
690 return buffer;
691 }
692
693
RunDebuggerShell()694 void Debugger::RunDebuggerShell() {
695 if (IsDebuggerRunning()) {
696 if (steps_ > 0) {
697 // Finish stepping first.
698 --steps_;
699 return;
700 }
701
702 printf("Next: ");
703 PrintInstructions(pc());
704 bool done = false;
705 while (!done) {
706 char buffer[kMaxDebugShellLine];
707 char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine);
708
709 if (line == NULL) continue; // An error occurred.
710
711 DebugCommand* command = DebugCommand::Parse(line);
712 if (command != NULL) {
713 last_command_ = command;
714 }
715
716 if (last_command_ != NULL) {
717 done = last_command_->Run(this);
718 } else {
719 printf("No previous command to run!\n");
720 }
721 }
722
723 if ((debug_parameters_ & DBG_BREAK) != 0) {
724 // The break request has now been handled, move to next instruction.
725 debug_parameters_ &= ~DBG_BREAK;
726 increment_pc();
727 }
728 }
729 }
730
731
DoBreakpoint(const Instruction * instr)732 void Debugger::DoBreakpoint(const Instruction* instr) {
733 VIXL_ASSERT(instr->Mask(ExceptionMask) == BRK);
734
735 printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<const void*>(instr));
736 set_debug_parameters(debug_parameters() | DBG_BREAK | DBG_ACTIVE);
737 // Make the shell point to the brk instruction.
738 set_pc(instr);
739 }
740
741
StringToUInt64(uint64_t * value,const char * line,int base=10)742 static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) {
743 char* endptr = NULL;
744 errno = 0; // Reset errors.
745 uint64_t parsed = strtoul(line, &endptr, base);
746
747 if (errno == ERANGE) {
748 // Overflow.
749 return false;
750 }
751
752 if (endptr == line) {
753 // No digits were parsed.
754 return false;
755 }
756
757 if (*endptr != '\0') {
758 // Non-digit characters present at the end.
759 return false;
760 }
761
762 *value = parsed;
763 return true;
764 }
765
766
StringToInt64(int64_t * value,const char * line,int base=10)767 static bool StringToInt64(int64_t* value, const char* line, int base = 10) {
768 char* endptr = NULL;
769 errno = 0; // Reset errors.
770 int64_t parsed = strtol(line, &endptr, base);
771
772 if (errno == ERANGE) {
773 // Overflow, undeflow.
774 return false;
775 }
776
777 if (endptr == line) {
778 // No digits were parsed.
779 return false;
780 }
781
782 if (*endptr != '\0') {
783 // Non-digit characters present at the end.
784 return false;
785 }
786
787 *value = parsed;
788 return true;
789 }
790
791
ToAddress(Debugger * debugger) const792 uint8_t* Token::ToAddress(Debugger* debugger) const {
793 USE(debugger);
794 VIXL_UNREACHABLE();
795 return NULL;
796 }
797
798
Tokenize(const char * arg)799 Token* Token::Tokenize(const char* arg) {
800 if ((arg == NULL) || (*arg == '\0')) {
801 return NULL;
802 }
803
804 // The order is important. For example Identifier::Tokenize would consider
805 // any register to be a valid identifier.
806
807 Token* token = RegisterToken::Tokenize(arg);
808 if (token != NULL) {
809 return token;
810 }
811
812 token = FPRegisterToken::Tokenize(arg);
813 if (token != NULL) {
814 return token;
815 }
816
817 token = IdentifierToken::Tokenize(arg);
818 if (token != NULL) {
819 return token;
820 }
821
822 token = AddressToken::Tokenize(arg);
823 if (token != NULL) {
824 return token;
825 }
826
827 token = IntegerToken::Tokenize(arg);
828 if (token != NULL) {
829 return token;
830 }
831
832 return new UnknownToken(arg);
833 }
834
835
ToAddress(Debugger * debugger) const836 uint8_t* RegisterToken::ToAddress(Debugger* debugger) const {
837 VIXL_ASSERT(CanAddressMemory());
838 uint64_t reg_value = debugger->xreg(value().code(), Reg31IsStackPointer);
839 uint8_t* address = NULL;
840 memcpy(&address, ®_value, sizeof(address));
841 return address;
842 }
843
844
Print(FILE * out) const845 void RegisterToken::Print(FILE* out) const {
846 VIXL_ASSERT(value().IsValid());
847 fprintf(out, "[Register %s]", Name());
848 }
849
850
Name() const851 const char* RegisterToken::Name() const {
852 if (value().Is32Bits()) {
853 return kWAliases[value().code()][0];
854 } else {
855 return kXAliases[value().code()][0];
856 }
857 }
858
859
Tokenize(const char * arg)860 Token* RegisterToken::Tokenize(const char* arg) {
861 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
862 // Is it a X register or alias?
863 for (const char** current = kXAliases[i]; *current != NULL; current++) {
864 if (strcmp(arg, *current) == 0) {
865 return new RegisterToken(Register::XRegFromCode(i));
866 }
867 }
868
869 // Is it a W register or alias?
870 for (const char** current = kWAliases[i]; *current != NULL; current++) {
871 if (strcmp(arg, *current) == 0) {
872 return new RegisterToken(Register::WRegFromCode(i));
873 }
874 }
875 }
876
877 return NULL;
878 }
879
880
Print(FILE * out) const881 void FPRegisterToken::Print(FILE* out) const {
882 VIXL_ASSERT(value().IsValid());
883 char prefix = value().Is32Bits() ? 's' : 'd';
884 fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().code());
885 }
886
887
Tokenize(const char * arg)888 Token* FPRegisterToken::Tokenize(const char* arg) {
889 if (strlen(arg) < 2) {
890 return NULL;
891 }
892
893 switch (*arg) {
894 case 's':
895 case 'd':
896 const char* cursor = arg + 1;
897 uint64_t code = 0;
898 if (!StringToUInt64(&code, cursor)) {
899 return NULL;
900 }
901
902 if (code > kNumberOfFPRegisters) {
903 return NULL;
904 }
905
906 VRegister fpreg = NoVReg;
907 switch (*arg) {
908 case 's': fpreg = VRegister::SRegFromCode(code); break;
909 case 'd': fpreg = VRegister::DRegFromCode(code); break;
910 default: VIXL_UNREACHABLE();
911 }
912
913 return new FPRegisterToken(fpreg);
914 }
915
916 return NULL;
917 }
918
919
ToAddress(Debugger * debugger) const920 uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const {
921 VIXL_ASSERT(CanAddressMemory());
922 const Instruction* pc_value = debugger->pc();
923 uint8_t* address = NULL;
924 memcpy(&address, &pc_value, sizeof(address));
925 return address;
926 }
927
Print(FILE * out) const928 void IdentifierToken::Print(FILE* out) const {
929 fprintf(out, "[Identifier %s]", value());
930 }
931
932
Tokenize(const char * arg)933 Token* IdentifierToken::Tokenize(const char* arg) {
934 if (!isalpha(arg[0])) {
935 return NULL;
936 }
937
938 const char* cursor = arg + 1;
939 while ((*cursor != '\0') && isalnum(*cursor)) {
940 ++cursor;
941 }
942
943 if (*cursor == '\0') {
944 return new IdentifierToken(arg);
945 }
946
947 return NULL;
948 }
949
950
ToAddress(Debugger * debugger) const951 uint8_t* AddressToken::ToAddress(Debugger* debugger) const {
952 USE(debugger);
953 return value();
954 }
955
956
Print(FILE * out) const957 void AddressToken::Print(FILE* out) const {
958 fprintf(out, "[Address %p]", value());
959 }
960
961
Tokenize(const char * arg)962 Token* AddressToken::Tokenize(const char* arg) {
963 if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) {
964 return NULL;
965 }
966
967 uint64_t ptr = 0;
968 if (!StringToUInt64(&ptr, arg, 16)) {
969 return NULL;
970 }
971
972 uint8_t* address = reinterpret_cast<uint8_t*>(ptr);
973 return new AddressToken(address);
974 }
975
976
Print(FILE * out) const977 void IntegerToken::Print(FILE* out) const {
978 fprintf(out, "[Integer %" PRId64 "]", value());
979 }
980
981
Tokenize(const char * arg)982 Token* IntegerToken::Tokenize(const char* arg) {
983 int64_t value = 0;
984 if (!StringToInt64(&value, arg)) {
985 return NULL;
986 }
987
988 return new IntegerToken(value);
989 }
990
991
Tokenize(const char * arg)992 Token* FormatToken::Tokenize(const char* arg) {
993 int length = strlen(arg);
994 switch (arg[0]) {
995 case 'x':
996 case 's':
997 case 'u':
998 case 'f':
999 if (length == 1) return NULL;
1000 break;
1001 case 'i':
1002 if (length == 1) return new Format<uint32_t>("%08" PRIx32, 'i');
1003 VIXL_FALLTHROUGH();
1004 default: return NULL;
1005 }
1006
1007 char* endptr = NULL;
1008 errno = 0; // Reset errors.
1009 uint64_t count = strtoul(arg + 1, &endptr, 10);
1010
1011 if (errno != 0) {
1012 // Overflow, etc.
1013 return NULL;
1014 }
1015
1016 if (endptr == arg) {
1017 // No digits were parsed.
1018 return NULL;
1019 }
1020
1021 if (*endptr != '\0') {
1022 // There are unexpected (non-digit) characters after the number.
1023 return NULL;
1024 }
1025
1026 switch (arg[0]) {
1027 case 'x':
1028 switch (count) {
1029 case 8: return new Format<uint8_t>("%02" PRIx8, 'x');
1030 case 16: return new Format<uint16_t>("%04" PRIx16, 'x');
1031 case 32: return new Format<uint32_t>("%08" PRIx32, 'x');
1032 case 64: return new Format<uint64_t>("%016" PRIx64, 'x');
1033 default: return NULL;
1034 }
1035 case 's':
1036 switch (count) {
1037 case 8: return new Format<int8_t>("%4" PRId8, 's');
1038 case 16: return new Format<int16_t>("%6" PRId16, 's');
1039 case 32: return new Format<int32_t>("%11" PRId32, 's');
1040 case 64: return new Format<int64_t>("%20" PRId64, 's');
1041 default: return NULL;
1042 }
1043 case 'u':
1044 switch (count) {
1045 case 8: return new Format<uint8_t>("%3" PRIu8, 'u');
1046 case 16: return new Format<uint16_t>("%5" PRIu16, 'u');
1047 case 32: return new Format<uint32_t>("%10" PRIu32, 'u');
1048 case 64: return new Format<uint64_t>("%20" PRIu64, 'u');
1049 default: return NULL;
1050 }
1051 case 'f':
1052 switch (count) {
1053 case 32: return new Format<float>("%13g", 'f');
1054 case 64: return new Format<double>("%13g", 'f');
1055 default: return NULL;
1056 }
1057 default:
1058 VIXL_UNREACHABLE();
1059 return NULL;
1060 }
1061 }
1062
1063
1064 template<typename T>
Print(FILE * out) const1065 void Format<T>::Print(FILE* out) const {
1066 unsigned size = sizeof(T) * 8;
1067 fprintf(out, "[Format %c%u - %s]", type_code_, size, fmt_);
1068 }
1069
1070
Print(FILE * out) const1071 void UnknownToken::Print(FILE* out) const {
1072 fprintf(out, "[Unknown %s]", unknown_);
1073 }
1074
1075
Print(FILE * out)1076 void DebugCommand::Print(FILE* out) {
1077 fprintf(out, "%s", name());
1078 }
1079
1080
Match(const char * name,const char ** aliases)1081 bool DebugCommand::Match(const char* name, const char** aliases) {
1082 for (const char** current = aliases; *current != NULL; current++) {
1083 if (strcmp(name, *current) == 0) {
1084 return true;
1085 }
1086 }
1087
1088 return false;
1089 }
1090
1091
Parse(char * line)1092 DebugCommand* DebugCommand::Parse(char* line) {
1093 std::vector<Token*> args;
1094
1095 for (char* chunk = strtok(line, " \t");
1096 chunk != NULL;
1097 chunk = strtok(NULL, " \t")) {
1098 char* dot = strchr(chunk, '.');
1099 if (dot != NULL) {
1100 // 'Token.format'.
1101 Token* format = FormatToken::Tokenize(dot + 1);
1102 if (format != NULL) {
1103 *dot = '\0';
1104 args.push_back(Token::Tokenize(chunk));
1105 args.push_back(format);
1106 } else {
1107 // Error while parsing the format, push the UnknownToken so an error
1108 // can be accurately reported.
1109 args.push_back(Token::Tokenize(chunk));
1110 }
1111 } else {
1112 args.push_back(Token::Tokenize(chunk));
1113 }
1114 }
1115
1116 if (args.size() == 0) {
1117 return NULL;
1118 }
1119
1120 if (!args[0]->IsIdentifier()) {
1121 return new InvalidCommand(args, 0, "command name is not valid");
1122 }
1123
1124 const char* name = IdentifierToken::Cast(args[0])->value();
1125 #define RETURN_IF_MATCH(Command) \
1126 if (Match(name, Command::kAliases)) { \
1127 return Command::Build(args); \
1128 }
1129 DEBUG_COMMAND_LIST(RETURN_IF_MATCH);
1130 #undef RETURN_IF_MATCH
1131
1132 return new UnknownCommand(args);
1133 }
1134
1135
PrintHelp(const char ** aliases,const char * args,const char * help)1136 void DebugCommand::PrintHelp(const char** aliases,
1137 const char* args,
1138 const char* help) {
1139 VIXL_ASSERT(aliases[0] != NULL);
1140 VIXL_ASSERT(help != NULL);
1141
1142 printf("\n----\n\n");
1143 for (const char** current = aliases; *current != NULL; current++) {
1144 if (args != NULL) {
1145 printf("%s %s\n", *current, args);
1146 } else {
1147 printf("%s\n", *current);
1148 }
1149 }
1150 printf("\n%s\n", help);
1151 }
1152
1153
Run(Debugger * debugger)1154 bool HelpCommand::Run(Debugger* debugger) {
1155 VIXL_ASSERT(debugger->IsDebuggerRunning());
1156 USE(debugger);
1157
1158 #define PRINT_HELP(Command) \
1159 DebugCommand::PrintHelp(Command::kAliases, \
1160 Command::kArguments, \
1161 Command::kHelp);
1162 DEBUG_COMMAND_LIST(PRINT_HELP);
1163 #undef PRINT_HELP
1164 printf("\n----\n\n");
1165
1166 return false;
1167 }
1168
1169
Build(std::vector<Token * > args)1170 DebugCommand* HelpCommand::Build(std::vector<Token*> args) {
1171 if (args.size() != 1) {
1172 return new InvalidCommand(args, -1, "too many arguments");
1173 }
1174
1175 return new HelpCommand(args[0]);
1176 }
1177
1178
Run(Debugger * debugger)1179 bool ContinueCommand::Run(Debugger* debugger) {
1180 VIXL_ASSERT(debugger->IsDebuggerRunning());
1181
1182 debugger->set_debug_parameters(debugger->debug_parameters() & ~DBG_ACTIVE);
1183 return true;
1184 }
1185
1186
Build(std::vector<Token * > args)1187 DebugCommand* ContinueCommand::Build(std::vector<Token*> args) {
1188 if (args.size() != 1) {
1189 return new InvalidCommand(args, -1, "too many arguments");
1190 }
1191
1192 return new ContinueCommand(args[0]);
1193 }
1194
1195
Run(Debugger * debugger)1196 bool StepCommand::Run(Debugger* debugger) {
1197 VIXL_ASSERT(debugger->IsDebuggerRunning());
1198
1199 int64_t steps = count();
1200 if (steps < 0) {
1201 printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
1202 } else if (steps > 1) {
1203 debugger->set_steps(steps - 1);
1204 }
1205
1206 return true;
1207 }
1208
1209
Print(FILE * out)1210 void StepCommand::Print(FILE* out) {
1211 fprintf(out, "%s %" PRId64 "", name(), count());
1212 }
1213
1214
Build(std::vector<Token * > args)1215 DebugCommand* StepCommand::Build(std::vector<Token*> args) {
1216 IntegerToken* count = NULL;
1217 switch (args.size()) {
1218 case 1: { // step [1]
1219 count = new IntegerToken(1);
1220 break;
1221 }
1222 case 2: { // step n
1223 Token* first = args[1];
1224 if (!first->IsInteger()) {
1225 return new InvalidCommand(args, 1, "expects int");
1226 }
1227 count = IntegerToken::Cast(first);
1228 break;
1229 }
1230 default:
1231 return new InvalidCommand(args, -1, "too many arguments");
1232 }
1233
1234 return new StepCommand(args[0], count);
1235 }
1236
1237
Build(std::vector<Token * > args)1238 DebugCommand* DisasmCommand::Build(std::vector<Token*> args) {
1239 IntegerToken* count = NULL;
1240 switch (args.size()) {
1241 case 1: { // disasm [10]
1242 count = new IntegerToken(10);
1243 break;
1244 }
1245 case 2: { // disasm n
1246 Token* first = args[1];
1247 if (!first->IsInteger()) {
1248 return new InvalidCommand(args, 1, "expects int");
1249 }
1250
1251 count = IntegerToken::Cast(first);
1252 break;
1253 }
1254 default:
1255 return new InvalidCommand(args, -1, "too many arguments");
1256 }
1257
1258 Token* target = new IdentifierToken("pc");
1259 FormatToken* format = new Format<uint32_t>("%08" PRIx32, 'i');
1260 return new ExamineCommand(args[0], target, format, count);
1261 }
1262
1263
Print(FILE * out)1264 void PrintCommand::Print(FILE* out) {
1265 fprintf(out, "%s ", name());
1266 target()->Print(out);
1267 if (format() != NULL) format()->Print(out);
1268 }
1269
1270
Run(Debugger * debugger)1271 bool PrintCommand::Run(Debugger* debugger) {
1272 VIXL_ASSERT(debugger->IsDebuggerRunning());
1273
1274 Token* tok = target();
1275 if (tok->IsIdentifier()) {
1276 char* identifier = IdentifierToken::Cast(tok)->value();
1277 if (strcmp(identifier, "regs") == 0) {
1278 debugger->PrintRegisters();
1279 } else if (strcmp(identifier, "fpregs") == 0) {
1280 debugger->PrintVRegisters();
1281 } else if (strcmp(identifier, "sysregs") == 0) {
1282 debugger->PrintSystemRegisters();
1283 } else if (strcmp(identifier, "pc") == 0) {
1284 printf("pc = %16p\n", reinterpret_cast<const void*>(debugger->pc()));
1285 } else {
1286 printf(" ** Unknown identifier to print: %s **\n", identifier);
1287 }
1288
1289 return false;
1290 }
1291
1292 FormatToken* format_tok = format();
1293 VIXL_ASSERT(format_tok != NULL);
1294 if (format_tok->type_code() == 'i') {
1295 // TODO(all): Add support for instruction disassembly.
1296 printf(" ** unsupported format: instructions **\n");
1297 return false;
1298 }
1299
1300 if (tok->IsRegister()) {
1301 RegisterToken* reg_tok = RegisterToken::Cast(tok);
1302 Register reg = reg_tok->value();
1303 debugger->PrintRegister(reg, reg_tok->Name(), format_tok);
1304 return false;
1305 }
1306
1307 if (tok->IsFPRegister()) {
1308 FPRegister fpreg = FPRegisterToken::Cast(tok)->value();
1309 debugger->PrintFPRegister(fpreg, format_tok);
1310 return false;
1311 }
1312
1313 VIXL_UNREACHABLE();
1314 return false;
1315 }
1316
1317
Build(std::vector<Token * > args)1318 DebugCommand* PrintCommand::Build(std::vector<Token*> args) {
1319 if (args.size() < 2) {
1320 return new InvalidCommand(args, -1, "too few arguments");
1321 }
1322
1323 Token* target = args[1];
1324 if (!target->IsRegister() &&
1325 !target->IsFPRegister() &&
1326 !target->IsIdentifier()) {
1327 return new InvalidCommand(args, 1, "expects reg or identifier");
1328 }
1329
1330 FormatToken* format = NULL;
1331 int target_size = 0;
1332 if (target->IsRegister()) {
1333 Register reg = RegisterToken::Cast(target)->value();
1334 target_size = reg.SizeInBytes();
1335 } else if (target->IsFPRegister()) {
1336 FPRegister fpreg = FPRegisterToken::Cast(target)->value();
1337 target_size = fpreg.SizeInBytes();
1338 }
1339 // If the target is an identifier there must be no format. This is checked
1340 // in the switch statement below.
1341
1342 switch (args.size()) {
1343 case 2: {
1344 if (target->IsRegister()) {
1345 switch (target_size) {
1346 case 4: format = new Format<uint32_t>("%08" PRIx32, 'x'); break;
1347 case 8: format = new Format<uint64_t>("%016" PRIx64, 'x'); break;
1348 default: VIXL_UNREACHABLE();
1349 }
1350 } else if (target->IsFPRegister()) {
1351 switch (target_size) {
1352 case 4: format = new Format<float>("%8g", 'f'); break;
1353 case 8: format = new Format<double>("%8g", 'f'); break;
1354 default: VIXL_UNREACHABLE();
1355 }
1356 }
1357 break;
1358 }
1359 case 3: {
1360 if (target->IsIdentifier()) {
1361 return new InvalidCommand(args, 2,
1362 "format is only allowed with registers");
1363 }
1364
1365 Token* second = args[2];
1366 if (!second->IsFormat()) {
1367 return new InvalidCommand(args, 2, "expects format");
1368 }
1369 format = FormatToken::Cast(second);
1370
1371 if (format->SizeOf() > target_size) {
1372 return new InvalidCommand(args, 2, "format too wide");
1373 }
1374
1375 break;
1376 }
1377 default:
1378 return new InvalidCommand(args, -1, "too many arguments");
1379 }
1380
1381 return new PrintCommand(args[0], target, format);
1382 }
1383
1384
Run(Debugger * debugger)1385 bool ExamineCommand::Run(Debugger* debugger) {
1386 VIXL_ASSERT(debugger->IsDebuggerRunning());
1387
1388 uint8_t* address = target()->ToAddress(debugger);
1389 int64_t amount = count()->value();
1390 if (format()->type_code() == 'i') {
1391 debugger->PrintInstructions(address, amount);
1392 } else {
1393 debugger->PrintMemory(address, format(), amount);
1394 }
1395
1396 return false;
1397 }
1398
1399
Print(FILE * out)1400 void ExamineCommand::Print(FILE* out) {
1401 fprintf(out, "%s ", name());
1402 format()->Print(out);
1403 target()->Print(out);
1404 }
1405
1406
Build(std::vector<Token * > args)1407 DebugCommand* ExamineCommand::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->CanAddressMemory()) {
1414 return new InvalidCommand(args, 1, "expects address");
1415 }
1416
1417 FormatToken* format = NULL;
1418 IntegerToken* count = NULL;
1419
1420 switch (args.size()) {
1421 case 2: { // mem addr[.x64] [10]
1422 format = new Format<uint64_t>("%016" PRIx64, 'x');
1423 count = new IntegerToken(10);
1424 break;
1425 }
1426 case 3: { // mem addr.format [10]
1427 // mem addr[.x64] n
1428 Token* second = args[2];
1429 if (second->IsFormat()) {
1430 format = FormatToken::Cast(second);
1431 count = new IntegerToken(10);
1432 break;
1433 } else if (second->IsInteger()) {
1434 format = new Format<uint64_t>("%016" PRIx64, 'x');
1435 count = IntegerToken::Cast(second);
1436 } else {
1437 return new InvalidCommand(args, 2, "expects format or integer");
1438 }
1439 VIXL_UNREACHABLE();
1440 break;
1441 }
1442 case 4: { // mem addr.format n
1443 Token* second = args[2];
1444 Token* third = args[3];
1445 if (!second->IsFormat() || !third->IsInteger()) {
1446 return new InvalidCommand(args, -1, "expects addr[.format] [n]");
1447 }
1448 format = FormatToken::Cast(second);
1449 count = IntegerToken::Cast(third);
1450 break;
1451 }
1452 default:
1453 return new InvalidCommand(args, -1, "too many arguments");
1454 }
1455
1456 return new ExamineCommand(args[0], target, format, count);
1457 }
1458
1459
~UnknownCommand()1460 UnknownCommand::~UnknownCommand() {
1461 const int size = args_.size();
1462 for (int i = 0; i < size; ++i) {
1463 delete args_[i];
1464 }
1465 }
1466
1467
Run(Debugger * debugger)1468 bool UnknownCommand::Run(Debugger* debugger) {
1469 VIXL_ASSERT(debugger->IsDebuggerRunning());
1470 USE(debugger);
1471
1472 printf(" ** Unknown Command:");
1473 const int size = args_.size();
1474 for (int i = 0; i < size; ++i) {
1475 printf(" ");
1476 args_[i]->Print(stdout);
1477 }
1478 printf(" **\n");
1479
1480 return false;
1481 }
1482
1483
~InvalidCommand()1484 InvalidCommand::~InvalidCommand() {
1485 const int size = args_.size();
1486 for (int i = 0; i < size; ++i) {
1487 delete args_[i];
1488 }
1489 }
1490
1491
Run(Debugger * debugger)1492 bool InvalidCommand::Run(Debugger* debugger) {
1493 VIXL_ASSERT(debugger->IsDebuggerRunning());
1494 USE(debugger);
1495
1496 printf(" ** Invalid Command:");
1497 const int size = args_.size();
1498 for (int i = 0; i < size; ++i) {
1499 printf(" ");
1500 if (i == index_) {
1501 printf(">>");
1502 args_[i]->Print(stdout);
1503 printf("<<");
1504 } else {
1505 args_[i]->Print(stdout);
1506 }
1507 }
1508 printf(" **\n");
1509 printf(" ** %s\n", cause_);
1510
1511 return false;
1512 }
1513
1514 } // namespace vixl
1515
1516 #endif // USE_SIMULATOR
1517