// Copyright 2014, ARM Limited // 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.
#include"jstypes.h"
#ifdef JS_SIMULATOR_ARM64
#include"jit/arm64/vixl/Debugger-vixl.h"
#include"mozilla/Vector.h"
#include"js/AllocPolicy.h"
namespace vixl {
// List of commands supported by the debugger. #define DEBUG_COMMAND_LIST(C) \
C(HelpCommand) \
C(ContinueCommand) \
C(StepCommand) \
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() {}
// Tokens often hold one value. template<typename T> class ValueToken : public Token { public: explicit ValueToken(T value) : value_(value) {}
ValueToken() {}
// 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<constRegister> { public: explicit RegisterToken(constRegister reg)
: ValueToken<constRegister>(reg) {}
// 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) {}
// 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() {}
// 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() { js_delete(name_); }
constchar* name() { return name_->value(); } // Run the command on the given debugger. The command returns true if // execution should move to the next instruction. virtualbool Run(Debugger * debugger) = 0; virtualvoid Print(FILE* out = stdout);
// For all commands below see their respective kHelp and kAliases in // debugger-a64.cc class HelpCommand : public DebugCommand { public: explicit HelpCommand(Token* name) : DebugCommand(name) {}
// Commands which name does not match any of the known commnand. class UnknownCommand : public DebugCommand { public: explicit UnknownCommand(TokenVector&& args) : args_(std::move(args)) {} virtual ~UnknownCommand();
virtualbool Run(Debugger* debugger) override;
private:
TokenVector args_;
};
// Commands which name match a known command but the syntax is invalid. class InvalidCommand : public DebugCommand { public:
InvalidCommand(TokenVector&& args, int index, constchar* cause)
: args_(std::move(args)), index_(index), cause_(cause) {} virtual ~InvalidCommand();
virtualbool Run(Debugger* debugger) override;
private:
TokenVector args_; int index_; constchar* cause_;
};
constchar* DisasmCommand::kAliases[] = { "disasm", "di", NULL }; constchar* DisasmCommand::kArguments = "[n = 10]"; constchar* DisasmCommand::kHelp = " Disassemble n instruction(s) at pc.\n" " This command is equivalent to x pc.i [n = 10]."
;
constchar* PrintCommand::kAliases[] = { "print", "p", NULL }; constchar* PrintCommand::kArguments = "<entity>[.format]"; constchar* 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"
;
constchar* ExamineCommand::kAliases[] = { "m", "mem", "x", NULL }; constchar* ExamineCommand::kArguments = "<addr>[.format] [n = 10]"; constchar* 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."
;
if (target_fpreg.Is32Bits()) {
printf("s%u = ", target_fpreg.code());
} else {
printf("d%u = ", target_fpreg.code());
} 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(constchar* 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 (IsDebuggerRunning()) { if (steps_ > 0) { // Finish stepping first.
--steps_; return;
}
printf("Next: ");
PrintInstructions(pc()); bool done = false; while (!done) { char buffer[kMaxDebugShellLine]; char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine);
if (last_command_ != NULL) {
done = last_command_->Run(this);
} else {
printf("No previous command to run!\n");
}
}
if ((debug_parameters_ & DBG_BREAK) != 0) { // The break request has now been handled, move to next instruction.
debug_parameters_ &= ~DBG_BREAK;
increment_pc();
}
}
}
printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<constvoid*>(instr));
set_debug_parameters(debug_parameters() | DBG_BREAK | DBG_ACTIVE); // Make the shell point to the brk instruction.
set_pc(instr);
}
Token* RegisterToken::Tokenize(constchar* arg) { for (unsigned i = 0; i < kNumberOfRegisters; i++) { // Is it a X register or alias? for (constchar** current = kXAliases[i]; *current != NULL; current++) { if (strcmp(arg, *current) == 0) { return js_new<RegisterToken>(Register::XRegFromCode(i));
}
}
// Is it a W register or alias? for (constchar** current = kWAliases[i]; *current != NULL; current++) { if (strcmp(arg, *current) == 0) { return js_new<RegisterToken>(Register::WRegFromCode(i));
}
}
}
DebugCommand* PrintCommand::Build(TokenVector&& args) { if (args.length() < 2) { return js_new<InvalidCommand>(std::move(args), -1, "too few arguments");
}
Token* target = args[1]; if (!target->IsRegister() &&
!target->IsFPRegister() &&
!target->IsIdentifier()) { return js_new<InvalidCommand>(std::move(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.SizeInBytes();
} elseif (target->IsFPRegister()) {
FPRegister fpreg = FPRegisterToken::Cast(target)->value();
target_size = fpreg.SizeInBytes();
} // If the target is an identifier there must be no format. This is checked // in the switch statement below.
switch (args.length()) { case 2: { if (target->IsRegister()) { switch (target_size) { case 4: format = js_new<Format<uint32_t>>("%08" PRIx32, 'x'); break; case 8: format = js_new<Format<uint64_t>>("%016" PRIx64, 'x'); break; default: VIXL_UNREACHABLE();
}
} elseif (target->IsFPRegister()) { switch (target_size) { case 4: format = js_new<Format<float>>("%8g", 'f'); break; case 8: format = js_new<Format<double>>("%8g", 'f'); break; default: VIXL_UNREACHABLE();
}
} break;
} case 3: { if (target->IsIdentifier()) { return js_new<InvalidCommand>(std::move(args), 2, "format is only allowed with registers");
}
Token* second = args[2]; if (!second->IsFormat()) { return js_new<InvalidCommand>(std::move(args), 2, "expects format");
}
format = FormatToken::Cast(second);
if (format->SizeOf() > target_size) { return js_new<InvalidCommand>(std::move(args), 2, "format too wide");
}
break;
} default: return js_new<InvalidCommand>(std::move(args), -1, "too many arguments");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.