summaryrefslogtreecommitdiff
path: root/src/core/gdbstub/gdbstub.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2018-08-05 23:36:26 -0400
committerGravatar GitHub2018-08-05 23:36:26 -0400
commitf1b93d63d14236f0c17403df3bda830dc5fcd3a4 (patch)
tree407363978389dcb0bb38781282673f1d43529e00 /src/core/gdbstub/gdbstub.cpp
parentMerge pull request #930 from lioncash/thread (diff)
parentgdbstub: Use type alias for breakpoint maps (diff)
downloadyuzu-f1b93d63d14236f0c17403df3bda830dc5fcd3a4.tar.gz
yuzu-f1b93d63d14236f0c17403df3bda830dc5fcd3a4.tar.xz
yuzu-f1b93d63d14236f0c17403df3bda830dc5fcd3a4.zip
Merge pull request #929 from lioncash/addr
gdbstub: Minor changes
Diffstat (limited to 'src/core/gdbstub/gdbstub.cpp')
-rw-r--r--src/core/gdbstub/gdbstub.cpp164
1 files changed, 85 insertions, 79 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 75f6b8235..884e64e99 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -41,40 +41,42 @@
41#include "core/loader/loader.h" 41#include "core/loader/loader.h"
42#include "core/memory.h" 42#include "core/memory.h"
43 43
44const int GDB_BUFFER_SIZE = 10000; 44namespace GDBStub {
45namespace {
46constexpr int GDB_BUFFER_SIZE = 10000;
45 47
46const char GDB_STUB_START = '$'; 48constexpr char GDB_STUB_START = '$';
47const char GDB_STUB_END = '#'; 49constexpr char GDB_STUB_END = '#';
48const char GDB_STUB_ACK = '+'; 50constexpr char GDB_STUB_ACK = '+';
49const char GDB_STUB_NACK = '-'; 51constexpr char GDB_STUB_NACK = '-';
50 52
51#ifndef SIGTRAP 53#ifndef SIGTRAP
52const u32 SIGTRAP = 5; 54constexpr u32 SIGTRAP = 5;
53#endif 55#endif
54 56
55#ifndef SIGTERM 57#ifndef SIGTERM
56const u32 SIGTERM = 15; 58constexpr u32 SIGTERM = 15;
57#endif 59#endif
58 60
59#ifndef MSG_WAITALL 61#ifndef MSG_WAITALL
60const u32 MSG_WAITALL = 8; 62constexpr u32 MSG_WAITALL = 8;
61#endif 63#endif
62 64
63const u32 LR_REGISTER = 30; 65constexpr u32 LR_REGISTER = 30;
64const u32 SP_REGISTER = 31; 66constexpr u32 SP_REGISTER = 31;
65const u32 PC_REGISTER = 32; 67constexpr u32 PC_REGISTER = 32;
66const u32 CPSR_REGISTER = 33; 68constexpr u32 CPSR_REGISTER = 33;
67const u32 UC_ARM64_REG_Q0 = 34; 69constexpr u32 UC_ARM64_REG_Q0 = 34;
68const u32 FPSCR_REGISTER = 66; 70constexpr u32 FPSCR_REGISTER = 66;
69 71
70// TODO/WiP - Used while working on support for FPU 72// TODO/WiP - Used while working on support for FPU
71const u32 TODO_DUMMY_REG_997 = 997; 73constexpr u32 TODO_DUMMY_REG_997 = 997;
72const u32 TODO_DUMMY_REG_998 = 998; 74constexpr u32 TODO_DUMMY_REG_998 = 998;
73 75
74// For sample XML files see the GDB source /gdb/features 76// For sample XML files see the GDB source /gdb/features
75// GDB also wants the l character at the start 77// GDB also wants the l character at the start
76// This XML defines what the registers are for this specific ARM device 78// This XML defines what the registers are for this specific ARM device
77static const char* target_xml = 79constexpr char target_xml[] =
78 R"(l<?xml version="1.0"?> 80 R"(l<?xml version="1.0"?>
79<!DOCTYPE target SYSTEM "gdb-target.dtd"> 81<!DOCTYPE target SYSTEM "gdb-target.dtd">
80<target version="1.0"> 82<target version="1.0">
@@ -140,30 +142,28 @@ static const char* target_xml =
140</target> 142</target>
141)"; 143)";
142 144
143namespace GDBStub { 145int gdbserver_socket = -1;
144
145static int gdbserver_socket = -1;
146 146
147static u8 command_buffer[GDB_BUFFER_SIZE]; 147u8 command_buffer[GDB_BUFFER_SIZE];
148static u32 command_length; 148u32 command_length;
149 149
150static u32 latest_signal = 0; 150u32 latest_signal = 0;
151static bool memory_break = false; 151bool memory_break = false;
152 152
153static Kernel::Thread* current_thread = nullptr; 153Kernel::Thread* current_thread = nullptr;
154static u32 current_core = 0; 154u32 current_core = 0;
155 155
156// Binding to a port within the reserved ports range (0-1023) requires root permissions, 156// Binding to a port within the reserved ports range (0-1023) requires root permissions,
157// so default to a port outside of that range. 157// so default to a port outside of that range.
158static u16 gdbstub_port = 24689; 158u16 gdbstub_port = 24689;
159 159
160static bool halt_loop = true; 160bool halt_loop = true;
161static bool step_loop = false; 161bool step_loop = false;
162static bool send_trap = false; 162bool send_trap = false;
163 163
164// If set to false, the server will never be started and no 164// If set to false, the server will never be started and no
165// gdbstub-related functions will be executed. 165// gdbstub-related functions will be executed.
166static std::atomic<bool> server_enabled(false); 166std::atomic<bool> server_enabled(false);
167 167
168#ifdef _WIN32 168#ifdef _WIN32
169WSADATA InitData; 169WSADATA InitData;
@@ -171,23 +171,25 @@ WSADATA InitData;
171 171
172struct Breakpoint { 172struct Breakpoint {
173 bool active; 173 bool active;
174 PAddr addr; 174 VAddr addr;
175 u64 len; 175 u64 len;
176}; 176};
177 177
178static std::map<u64, Breakpoint> breakpoints_execute; 178using BreakpointMap = std::map<VAddr, Breakpoint>;
179static std::map<u64, Breakpoint> breakpoints_read; 179BreakpointMap breakpoints_execute;
180static std::map<u64, Breakpoint> breakpoints_write; 180BreakpointMap breakpoints_read;
181BreakpointMap breakpoints_write;
181 182
182struct Module { 183struct Module {
183 std::string name; 184 std::string name;
184 PAddr beg; 185 VAddr beg;
185 PAddr end; 186 VAddr end;
186}; 187};
187 188
188static std::vector<Module> modules; 189std::vector<Module> modules;
190} // Anonymous namespace
189 191
190void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext) { 192void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext) {
191 Module module; 193 Module module;
192 if (add_elf_ext) { 194 if (add_elf_ext) {
193 Common::SplitPath(name, nullptr, &module.name, nullptr); 195 Common::SplitPath(name, nullptr, &module.name, nullptr);
@@ -418,11 +420,11 @@ static u8 CalculateChecksum(const u8* buffer, size_t length) {
418} 420}
419 421
420/** 422/**
421 * Get the list of breakpoints for a given breakpoint type. 423 * Get the map of breakpoints for a given breakpoint type.
422 * 424 *
423 * @param type Type of breakpoint list. 425 * @param type Type of breakpoint map.
424 */ 426 */
425static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) { 427static BreakpointMap& GetBreakpointMap(BreakpointType type) {
426 switch (type) { 428 switch (type) {
427 case BreakpointType::Execute: 429 case BreakpointType::Execute:
428 return breakpoints_execute; 430 return breakpoints_execute;
@@ -441,20 +443,22 @@ static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) {
441 * @param type Type of breakpoint. 443 * @param type Type of breakpoint.
442 * @param addr Address of breakpoint. 444 * @param addr Address of breakpoint.
443 */ 445 */
444static void RemoveBreakpoint(BreakpointType type, PAddr addr) { 446static void RemoveBreakpoint(BreakpointType type, VAddr addr) {
445 std::map<u64, Breakpoint>& p = GetBreakpointList(type); 447 BreakpointMap& p = GetBreakpointMap(type);
446 448
447 auto bp = p.find(static_cast<u64>(addr)); 449 const auto bp = p.find(addr);
448 if (bp != p.end()) { 450 if (bp == p.end()) {
449 LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", 451 return;
450 bp->second.len, bp->second.addr, static_cast<int>(type));
451 p.erase(static_cast<u64>(addr));
452 } 452 }
453
454 LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
455 bp->second.len, bp->second.addr, static_cast<int>(type));
456 p.erase(addr);
453} 457}
454 458
455BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { 459BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, BreakpointType type) {
456 std::map<u64, Breakpoint>& p = GetBreakpointList(type); 460 const BreakpointMap& p = GetBreakpointMap(type);
457 auto next_breakpoint = p.lower_bound(static_cast<u64>(addr)); 461 const auto next_breakpoint = p.lower_bound(addr);
458 BreakpointAddress breakpoint; 462 BreakpointAddress breakpoint;
459 463
460 if (next_breakpoint != p.end()) { 464 if (next_breakpoint != p.end()) {
@@ -468,36 +472,38 @@ BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type)
468 return breakpoint; 472 return breakpoint;
469} 473}
470 474
471bool CheckBreakpoint(PAddr addr, BreakpointType type) { 475bool CheckBreakpoint(VAddr addr, BreakpointType type) {
472 if (!IsConnected()) { 476 if (!IsConnected()) {
473 return false; 477 return false;
474 } 478 }
475 479
476 std::map<u64, Breakpoint>& p = GetBreakpointList(type); 480 const BreakpointMap& p = GetBreakpointMap(type);
481 const auto bp = p.find(addr);
477 482
478 auto bp = p.find(static_cast<u64>(addr)); 483 if (bp == p.end()) {
479 if (bp != p.end()) { 484 return false;
480 u64 len = bp->second.len; 485 }
481 486
482 // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints 487 u64 len = bp->second.len;
483 // no matter if it's a 4-byte or 2-byte instruction. When you execute a
484 // Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on
485 // two instructions instead of the single instruction you placed the breakpoint
486 // on. So, as a way to make sure that execution breakpoints are only breaking
487 // on the instruction that was specified, set the length of an execution
488 // breakpoint to 1. This should be fine since the CPU should never begin executing
489 // an instruction anywhere except the beginning of the instruction.
490 if (type == BreakpointType::Execute) {
491 len = 1;
492 }
493 488
494 if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { 489 // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints
495 LOG_DEBUG(Debug_GDBStub, 490 // no matter if it's a 4-byte or 2-byte instruction. When you execute a
496 "Found breakpoint type {} @ {:016X}, range: {:016X}" 491 // Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on
497 " - {:016X} ({:X} bytes)", 492 // two instructions instead of the single instruction you placed the breakpoint
498 static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len); 493 // on. So, as a way to make sure that execution breakpoints are only breaking
499 return true; 494 // on the instruction that was specified, set the length of an execution
500 } 495 // breakpoint to 1. This should be fine since the CPU should never begin executing
496 // an instruction anywhere except the beginning of the instruction.
497 if (type == BreakpointType::Execute) {
498 len = 1;
499 }
500
501 if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
502 LOG_DEBUG(Debug_GDBStub,
503 "Found breakpoint type {} @ {:016X}, range: {:016X}"
504 " - {:016X} ({:X} bytes)",
505 static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len);
506 return true;
501 } 507 }
502 508
503 return false; 509 return false;
@@ -975,8 +981,8 @@ static void Continue() {
975 * @param addr Address of breakpoint. 981 * @param addr Address of breakpoint.
976 * @param len Length of breakpoint. 982 * @param len Length of breakpoint.
977 */ 983 */
978static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) { 984static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
979 std::map<u64, Breakpoint>& p = GetBreakpointList(type); 985 BreakpointMap& p = GetBreakpointMap(type);
980 986
981 Breakpoint breakpoint; 987 Breakpoint breakpoint;
982 breakpoint.active = true; 988 breakpoint.active = true;
@@ -1015,7 +1021,7 @@ static void AddBreakpoint() {
1015 1021
1016 auto start_offset = command_buffer + 3; 1022 auto start_offset = command_buffer + 3;
1017 auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); 1023 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
1018 PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); 1024 VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
1019 1025
1020 start_offset = addr_pos + 1; 1026 start_offset = addr_pos + 1;
1021 u64 len = 1027 u64 len =
@@ -1064,7 +1070,7 @@ static void RemoveBreakpoint() {
1064 1070
1065 auto start_offset = command_buffer + 3; 1071 auto start_offset = command_buffer + 3;
1066 auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); 1072 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
1067 PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); 1073 VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
1068 1074
1069 if (type == BreakpointType::Access) { 1075 if (type == BreakpointType::Access) {
1070 // Access is made up of Read and Write types, so add both breakpoints 1076 // Access is made up of Read and Write types, so add both breakpoints