1ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Copyright 2013, ARM Limited 2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved. 3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without 5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met: 6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// * Redistributions of source code must retain the above copyright notice, 8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// this list of conditions and the following disclaimer. 9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// * Redistributions in binary form must reproduce the above copyright notice, 10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// this list of conditions and the following disclaimer in the documentation 11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// and/or other materials provided with the distribution. 12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// * Neither the name of ARM Limited nor the names of its contributors may be 13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// used to endorse or promote products derived from this software without 14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// specific prior written permission. 15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 27ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#ifndef VIXL_A64_DEBUGGER_A64_H_ 28ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define VIXL_A64_DEBUGGER_A64_H_ 29ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 30ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <ctype.h> 31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <limits.h> 32ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <errno.h> 33ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <vector> 34ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 35bc4afbd2754e20d14114e4ba83f9035b26ab701dSerban Constantinescu#include "globals-vixl.h" 36bc4afbd2754e20d14114e4ba83f9035b26ab701dSerban Constantinescu#include "utils-vixl.h" 37ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/constants-a64.h" 38ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/simulator-a64.h" 39ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 40ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl { 41ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 42ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Debug instructions. 43ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 44ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// VIXL's macro-assembler and debugger support a few pseudo instructions to 45ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// make debugging easier. These pseudo instructions do not exist on real 46ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// hardware. 47ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 48ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Each debug pseudo instruction is represented by a HLT instruction. The HLT 49ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// immediate field is used to identify the type of debug pseudo isntruction. 50ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Each pseudo instruction use a custom encoding for additional arguments, as 51ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// described below. 52ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 53ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Unreachable 54ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 55ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Instruction which should never be executed. This is used as a guard in parts 56ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// of the code that should not be reachable, such as in data encoded inline in 57ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// the instructions. 58ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instr kUnreachableOpcode = 0xdeb0; 59ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 60ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Trace 61ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// - parameter: TraceParameter stored as a uint32_t 62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// - command: TraceCommand stored as a uint32_t 63ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 64ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Allow for trace management in the generated code. See the corresponding 65ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// enums for more information on permitted actions. 66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instr kTraceOpcode = 0xdeb2; 67ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kTraceParamsOffset = 1 * kInstructionSize; 68ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kTraceCommandOffset = 2 * kInstructionSize; 69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kTraceLength = 3 * kInstructionSize; 70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Log 72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// - parameter: TraceParameter stored as a uint32_t 73ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// 74ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Output the requested information. 75ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instr kLogOpcode = 0xdeb3; 76ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kLogParamsOffset = 1 * kInstructionSize; 77ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kLogLength = 2 * kInstructionSize; 78ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 79ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Trace commands. 80ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlenum TraceCommand { 81ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl TRACE_ENABLE = 1, 82ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl TRACE_DISABLE = 2 83ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}; 84ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Trace parameters. 86ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlenum TraceParameters { 87ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl LOG_DISASM = 1 << 0, // Log disassembly. 88ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl LOG_REGS = 1 << 1, // Log general purpose registers. 89ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl LOG_FP_REGS = 1 << 2, // Log floating-point registers. 90578645f14e122d2b87d907e298cda7e7d0babf1farmvixl LOG_SYS_REGS = 1 << 3, // Log the flags and system registers. 91ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 92578645f14e122d2b87d907e298cda7e7d0babf1farmvixl LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS, 93578645f14e122d2b87d907e298cda7e7d0babf1farmvixl LOG_ALL = LOG_DISASM | LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS 94ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}; 95ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 96ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Debugger parameters 97ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlenum DebugParameters { 98ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl DBG_ACTIVE = 1 << 0, // The debugger is active. 99ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl DBG_BREAK = 1 << 1 // The debugger is at a breakpoint. 100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}; 101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Forward declarations. 103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass DebugCommand; 104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass Token; 105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass FormatToken; 106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass Debugger : public Simulator { 108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl public: 109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl Debugger(Decoder* decoder, FILE* stream = stdout); 110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl virtual void Run(); 112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void VisitException(Instruction* instr); 113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline int log_parameters() { 115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl // The simulator can control disassembly, so make sure that the Debugger's 116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl // log parameters agree with it. 117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl if (disasm_trace()) { 118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl log_parameters_ |= LOG_DISASM; 119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl return log_parameters_; 121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline void set_log_parameters(int parameters) { 123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl set_disasm_trace((parameters & LOG_DISASM) != 0); 124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl log_parameters_ = parameters; 125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl update_pending_request(); 127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline int debug_parameters() { return debug_parameters_; } 130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline void set_debug_parameters(int parameters) { 131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl debug_parameters_ = parameters; 132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl update_pending_request(); 134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl // Numbers of instructions to execute before the debugger shell is given 137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl // back control. 138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline int steps() { return steps_; } 139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline void set_steps(int value) { 1401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl VIXL_ASSERT(value > 1); 141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl steps_ = value; 142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline bool IsDebuggerRunning() { 145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl return (debug_parameters_ & DBG_ACTIVE) != 0; 146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline bool pending_request() { return pending_request_; } 149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl inline void update_pending_request() { 150578645f14e122d2b87d907e298cda7e7d0babf1farmvixl const int kLoggingMask = LOG_STATE; 151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl const bool logging = (log_parameters_ & kLoggingMask) != 0; 152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl const bool debugging = IsDebuggerRunning(); 153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl pending_request_ = logging || debugging; 155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl } 156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void PrintInstructions(void* address, int64_t count = 1); 158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void PrintMemory(const uint8_t* address, 159f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl const FormatToken* format, 160f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl int64_t count = 1); 161f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl void PrintRegister(const Register& target_reg, 162f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl const char* name, 163f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl const FormatToken* format); 164f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl void PrintFPRegister(const FPRegister& target_fpreg, 165f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl const FormatToken* format); 166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl private: 168578645f14e122d2b87d907e298cda7e7d0babf1farmvixl void LogSystemRegisters(); 169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void LogRegisters(); 170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void LogFPRegisters(); 171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void LogProcessorState(); 172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl char* ReadCommandLine(const char* prompt, char* buffer, int length); 173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void RunDebuggerShell(); 174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void DoBreakpoint(Instruction* instr); 175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void DoUnreachable(Instruction* instr); 176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void DoTrace(Instruction* instr); 177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl void DoLog(Instruction* instr); 178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl int log_parameters_; 180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl int debug_parameters_; 181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl bool pending_request_; 182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl int steps_; 183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl DebugCommand* last_command_; 184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl PrintDisassembler* disasm_; 185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl Decoder* printer_; 186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl // Length of the biggest command line accepted by the debugger shell. 188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl static const int kMaxDebugShellLine = 256; 189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}; 190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl} // namespace vixl 192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl 193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#endif // VIXL_A64_DEBUGGER_A64_H_ 194