diff options
author | Jacob Bramley <jacob.bramley@arm.com> | 2018-07-03 17:58:44 +0100 |
---|---|---|
committer | Jacob Bramley <jacob.bramley@arm.com> | 2018-07-04 11:10:17 +0100 |
commit | c919d87b7fd272eb8bfb05b395e5fc0b6dbc289c (patch) | |
tree | 41b6ee9a3d90923cbaccba06576e1e7e6d6c8b15 | |
parent | d6166b0a0c6168dddcf1529b7271c3e4b7807372 (diff) |
Remove the Debugger.
The Debugger isn't well maintained, and its presence has an impact on testing
and validation time.
Change-Id: I9ad664ec3150e7f4ea1da2e3201682fb5684c610
-rw-r--r-- | examples/aarch64/debugger.cc | 73 | ||||
-rw-r--r-- | examples/aarch64/examples.h | 2 | ||||
-rw-r--r-- | src/aarch64/debugger-aarch64.cc | 1589 | ||||
-rw-r--r-- | src/aarch64/debugger-aarch64.h | 109 | ||||
-rw-r--r-- | src/aarch64/macro-assembler-aarch64.h | 5 | ||||
-rw-r--r-- | test/aarch64/examples/test-examples.cc | 3 | ||||
-rw-r--r-- | test/aarch64/test-assembler-aarch64.cc | 47 | ||||
-rw-r--r-- | test/aarch64/test-simulator-aarch64.cc | 39 | ||||
-rw-r--r-- | test/aarch64/test-trace-aarch64.cc | 1 | ||||
-rw-r--r-- | test/test-runner.cc | 8 | ||||
-rw-r--r-- | test/test-runner.h | 6 | ||||
-rwxr-xr-x | tools/test.py | 17 |
12 files changed, 46 insertions, 1853 deletions
diff --git a/examples/aarch64/debugger.cc b/examples/aarch64/debugger.cc deleted file mode 100644 index 560817df..00000000 --- a/examples/aarch64/debugger.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2014, VIXL authors -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of ARM Limited nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "examples.h" - - -// This is an interactive example, not to be used for testing. -#ifndef TEST_EXAMPLES - -#define __ masm-> - -// The aim is to let the user "play" with the debugger. Brk will trigger the -// debugger shell. -void GenerateBreak(MacroAssembler* masm) { - Label hop; - __ Brk(); - __ Nop(); - __ B(&hop); - __ Nop(); - __ Bind(&hop); - __ Mov(x1, 123); - __ Mov(x2, 456); - __ Add(x0, x1, x2); - __ Ret(); -} - - -#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 -int main(void) { - MacroAssembler masm; - Decoder decoder; - Debugger debugger(&decoder); - - // Generate the code for the example function. - Label start; - masm.Bind(&start); - GenerateBreak(&masm); - masm.FinalizeCode(); - - // Run the example function. - debugger.RunFrom(masm.GetLabelAddress<Instruction*>(&start)); - printf("Debugger example run\n"); - - return 0; -} -#else -// Without the simulator there is nothing to test. -int main(void) { return 0; } -#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 -#endif // TEST_EXAMPLES diff --git a/examples/aarch64/examples.h b/examples/aarch64/examples.h index 182b8138..31e65806 100644 --- a/examples/aarch64/examples.h +++ b/examples/aarch64/examples.h @@ -27,8 +27,8 @@ #ifndef VIXL_EXAMPLE_EXAMPLES_H_ #define VIXL_EXAMPLE_EXAMPLES_H_ -#include "aarch64/debugger-aarch64.h" #include "aarch64/macro-assembler-aarch64.h" +#include "aarch64/simulator-aarch64.h" using namespace vixl; using namespace vixl::aarch64; diff --git a/src/aarch64/debugger-aarch64.cc b/src/aarch64/debugger-aarch64.cc deleted file mode 100644 index 9128bd02..00000000 --- a/src/aarch64/debugger-aarch64.cc +++ /dev/null @@ -1,1589 +0,0 @@ -// Copyright 2014, VIXL authors -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of ARM Limited nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 - -#include "debugger-aarch64.h" - -namespace vixl { -namespace aarch64 { - -// List of commands supported by the debugger. -#define DEBUG_COMMAND_LIST(C) \ - C(HelpCommand) \ - C(ContinueCommand) \ - C(StepCommand) \ - C(SkipCommand) \ - C(DisasmCommand) \ - C(PrintCommand) \ - C(ExamineCommand) - -// Debugger command lines are broken up in token of different type to make -// processing easier later on. -class Token { - public: - virtual ~Token() {} - - // Token type. - virtual bool IsRegister() const { return false; } - virtual bool IsFPRegister() const { return false; } - virtual bool IsIdentifier() const { return false; } - virtual bool IsAddress() const { return false; } - virtual bool IsInteger() const { return false; } - virtual bool IsFormat() const { return false; } - virtual bool IsUnknown() const { return false; } - // Token properties. - virtual bool CanAddressMemory() const { return false; } - virtual uint8_t* ToAddress(Debugger* debugger) const = 0; - virtual void Print(FILE* out = stdout) const = 0; - - static Token* Tokenize(const char* arg); -}; - -// Tokens often hold one value. -template <typename T> -class ValueToken : public Token { - public: - explicit ValueToken(T value) : value_(value) {} - ValueToken() {} - - T value() const { return value_; } - - VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const - VIXL_OVERRIDE { - USE(debugger); - VIXL_ABORT(); - } - - protected: - T value_; -}; - -// Integer registers (X or W) and their aliases. -// Format: wn or xn with 0 <= n < 32 or a name in the aliases list. -class RegisterToken : public ValueToken<const Register> { - public: - explicit RegisterToken(const Register reg) - : ValueToken<const Register>(reg) {} - - virtual bool IsRegister() const VIXL_OVERRIDE { return true; } - virtual bool CanAddressMemory() const VIXL_OVERRIDE { - return value().Is64Bits(); - } - virtual uint8_t* ToAddress(Debugger* debugger) const VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - const char* Name() const; - - static Token* Tokenize(const char* arg); - static RegisterToken* Cast(Token* tok) { - VIXL_ASSERT(tok->IsRegister()); - return reinterpret_cast<RegisterToken*>(tok); - } - - private: - static const int kMaxAliasNumber = 4; - static const char* kXAliases[kNumberOfRegisters][kMaxAliasNumber]; - static const char* kWAliases[kNumberOfRegisters][kMaxAliasNumber]; -}; - -// Floating point registers (D or S). -// Format: sn or dn with 0 <= n < 32. -class FPRegisterToken : public ValueToken<const FPRegister> { - public: - explicit FPRegisterToken(const FPRegister fpreg) - : ValueToken<const FPRegister>(fpreg) {} - - virtual bool IsFPRegister() const VIXL_OVERRIDE { return true; } - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - - static Token* Tokenize(const char* arg); - static FPRegisterToken* Cast(Token* tok) { - VIXL_ASSERT(tok->IsFPRegister()); - return reinterpret_cast<FPRegisterToken*>(tok); - } -}; - - -// Non-register identifiers. -// Format: Alphanumeric string starting with a letter. -class IdentifierToken : public ValueToken<char*> { - public: - explicit IdentifierToken(const char* name) { - size_t size = strlen(name) + 1; - value_ = new char[size]; - strncpy(value_, name, size); - } - virtual ~IdentifierToken() { delete[] value_; } - - virtual bool IsIdentifier() const VIXL_OVERRIDE { return true; } - virtual bool CanAddressMemory() const VIXL_OVERRIDE { - return strcmp(value(), "pc") == 0; - } - virtual uint8_t* ToAddress(Debugger* debugger) const VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - - static Token* Tokenize(const char* arg); - static IdentifierToken* Cast(Token* tok) { - VIXL_ASSERT(tok->IsIdentifier()); - return reinterpret_cast<IdentifierToken*>(tok); - } -}; - -// 64-bit address literal. -// Format: 0x... with up to 16 hexadecimal digits. -class AddressToken : public ValueToken<uint8_t*> { - public: - explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {} - - virtual bool IsAddress() const VIXL_OVERRIDE { return true; } - virtual bool CanAddressMemory() const VIXL_OVERRIDE { return true; } - virtual uint8_t* ToAddress(Debugger* debugger) const VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - - static Token* Tokenize(const char* arg); - static AddressToken* Cast(Token* tok) { - VIXL_ASSERT(tok->IsAddress()); - return reinterpret_cast<AddressToken*>(tok); - } -}; - - -// 64-bit decimal integer literal. -// Format: n. -class IntegerToken : public ValueToken<int64_t> { - public: - explicit IntegerToken(int64_t value) : ValueToken<int64_t>(value) {} - - virtual bool IsInteger() const VIXL_OVERRIDE { return true; } - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - - static Token* Tokenize(const char* arg); - static IntegerToken* Cast(Token* tok) { - VIXL_ASSERT(tok->IsInteger()); - return reinterpret_cast<IntegerToken*>(tok); - } -}; - -// Literal describing how to print a chunk of data (up to 64 bits). -// Format: .ln -// where l (letter) is one of -// * x: hexadecimal -// * s: signed integer -// * u: unsigned integer -// * f: floating point -// * i: instruction -// and n (size) is one of 8, 16, 32 and 64. n should be omitted for -// instructions. -class FormatToken : public Token { - public: - FormatToken() {} - - virtual bool IsFormat() const VIXL_OVERRIDE { return true; } - virtual int SizeOf() const = 0; - virtual char GetTypeCode() const = 0; - virtual void PrintData(void* data, FILE* out = stdout) const = 0; - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE = 0; - - VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const - VIXL_OVERRIDE { - USE(debugger); - VIXL_ABORT(); - } - - static Token* Tokenize(const char* arg); - static FormatToken* Cast(Token* tok) { - VIXL_ASSERT(tok->IsFormat()); - return reinterpret_cast<FormatToken*>(tok); - } -}; - - -template <typename T> -class Format : public FormatToken { - public: - Format(const char* fmt, char type_code) : fmt_(fmt), type_code_(type_code) {} - - virtual int SizeOf() const VIXL_OVERRIDE { return sizeof(T); } - virtual char GetTypeCode() const VIXL_OVERRIDE { return type_code_; } - virtual void PrintData(void* data, FILE* out = stdout) const VIXL_OVERRIDE { - T value; - memcpy(&value, data, sizeof(value)); - fprintf(out, fmt_, value); - } - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - - private: - const char* fmt_; - char type_code_; -}; - -// Tokens which don't fit any of the above. -class UnknownToken : public Token { - public: - explicit UnknownToken(const char* arg) { - size_t size = strlen(arg) + 1; - unknown_ = new char[size]; - strncpy(unknown_, arg, size); - } - virtual ~UnknownToken() { delete[] unknown_; } - VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const - VIXL_OVERRIDE { - USE(debugger); - VIXL_ABORT(); - } - - virtual bool IsUnknown() const VIXL_OVERRIDE { return true; } - virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE; - - private: - char* unknown_; -}; - - -// All debugger commands must subclass DebugCommand and implement Run, Print -// and Build. Commands must also define kHelp and kAliases. -class DebugCommand { - public: - explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {} - DebugCommand() : name_(NULL) {} - virtual ~DebugCommand() { delete name_; } - - const char* name() { return name_->value(); } - // Run the command on the given debugger. - // Return `true` if control should be given back to the debugger. - virtual bool Run(Debugger* debugger) = 0; - virtual void Print(FILE* out = stdout); - - static bool Match(const char* name, const char** aliases); - static DebugCommand* Parse(char* line); - static void PrintHelp(const char** aliases, - const char* args, - const char* help); - - private: - IdentifierToken* name_; -}; - -// For all commands below see their respective kHelp and kAliases in -// debugger-aarch64.cc -class HelpCommand : public DebugCommand { - public: - explicit HelpCommand(Token* name) : DebugCommand(name) {} - - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; -}; - - -class ContinueCommand : public DebugCommand { - public: - explicit ContinueCommand(Token* name) : DebugCommand(name) {} - - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; -}; - - -class StepCommand : public DebugCommand { - public: - StepCommand(Token* name, IntegerToken* count) - : DebugCommand(name), count_(count) {} - virtual ~StepCommand() { delete count_; } - - int64_t count() { return count_->value(); } - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) VIXL_OVERRIDE; - - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; - - private: - IntegerToken* count_; -}; - -class SkipCommand : public DebugCommand { - public: - SkipCommand(Token* name, IntegerToken* count) - : DebugCommand(name), count_(count) {} - virtual ~SkipCommand() { delete count_; } - - int64_t count() { return count_->value(); } - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) VIXL_OVERRIDE; - - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; - - private: - IntegerToken* count_; -}; - -class DisasmCommand : public DebugCommand { - public: - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; -}; - - -class PrintCommand : public DebugCommand { - public: - PrintCommand(Token* name, Token* target, FormatToken* format) - : DebugCommand(name), target_(target), format_(format) {} - virtual ~PrintCommand() { - delete target_; - delete format_; - } - - Token* target() { return target_; } - FormatToken* format() { return format_; } - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) VIXL_OVERRIDE; - - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; - - private: - Token* target_; - FormatToken* format_; -}; - -class ExamineCommand : public DebugCommand { - public: - ExamineCommand(Token* name, - Token* target, - FormatToken* format, - IntegerToken* count) - : DebugCommand(name), target_(target), format_(format), count_(count) {} - virtual ~ExamineCommand() { - delete target_; - delete format_; - delete count_; - } - - Token* target() { return target_; } - FormatToken* format() { return format_; } - IntegerToken* count() { return count_; } - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - virtual void Print(FILE* out = stdout) VIXL_OVERRIDE; - - static DebugCommand* Build(std::vector<Token*> args); - - static const char* kHelp; - static const char* kAliases[]; - static const char* kArguments; - - private: - Token* target_; - FormatToken* format_; - IntegerToken* count_; -}; - -// Commands which name does not match any of the known commnand. -class UnknownCommand : public DebugCommand { - public: - explicit UnknownCommand(std::vector<Token*> args) : args_(args) {} - virtual ~UnknownCommand(); - - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - - private: - std::vector<Token*> args_; -}; - -// Commands which name match a known command but the syntax is invalid. -class InvalidCommand : public DebugCommand { - public: - InvalidCommand(std::vector<Token*> args, int index, const char* cause) - : args_(args), index_(index), cause_(cause) {} - virtual ~InvalidCommand(); - - virtual bool Run(Debugger* debugger) VIXL_OVERRIDE; - - private: - std::vector<Token*> args_; - int index_; - const char* cause_; -}; - -const char* HelpCommand::kAliases[] = {"help", NULL}; -const char* HelpCommand::kArguments = NULL; -const char* HelpCommand::kHelp = " Print this help."; - -const char* ContinueCommand::kAliases[] = {"continue", "c", NULL}; -const char* ContinueCommand::kArguments = NULL; -const char* ContinueCommand::kHelp = " Resume execution."; - -const char* StepCommand::kAliases[] = {"stepi", "si", NULL}; -const char* StepCommand::kArguments = "[n = 1]"; -const char* StepCommand::kHelp = " Execute n next instruction(s)."; - -const char* SkipCommand::kAliases[] = {"skip", NULL}; -const char* SkipCommand::kArguments = "[n = 1]"; -const char* SkipCommand::kHelp = " Skip the next n instruction(s)."; - -const char* DisasmCommand::kAliases[] = {"disasm", "di", NULL}; -const char* DisasmCommand::kArguments = "[n = 10]"; -const char* DisasmCommand::kHelp = - " Disassemble n instruction(s) at pc.\n" - " This command is equivalent to x pc.i [n = 10]."; - -const char* PrintCommand::kAliases[] = {"print", "p", NULL}; -const char* PrintCommand::kArguments = "<entity>[.format]"; -const char* PrintCommand::kHelp = - " Print the given entity according to the given format.\n" - " The format parameter only affects individual registers; it is ignored\n" - " for other entities.\n" - " <entity> can be one of the following:\n" - " * A register name (such as x0, s1, ...).\n" - " * 'regs', to print all integer (W and X) registers.\n" - " * 'fpregs' to print all floating-point (S and D) registers.\n" - " * 'sysregs' to print all system registers (including NZCV).\n" - " * 'pc' to print the current program counter.\n"; - -const char* ExamineCommand::kAliases[] = {"m", "mem", "x", NULL}; -const char* ExamineCommand::kArguments = "<addr>[.format] [n = 10]"; -const char* ExamineCommand::kHelp = - " Examine memory. Print n items of memory at address <addr> according to\n" - " the given [.format].\n" - " Addr can be an immediate address, a register name or pc.\n" - " Format is made of a type letter: 'x' (hexadecimal), 's' (signed), 'u'\n" - " (unsigned), 'f' (floating point), i (instruction) and a size in bits\n" - " when appropriate (8, 16, 32, 64)\n" - " E.g 'x sp.x64' will print 10 64-bit words from the stack in\n" - " hexadecimal format."; - -const char* RegisterToken::kXAliases[kNumberOfRegisters][kMaxAliasNumber] = - {{"x0", NULL}, {"x1", NULL}, {"x2", NULL}, - {"x3", NULL}, {"x4", NULL}, {"x5", NULL}, - {"x6", NULL}, {"x7", NULL}, {"x8", NULL}, - {"x9", NULL}, {"x10", NULL}, {"x11", NULL}, - {"x12", NULL}, {"x13", NULL}, {"x14", NULL}, - {"x15", NULL}, {"ip0", "x16", NULL}, {"ip1", "x17", NULL}, - {"x18", "pr", NULL}, {"x19", NULL}, {"x20", NULL}, - {"x21", NULL}, {"x22", NULL}, {"x23", NULL}, - {"x24", NULL}, {"x25", NULL}, {"x26", NULL}, - {"x27", NULL}, {"x28", NULL}, {"fp", "x29", NULL}, - {"lr", "x30", NULL}, {"sp", NULL}}; - -const char* RegisterToken::kWAliases[kNumberOfRegisters][kMaxAliasNumber] = - {{"w0", NULL}, {"w1", NULL}, {"w2", NULL}, {"w3", NULL}, {"w4", NULL}, - {"w5", NULL}, {"w6", NULL}, {"w7", NULL}, {"w8", NULL}, {"w9", NULL}, - {"w10", NULL}, {"w11", NULL}, {"w12", NULL}, {"w13", NULL}, {"w14", NULL}, - {"w15", NULL}, {"w16", NULL}, {"w17", NULL}, {"w18", NULL}, {"w19", NULL}, - {"w20", NULL}, {"w21", NULL}, {"w22", NULL}, {"w23", NULL}, {"w24", NULL}, - {"w25", NULL}, {"w26", NULL}, {"w27", NULL}, {"w28", NULL}, {"w29", NULL}, - {"w30", NULL}, {"wsp", NULL}}; - - -Debugger::Debugger(Decoder* decoder, FILE* stream) - : Simulator(decoder, stream), - debugger_active_(false), - steps_(0), - last_command_(NULL) { - disasm_ = new PrintDisassembler(stdout); - printer_ = new Decoder(); - printer_->AppendVisitor(disasm_); -} - -Debugger::~Debugger() { - delete disasm_; - delete printer_; -} - - -void Debugger::Run() { - // Flush any written registers before executing anything, so that - // manually-set registers are logged _before_ the first instruction. - LogAllWrittenRegisters(); - - while (pc_ != kEndOfSimAddress) { - if (IsDebuggerActive()) RunDebuggerShell(); - ExecuteInstruction(); - } -} - - -void Debugger::PrintInstructions(const void* address, - int64_t count, - const char* prefix) { - if (count == 0) { - return; - } - - const Instruction* from = Instruction::CastConst(address); - if (count < 0) { - count = -count; - from -= (count - 1) * kInstructionSize; - } - const Instruction* to = from + count * kInstructionSize; - - for (const Instruction* current = from; current < to; - current = current->GetNextInstruction()) { - printf("%s", prefix); - printer_->Decode(current); - } -} - - -void Debugger::PrintMemory(const uint8_t* address, - const FormatToken* format, - int64_t count) { - if (count == 0) { - return; - } - - const uint8_t* from = address; - int size = format->SizeOf(); - if (count < 0) { - count = -count; - from -= (count - 1) * size; - } - const uint8_t* to = from + count * size; - - for (const uint8_t* current = from; current < to; current += size) { - if (((current - from) % 8) == 0) { - printf("\n%p: ", reinterpret_cast<const void*>(current)); - } - - uint64_t data = Memory::Read<uint64_t>(current); - format->PrintData(&data); - printf(" "); - } - printf("\n\n"); -} - - -void Debugger::PrintRegister(const Register& target_reg, - const char* name, - const FormatToken* format) { - const uint64_t reg_size = target_reg.GetSizeInBits(); - const uint64_t format_size = format->SizeOf() * 8; - const uint64_t count = reg_size / format_size; - const uint64_t mask = 0xffffffffffffffff >> (64 - format_size); - const uint64_t reg_value = - ReadRegister<uint64_t>(target_reg.GetCode(), Reg31IsStackPointer); - VIXL_ASSERT(count > 0); - - printf("%s = ", name); - for (uint64_t i = 1; i <= count; i++) { - uint64_t data = reg_value >> (reg_size - (i * format_size)); - data &= mask; - format->PrintData(&data); - printf(" "); - } - printf("\n"); -} - - -// TODO(all): fix this for vector registers. -void Debugger::PrintFPRegister(const FPRegister& target_fpreg, - const FormatToken* format) { - const unsigned fpreg_size = target_fpreg.GetSizeInBits(); - const uint64_t format_size = format->SizeOf() * 8; - const uint64_t count = fpreg_size / format_size; - const uint64_t mask = 0xffffffffffffffff >> (64 - format_size); - const uint64_t fpreg_value = - ReadVRegister<uint64_t>(fpreg_size, target_fpreg.GetCode()); - VIXL_ASSERT(count > 0); - - if (target_fpreg.Is32Bits()) { - printf("s%u = ", target_fpreg.GetCode()); - } else { - printf("d%u = ", target_fpreg.GetCode()); - } - for (uint64_t i = 1; i <= count; i++) { - uint64_t data = fpreg_value >> (fpreg_size - (i * format_size)); - data &= mask; - format->PrintData(&data); - printf(" "); - } - printf("\n"); -} - - -void Debugger::VisitException(const Instruction* instr) { - switch (instr->Mask(ExceptionMask)) { - case BRK: - DoBreakpoint(instr); - return; - case HLT: - VIXL_FALLTHROUGH(); - default: - Simulator::VisitException(instr); - } -} - - -// Read a command. A command will be at most kMaxDebugShellLine char long and -// ends with '\n\0'. -// TODO: Should this be a utility function? -char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) { - int fgets_calls = 0; - char* end = NULL; - - printf("%s", prompt); - fflush(stdout); - - do { - if (fgets(buffer, length, stdin) == NULL) { - printf(" ** Error while reading command. **\n"); - return NULL; - } - - fgets_calls++; - end = strchr(buffer, '\n'); - } while (end == NULL); - - if (fgets_calls != 1) { - printf(" ** Command too long. **\n"); - return NULL; - } - - // Remove the newline from the end of the command. - VIXL_ASSERT(end[1] == '\0'); - VIXL_ASSERT((end - buffer) < (length - 1)); - end[0] = '\0'; - - return buffer; -} - - -void Debugger::RunDebuggerShell() { - if (IsDebuggerActive()) { - if (steps_ > 0) { - // Finish stepping first. - --steps_; - return; - } - - PrintNextInstruction(); - bool done = false; - while (!done) { - char buffer[kMaxDebugShellLine]; - char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine); - - if (line == NULL) continue; // An error occurred. - - DebugCommand* command = DebugCommand::Parse(line); - if (command != NULL) { - last_command_ = command; - } - - if (last_command_ != NULL) { - done = last_command_->Run(this); - } else { - printf("No previous command to run!\n"); - } - } - } -} - - -void Debugger::DoBreakpoint(const Instruction* instr) { - VIXL_ASSERT(instr->Mask(ExceptionMask) == BRK); - - printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<const void*>(instr)); - ActivateDebugger(); -} - - -static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) { - char* endptr = NULL; - errno = 0; // Reset errors. - uint64_t parsed = strtoul(line, &endptr, base); - - if (errno == ERANGE) { - // Overflow. - return false; - } - - if (endptr == line) { - // No digits were parsed. - return false; - } - - if (*endptr != '\0') { - // Non-digit characters present at the end. - return false; - } - - *value = parsed; - return true; -} - - -static bool StringToInt64(int64_t* value, const char* line, int base = 10) { - char* endptr = NULL; - errno = 0; // Reset errors. - int64_t parsed = strtol(line, &endptr, base); - - if (errno == ERANGE) { - // Overflow, undeflow. - return false; - } - - if (endptr == line) { - // No digits were parsed. - return false; - } - - if (*endptr != '\0') { - // Non-digit characters present at the end. - return false; - } - - *value = parsed; - return true; -} - - -Token* Token::Tokenize(const char* arg) { - if ((arg == NULL) || (*arg == '\0')) { - return NULL; - } - - // The order is important. For example Identifier::Tokenize would consider - // any register to be a valid identifier. - - Token* token = RegisterToken::Tokenize(arg); - if (token != NULL) { - return token; - } - - token = FPRegisterToken::Tokenize(arg); - if (token != NULL) { - return token; - } - - token = IdentifierToken::Tokenize(arg); - if (token != NULL) { - return token; - } - - token = AddressToken::Tokenize(arg); - if (token != NULL) { - return token; - } - - token = IntegerToken::Tokenize(arg); - if (token != NULL) { - return token; - } - - return new UnknownToken(arg); -} - - -uint8_t* RegisterToken::ToAddress(Debugger* debugger) const { - VIXL_ASSERT(CanAddressMemory()); - uint64_t reg_value = - debugger->ReadXRegister(value().GetCode(), Reg31IsStackPointer); - uint8_t* address = NULL; - memcpy(&address, ®_value, sizeof(address)); - return address; -} - - -void RegisterToken::Print(FILE* out) const { - VIXL_ASSERT(value().IsValid()); - fprintf(out, "[Register %s]", Name()); -} - - -const char* RegisterToken::Name() const { - if (value().Is32Bits()) { - return kWAliases[value().GetCode()][0]; - } else { - return kXAliases[value().GetCode()][0]; - } -} - - -Token* RegisterToken::Tokenize(const char* arg) { - for (unsigned i = 0; i < kNumberOfRegisters; i++) { - // Is it a X register or alias? - for (const char** current = kXAliases[i]; *current != NULL; current++) { - if (strcmp(arg, *current) == 0) { - return new RegisterToken(Register::GetXRegFromCode(i)); - } - } - - // Is it a W register or alias? - for (const char** current = kWAliases[i]; *current != NULL; current++) { - if (strcmp(arg, *current) == 0) { - return new RegisterToken(Register::GetWRegFromCode(i)); - } - } - } - - return NULL; -} - - -void FPRegisterToken::Print(FILE* out) const { - VIXL_ASSERT(value().IsValid()); - char prefix = value().Is32Bits() ? 's' : 'd'; - fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().GetCode()); -} - - -Token* FPRegisterToken::Tokenize(const char* arg) { - if (strlen(arg) < 2) { - return NULL; - } - - switch (*arg) { - case 's': - case 'd': - const char* cursor = arg + 1; - uint64_t code = 0; - if (!StringToUInt64(&code, cursor)) { - return NULL; - } - - if (code > kNumberOfFPRegisters) { - return NULL; - } - - VRegister fpreg = NoVReg; - switch (*arg) { - case 's': - fpreg = VRegister::GetSRegFromCode(static_cast<unsigned>(code)); - break; - case 'd': - fpreg = VRegister::GetDRegFromCode(static_cast<unsigned>(code)); - break; - default: - VIXL_UNREACHABLE(); - } - - return new FPRegisterToken(fpreg); - } - - return NULL; -} - - -uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const { - VIXL_ASSERT(CanAddressMemory()); - const Instruction* pc_value = debugger->ReadPc(); - uint8_t* address = NULL; - memcpy(&address, &pc_value, sizeof(address)); - return address; -} - -void IdentifierToken::Print(FILE* out) const { - fprintf(out, "[Identifier %s]", value()); -} - - -Token* IdentifierToken::Tokenize(const char* arg) { - if (!isalpha(arg[0])) { - return NULL; - } - - const char* cursor = arg + 1; - while ((*cursor != '\0') && isalnum(*cursor)) { - ++cursor; - } - - if (*cursor == '\0') { - return new IdentifierToken(arg); - } - - return NULL; -} - - -uint8_t* AddressToken::ToAddress(Debugger* debugger) const { - USE(debugger); - return value(); -} - - -void AddressToken::Print(FILE* out) const { - fprintf(out, "[Address %p]", reinterpret_cast<const void*>(value())); -} - - -Token* AddressToken::Tokenize(const char* arg) { - if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) { - return NULL; - } - - uint64_t ptr = 0; - if (!StringToUInt64(&ptr, arg, 16)) { - return NULL; - } - - uint8_t* address = reinterpret_cast<uint8_t*>(ptr); - return new AddressToken(address); -} - - -void IntegerToken::Print(FILE* out) const { - fprintf(out, "[Integer %" PRId64 "]", value()); -} - - -Token* IntegerToken::Tokenize(const char* arg) { - int64_t value = 0; - if (!StringToInt64(&value, arg)) { - return NULL; - } - - return new IntegerToken(value); -} - - -Token* FormatToken::Tokenize(const char* arg) { - size_t length = strlen(arg); - switch (arg[0]) { - case 'x': - case 's': - case 'u': - case 'f': - if (length == 1) return NULL; - break; - case 'i': - if (length == 1) return new Format<uint32_t>("%08" PRIx32, 'i'); - VIXL_FALLTHROUGH(); - default: - return NULL; - } - - char* endptr = NULL; - errno = 0; // Reset errors. - uint64_t count = strtoul(arg + 1, &endptr, 10); - - if (errno != 0) { - // Overflow, etc. - return NULL; - } - - if (endptr == arg) { - // No digits were parsed. - return NULL; - } - - if (*endptr != '\0') { - // There are unexpected (non-digit) characters after the number. - return NULL; - } - - switch (arg[0]) { - case 'x': - switch (count) { - case 8: - return new Format<uint8_t>("%02" PRIx8, 'x'); - case 16: - return new Format<uint16_t>("%04" PRIx16, 'x'); - case 32: - return new Format<uint32_t>("%08" PRIx32, 'x'); - case 64: - return new Format<uint64_t>("%016" PRIx64, 'x'); - default: - return NULL; - } - case 's': - switch (count) { - case 8: - return new Format<int8_t>("%4" PRId8, 's'); - case 16: - return new Format<int16_t>("%6" PRId16, 's'); - case 32: - return new Format<int32_t>("%11" PRId32, 's'); - case 64: - return new Format<int64_t>("%20" PRId64, 's'); - default: - return NULL; - } - case 'u': - switch (count) { - case 8: - return new Format<uint8_t>("%3" PRIu8, 'u'); - case 16: - return new Format<uint16_t>("%5" PRIu16, 'u'); - case 32: - return new Format<uint32_t>("%10" PRIu32, 'u'); - case 64: - return new Format<uint64_t>("%20" PRIu64, 'u'); - default: - return NULL; - } - case 'f': - switch (count) { - case 32: - return new Format<float>("%13g", 'f'); - case 64: - return new Format<double>("%13g", 'f'); - default: - return NULL; - } - default: - VIXL_UNREACHABLE(); - return NULL; - } -} - - -template <typename T> -void Format<T>::Print(FILE* out) const { - unsigned size = sizeof(T) * 8; - fprintf(out, "[Format %c%u - %s]", type_code_, size, fmt_); -} - - -void UnknownToken::Print(FILE* out) const { - fprintf(out, "[Unknown %s]", unknown_); -} - - -void DebugCommand::Print(FILE* out) { fprintf(out, "%s", name()); } - - -bool DebugCommand::Match(const char* name, const char** aliases) { - for (const char** current = aliases; *current != NULL; current++) { - if (strcmp(name, *current) == 0) { - return true; - } - } - - return false; -} - - -DebugCommand* DebugCommand::Parse(char* line) { - std::vector<Token*> args; - - for (char* chunk = strtok(line, " \t"); chunk != NULL; - chunk = strtok(NULL, " \t")) { - char* dot = strchr(chunk, '.'); - if (dot != NULL) { - // 'Token.format'. - Token* format = FormatToken::Tokenize(dot + 1); - if (format != NULL) { - *dot = '\0'; - args.push_back(Token::Tokenize(chunk)); - args.push_back(format); - } else { - // Error while parsing the format, push the UnknownToken so an error - // can be accurately reported. - args.push_back(Token::Tokenize(chunk)); - } - } else { - args.push_back(Token::Tokenize(chunk)); - } - } - - if (args.size() == 0) { - return NULL; - } - - if (!args[0]->IsIdentifier()) { - return new InvalidCommand(args, 0, "command name is not valid"); - } - - const char* name = IdentifierToken::Cast(args[0])->value(); -#define RETURN_IF_MATCH(Command) \ - if (Match(name, Command::kAliases)) { \ - return Command::Build(args); \ - } - DEBUG_COMMAND_LIST(RETURN_IF_MATCH); -#undef RETURN_IF_MATCH - - return new UnknownCommand(args); -} - - -void DebugCommand::PrintHelp(const char** aliases, - const char* args, - const char* help) { - VIXL_ASSERT(aliases[0] != NULL); - VIXL_ASSERT(help != NULL); - - printf("\n----\n\n"); - for (const char** current = aliases; *current != NULL; current++) { - if (args != NULL) { - printf("%s %s\n", *current, args); - } else { - printf("%s\n", *current); - } - } - printf("\n%s\n", help); -} - - -bool HelpCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - USE(debugger); - -#define PRINT_HELP(Command) \ - DebugCommand::PrintHelp(Command::kAliases, \ - Command::kArguments, \ - Command::kHelp); - DEBUG_COMMAND_LIST(PRINT_HELP); -#undef PRINT_HELP - printf("\n----\n\n"); - - return false; -} - - -DebugCommand* HelpCommand::Build(std::vector<Token*> args) { - if (args.size() != 1) { - return new InvalidCommand(args, -1, "too many arguments"); - } - - return new HelpCommand(args[0]); -} - - -bool ContinueCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - - debugger->DeactivateDebugger(); - return true; -} - - -DebugCommand* ContinueCommand::Build(std::vector<Token*> args) { - if (args.size() != 1) { - return new InvalidCommand(args, -1, "too many arguments"); - } - - return new ContinueCommand(args[0]); -} - - -bool StepCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - - // To avoid recursive calls to the debugger shell when hitting breakpoints - // while stepping, stepping is implemented by telling the debugger how many - // instructions to execute before starting the shell again. - int64_t steps = count(); - if (steps <= 0) { - if (steps < 0) { - printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps); - } - // Execute nothing and stay in the shell. - return false; - } else { - debugger->SetSteps(steps - 1); - // Relinquish control to the debugger. It will execute the next instruction, - // followed by `steps - 1` instructions, before starting the shell again. - // (Unless another breakpoint is hit in the meantime.) - return true; - } -} - - -void StepCommand::Print(FILE* out) { - fprintf(out, "%s %" PRId64 "", name(), count()); -} - - -DebugCommand* StepCommand::Build(std::vector<Token*> args) { - IntegerToken* count = NULL; - switch (args.size()) { - case 1: { // step [1] - count = new IntegerToken(1); - break; - } - case 2: { // step n - Token* first = args[1]; - if (!first->IsInteger()) { - return new InvalidCommand(args, 1, "expects int"); - } - count = IntegerToken::Cast(first); - break; - } - default: - return new InvalidCommand(args, -1, "too many arguments"); - } - - return new StepCommand(args[0], count); -} - - -bool SkipCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - - int64_t steps = count(); - if (steps < 0) { - printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps); - } else { - printf("Skipping over %" PRId64 " instructions:\n", steps); - debugger->PrintInstructions(debugger->ReadPc(), steps, "Skip: "); - debugger->WritePc(debugger->ReadPc() + steps * kInstructionSize); - debugger->PrintNextInstruction(); - } - - return false; -} - - -void SkipCommand::Print(FILE* out) { - fprintf(out, "%s %" PRId64 "", name(), count()); -} - - -DebugCommand* SkipCommand::Build(std::vector<Token*> args) { - IntegerToken* count = NULL; - switch (args.size()) { - case 1: { // step [1] - count = new IntegerToken(1); - break; - } - case 2: { // step n - Token* first = args[1]; - if (!first->IsInteger()) { - return new InvalidCommand(args, 1, "expects int"); - } - count = IntegerToken::Cast(first); - break; - } - default: - return new InvalidCommand(args, -1, "too many arguments"); - } - - return new SkipCommand(args[0], count); -} - - -DebugCommand* DisasmCommand::Build(std::vector<Token*> args) { - IntegerToken* count = NULL; - switch (args.size()) { - case 1: { // disasm [10] - count = new IntegerToken(10); - break; - } - case 2: { // disasm n - Token* first = args[1]; - if (!first->IsInteger()) { - return new InvalidCommand(args, 1, "expects int"); - } - - count = IntegerToken::Cast(first); - break; - } - default: - return new InvalidCommand(args, -1, "too many arguments"); - } - - Token* target = new IdentifierToken("pc"); - FormatToken* format = new Format<uint32_t>("%08" PRIx32, 'i'); - return new ExamineCommand(args[0], target, format, count); -} - - -void PrintCommand::Print(FILE* out) { - fprintf(out, "%s ", name()); - target()->Print(out); - if (format() != NULL) format()->Print(out); -} - - -bool PrintCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - - Token* tok = target(); - if (tok->IsIdentifier()) { - char* identifier = IdentifierToken::Cast(tok)->value(); - if (strcmp(identifier, "regs") == 0) { - debugger->PrintRegisters(); - } else if (strcmp(identifier, "fpregs") == 0) { - debugger->PrintVRegisters(); - } else if (strcmp(identifier, "sysregs") == 0) { - debugger->PrintSystemRegisters(); - } else if (strcmp(identifier, "pc") == 0) { - printf("pc = %16p\n", reinterpret_cast<const void*>(debugger->ReadPc())); - } else { - printf(" ** Unknown identifier to print: %s **\n", identifier); - } - - return false; - } - - FormatToken* format_tok = format(); - VIXL_ASSERT(format_tok != NULL); - if (format_tok->GetTypeCode() == 'i') { - // TODO(all): Add support for instruction disassembly. - printf(" ** unsupported format: instructions **\n"); - return false; - } - - if (tok->IsRegister()) { - RegisterToken* reg_tok = RegisterToken::Cast(tok); - Register reg = reg_tok->value(); - debugger->PrintRegister(reg, reg_tok->Name(), format_tok); - return false; - } - - if (tok->IsFPRegister()) { - FPRegister fpreg = FPRegisterToken::Cast(tok)->value(); - debugger->PrintFPRegister(fpreg, format_tok); - return false; - } - - VIXL_UNREACHABLE(); - return false; -} - - -DebugCommand* PrintCommand::Build(std::vector<Token*> args) { - if (args.size() < 2) { - return new InvalidCommand(args, -1, "too few arguments"); - } - - Token* target = args[1]; - if (!target->IsRegister() && !target->IsFPRegister() && - !target->IsIdentifier()) { - return new InvalidCommand(args, 1, "expects reg or identifier"); - } - - FormatToken* format = NULL; - int target_size = 0; - if (target->IsRegister()) { - Register reg = RegisterToken::Cast(target)->value(); - target_size = reg.GetSizeInBytes(); - } else if (target->IsFPRegister()) { - FPRegister fpreg = FPRegisterToken::Cast(target)->value(); - target_size = fpreg.GetSizeInBytes(); - } - // If the target is an identifier there must be no format. This is checked - // in the switch statement below. - - switch (args.size()) { - case 2: { - if (target->IsRegister()) { - switch (target_size) { - case 4: - format = new Format<uint32_t>("%08" PRIx32, 'x'); - break; - case 8: - format = new Format<uint64_t>("%016" PRIx64, 'x'); - break; - default: - VIXL_UNREACHABLE(); - } - } else if (target->IsFPRegister()) { - switch (target_size) { - case 4: - format = new Format<float>("%8g", 'f'); - break; - case 8: - format = new Format<double>("%8g", 'f'); - break; - default: - VIXL_UNREACHABLE(); - } - } - break; - } - case 3: { - if (target->IsIdentifier()) { - return new InvalidCommand(args, - 2, - "format is only allowed with registers"); - } - - Token* second = args[2]; - if (!second->IsFormat()) { - return new InvalidCommand(args, 2, "expects format"); - } - format = FormatToken::Cast(second); - - if (format->SizeOf() > target_size) { - return new InvalidCommand(args, 2, "format too wide"); - } - - break; - } - default: - return new InvalidCommand(args, -1, "too many arguments"); - } - - return new PrintCommand(args[0], target, format); -} - - -bool ExamineCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - - uint8_t* address = target()->ToAddress(debugger); - int64_t amount = count()->value(); - if (format()->GetTypeCode() == 'i') { - debugger->PrintInstructions(address, amount); - } else { - debugger->PrintMemory(address, format(), amount); - } - - return false; -} - - -void ExamineCommand::Print(FILE* out) { - fprintf(out, "%s ", name()); - format()->Print(out); - target()->Print(out); -} - - -DebugCommand* ExamineCommand::Build(std::vector<Token*> args) { - if (args.size() < 2) { - return new InvalidCommand(args, -1, "too few arguments"); - } - - Token* target = args[1]; - if (!target->CanAddressMemory()) { - return new InvalidCommand(args, 1, "expects address"); - } - - FormatToken* format = NULL; - IntegerToken* count = NULL; - - switch (args.size()) { - case 2: { // mem addr[.x64] [10] - format = new Format<uint64_t>("%016" PRIx64, 'x'); - count = new IntegerToken(10); - break; - } - case 3: { // mem addr.format [10] - // mem addr[.x64] n - Token* second = args[2]; - if (second->IsFormat()) { - format = FormatToken::Cast(second); - count = new IntegerToken(10); - break; - } else if (second->IsInteger()) { - format = new Format<uint64_t>("%016" PRIx64, 'x'); - count = IntegerToken::Cast(second); - } else { - return new InvalidCommand(args, 2, "expects format or integer"); - } - VIXL_UNREACHABLE(); - break; - } - case 4: { // mem addr.format n - Token* second = args[2]; - Token* third = args[3]; - if (!second->IsFormat() || !third->IsInteger()) { - return new InvalidCommand(args, -1, "expects addr[.format] [n]"); - } - format = FormatToken::Cast(second); - count = IntegerToken::Cast(third); - break; - } - default: - return new InvalidCommand(args, -1, "too many arguments"); - } - - return new ExamineCommand(args[0], target, format, count); -} - - -UnknownCommand::~UnknownCommand() { - const size_t size = args_.size(); - for (size_t i = 0; i < size; ++i) { - delete args_[i]; - } -} - - -bool UnknownCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - USE(debugger); - - printf(" ** Unknown Command:"); - const size_t size = args_.size(); - for (size_t i = 0; i < size; ++i) { - printf(" "); - args_[i]->Print(stdout); - } - printf(" **\n"); - - return false; -} - - -InvalidCommand::~InvalidCommand() { - const size_t size = args_.size(); - for (size_t i = 0; i < size; ++i) { - delete args_[i]; - } -} - - -bool InvalidCommand::Run(Debugger* debugger) { - VIXL_ASSERT(debugger->IsDebuggerActive()); - USE(debugger); - - printf(" ** Invalid Command:"); - const size_t size = args_.size(); - for (size_t i = 0; i < size; ++i) { - printf(" "); - if (i == static_cast<size_t>(index_)) { - printf(">>"); - args_[i]->Print(stdout); - printf("<<"); - } else { - args_[i]->Print(stdout); - } - } - printf(" **\n"); - printf(" ** %s\n", cause_); - - return false; -} - -} // namespace aarch64 -} // namespace vixl - -#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 diff --git a/src/aarch64/debugger-aarch64.h b/src/aarch64/debugger-aarch64.h deleted file mode 100644 index c05d530f..00000000 --- a/src/aarch64/debugger-aarch64.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2014, VIXL authors -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of ARM Limited nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 - -#ifndef VIXL_AARCH64_DEBUGGER_AARCH64_H_ -#define VIXL_AARCH64_DEBUGGER_AARCH64_H_ - -#include <cctype> -#include <cerrno> -#include <climits> -#include <vector> - -#include "../globals-vixl.h" -#include "../utils-vixl.h" - -#include "constants-aarch64.h" -#include "simulator-aarch64.h" - -namespace vixl { -namespace aarch64 { - -// Forward declarations. -class DebugCommand; -class Token; -class FormatToken; - -class Debugger : public Simulator { - public: - explicit Debugger(Decoder* decoder, FILE* stream = stdout); - ~Debugger(); - - virtual void Run() VIXL_OVERRIDE; - virtual void VisitException(const Instruction* instr) VIXL_OVERRIDE; - - bool IsDebuggerActive() const { return debugger_active_; } - void ActivateDebugger() { debugger_active_ = true; } - void DeactivateDebugger() { debugger_active_ = false; } - - // Numbers of instructions to execute before the debugger shell is given - // back control. - int64_t GetSteps() const { return steps_; } - VIXL_DEPRECATED("GetSteps", int64_t steps() const) { return GetSteps(); } - - void SetSteps(int64_t value) { - VIXL_ASSERT(value >= 0); - steps_ = value; - } - VIXL_DEPRECATED("SetSteps", void set_steps(int64_t value)) { - return SetSteps(value); - } - - void PrintInstructions(const void* address, - int64_t count = 1, - const char* prefix = ""); - void PrintNextInstruction() { PrintInstructions(ReadPc(), 1, "Next: "); } - void PrintMemory(const uint8_t* address, - const FormatToken* format, - int64_t count = 1); - void PrintRegister(const Register& target_reg, - const char* name, - const FormatToken* format); - void PrintFPRegister(const FPRegister& target_fpreg, - const FormatToken* format); - - private: - char* ReadCommandLine(const char* prompt, char* buffer, int length); - void RunDebuggerShell(); - void DoBreakpoint(const Instruction* instr); - - bool debugger_active_; - int64_t steps_; - DebugCommand* last_command_; - PrintDisassembler* disasm_; - Decoder* printer_; - - // Length of the biggest command line accepted by the debugger shell. - static const int kMaxDebugShellLine = 256; -}; - -} // namespace aarch64 -} // namespace vixl - -#endif // VIXL_AARCH64_DEBUGGER_AARCH64_H_ - -#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 diff --git a/src/aarch64/macro-assembler-aarch64.h b/src/aarch64/macro-assembler-aarch64.h index 072d4be8..47929c38 100644 --- a/src/aarch64/macro-assembler-aarch64.h +++ b/src/aarch64/macro-assembler-aarch64.h @@ -35,8 +35,11 @@ #include "../macro-assembler-interface.h" #include "assembler-aarch64.h" -#include "debugger-aarch64.h" #include "instrument-aarch64.h" +// Required for runtime call support. +// TODO: Break this dependency. We should be able to separate out the necessary +// parts so that we don't need to include the whole simulator header. +#include "simulator-aarch64.h" // Required in order to generate debugging instructions for the simulator. This // is needed regardless of whether the simulator is included or not, since // generating simulator specific instructions is controlled at runtime. diff --git a/test/aarch64/examples/test-examples.cc b/test/aarch64/examples/test-examples.cc index ef44c617..1a867988 100644 --- a/test/aarch64/examples/test-examples.cc +++ b/test/aarch64/examples/test-examples.cc @@ -30,7 +30,6 @@ #include "non-const-visitor.h" #include "../test-utils-aarch64.h" -#include "aarch64/debugger-aarch64.h" #include "aarch64/macro-assembler-aarch64.h" #include "aarch64/simulator-aarch64.h" #define TEST(name) TEST_(EXAMPLE_##name) @@ -166,7 +165,7 @@ void GenerateTestWrapper(MacroAssembler* masm, RegisterDump* regs) { #define START() \ MacroAssembler masm; \ Decoder decoder; \ - Debugger simulator(&decoder); \ + Simulator simulator(&decoder); \ simulator.SetColouredTrace(Test::coloured_trace()); \ PrintDisassembler* pdis = NULL; \ Instrument* inst = NULL; \ diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc index a399a936..aa2e4297 100644 --- a/test/aarch64/test-assembler-aarch64.cc +++ b/test/aarch64/test-assembler-aarch64.cc @@ -37,7 +37,6 @@ #include "aarch64/test-utils-aarch64.h" #include "aarch64/cpu-aarch64.h" -#include "aarch64/debugger-aarch64.h" #include "aarch64/disasm-aarch64.h" #include "aarch64/macro-assembler-aarch64.h" #include "aarch64/simulator-aarch64.h" @@ -109,24 +108,22 @@ namespace aarch64 { MacroAssembler masm(buf, size + CodeBuffer::kDefaultCapacity, pic); \ SETUP_COMMON() -#define SETUP_COMMON() \ - masm.SetGenerateSimulatorCode(true); \ - Decoder simulator_decoder; \ - Simulator* simulator = Test::run_debugger() \ - ? new Debugger(&simulator_decoder) \ - : new Simulator(&simulator_decoder); \ - simulator->SetColouredTrace(Test::coloured_trace()); \ - simulator->SetInstructionStats(Test::instruction_stats()); \ - Disassembler disasm; \ - Decoder disassembler_decoder; \ - disassembler_decoder.AppendVisitor(&disasm); \ - RegisterDump core; \ - ptrdiff_t offset_after_infrastructure_start; \ +#define SETUP_COMMON() \ + masm.SetGenerateSimulatorCode(true); \ + Decoder simulator_decoder; \ + Simulator simulator(&simulator_decoder); \ + simulator.SetColouredTrace(Test::coloured_trace()); \ + simulator.SetInstructionStats(Test::instruction_stats()); \ + Disassembler disasm; \ + Decoder disassembler_decoder; \ + disassembler_decoder.AppendVisitor(&disasm); \ + RegisterDump core; \ + ptrdiff_t offset_after_infrastructure_start; \ ptrdiff_t offset_before_infrastructure_end #define START() \ masm.Reset(); \ - simulator->ResetState(); \ + simulator.ResetState(); \ __ PushCalleeSavedRegisters(); \ { \ int trace_parameters = 0; \ @@ -160,17 +157,13 @@ namespace aarch64 { #define RUN() \ DISASSEMBLE(); \ - simulator->RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>()) + simulator.RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>()) #define RUN_CUSTOM() RUN() -#define TEARDOWN() TEARDOWN_COMMON() - -#define TEARDOWN_CUSTOM() \ - delete[] buf; \ - TEARDOWN_COMMON() +#define TEARDOWN() -#define TEARDOWN_COMMON() delete simulator; +#define TEARDOWN_CUSTOM() delete[] buf; #else // ifdef VIXL_INCLUDE_SIMULATOR_AARCH64. // Run the test on real hardware or models. @@ -10178,7 +10171,7 @@ static void FmaddFmsubHelper(double n, TEST(fmadd_fmsub_double) { // It's hard to check the result of fused operations because the only way to - // calculate the result is using fma, which is what the simulator uses anyway. + // calculate the result is using fma, which is what the Simulator uses anyway. // Basic operation. FmaddFmsubHelper(1.0, 2.0, 3.0, 5.0, 1.0, -5.0, -1.0); @@ -15234,8 +15227,8 @@ TEST(printf_no_preserve) { #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64 TEST(trace) { - // The Trace helper should not generate any code unless the simulator (or - // debugger) is being used. + // The Trace helper should not generate any code unless the simulator is being + // used. SETUP(); START(); @@ -15253,8 +15246,8 @@ TEST(trace) { #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64 TEST(log) { - // The Log helper should not generate any code unless the simulator (or - // debugger) is being used. + // The Log helper should not generate any code unless the simulator is being + // used. SETUP(); START(); diff --git a/test/aarch64/test-simulator-aarch64.cc b/test/aarch64/test-simulator-aarch64.cc index 00d833eb..11f53c02 100644 --- a/test/aarch64/test-simulator-aarch64.cc +++ b/test/aarch64/test-simulator-aarch64.cc @@ -57,17 +57,16 @@ namespace aarch64 { #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 -#define SETUP() \ - MacroAssembler masm; \ - Decoder decoder; \ - Simulator* simulator = \ - Test::run_debugger() ? new Debugger(&decoder) : new Simulator(&decoder); \ - simulator->SetColouredTrace(Test::coloured_trace()); \ - simulator->SetInstructionStats(Test::instruction_stats()); +#define SETUP() \ + MacroAssembler masm; \ + Decoder decoder; \ + Simulator simulator(&decoder); \ + simulator.SetColouredTrace(Test::coloured_trace()); \ + simulator.SetInstructionStats(Test::instruction_stats()); #define START() \ masm.Reset(); \ - simulator->ResetState(); \ + simulator.ResetState(); \ __ PushCalleeSavedRegisters(); \ if (Test::trace_reg()) { \ __ Trace(LOG_STATE, TRACE_ENABLE); \ @@ -92,9 +91,9 @@ namespace aarch64 { masm.FinalizeCode() #define RUN() \ - simulator->RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>()) + simulator.RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>()) -#define TEARDOWN() delete simulator; +#define TEARDOWN() #else // VIXL_INCLUDE_SIMULATOR_AARCH64 @@ -4559,32 +4558,30 @@ TEST(RunFrom) { // Run a function returning `void` and taking no argument. int32_t value = 0xbad; - simulator->RunFrom(GenerateStoreZero(&masm, &value)); + simulator.RunFrom(GenerateStoreZero(&masm, &value)); VIXL_CHECK(value == 0); // Run a function returning `void` and taking one argument. int32_t argument = 0xf00d; - simulator->RunFrom<void, int32_t>(GenerateStoreInput(&masm, &value), - argument); + simulator.RunFrom<void, int32_t>(GenerateStoreInput(&masm, &value), argument); VIXL_CHECK(value == 0xf00d); // Run a function taking one argument and returning a value. int64_t res_int64_t; res_int64_t = - simulator->RunFrom<int64_t, int64_t>(GeneratePow(&masm, 0), 0xbad); + simulator.RunFrom<int64_t, int64_t>(GeneratePow(&masm, 0), 0xbad); VIXL_CHECK(res_int64_t == 1); - res_int64_t = - simulator->RunFrom<int64_t, int64_t>(GeneratePow(&masm, 1), 123); + res_int64_t = simulator.RunFrom<int64_t, int64_t>(GeneratePow(&masm, 1), 123); VIXL_CHECK(res_int64_t == 123); - res_int64_t = simulator->RunFrom<int64_t, int64_t>(GeneratePow(&masm, 10), 2); + res_int64_t = simulator.RunFrom<int64_t, int64_t>(GeneratePow(&masm, 10), 2); VIXL_CHECK(res_int64_t == 1024); // Run a function taking multiple arguments in registers. double res_double = - simulator->RunFrom<double, float, int64_t, double>(GenerateSum(&masm), - 1.0, - 2, - 3.0); + simulator.RunFrom<double, float, int64_t, double>(GenerateSum(&masm), + 1.0, + 2, + 3.0); VIXL_CHECK(res_double == 6.0); } #endif diff --git a/test/aarch64/test-trace-aarch64.cc b/test/aarch64/test-trace-aarch64.cc index 673161e8..f41dc39b 100644 --- a/test/aarch64/test-trace-aarch64.cc +++ b/test/aarch64/test-trace-aarch64.cc @@ -34,7 +34,6 @@ #include "test-utils-aarch64.h" #include "aarch64/cpu-aarch64.h" -#include "aarch64/debugger-aarch64.h" #include "aarch64/disasm-aarch64.h" #include "aarch64/macro-assembler-aarch64.h" #include "aarch64/simulator-aarch64.h" diff --git a/test/test-runner.cc b/test/test-runner.cc index fc67b64d..b0e1d11b 100644 --- a/test/test-runner.cc +++ b/test/test-runner.cc @@ -36,9 +36,6 @@ vixl::Test* vixl::Test::last_ = NULL; bool vixl::Test::verbose_ = false; -// No debugger to start with. -bool vixl::Test::debug_ = false; - // No tracing to start with. bool vixl::Test::trace_sim_ = false; bool vixl::Test::trace_reg_ = false; @@ -109,7 +106,6 @@ static void PrintHelpMessage() { "--list List all available tests.\n" "--run_all Run all available tests.\n" "--verbose Print verbose output when available.\n" - "--debugger Run in the debugger.\n" "--trace_all " "Enable all trace options, plus --coloured_trace.\n" "--trace_sim " @@ -159,10 +155,6 @@ int main(int argc, char* argv[]) { vixl::Test::set_verbose(true); } - if (IsInArgs("--debugger", argc, argv)) { - vixl::Test::set_debug(true); - } - if (IsInArgs("--trace-write", argc, argv)) { vixl::Test::set_trace_write(true); } diff --git a/test/test-runner.h b/test/test-runner.h index 83361054..45303cf0 100644 --- a/test/test-runner.h +++ b/test/test-runner.h @@ -46,8 +46,6 @@ class Test { Test* next() { return next_; } static bool verbose() { return verbose_; } static void set_verbose(bool value) { verbose_ = value; } - static bool debug() { return debug_; } - static void set_debug(bool value) { debug_ = value; } static bool trace_sim() { return trace_sim_; } static void set_trace_sim(bool value) { trace_sim_ = value; } static bool trace_reg() { return trace_reg_; } @@ -73,9 +71,6 @@ class Test { generate_test_trace_ = value; } - // The debugger is needed to trace register values. - static bool run_debugger() { return debug_; } - private: const char* name_; TestFunction* callback_; @@ -84,7 +79,6 @@ class Test { static Test* last_; Test* next_; static bool verbose_; - static bool debug_; static bool trace_sim_; static bool trace_reg_; static bool trace_write_; diff --git a/tools/test.py b/tools/test.py index 8300475a..f7dbd067 100755 --- a/tools/test.py +++ b/tools/test.py @@ -175,17 +175,10 @@ test_build_options = [ build_option_negative_testing ] -runtime_option_debugger = \ - RuntimeOption('debugger', - '''Test with the specified configurations for the debugger. - Note that this is only tested if we are using the simulator.''', - val_test_choices=['all', 'on', 'off']) -test_runtime_options = [ - runtime_option_debugger -] +test_runtime_options = [] test_options = \ - test_environment_options + test_build_options + test_runtime_options + test_environment_options + test_build_options + test_runtime_options def BuildOptions(): @@ -441,7 +434,6 @@ if __name__ == '__main__': SetFast(environment_option_compiler, args.compiler, 'clang++') SetFast(build_option_standard, args.std, 'c++98') SetFast(build_option_mode, args.mode, 'debug') - SetFast(runtime_option_debugger, args.debugger, 'on') if not args.nolint and not (args.fast or args.dry_run): rc |= RunLinter() @@ -451,11 +443,6 @@ if __name__ == '__main__': rc |= RunClangFormat() MaybeExitEarly(rc) - # Don't try to test the debugger if we are not running with the simulator. - if not args.simulator: - test_runtime_options = \ - filter(lambda x: x.name != 'debugger', test_runtime_options) - # List all combinations of options that will be tested. def ListCombinations(args, options): opts_list = [ |