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, ®_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