Merge pull request #929 from lioncash/addr

gdbstub: Minor changes
This commit is contained in:
bunnei 2018-08-05 23:36:26 -04:00 committed by GitHub
commit f1b93d63d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 83 deletions

View File

@ -41,40 +41,42 @@
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/memory.h" #include "core/memory.h"
const int GDB_BUFFER_SIZE = 10000; namespace GDBStub {
namespace {
constexpr int GDB_BUFFER_SIZE = 10000;
const char GDB_STUB_START = '$'; constexpr char GDB_STUB_START = '$';
const char GDB_STUB_END = '#'; constexpr char GDB_STUB_END = '#';
const char GDB_STUB_ACK = '+'; constexpr char GDB_STUB_ACK = '+';
const char GDB_STUB_NACK = '-'; constexpr char GDB_STUB_NACK = '-';
#ifndef SIGTRAP #ifndef SIGTRAP
const u32 SIGTRAP = 5; constexpr u32 SIGTRAP = 5;
#endif #endif
#ifndef SIGTERM #ifndef SIGTERM
const u32 SIGTERM = 15; constexpr u32 SIGTERM = 15;
#endif #endif
#ifndef MSG_WAITALL #ifndef MSG_WAITALL
const u32 MSG_WAITALL = 8; constexpr u32 MSG_WAITALL = 8;
#endif #endif
const u32 LR_REGISTER = 30; constexpr u32 LR_REGISTER = 30;
const u32 SP_REGISTER = 31; constexpr u32 SP_REGISTER = 31;
const u32 PC_REGISTER = 32; constexpr u32 PC_REGISTER = 32;
const u32 CPSR_REGISTER = 33; constexpr u32 CPSR_REGISTER = 33;
const u32 UC_ARM64_REG_Q0 = 34; constexpr u32 UC_ARM64_REG_Q0 = 34;
const u32 FPSCR_REGISTER = 66; constexpr u32 FPSCR_REGISTER = 66;
// TODO/WiP - Used while working on support for FPU // TODO/WiP - Used while working on support for FPU
const u32 TODO_DUMMY_REG_997 = 997; constexpr u32 TODO_DUMMY_REG_997 = 997;
const u32 TODO_DUMMY_REG_998 = 998; constexpr u32 TODO_DUMMY_REG_998 = 998;
// For sample XML files see the GDB source /gdb/features // For sample XML files see the GDB source /gdb/features
// GDB also wants the l character at the start // GDB also wants the l character at the start
// This XML defines what the registers are for this specific ARM device // This XML defines what the registers are for this specific ARM device
static const char* target_xml = constexpr char target_xml[] =
R"(l<?xml version="1.0"?> R"(l<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd"> <!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0"> <target version="1.0">
@ -140,30 +142,28 @@ static const char* target_xml =
</target> </target>
)"; )";
namespace GDBStub { int gdbserver_socket = -1;
static int gdbserver_socket = -1; u8 command_buffer[GDB_BUFFER_SIZE];
u32 command_length;
static u8 command_buffer[GDB_BUFFER_SIZE]; u32 latest_signal = 0;
static u32 command_length; bool memory_break = false;
static u32 latest_signal = 0; Kernel::Thread* current_thread = nullptr;
static bool memory_break = false; u32 current_core = 0;
static Kernel::Thread* current_thread = nullptr;
static u32 current_core = 0;
// Binding to a port within the reserved ports range (0-1023) requires root permissions, // Binding to a port within the reserved ports range (0-1023) requires root permissions,
// so default to a port outside of that range. // so default to a port outside of that range.
static u16 gdbstub_port = 24689; u16 gdbstub_port = 24689;
static bool halt_loop = true; bool halt_loop = true;
static bool step_loop = false; bool step_loop = false;
static bool send_trap = false; bool send_trap = false;
// If set to false, the server will never be started and no // If set to false, the server will never be started and no
// gdbstub-related functions will be executed. // gdbstub-related functions will be executed.
static std::atomic<bool> server_enabled(false); std::atomic<bool> server_enabled(false);
#ifdef _WIN32 #ifdef _WIN32
WSADATA InitData; WSADATA InitData;
@ -171,23 +171,25 @@ WSADATA InitData;
struct Breakpoint { struct Breakpoint {
bool active; bool active;
PAddr addr; VAddr addr;
u64 len; u64 len;
}; };
static std::map<u64, Breakpoint> breakpoints_execute; using BreakpointMap = std::map<VAddr, Breakpoint>;
static std::map<u64, Breakpoint> breakpoints_read; BreakpointMap breakpoints_execute;
static std::map<u64, Breakpoint> breakpoints_write; BreakpointMap breakpoints_read;
BreakpointMap breakpoints_write;
struct Module { struct Module {
std::string name; std::string name;
PAddr beg; VAddr beg;
PAddr end; VAddr end;
}; };
static std::vector<Module> modules; std::vector<Module> modules;
} // Anonymous namespace
void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext) { void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext) {
Module module; Module module;
if (add_elf_ext) { if (add_elf_ext) {
Common::SplitPath(name, nullptr, &module.name, nullptr); Common::SplitPath(name, nullptr, &module.name, nullptr);
@ -418,11 +420,11 @@ static u8 CalculateChecksum(const u8* buffer, size_t length) {
} }
/** /**
* Get the list of breakpoints for a given breakpoint type. * Get the map of breakpoints for a given breakpoint type.
* *
* @param type Type of breakpoint list. * @param type Type of breakpoint map.
*/ */
static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) { static BreakpointMap& GetBreakpointMap(BreakpointType type) {
switch (type) { switch (type) {
case BreakpointType::Execute: case BreakpointType::Execute:
return breakpoints_execute; return breakpoints_execute;
@ -441,20 +443,22 @@ static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) {
* @param type Type of breakpoint. * @param type Type of breakpoint.
* @param addr Address of breakpoint. * @param addr Address of breakpoint.
*/ */
static void RemoveBreakpoint(BreakpointType type, PAddr addr) { static void RemoveBreakpoint(BreakpointType type, VAddr addr) {
std::map<u64, Breakpoint>& p = GetBreakpointList(type); BreakpointMap& p = GetBreakpointMap(type);
auto bp = p.find(static_cast<u64>(addr)); const auto bp = p.find(addr);
if (bp != p.end()) { if (bp == p.end()) {
LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", return;
bp->second.len, bp->second.addr, static_cast<int>(type));
p.erase(static_cast<u64>(addr));
} }
LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
bp->second.len, bp->second.addr, static_cast<int>(type));
p.erase(addr);
} }
BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, BreakpointType type) {
std::map<u64, Breakpoint>& p = GetBreakpointList(type); const BreakpointMap& p = GetBreakpointMap(type);
auto next_breakpoint = p.lower_bound(static_cast<u64>(addr)); const auto next_breakpoint = p.lower_bound(addr);
BreakpointAddress breakpoint; BreakpointAddress breakpoint;
if (next_breakpoint != p.end()) { if (next_breakpoint != p.end()) {
@ -468,36 +472,38 @@ BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type)
return breakpoint; return breakpoint;
} }
bool CheckBreakpoint(PAddr addr, BreakpointType type) { bool CheckBreakpoint(VAddr addr, BreakpointType type) {
if (!IsConnected()) { if (!IsConnected()) {
return false; return false;
} }
std::map<u64, Breakpoint>& p = GetBreakpointList(type); const BreakpointMap& p = GetBreakpointMap(type);
const auto bp = p.find(addr);
auto bp = p.find(static_cast<u64>(addr)); if (bp == p.end()) {
if (bp != p.end()) { return false;
u64 len = bp->second.len; }
// IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints u64 len = bp->second.len;
// no matter if it's a 4-byte or 2-byte instruction. When you execute a
// Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on
// two instructions instead of the single instruction you placed the breakpoint
// on. So, as a way to make sure that execution breakpoints are only breaking
// on the instruction that was specified, set the length of an execution
// breakpoint to 1. This should be fine since the CPU should never begin executing
// an instruction anywhere except the beginning of the instruction.
if (type == BreakpointType::Execute) {
len = 1;
}
if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints
LOG_DEBUG(Debug_GDBStub, // no matter if it's a 4-byte or 2-byte instruction. When you execute a
"Found breakpoint type {} @ {:016X}, range: {:016X}" // Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on
" - {:016X} ({:X} bytes)", // two instructions instead of the single instruction you placed the breakpoint
static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len); // on. So, as a way to make sure that execution breakpoints are only breaking
return true; // on the instruction that was specified, set the length of an execution
} // breakpoint to 1. This should be fine since the CPU should never begin executing
// an instruction anywhere except the beginning of the instruction.
if (type == BreakpointType::Execute) {
len = 1;
}
if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
LOG_DEBUG(Debug_GDBStub,
"Found breakpoint type {} @ {:016X}, range: {:016X}"
" - {:016X} ({:X} bytes)",
static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len);
return true;
} }
return false; return false;
@ -975,8 +981,8 @@ static void Continue() {
* @param addr Address of breakpoint. * @param addr Address of breakpoint.
* @param len Length of breakpoint. * @param len Length of breakpoint.
*/ */
static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) { static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
std::map<u64, Breakpoint>& p = GetBreakpointList(type); BreakpointMap& p = GetBreakpointMap(type);
Breakpoint breakpoint; Breakpoint breakpoint;
breakpoint.active = true; breakpoint.active = true;
@ -1015,7 +1021,7 @@ static void AddBreakpoint() {
auto start_offset = command_buffer + 3; auto start_offset = command_buffer + 3;
auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
start_offset = addr_pos + 1; start_offset = addr_pos + 1;
u64 len = u64 len =
@ -1064,7 +1070,7 @@ static void RemoveBreakpoint() {
auto start_offset = command_buffer + 3; auto start_offset = command_buffer + 3;
auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
if (type == BreakpointType::Access) { if (type == BreakpointType::Access) {
// Access is made up of Read and Write types, so add both breakpoints // Access is made up of Read and Write types, so add both breakpoints

View File

@ -22,7 +22,7 @@ enum class BreakpointType {
}; };
struct BreakpointAddress { struct BreakpointAddress {
PAddr address; VAddr address;
BreakpointType type; BreakpointType type;
}; };
@ -53,7 +53,7 @@ bool IsServerEnabled();
bool IsConnected(); bool IsConnected();
/// Register module. /// Register module.
void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext = true); void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext = true);
/** /**
* Signal to the gdbstub server that it should halt CPU execution. * Signal to the gdbstub server that it should halt CPU execution.
@ -74,7 +74,7 @@ void HandlePacket();
* @param addr Address to search from. * @param addr Address to search from.
* @param type Type of breakpoint. * @param type Type of breakpoint.
*/ */
BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, GDBStub::BreakpointType type); BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, GDBStub::BreakpointType type);
/** /**
* Check if a breakpoint of the specified type exists at the given address. * Check if a breakpoint of the specified type exists at the given address.
@ -82,7 +82,7 @@ BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, GDBStub::BreakpointTy
* @param addr Address of breakpoint. * @param addr Address of breakpoint.
* @param type Type of breakpoint. * @param type Type of breakpoint.
*/ */
bool CheckBreakpoint(PAddr addr, GDBStub::BreakpointType type); bool CheckBreakpoint(VAddr addr, GDBStub::BreakpointType type);
/// If set to true, the CPU will halt at the beginning of the next CPU loop. /// If set to true, the CPU will halt at the beginning of the next CPU loop.
bool GetCpuHaltFlag(); bool GetCpuHaltFlag();