tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Debugger-vixl.cpp (40929B)


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