diff options
| author | 2018-08-05 23:36:26 -0400 | |
|---|---|---|
| committer | 2018-08-05 23:36:26 -0400 | |
| commit | f1b93d63d14236f0c17403df3bda830dc5fcd3a4 (patch) | |
| tree | 407363978389dcb0bb38781282673f1d43529e00 /src/core/gdbstub/gdbstub.cpp | |
| parent | Merge pull request #930 from lioncash/thread (diff) | |
| parent | gdbstub: Use type alias for breakpoint maps (diff) | |
| download | yuzu-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.cpp | 164 |
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 | ||
| 44 | const int GDB_BUFFER_SIZE = 10000; | 44 | namespace GDBStub { |
| 45 | namespace { | ||
| 46 | constexpr int GDB_BUFFER_SIZE = 10000; | ||
| 45 | 47 | ||
| 46 | const char GDB_STUB_START = '$'; | 48 | constexpr char GDB_STUB_START = '$'; |
| 47 | const char GDB_STUB_END = '#'; | 49 | constexpr char GDB_STUB_END = '#'; |
| 48 | const char GDB_STUB_ACK = '+'; | 50 | constexpr char GDB_STUB_ACK = '+'; |
| 49 | const char GDB_STUB_NACK = '-'; | 51 | constexpr char GDB_STUB_NACK = '-'; |
| 50 | 52 | ||
| 51 | #ifndef SIGTRAP | 53 | #ifndef SIGTRAP |
| 52 | const u32 SIGTRAP = 5; | 54 | constexpr u32 SIGTRAP = 5; |
| 53 | #endif | 55 | #endif |
| 54 | 56 | ||
| 55 | #ifndef SIGTERM | 57 | #ifndef SIGTERM |
| 56 | const u32 SIGTERM = 15; | 58 | constexpr u32 SIGTERM = 15; |
| 57 | #endif | 59 | #endif |
| 58 | 60 | ||
| 59 | #ifndef MSG_WAITALL | 61 | #ifndef MSG_WAITALL |
| 60 | const u32 MSG_WAITALL = 8; | 62 | constexpr u32 MSG_WAITALL = 8; |
| 61 | #endif | 63 | #endif |
| 62 | 64 | ||
| 63 | const u32 LR_REGISTER = 30; | 65 | constexpr u32 LR_REGISTER = 30; |
| 64 | const u32 SP_REGISTER = 31; | 66 | constexpr u32 SP_REGISTER = 31; |
| 65 | const u32 PC_REGISTER = 32; | 67 | constexpr u32 PC_REGISTER = 32; |
| 66 | const u32 CPSR_REGISTER = 33; | 68 | constexpr u32 CPSR_REGISTER = 33; |
| 67 | const u32 UC_ARM64_REG_Q0 = 34; | 69 | constexpr u32 UC_ARM64_REG_Q0 = 34; |
| 68 | const u32 FPSCR_REGISTER = 66; | 70 | constexpr 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 |
| 71 | const u32 TODO_DUMMY_REG_997 = 997; | 73 | constexpr u32 TODO_DUMMY_REG_997 = 997; |
| 72 | const u32 TODO_DUMMY_REG_998 = 998; | 74 | constexpr 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 |
| 77 | static const char* target_xml = | 79 | constexpr 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 | ||
| 143 | namespace GDBStub { | 145 | int gdbserver_socket = -1; |
| 144 | |||
| 145 | static int gdbserver_socket = -1; | ||
| 146 | 146 | ||
| 147 | static u8 command_buffer[GDB_BUFFER_SIZE]; | 147 | u8 command_buffer[GDB_BUFFER_SIZE]; |
| 148 | static u32 command_length; | 148 | u32 command_length; |
| 149 | 149 | ||
| 150 | static u32 latest_signal = 0; | 150 | u32 latest_signal = 0; |
| 151 | static bool memory_break = false; | 151 | bool memory_break = false; |
| 152 | 152 | ||
| 153 | static Kernel::Thread* current_thread = nullptr; | 153 | Kernel::Thread* current_thread = nullptr; |
| 154 | static u32 current_core = 0; | 154 | u32 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. |
| 158 | static u16 gdbstub_port = 24689; | 158 | u16 gdbstub_port = 24689; |
| 159 | 159 | ||
| 160 | static bool halt_loop = true; | 160 | bool halt_loop = true; |
| 161 | static bool step_loop = false; | 161 | bool step_loop = false; |
| 162 | static bool send_trap = false; | 162 | bool 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. |
| 166 | static std::atomic<bool> server_enabled(false); | 166 | std::atomic<bool> server_enabled(false); |
| 167 | 167 | ||
| 168 | #ifdef _WIN32 | 168 | #ifdef _WIN32 |
| 169 | WSADATA InitData; | 169 | WSADATA InitData; |
| @@ -171,23 +171,25 @@ WSADATA InitData; | |||
| 171 | 171 | ||
| 172 | struct Breakpoint { | 172 | struct Breakpoint { |
| 173 | bool active; | 173 | bool active; |
| 174 | PAddr addr; | 174 | VAddr addr; |
| 175 | u64 len; | 175 | u64 len; |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | static std::map<u64, Breakpoint> breakpoints_execute; | 178 | using BreakpointMap = std::map<VAddr, Breakpoint>; |
| 179 | static std::map<u64, Breakpoint> breakpoints_read; | 179 | BreakpointMap breakpoints_execute; |
| 180 | static std::map<u64, Breakpoint> breakpoints_write; | 180 | BreakpointMap breakpoints_read; |
| 181 | BreakpointMap breakpoints_write; | ||
| 181 | 182 | ||
| 182 | struct Module { | 183 | struct 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 | ||
| 188 | static std::vector<Module> modules; | 189 | std::vector<Module> modules; |
| 190 | } // Anonymous namespace | ||
| 189 | 191 | ||
| 190 | void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext) { | 192 | void 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 | */ |
| 425 | static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) { | 427 | static 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 | */ |
| 444 | static void RemoveBreakpoint(BreakpointType type, PAddr addr) { | 446 | static 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 | ||
| 455 | BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { | 459 | BreakpointAddress 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 | ||
| 471 | bool CheckBreakpoint(PAddr addr, BreakpointType type) { | 475 | bool 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 | */ |
| 978 | static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) { | 984 | static 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 |