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 
31 namespace vixl {
32 namespace 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.
46 class Token {
47  public:
~Token()48   virtual ~Token() {}
49 
50   // Token type.
IsRegister() const51   virtual bool IsRegister() const { return false; }
IsFPRegister() const52   virtual bool IsFPRegister() const { return false; }
IsIdentifier() const53   virtual bool IsIdentifier() const { return false; }
IsAddress() const54   virtual bool IsAddress() const { return false; }
IsInteger() const55   virtual bool IsInteger() const { return false; }
IsFormat() const56   virtual bool IsFormat() const { return false; }
IsUnknown() const57   virtual bool IsUnknown() const { return false; }
58   // Token properties.
CanAddressMemory() const59   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.
67 template <typename T>
68 class ValueToken : public Token {
69  public:
ValueToken(T value)70   explicit ValueToken(T value) : value_(value) {}
ValueToken()71   ValueToken() {}
72 
value() const73   T value() const { return value_; }
74 
ToAddress(Debugger * debugger) const75   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.
87 class RegisterToken : public ValueToken<const Register> {
88  public:
RegisterToken(const Register reg)89   explicit RegisterToken(const Register reg)
90       : ValueToken<const Register>(reg) {}
91 
IsRegister() const92   virtual bool IsRegister() const VIXL_OVERRIDE { return true; }
CanAddressMemory() const93   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);
Cast(Token * tok)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.
114 class FPRegisterToken : public ValueToken<const FPRegister> {
115  public:
FPRegisterToken(const FPRegister fpreg)116   explicit FPRegisterToken(const FPRegister fpreg)
117       : ValueToken<const FPRegister>(fpreg) {}
118 
IsFPRegister() const119   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);
Cast(Token * tok)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.
132 class IdentifierToken : public ValueToken<char*> {
133  public:
IdentifierToken(const char * name)134   explicit IdentifierToken(const char* name) {
135     size_t size = strlen(name) + 1;
136     value_ = new char[size];
137     strncpy(value_, name, size);
138   }
~IdentifierToken()139   virtual ~IdentifierToken() { delete[] value_; }
140 
IsIdentifier() const141   virtual bool IsIdentifier() const VIXL_OVERRIDE { return true; }
CanAddressMemory() const142   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);
Cast(Token * tok)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.
157 class AddressToken : public ValueToken<uint8_t*> {
158  public:
AddressToken(uint8_t * address)159   explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {}
160 
IsAddress() const161   virtual bool IsAddress() const VIXL_OVERRIDE { return true; }
CanAddressMemory() const162   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);
Cast(Token * tok)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.
176 class IntegerToken : public ValueToken<int64_t> {
177  public:
IntegerToken(int64_t value)178   explicit IntegerToken(int64_t value) : ValueToken<int64_t>(value) {}
179 
IsInteger() const180   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);
Cast(Token * tok)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.
200 class FormatToken : public Token {
201  public:
FormatToken()202   FormatToken() {}
203 
IsFormat() const204   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 
ToAddress(Debugger * debugger) const210   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);
Cast(Token * tok)217   static FormatToken* Cast(Token* tok) {
218     VIXL_ASSERT(tok->IsFormat());
219     return reinterpret_cast<FormatToken*>(tok);
220   }
221 };
222 
223 
224 template <typename T>
225 class Format : public FormatToken {
226  public:
Format(const char * fmt,char type_code)227   Format(const char* fmt, char type_code) : fmt_(fmt), type_code_(type_code) {}
228 
SizeOf() const229   virtual int SizeOf() const VIXL_OVERRIDE { return sizeof(T); }
GetTypeCode() const230   virtual char GetTypeCode() const VIXL_OVERRIDE { return type_code_; }
PrintData(void * data,FILE * out=stdout) const231   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.
244 class UnknownToken : public Token {
245  public:
UnknownToken(const char * arg)246   explicit UnknownToken(const char* arg) {
247     size_t size = strlen(arg) + 1;
248     unknown_ = new char[size];
249     strncpy(unknown_, arg, size);
250   }
~UnknownToken()251   virtual ~UnknownToken() { delete[] unknown_; }
ToAddress(Debugger * debugger) const252   VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const
253       VIXL_OVERRIDE {
254     USE(debugger);
255     VIXL_ABORT();
256   }
257 
IsUnknown() const258   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.
268 class DebugCommand {
269  public:
DebugCommand(Token * name)270   explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {}
DebugCommand()271   DebugCommand() : name_(NULL) {}
~DebugCommand()272   virtual ~DebugCommand() { delete name_; }
273 
name()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
292 class HelpCommand : public DebugCommand {
293  public:
HelpCommand(Token * name)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 
306 class ContinueCommand : public DebugCommand {
307  public:
ContinueCommand(Token * name)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 
320 class StepCommand : public DebugCommand {
321  public:
StepCommand(Token * name,IntegerToken * count)322   StepCommand(Token* name, IntegerToken* count)
323       : DebugCommand(name), count_(count) {}
~StepCommand()324   virtual ~StepCommand() { delete count_; }
325 
count()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 
340 class SkipCommand : public DebugCommand {
341  public:
SkipCommand(Token * name,IntegerToken * count)342   SkipCommand(Token* name, IntegerToken* count)
343       : DebugCommand(name), count_(count) {}
~SkipCommand()344   virtual ~SkipCommand() { delete count_; }
345 
count()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 
360 class 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 
370 class PrintCommand : public DebugCommand {
371  public:
PrintCommand(Token * name,Token * target,FormatToken * format)372   PrintCommand(Token* name, Token* target, FormatToken* format)
373       : DebugCommand(name), target_(target), format_(format) {}
~PrintCommand()374   virtual ~PrintCommand() {
375     delete target_;
376     delete format_;
377   }
378 
target()379   Token* target() { return target_; }
format()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 
395 class ExamineCommand : public DebugCommand {
396  public:
ExamineCommand(Token * name,Token * target,FormatToken * format,IntegerToken * count)397   ExamineCommand(Token* name,
398                  Token* target,
399                  FormatToken* format,
400                  IntegerToken* count)
401       : DebugCommand(name), target_(target), format_(format), count_(count) {}
~ExamineCommand()402   virtual ~ExamineCommand() {
403     delete target_;
404     delete format_;
405     delete count_;
406   }
407 
target()408   Token* target() { return target_; }
format()409   FormatToken* format() { return format_; }
count()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.
427 class UnknownCommand : public DebugCommand {
428  public:
UnknownCommand(std::vector<Token * > args)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.
439 class InvalidCommand : public DebugCommand {
440  public:
InvalidCommand(std::vector<Token * > args,int index,const char * cause)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 
453 const char* HelpCommand::kAliases[] = {"help", NULL};
454 const char* HelpCommand::kArguments = NULL;
455 const char* HelpCommand::kHelp = "  Print this help.";
456 
457 const char* ContinueCommand::kAliases[] = {"continue", "c", NULL};
458 const char* ContinueCommand::kArguments = NULL;
459 const char* ContinueCommand::kHelp = "  Resume execution.";
460 
461 const char* StepCommand::kAliases[] = {"stepi", "si", NULL};
462 const char* StepCommand::kArguments = "[n = 1]";
463 const char* StepCommand::kHelp = "  Execute n next instruction(s).";
464 
465 const char* SkipCommand::kAliases[] = {"skip", NULL};
466 const char* SkipCommand::kArguments = "[n = 1]";
467 const char* SkipCommand::kHelp = "  Skip the next n instruction(s).";
468 
469 const char* DisasmCommand::kAliases[] = {"disasm", "di", NULL};
470 const char* DisasmCommand::kArguments = "[n = 10]";
471 const char* DisasmCommand::kHelp =
472     "  Disassemble n instruction(s) at pc.\n"
473     "  This command is equivalent to x pc.i [n = 10].";
474 
475 const char* PrintCommand::kAliases[] = {"print", "p", NULL};
476 const char* PrintCommand::kArguments = "<entity>[.format]";
477 const 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 
488 const char* ExamineCommand::kAliases[] = {"m", "mem", "x", NULL};
489 const char* ExamineCommand::kArguments = "<addr>[.format] [n = 10]";
490 const 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 
500 const char* RegisterToken::kXAliases[kNumberOfRegisters][kMaxAliasNumber] =
501     {{"x0", NULL},
502      {"x1", NULL},
503      {"x2", NULL},
504      {"x3", NULL},
505      {"x4", NULL},
506      {"x5", NULL},
507      {"x6", NULL},
508      {"x7", NULL},
509      {"x8", NULL},
510      {"x9", NULL},
511      {"x10", NULL},
512      {"x11", NULL},
513      {"x12", NULL},
514      {"x13", NULL},
515      {"x14", NULL},
516      {"x15", NULL},
517      {"ip0", "x16", NULL},
518      {"ip1", "x17", NULL},
519      {"x18", "pr", NULL},
520      {"x19", NULL},
521      {"x20", NULL},
522      {"x21", NULL},
523      {"x22", NULL},
524      {"x23", NULL},
525      {"x24", NULL},
526      {"x25", NULL},
527      {"x26", NULL},
528      {"x27", NULL},
529      {"x28", NULL},
530      {"fp", "x29", NULL},
531      {"lr", "x30", NULL},
532      {"sp", NULL}};
533 
534 const char* RegisterToken::kWAliases[kNumberOfRegisters][kMaxAliasNumber] =
535     {{"w0", NULL},
536      {"w1", NULL},
537      {"w2", NULL},
538      {"w3", NULL},
539      {"w4", NULL},
540      {"w5", NULL},
541      {"w6", NULL},
542      {"w7", NULL},
543      {"w8", NULL},
544      {"w9", NULL},
545      {"w10", NULL},
546      {"w11", NULL},
547      {"w12", NULL},
548      {"w13", NULL},
549      {"w14", NULL},
550      {"w15", NULL},
551      {"w16", NULL},
552      {"w17", NULL},
553      {"w18", NULL},
554      {"w19", NULL},
555      {"w20", NULL},
556      {"w21", NULL},
557      {"w22", NULL},
558      {"w23", NULL},
559      {"w24", NULL},
560      {"w25", NULL},
561      {"w26", NULL},
562      {"w27", NULL},
563      {"w28", NULL},
564      {"w29", NULL},
565      {"w30", NULL},
566      {"wsp", NULL}};
567 
568 
Debugger(Decoder * decoder,FILE * stream)569 Debugger::Debugger(Decoder* decoder, FILE* stream)
570     : Simulator(decoder, stream),
571       debugger_active_(false),
572       steps_(0),
573       last_command_(NULL) {
574   disasm_ = new PrintDisassembler(stdout);
575   printer_ = new Decoder();
576   printer_->AppendVisitor(disasm_);
577 }
578 
~Debugger()579 Debugger::~Debugger() {
580   delete disasm_;
581   delete printer_;
582 }
583 
584 
Run()585 void Debugger::Run() {
586   // Flush any written registers before executing anything, so that
587   // manually-set registers are logged _before_ the first instruction.
588   LogAllWrittenRegisters();
589 
590   while (pc_ != kEndOfSimAddress) {
591     if (IsDebuggerActive()) RunDebuggerShell();
592     ExecuteInstruction();
593   }
594 }
595 
596 
PrintInstructions(const void * address,int64_t count,const char * prefix)597 void Debugger::PrintInstructions(const void* address,
598                                  int64_t count,
599                                  const char* prefix) {
600   if (count == 0) {
601     return;
602   }
603 
604   const Instruction* from = Instruction::CastConst(address);
605   if (count < 0) {
606     count = -count;
607     from -= (count - 1) * kInstructionSize;
608   }
609   const Instruction* to = from + count * kInstructionSize;
610 
611   for (const Instruction* current = from; current < to;
612        current = current->GetNextInstruction()) {
613     printf("%s", prefix);
614     printer_->Decode(current);
615   }
616 }
617 
618 
PrintMemory(const uint8_t * address,const FormatToken * format,int64_t count)619 void Debugger::PrintMemory(const uint8_t* address,
620                            const FormatToken* format,
621                            int64_t count) {
622   if (count == 0) {
623     return;
624   }
625 
626   const uint8_t* from = address;
627   int size = format->SizeOf();
628   if (count < 0) {
629     count = -count;
630     from -= (count - 1) * size;
631   }
632   const uint8_t* to = from + count * size;
633 
634   for (const uint8_t* current = from; current < to; current += size) {
635     if (((current - from) % 8) == 0) {
636       printf("\n%p: ", reinterpret_cast<const void*>(current));
637     }
638 
639     uint64_t data = Memory::Read<uint64_t>(current);
640     format->PrintData(&data);
641     printf(" ");
642   }
643   printf("\n\n");
644 }
645 
646 
PrintRegister(const Register & target_reg,const char * name,const FormatToken * format)647 void Debugger::PrintRegister(const Register& target_reg,
648                              const char* name,
649                              const FormatToken* format) {
650   const uint64_t reg_size = target_reg.GetSizeInBits();
651   const uint64_t format_size = format->SizeOf() * 8;
652   const uint64_t count = reg_size / format_size;
653   const uint64_t mask = 0xffffffffffffffff >> (64 - format_size);
654   const uint64_t reg_value =
655       ReadRegister<uint64_t>(target_reg.GetCode(), Reg31IsStackPointer);
656   VIXL_ASSERT(count > 0);
657 
658   printf("%s = ", name);
659   for (uint64_t i = 1; i <= count; i++) {
660     uint64_t data = reg_value >> (reg_size - (i * format_size));
661     data &= mask;
662     format->PrintData(&data);
663     printf(" ");
664   }
665   printf("\n");
666 }
667 
668 
669 // TODO(all): fix this for vector registers.
PrintFPRegister(const FPRegister & target_fpreg,const FormatToken * format)670 void Debugger::PrintFPRegister(const FPRegister& target_fpreg,
671                                const FormatToken* format) {
672   const unsigned fpreg_size = target_fpreg.GetSizeInBits();
673   const uint64_t format_size = format->SizeOf() * 8;
674   const uint64_t count = fpreg_size / format_size;
675   const uint64_t mask = 0xffffffffffffffff >> (64 - format_size);
676   const uint64_t fpreg_value =
677       ReadVRegister<uint64_t>(fpreg_size, target_fpreg.GetCode());
678   VIXL_ASSERT(count > 0);
679 
680   if (target_fpreg.Is32Bits()) {
681     printf("s%u = ", target_fpreg.GetCode());
682   } else {
683     printf("d%u = ", target_fpreg.GetCode());
684   }
685   for (uint64_t i = 1; i <= count; i++) {
686     uint64_t data = fpreg_value >> (fpreg_size - (i * format_size));
687     data &= mask;
688     format->PrintData(&data);
689     printf(" ");
690   }
691   printf("\n");
692 }
693 
694 
VisitException(const Instruction * instr)695 void Debugger::VisitException(const Instruction* instr) {
696   switch (instr->Mask(ExceptionMask)) {
697     case BRK:
698       DoBreakpoint(instr);
699       return;
700     case HLT:
701       VIXL_FALLTHROUGH();
702     default:
703       Simulator::VisitException(instr);
704   }
705 }
706 
707 
708 // Read a command. A command will be at most kMaxDebugShellLine char long and
709 // ends with '\n\0'.
710 // TODO: Should this be a utility function?
ReadCommandLine(const char * prompt,char * buffer,int length)711 char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) {
712   int fgets_calls = 0;
713   char* end = NULL;
714 
715   printf("%s", prompt);
716   fflush(stdout);
717 
718   do {
719     if (fgets(buffer, length, stdin) == NULL) {
720       printf(" ** Error while reading command. **\n");
721       return NULL;
722     }
723 
724     fgets_calls++;
725     end = strchr(buffer, '\n');
726   } while (end == NULL);
727 
728   if (fgets_calls != 1) {
729     printf(" ** Command too long. **\n");
730     return NULL;
731   }
732 
733   // Remove the newline from the end of the command.
734   VIXL_ASSERT(end[1] == '\0');
735   VIXL_ASSERT((end - buffer) < (length - 1));
736   end[0] = '\0';
737 
738   return buffer;
739 }
740 
741 
RunDebuggerShell()742 void Debugger::RunDebuggerShell() {
743   if (IsDebuggerActive()) {
744     if (steps_ > 0) {
745       // Finish stepping first.
746       --steps_;
747       return;
748     }
749 
750     PrintNextInstruction();
751     bool done = false;
752     while (!done) {
753       char buffer[kMaxDebugShellLine];
754       char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine);
755 
756       if (line == NULL) continue;  // An error occurred.
757 
758       DebugCommand* command = DebugCommand::Parse(line);
759       if (command != NULL) {
760         last_command_ = command;
761       }
762 
763       if (last_command_ != NULL) {
764         done = last_command_->Run(this);
765       } else {
766         printf("No previous command to run!\n");
767       }
768     }
769   }
770 }
771 
772 
DoBreakpoint(const Instruction * instr)773 void Debugger::DoBreakpoint(const Instruction* instr) {
774   VIXL_ASSERT(instr->Mask(ExceptionMask) == BRK);
775 
776   printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<const void*>(instr));
777   ActivateDebugger();
778 }
779 
780 
StringToUInt64(uint64_t * value,const char * line,int base=10)781 static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) {
782   char* endptr = NULL;
783   errno = 0;  // Reset errors.
784   uint64_t parsed = strtoul(line, &endptr, base);
785 
786   if (errno == ERANGE) {
787     // Overflow.
788     return false;
789   }
790 
791   if (endptr == line) {
792     // No digits were parsed.
793     return false;
794   }
795 
796   if (*endptr != '\0') {
797     // Non-digit characters present at the end.
798     return false;
799   }
800 
801   *value = parsed;
802   return true;
803 }
804 
805 
StringToInt64(int64_t * value,const char * line,int base=10)806 static bool StringToInt64(int64_t* value, const char* line, int base = 10) {
807   char* endptr = NULL;
808   errno = 0;  // Reset errors.
809   int64_t parsed = strtol(line, &endptr, base);
810 
811   if (errno == ERANGE) {
812     // Overflow, undeflow.
813     return false;
814   }
815 
816   if (endptr == line) {
817     // No digits were parsed.
818     return false;
819   }
820 
821   if (*endptr != '\0') {
822     // Non-digit characters present at the end.
823     return false;
824   }
825 
826   *value = parsed;
827   return true;
828 }
829 
830 
Tokenize(const char * arg)831 Token* Token::Tokenize(const char* arg) {
832   if ((arg == NULL) || (*arg == '\0')) {
833     return NULL;
834   }
835 
836   // The order is important. For example Identifier::Tokenize would consider
837   // any register to be a valid identifier.
838 
839   Token* token = RegisterToken::Tokenize(arg);
840   if (token != NULL) {
841     return token;
842   }
843 
844   token = FPRegisterToken::Tokenize(arg);
845   if (token != NULL) {
846     return token;
847   }
848 
849   token = IdentifierToken::Tokenize(arg);
850   if (token != NULL) {
851     return token;
852   }
853 
854   token = AddressToken::Tokenize(arg);
855   if (token != NULL) {
856     return token;
857   }
858 
859   token = IntegerToken::Tokenize(arg);
860   if (token != NULL) {
861     return token;
862   }
863 
864   return new UnknownToken(arg);
865 }
866 
867 
ToAddress(Debugger * debugger) const868 uint8_t* RegisterToken::ToAddress(Debugger* debugger) const {
869   VIXL_ASSERT(CanAddressMemory());
870   uint64_t reg_value =
871       debugger->ReadXRegister(value().GetCode(), Reg31IsStackPointer);
872   uint8_t* address = NULL;
873   memcpy(&address, &reg_value, sizeof(address));
874   return address;
875 }
876 
877 
Print(FILE * out) const878 void RegisterToken::Print(FILE* out) const {
879   VIXL_ASSERT(value().IsValid());
880   fprintf(out, "[Register %s]", Name());
881 }
882 
883 
Name() const884 const char* RegisterToken::Name() const {
885   if (value().Is32Bits()) {
886     return kWAliases[value().GetCode()][0];
887   } else {
888     return kXAliases[value().GetCode()][0];
889   }
890 }
891 
892 
Tokenize(const char * arg)893 Token* RegisterToken::Tokenize(const char* arg) {
894   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
895     // Is it a X register or alias?
896     for (const char** current = kXAliases[i]; *current != NULL; current++) {
897       if (strcmp(arg, *current) == 0) {
898         return new RegisterToken(Register::GetXRegFromCode(i));
899       }
900     }
901 
902     // Is it a W register or alias?
903     for (const char** current = kWAliases[i]; *current != NULL; current++) {
904       if (strcmp(arg, *current) == 0) {
905         return new RegisterToken(Register::GetWRegFromCode(i));
906       }
907     }
908   }
909 
910   return NULL;
911 }
912 
913 
Print(FILE * out) const914 void FPRegisterToken::Print(FILE* out) const {
915   VIXL_ASSERT(value().IsValid());
916   char prefix = value().Is32Bits() ? 's' : 'd';
917   fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().GetCode());
918 }
919 
920 
Tokenize(const char * arg)921 Token* FPRegisterToken::Tokenize(const char* arg) {
922   if (strlen(arg) < 2) {
923     return NULL;
924   }
925 
926   switch (*arg) {
927     case 's':
928     case 'd':
929       const char* cursor = arg + 1;
930       uint64_t code = 0;
931       if (!StringToUInt64(&code, cursor)) {
932         return NULL;
933       }
934 
935       if (code > kNumberOfFPRegisters) {
936         return NULL;
937       }
938 
939       VRegister fpreg = NoVReg;
940       switch (*arg) {
941         case 's':
942           fpreg = VRegister::GetSRegFromCode(static_cast<unsigned>(code));
943           break;
944         case 'd':
945           fpreg = VRegister::GetDRegFromCode(static_cast<unsigned>(code));
946           break;
947         default:
948           VIXL_UNREACHABLE();
949       }
950 
951       return new FPRegisterToken(fpreg);
952   }
953 
954   return NULL;
955 }
956 
957 
ToAddress(Debugger * debugger) const958 uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const {
959   VIXL_ASSERT(CanAddressMemory());
960   const Instruction* pc_value = debugger->ReadPc();
961   uint8_t* address = NULL;
962   memcpy(&address, &pc_value, sizeof(address));
963   return address;
964 }
965 
Print(FILE * out) const966 void IdentifierToken::Print(FILE* out) const {
967   fprintf(out, "[Identifier %s]", value());
968 }
969 
970 
Tokenize(const char * arg)971 Token* IdentifierToken::Tokenize(const char* arg) {
972   if (!isalpha(arg[0])) {
973     return NULL;
974   }
975 
976   const char* cursor = arg + 1;
977   while ((*cursor != '\0') && isalnum(*cursor)) {
978     ++cursor;
979   }
980 
981   if (*cursor == '\0') {
982     return new IdentifierToken(arg);
983   }
984 
985   return NULL;
986 }
987 
988 
ToAddress(Debugger * debugger) const989 uint8_t* AddressToken::ToAddress(Debugger* debugger) const {
990   USE(debugger);
991   return value();
992 }
993 
994 
Print(FILE * out) const995 void AddressToken::Print(FILE* out) const {
996   fprintf(out, "[Address %p]", reinterpret_cast<const void*>(value()));
997 }
998 
999 
Tokenize(const char * arg)1000 Token* AddressToken::Tokenize(const char* arg) {
1001   if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) {
1002     return NULL;
1003   }
1004 
1005   uint64_t ptr = 0;
1006   if (!StringToUInt64(&ptr, arg, 16)) {
1007     return NULL;
1008   }
1009 
1010   uint8_t* address = reinterpret_cast<uint8_t*>(ptr);
1011   return new AddressToken(address);
1012 }
1013 
1014 
Print(FILE * out) const1015 void IntegerToken::Print(FILE* out) const {
1016   fprintf(out, "[Integer %" PRId64 "]", value());
1017 }
1018 
1019 
Tokenize(const char * arg)1020 Token* IntegerToken::Tokenize(const char* arg) {
1021   int64_t value = 0;
1022   if (!StringToInt64(&value, arg)) {
1023     return NULL;
1024   }
1025 
1026   return new IntegerToken(value);
1027 }
1028 
1029 
Tokenize(const char * arg)1030 Token* FormatToken::Tokenize(const char* arg) {
1031   size_t length = strlen(arg);
1032   switch (arg[0]) {
1033     case 'x':
1034     case 's':
1035     case 'u':
1036     case 'f':
1037       if (length == 1) return NULL;
1038       break;
1039     case 'i':
1040       if (length == 1) return new Format<uint32_t>("%08" PRIx32, 'i');
1041       VIXL_FALLTHROUGH();
1042     default:
1043       return NULL;
1044   }
1045 
1046   char* endptr = NULL;
1047   errno = 0;  // Reset errors.
1048   uint64_t count = strtoul(arg + 1, &endptr, 10);
1049 
1050   if (errno != 0) {
1051     // Overflow, etc.
1052     return NULL;
1053   }
1054 
1055   if (endptr == arg) {
1056     // No digits were parsed.
1057     return NULL;
1058   }
1059 
1060   if (*endptr != '\0') {
1061     // There are unexpected (non-digit) characters after the number.
1062     return NULL;
1063   }
1064 
1065   switch (arg[0]) {
1066     case 'x':
1067       switch (count) {
1068         case 8:
1069           return new Format<uint8_t>("%02" PRIx8, 'x');
1070         case 16:
1071           return new Format<uint16_t>("%04" PRIx16, 'x');
1072         case 32:
1073           return new Format<uint32_t>("%08" PRIx32, 'x');
1074         case 64:
1075           return new Format<uint64_t>("%016" PRIx64, 'x');
1076         default:
1077           return NULL;
1078       }
1079     case 's':
1080       switch (count) {
1081         case 8:
1082           return new Format<int8_t>("%4" PRId8, 's');
1083         case 16:
1084           return new Format<int16_t>("%6" PRId16, 's');
1085         case 32:
1086           return new Format<int32_t>("%11" PRId32, 's');
1087         case 64:
1088           return new Format<int64_t>("%20" PRId64, 's');
1089         default:
1090           return NULL;
1091       }
1092     case 'u':
1093       switch (count) {
1094         case 8:
1095           return new Format<uint8_t>("%3" PRIu8, 'u');
1096         case 16:
1097           return new Format<uint16_t>("%5" PRIu16, 'u');
1098         case 32:
1099           return new Format<uint32_t>("%10" PRIu32, 'u');
1100         case 64:
1101           return new Format<uint64_t>("%20" PRIu64, 'u');
1102         default:
1103           return NULL;
1104       }
1105     case 'f':
1106       switch (count) {
1107         case 32:
1108           return new Format<float>("%13g", 'f');
1109         case 64:
1110           return new Format<double>("%13g", 'f');
1111         default:
1112           return NULL;
1113       }
1114     default:
1115       VIXL_UNREACHABLE();
1116       return NULL;
1117   }
1118 }
1119 
1120 
1121 template <typename T>
Print(FILE * out) const1122 void Format<T>::Print(FILE* out) const {
1123   unsigned size = sizeof(T) * 8;
1124   fprintf(out, "[Format %c%u - %s]", type_code_, size, fmt_);
1125 }
1126 
1127 
Print(FILE * out) const1128 void UnknownToken::Print(FILE* out) const {
1129   fprintf(out, "[Unknown %s]", unknown_);
1130 }
1131 
1132 
Print(FILE * out)1133 void DebugCommand::Print(FILE* out) { fprintf(out, "%s", name()); }
1134 
1135 
Match(const char * name,const char ** aliases)1136 bool DebugCommand::Match(const char* name, const char** aliases) {
1137   for (const char** current = aliases; *current != NULL; current++) {
1138     if (strcmp(name, *current) == 0) {
1139       return true;
1140     }
1141   }
1142 
1143   return false;
1144 }
1145 
1146 
Parse(char * line)1147 DebugCommand* DebugCommand::Parse(char* line) {
1148   std::vector<Token*> args;
1149 
1150   for (char* chunk = strtok(line, " \t"); chunk != NULL;
1151        chunk = strtok(NULL, " \t")) {
1152     char* dot = strchr(chunk, '.');
1153     if (dot != NULL) {
1154       // 'Token.format'.
1155       Token* format = FormatToken::Tokenize(dot + 1);
1156       if (format != NULL) {
1157         *dot = '\0';
1158         args.push_back(Token::Tokenize(chunk));
1159         args.push_back(format);
1160       } else {
1161         // Error while parsing the format, push the UnknownToken so an error
1162         // can be accurately reported.
1163         args.push_back(Token::Tokenize(chunk));
1164       }
1165     } else {
1166       args.push_back(Token::Tokenize(chunk));
1167     }
1168   }
1169 
1170   if (args.size() == 0) {
1171     return NULL;
1172   }
1173 
1174   if (!args[0]->IsIdentifier()) {
1175     return new InvalidCommand(args, 0, "command name is not valid");
1176   }
1177 
1178   const char* name = IdentifierToken::Cast(args[0])->value();
1179 #define RETURN_IF_MATCH(Command)        \
1180   if (Match(name, Command::kAliases)) { \
1181     return Command::Build(args);        \
1182   }
1183   DEBUG_COMMAND_LIST(RETURN_IF_MATCH);
1184 #undef RETURN_IF_MATCH
1185 
1186   return new UnknownCommand(args);
1187 }
1188 
1189 
PrintHelp(const char ** aliases,const char * args,const char * help)1190 void DebugCommand::PrintHelp(const char** aliases,
1191                              const char* args,
1192                              const char* help) {
1193   VIXL_ASSERT(aliases[0] != NULL);
1194   VIXL_ASSERT(help != NULL);
1195 
1196   printf("\n----\n\n");
1197   for (const char** current = aliases; *current != NULL; current++) {
1198     if (args != NULL) {
1199       printf("%s %s\n", *current, args);
1200     } else {
1201       printf("%s\n", *current);
1202     }
1203   }
1204   printf("\n%s\n", help);
1205 }
1206 
1207 
Run(Debugger * debugger)1208 bool HelpCommand::Run(Debugger* debugger) {
1209   VIXL_ASSERT(debugger->IsDebuggerActive());
1210   USE(debugger);
1211 
1212 #define PRINT_HELP(Command)                    \
1213   DebugCommand::PrintHelp(Command::kAliases,   \
1214                           Command::kArguments, \
1215                           Command::kHelp);
1216   DEBUG_COMMAND_LIST(PRINT_HELP);
1217 #undef PRINT_HELP
1218   printf("\n----\n\n");
1219 
1220   return false;
1221 }
1222 
1223 
Build(std::vector<Token * > args)1224 DebugCommand* HelpCommand::Build(std::vector<Token*> args) {
1225   if (args.size() != 1) {
1226     return new InvalidCommand(args, -1, "too many arguments");
1227   }
1228 
1229   return new HelpCommand(args[0]);
1230 }
1231 
1232 
Run(Debugger * debugger)1233 bool ContinueCommand::Run(Debugger* debugger) {
1234   VIXL_ASSERT(debugger->IsDebuggerActive());
1235 
1236   debugger->DeactivateDebugger();
1237   return true;
1238 }
1239 
1240 
Build(std::vector<Token * > args)1241 DebugCommand* ContinueCommand::Build(std::vector<Token*> args) {
1242   if (args.size() != 1) {
1243     return new InvalidCommand(args, -1, "too many arguments");
1244   }
1245 
1246   return new ContinueCommand(args[0]);
1247 }
1248 
1249 
Run(Debugger * debugger)1250 bool StepCommand::Run(Debugger* debugger) {
1251   VIXL_ASSERT(debugger->IsDebuggerActive());
1252 
1253   // To avoid recursive calls to the debugger shell when hitting breakpoints
1254   // while stepping, stepping is implemented by telling the debugger how many
1255   // instructions to execute before starting the shell again.
1256   int64_t steps = count();
1257   if (steps <= 0) {
1258     if (steps < 0) {
1259       printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
1260     }
1261     // Execute nothing and stay in the shell.
1262     return false;
1263   } else {
1264     debugger->SetSteps(steps - 1);
1265     // Relinquish control to the debugger. It will execute the next instruction,
1266     // followed by `steps - 1` instructions, before starting the shell again.
1267     // (Unless another breakpoint is hit in the meantime.)
1268     return true;
1269   }
1270 }
1271 
1272 
Print(FILE * out)1273 void StepCommand::Print(FILE* out) {
1274   fprintf(out, "%s %" PRId64 "", name(), count());
1275 }
1276 
1277 
Build(std::vector<Token * > args)1278 DebugCommand* StepCommand::Build(std::vector<Token*> args) {
1279   IntegerToken* count = NULL;
1280   switch (args.size()) {
1281     case 1: {  // step [1]
1282       count = new IntegerToken(1);
1283       break;
1284     }
1285     case 2: {  // step n
1286       Token* first = args[1];
1287       if (!first->IsInteger()) {
1288         return new InvalidCommand(args, 1, "expects int");
1289       }
1290       count = IntegerToken::Cast(first);
1291       break;
1292     }
1293     default:
1294       return new InvalidCommand(args, -1, "too many arguments");
1295   }
1296 
1297   return new StepCommand(args[0], count);
1298 }
1299 
1300 
Run(Debugger * debugger)1301 bool SkipCommand::Run(Debugger* debugger) {
1302   VIXL_ASSERT(debugger->IsDebuggerActive());
1303 
1304   int64_t steps = count();
1305   if (steps < 0) {
1306     printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
1307   } else {
1308     printf("Skipping over %" PRId64 " instructions:\n", steps);
1309     debugger->PrintInstructions(debugger->ReadPc(), steps, "Skip: ");
1310     debugger->WritePc(debugger->ReadPc() + steps * kInstructionSize);
1311     debugger->PrintNextInstruction();
1312   }
1313 
1314   return false;
1315 }
1316 
1317 
Print(FILE * out)1318 void SkipCommand::Print(FILE* out) {
1319   fprintf(out, "%s %" PRId64 "", name(), count());
1320 }
1321 
1322 
Build(std::vector<Token * > args)1323 DebugCommand* SkipCommand::Build(std::vector<Token*> args) {
1324   IntegerToken* count = NULL;
1325   switch (args.size()) {
1326     case 1: {  // step [1]
1327       count = new IntegerToken(1);
1328       break;
1329     }
1330     case 2: {  // step n
1331       Token* first = args[1];
1332       if (!first->IsInteger()) {
1333         return new InvalidCommand(args, 1, "expects int");
1334       }
1335       count = IntegerToken::Cast(first);
1336       break;
1337     }
1338     default:
1339       return new InvalidCommand(args, -1, "too many arguments");
1340   }
1341 
1342   return new SkipCommand(args[0], count);
1343 }
1344 
1345 
Build(std::vector<Token * > args)1346 DebugCommand* DisasmCommand::Build(std::vector<Token*> args) {
1347   IntegerToken* count = NULL;
1348   switch (args.size()) {
1349     case 1: {  // disasm [10]
1350       count = new IntegerToken(10);
1351       break;
1352     }
1353     case 2: {  // disasm n
1354       Token* first = args[1];
1355       if (!first->IsInteger()) {
1356         return new InvalidCommand(args, 1, "expects int");
1357       }
1358 
1359       count = IntegerToken::Cast(first);
1360       break;
1361     }
1362     default:
1363       return new InvalidCommand(args, -1, "too many arguments");
1364   }
1365 
1366   Token* target = new IdentifierToken("pc");
1367   FormatToken* format = new Format<uint32_t>("%08" PRIx32, 'i');
1368   return new ExamineCommand(args[0], target, format, count);
1369 }
1370 
1371 
Print(FILE * out)1372 void PrintCommand::Print(FILE* out) {
1373   fprintf(out, "%s ", name());
1374   target()->Print(out);
1375   if (format() != NULL) format()->Print(out);
1376 }
1377 
1378 
Run(Debugger * debugger)1379 bool PrintCommand::Run(Debugger* debugger) {
1380   VIXL_ASSERT(debugger->IsDebuggerActive());
1381 
1382   Token* tok = target();
1383   if (tok->IsIdentifier()) {
1384     char* identifier = IdentifierToken::Cast(tok)->value();
1385     if (strcmp(identifier, "regs") == 0) {
1386       debugger->PrintRegisters();
1387     } else if (strcmp(identifier, "fpregs") == 0) {
1388       debugger->PrintVRegisters();
1389     } else if (strcmp(identifier, "sysregs") == 0) {
1390       debugger->PrintSystemRegisters();
1391     } else if (strcmp(identifier, "pc") == 0) {
1392       printf("pc = %16p\n", reinterpret_cast<const void*>(debugger->ReadPc()));
1393     } else {
1394       printf(" ** Unknown identifier to print: %s **\n", identifier);
1395     }
1396 
1397     return false;
1398   }
1399 
1400   FormatToken* format_tok = format();
1401   VIXL_ASSERT(format_tok != NULL);
1402   if (format_tok->GetTypeCode() == 'i') {
1403     // TODO(all): Add support for instruction disassembly.
1404     printf(" ** unsupported format: instructions **\n");
1405     return false;
1406   }
1407 
1408   if (tok->IsRegister()) {
1409     RegisterToken* reg_tok = RegisterToken::Cast(tok);
1410     Register reg = reg_tok->value();
1411     debugger->PrintRegister(reg, reg_tok->Name(), format_tok);
1412     return false;
1413   }
1414 
1415   if (tok->IsFPRegister()) {
1416     FPRegister fpreg = FPRegisterToken::Cast(tok)->value();
1417     debugger->PrintFPRegister(fpreg, format_tok);
1418     return false;
1419   }
1420 
1421   VIXL_UNREACHABLE();
1422   return false;
1423 }
1424 
1425 
Build(std::vector<Token * > args)1426 DebugCommand* PrintCommand::Build(std::vector<Token*> args) {
1427   if (args.size() < 2) {
1428     return new InvalidCommand(args, -1, "too few arguments");
1429   }
1430 
1431   Token* target = args[1];
1432   if (!target->IsRegister() && !target->IsFPRegister() &&
1433       !target->IsIdentifier()) {
1434     return new InvalidCommand(args, 1, "expects reg or identifier");
1435   }
1436 
1437   FormatToken* format = NULL;
1438   int target_size = 0;
1439   if (target->IsRegister()) {
1440     Register reg = RegisterToken::Cast(target)->value();
1441     target_size = reg.GetSizeInBytes();
1442   } else if (target->IsFPRegister()) {
1443     FPRegister fpreg = FPRegisterToken::Cast(target)->value();
1444     target_size = fpreg.GetSizeInBytes();
1445   }
1446   // If the target is an identifier there must be no format. This is checked
1447   // in the switch statement below.
1448 
1449   switch (args.size()) {
1450     case 2: {
1451       if (target->IsRegister()) {
1452         switch (target_size) {
1453           case 4:
1454             format = new Format<uint32_t>("%08" PRIx32, 'x');
1455             break;
1456           case 8:
1457             format = new Format<uint64_t>("%016" PRIx64, 'x');
1458             break;
1459           default:
1460             VIXL_UNREACHABLE();
1461         }
1462       } else if (target->IsFPRegister()) {
1463         switch (target_size) {
1464           case 4:
1465             format = new Format<float>("%8g", 'f');
1466             break;
1467           case 8:
1468             format = new Format<double>("%8g", 'f');
1469             break;
1470           default:
1471             VIXL_UNREACHABLE();
1472         }
1473       }
1474       break;
1475     }
1476     case 3: {
1477       if (target->IsIdentifier()) {
1478         return new InvalidCommand(args,
1479                                   2,
1480                                   "format is only allowed with registers");
1481       }
1482 
1483       Token* second = args[2];
1484       if (!second->IsFormat()) {
1485         return new InvalidCommand(args, 2, "expects format");
1486       }
1487       format = FormatToken::Cast(second);
1488 
1489       if (format->SizeOf() > target_size) {
1490         return new InvalidCommand(args, 2, "format too wide");
1491       }
1492 
1493       break;
1494     }
1495     default:
1496       return new InvalidCommand(args, -1, "too many arguments");
1497   }
1498 
1499   return new PrintCommand(args[0], target, format);
1500 }
1501 
1502 
Run(Debugger * debugger)1503 bool ExamineCommand::Run(Debugger* debugger) {
1504   VIXL_ASSERT(debugger->IsDebuggerActive());
1505 
1506   uint8_t* address = target()->ToAddress(debugger);
1507   int64_t amount = count()->value();
1508   if (format()->GetTypeCode() == 'i') {
1509     debugger->PrintInstructions(address, amount);
1510   } else {
1511     debugger->PrintMemory(address, format(), amount);
1512   }
1513 
1514   return false;
1515 }
1516 
1517 
Print(FILE * out)1518 void ExamineCommand::Print(FILE* out) {
1519   fprintf(out, "%s ", name());
1520   format()->Print(out);
1521   target()->Print(out);
1522 }
1523 
1524 
Build(std::vector<Token * > args)1525 DebugCommand* ExamineCommand::Build(std::vector<Token*> args) {
1526   if (args.size() < 2) {
1527     return new InvalidCommand(args, -1, "too few arguments");
1528   }
1529 
1530   Token* target = args[1];
1531   if (!target->CanAddressMemory()) {
1532     return new InvalidCommand(args, 1, "expects address");
1533   }
1534 
1535   FormatToken* format = NULL;
1536   IntegerToken* count = NULL;
1537 
1538   switch (args.size()) {
1539     case 2: {  // mem addr[.x64] [10]
1540       format = new Format<uint64_t>("%016" PRIx64, 'x');
1541       count = new IntegerToken(10);
1542       break;
1543     }
1544     case 3: {  // mem addr.format [10]
1545                // mem addr[.x64] n
1546       Token* second = args[2];
1547       if (second->IsFormat()) {
1548         format = FormatToken::Cast(second);
1549         count = new IntegerToken(10);
1550         break;
1551       } else if (second->IsInteger()) {
1552         format = new Format<uint64_t>("%016" PRIx64, 'x');
1553         count = IntegerToken::Cast(second);
1554       } else {
1555         return new InvalidCommand(args, 2, "expects format or integer");
1556       }
1557       VIXL_UNREACHABLE();
1558       break;
1559     }
1560     case 4: {  // mem addr.format n
1561       Token* second = args[2];
1562       Token* third = args[3];
1563       if (!second->IsFormat() || !third->IsInteger()) {
1564         return new InvalidCommand(args, -1, "expects addr[.format] [n]");
1565       }
1566       format = FormatToken::Cast(second);
1567       count = IntegerToken::Cast(third);
1568       break;
1569     }
1570     default:
1571       return new InvalidCommand(args, -1, "too many arguments");
1572   }
1573 
1574   return new ExamineCommand(args[0], target, format, count);
1575 }
1576 
1577 
~UnknownCommand()1578 UnknownCommand::~UnknownCommand() {
1579   const size_t size = args_.size();
1580   for (size_t i = 0; i < size; ++i) {
1581     delete args_[i];
1582   }
1583 }
1584 
1585 
Run(Debugger * debugger)1586 bool UnknownCommand::Run(Debugger* debugger) {
1587   VIXL_ASSERT(debugger->IsDebuggerActive());
1588   USE(debugger);
1589 
1590   printf(" ** Unknown Command:");
1591   const size_t size = args_.size();
1592   for (size_t i = 0; i < size; ++i) {
1593     printf(" ");
1594     args_[i]->Print(stdout);
1595   }
1596   printf(" **\n");
1597 
1598   return false;
1599 }
1600 
1601 
~InvalidCommand()1602 InvalidCommand::~InvalidCommand() {
1603   const size_t size = args_.size();
1604   for (size_t i = 0; i < size; ++i) {
1605     delete args_[i];
1606   }
1607 }
1608 
1609 
Run(Debugger * debugger)1610 bool InvalidCommand::Run(Debugger* debugger) {
1611   VIXL_ASSERT(debugger->IsDebuggerActive());
1612   USE(debugger);
1613 
1614   printf(" ** Invalid Command:");
1615   const size_t size = args_.size();
1616   for (size_t i = 0; i < size; ++i) {
1617     printf(" ");
1618     if (i == static_cast<size_t>(index_)) {
1619       printf(">>");
1620       args_[i]->Print(stdout);
1621       printf("<<");
1622     } else {
1623       args_[i]->Print(stdout);
1624     }
1625   }
1626   printf(" **\n");
1627   printf(" ** %s\n", cause_);
1628 
1629   return false;
1630 }
1631 
1632 }  // namespace aarch64
1633 }  // namespace vixl
1634 
1635 #endif  // VIXL_INCLUDE_SIMULATOR_AARCH64
1636