From 5bc4eabe36b7ef4dcd5ad8db1e944705655be432 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 27 Nov 2020 10:50:48 -0500 Subject: [PATCH] core: Eliminate remaining usages of the global system instance Removes all remaining usages of the global system instance. After this, migration can begin to migrate to being constructed and managed entirely by the various frontends. --- src/core/CMakeLists.txt | 2 - src/core/arm/dynarmic/arm_dynarmic_64.cpp | 11 - src/core/core.cpp | 7 +- src/core/cpu_manager.cpp | 1 - src/core/gdbstub/gdbstub.cpp | 1397 ----------------- src/core/gdbstub/gdbstub.h | 114 -- .../loader/deconstructed_rom_directory.cpp | 3 - src/core/loader/kip.cpp | 3 - src/core/loader/nro.cpp | 6 +- src/core/loader/nso.cpp | 5 +- src/core/settings.cpp | 17 +- src/core/settings.h | 8 +- src/yuzu/configuration/config.cpp | 3 +- src/yuzu/configuration/configure_dialog.cpp | 3 +- src/yuzu/configuration/configure_per_game.cpp | 2 +- .../configure_profile_manager.cpp | 2 +- src/yuzu/configuration/configure_system.cpp | 12 +- src/yuzu/configuration/configure_ui.cpp | 3 +- src/yuzu/main.cpp | 36 +- src/yuzu_cmd/yuzu.cpp | 9 +- src/yuzu_tester/yuzu.cpp | 9 +- 21 files changed, 59 insertions(+), 1594 deletions(-) delete mode 100644 src/core/gdbstub/gdbstub.cpp delete mode 100644 src/core/gdbstub/gdbstub.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e370fd2251..66de33799d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -135,8 +135,6 @@ add_library(core STATIC frontend/framebuffer_layout.cpp frontend/framebuffer_layout.h frontend/input.h - gdbstub/gdbstub.cpp - gdbstub/gdbstub.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h hle/ipc.h diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 9f170a2247..5c2060d789 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -14,7 +14,6 @@ #include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/gdbstub/gdbstub.h" #include "core/hardware_properties.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/scheduler.h" @@ -96,16 +95,6 @@ public: case Dynarmic::A64::Exception::Yield: return; case Dynarmic::A64::Exception::Breakpoint: - if (GDBStub::IsServerEnabled()) { - parent.jit->HaltExecution(); - parent.SetPC(pc); - Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread(); - parent.SaveContext(thread->GetContext64()); - GDBStub::Break(); - GDBStub::SendTrap(thread, 5); - return; - } - [[fallthrough]]; default: ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", static_cast(exception), pc, MemoryReadCode(pc)); diff --git a/src/core/core.cpp b/src/core/core.cpp index 7ca3652afd..f4bbc9ec32 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -25,7 +25,6 @@ #include "core/file_sys/sdmc_factory.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" -#include "core/gdbstub/gdbstub.h" #include "core/hardware_interrupt_manager.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" @@ -186,11 +185,8 @@ struct System::Impl { } service_manager = std::make_shared(kernel); - services = std::make_unique(service_manager, system); - GDBStub::DeferStart(); - - interrupt_manager = std::make_unique(system); + interrupt_manager = std::make_unique(system); // Initialize time manager, which must happen after kernel is created time_manager.Initialize(); @@ -297,7 +293,6 @@ struct System::Impl { } // Shutdown emulation session - GDBStub::Shutdown(); services.reset(); service_manager.reset(); cheat_engine.reset(); diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 100e90d823..eeeb6e8df4 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -10,7 +10,6 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/cpu_manager.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/scheduler.h" diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp deleted file mode 100644 index 97ee65464b..0000000000 --- a/src/core/gdbstub/gdbstub.cpp +++ /dev/null @@ -1,1397 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -// Originally written by Sven Peter for anergistic. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -// winsock2.h needs to be included first to prevent winsock.h being included by other includes -#include -#include -#include -#define SHUT_RDWR 2 -#else -#include -#include -#include -#include -#include -#endif - -#include "common/logging/log.h" -#include "common/string_util.h" -#include "common/swap.h" -#include "core/arm/arm_interface.h" -#include "core/core.h" -#include "core/gdbstub/gdbstub.h" -#include "core/hle/kernel/memory/page_table.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/scheduler.h" -#include "core/loader/loader.h" -#include "core/memory.h" - -namespace GDBStub { -namespace { -constexpr int GDB_BUFFER_SIZE = 10000; - -constexpr char GDB_STUB_START = '$'; -constexpr char GDB_STUB_END = '#'; -constexpr char GDB_STUB_ACK = '+'; -constexpr char GDB_STUB_NACK = '-'; - -#ifndef SIGTRAP -constexpr u32 SIGTRAP = 5; -#endif - -#ifndef SIGTERM -constexpr u32 SIGTERM = 15; -#endif - -#ifndef MSG_WAITALL -constexpr u32 MSG_WAITALL = 8; -#endif - -constexpr u32 LR_REGISTER = 30; -constexpr u32 SP_REGISTER = 31; -constexpr u32 PC_REGISTER = 32; -constexpr u32 PSTATE_REGISTER = 33; -constexpr u32 UC_ARM64_REG_Q0 = 34; -constexpr u32 FPCR_REGISTER = 66; - -// For sample XML files see the GDB source /gdb/features -// GDB also wants the l character at the start -// This XML defines what the registers are for this specific ARM device -constexpr char target_xml[] = - R"(l - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -)"; - -int gdbserver_socket = -1; -bool defer_start = false; - -u8 command_buffer[GDB_BUFFER_SIZE]; -u32 command_length; - -u32 latest_signal = 0; -bool memory_break = false; - -Kernel::Thread* current_thread = nullptr; -u32 current_core = 0; - -// Binding to a port within the reserved ports range (0-1023) requires root permissions, -// so default to a port outside of that range. -u16 gdbstub_port = 24689; - -bool halt_loop = true; -bool step_loop = false; -bool send_trap = false; - -// If set to false, the server will never be started and no -// gdbstub-related functions will be executed. -std::atomic server_enabled(false); - -#ifdef _WIN32 -WSADATA InitData; -#endif - -struct Breakpoint { - bool active; - VAddr addr; - u64 len; - std::array inst; -}; - -using BreakpointMap = std::map; -BreakpointMap breakpoints_execute; -BreakpointMap breakpoints_read; -BreakpointMap breakpoints_write; - -struct Module { - std::string name; - VAddr beg; - VAddr end; -}; - -std::vector modules; -} // Anonymous namespace - -void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext) { - Module module; - if (add_elf_ext) { - Common::SplitPath(name, nullptr, &module.name, nullptr); - module.name += ".elf"; - } else { - module.name = std::move(name); - } - module.beg = beg; - module.end = end; - modules.push_back(std::move(module)); -} - -static Kernel::Thread* FindThreadById(s64 id) { - const auto& threads = Core::System::GetInstance().GlobalScheduler().GetThreadList(); - for (auto& thread : threads) { - if (thread->GetThreadID() == static_cast(id)) { - current_core = thread->GetProcessorID(); - return thread.get(); - } - } - return nullptr; -} - -static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) { - if (!thread) { - return 0; - } - - const auto& thread_context = thread->GetContext64(); - - if (id < SP_REGISTER) { - return thread_context.cpu_registers[id]; - } else if (id == SP_REGISTER) { - return thread_context.sp; - } else if (id == PC_REGISTER) { - return thread_context.pc; - } else if (id == PSTATE_REGISTER) { - return thread_context.pstate; - } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) { - return thread_context.vector_registers[id - UC_ARM64_REG_Q0][0]; - } else { - return 0; - } -} - -static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr) { - if (!thread) { - return; - } - - auto& thread_context = thread->GetContext64(); - - if (id < SP_REGISTER) { - thread_context.cpu_registers[id] = val; - } else if (id == SP_REGISTER) { - thread_context.sp = val; - } else if (id == PC_REGISTER) { - thread_context.pc = val; - } else if (id == PSTATE_REGISTER) { - thread_context.pstate = static_cast(val); - } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) { - thread_context.vector_registers[id - (PSTATE_REGISTER + 1)][0] = val; - } -} - -static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) { - if (!thread) { - return u128{0}; - } - - auto& thread_context = thread->GetContext64(); - - if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - return thread_context.vector_registers[id - UC_ARM64_REG_Q0]; - } else if (id == FPCR_REGISTER) { - return u128{thread_context.fpcr, 0}; - } else { - return u128{0}; - } -} - -static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr) { - if (!thread) { - return; - } - - auto& thread_context = thread->GetContext64(); - - if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val; - } else if (id == FPCR_REGISTER) { - thread_context.fpcr = static_cast(val[0]); - } -} - -/** - * Turns hex string character into the equivalent byte. - * - * @param hex Input hex character to be turned into byte. - */ -static u8 HexCharToValue(u8 hex) { - if (hex >= '0' && hex <= '9') { - return static_cast(hex - '0'); - } else if (hex >= 'a' && hex <= 'f') { - return static_cast(hex - 'a' + 0xA); - } else if (hex >= 'A' && hex <= 'F') { - return static_cast(hex - 'A' + 0xA); - } - - LOG_ERROR(Debug_GDBStub, "Invalid nibble: {} ({:02X})", hex, hex); - return 0; -} - -/** - * Turn nibble of byte into hex string character. - * - * @param n Nibble to be turned into hex character. - */ -static u8 NibbleToHex(u8 n) { - n &= 0xF; - if (n < 0xA) { - return static_cast('0' + n); - } else { - return static_cast('a' + n - 0xA); - } -} - -/** - * Converts input hex string characters into an array of equivalent of u8 bytes. - * - * @param src Pointer to array of output hex string characters. - * @param len Length of src array. - */ -static u32 HexToInt(const u8* src, std::size_t len) { - u32 output = 0; - while (len-- > 0) { - output = (output << 4) | HexCharToValue(src[0]); - src++; - } - return output; -} - -/** - * Converts input hex string characters into an array of equivalent of u8 bytes. - * - * @param src Pointer to array of output hex string characters. - * @param len Length of src array. - */ -static u64 HexToLong(const u8* src, std::size_t len) { - u64 output = 0; - while (len-- > 0) { - output = (output << 4) | HexCharToValue(src[0]); - src++; - } - return output; -} - -/** - * Converts input array of u8 bytes into their equivalent hex string characters. - * - * @param dest Pointer to buffer to store output hex string characters. - * @param src Pointer to array of u8 bytes. - * @param len Length of src array. - */ -static void MemToGdbHex(u8* dest, const u8* src, std::size_t len) { - while (len-- > 0) { - const u8 tmp = *src++; - *dest++ = NibbleToHex(static_cast(tmp >> 4)); - *dest++ = NibbleToHex(tmp); - } -} - -/** - * Converts input gdb-formatted hex string characters into an array of equivalent of u8 bytes. - * - * @param dest Pointer to buffer to store u8 bytes. - * @param src Pointer to array of output hex string characters. - * @param len Length of src array. - */ -static void GdbHexToMem(u8* dest, const u8* src, std::size_t len) { - while (len-- > 0) { - *dest++ = static_cast((HexCharToValue(src[0]) << 4) | HexCharToValue(src[1])); - src += 2; - } -} - -/** - * Convert a u32 into a gdb-formatted hex string. - * - * @param dest Pointer to buffer to store output hex string characters. - * @param v Value to convert. - */ -static void IntToGdbHex(u8* dest, u32 v) { - for (int i = 0; i < 8; i += 2) { - dest[i + 1] = NibbleToHex(static_cast(v >> (4 * i))); - dest[i] = NibbleToHex(static_cast(v >> (4 * (i + 1)))); - } -} - -/** - * Convert a u64 into a gdb-formatted hex string. - * - * @param dest Pointer to buffer to store output hex string characters. - * @param v Value to convert. - */ -static void LongToGdbHex(u8* dest, u64 v) { - for (int i = 0; i < 16; i += 2) { - dest[i + 1] = NibbleToHex(static_cast(v >> (4 * i))); - dest[i] = NibbleToHex(static_cast(v >> (4 * (i + 1)))); - } -} - -/** - * Convert a gdb-formatted hex string into a u32. - * - * @param src Pointer to hex string. - */ -static u32 GdbHexToInt(const u8* src) { - u32 output = 0; - - for (int i = 0; i < 8; i += 2) { - output = (output << 4) | HexCharToValue(src[7 - i - 1]); - output = (output << 4) | HexCharToValue(src[7 - i]); - } - - return output; -} - -/** - * Convert a gdb-formatted hex string into a u64. - * - * @param src Pointer to hex string. - */ -static u64 GdbHexToLong(const u8* src) { - u64 output = 0; - - for (int i = 0; i < 16; i += 2) { - output = (output << 4) | HexCharToValue(src[15 - i - 1]); - output = (output << 4) | HexCharToValue(src[15 - i]); - } - - return output; -} - -/** - * Convert a gdb-formatted hex string into a u128. - * - * @param src Pointer to hex string. - */ -static u128 GdbHexToU128(const u8* src) { - u128 output; - - for (int i = 0; i < 16; i += 2) { - output[0] = (output[0] << 4) | HexCharToValue(src[15 - i - 1]); - output[0] = (output[0] << 4) | HexCharToValue(src[15 - i]); - } - - for (int i = 0; i < 16; i += 2) { - output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i - 1]); - output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i]); - } - - return output; -} - -/// Read a byte from the gdb client. -static u8 ReadByte() { - u8 c; - std::size_t received_size = recv(gdbserver_socket, reinterpret_cast(&c), 1, MSG_WAITALL); - if (received_size != 1) { - LOG_ERROR(Debug_GDBStub, "recv failed: {}", received_size); - Shutdown(); - } - - return c; -} - -/// Calculate the checksum of the current command buffer. -static u8 CalculateChecksum(const u8* buffer, std::size_t length) { - return static_cast(std::accumulate(buffer, buffer + length, u8{0}, - [](u8 lhs, u8 rhs) { return u8(lhs + rhs); })); -} - -/** - * Get the map of breakpoints for a given breakpoint type. - * - * @param type Type of breakpoint map. - */ -static BreakpointMap& GetBreakpointMap(BreakpointType type) { - switch (type) { - case BreakpointType::Execute: - return breakpoints_execute; - case BreakpointType::Read: - return breakpoints_read; - case BreakpointType::Write: - return breakpoints_write; - default: - return breakpoints_read; - } -} - -/** - * Remove the breakpoint from the given address of the specified type. - * - * @param type Type of breakpoint. - * @param addr Address of breakpoint. - */ -static void RemoveBreakpoint(BreakpointType type, VAddr addr) { - BreakpointMap& p = GetBreakpointMap(type); - - const auto bp = p.find(addr); - if (bp == p.end()) { - return; - } - - LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", - bp->second.len, bp->second.addr, static_cast(type)); - - if (type == BreakpointType::Execute) { - auto& system = Core::System::GetInstance(); - system.Memory().WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size()); - system.InvalidateCpuInstructionCaches(); - } - p.erase(addr); -} - -BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, BreakpointType type) { - const BreakpointMap& p = GetBreakpointMap(type); - const auto next_breakpoint = p.lower_bound(addr); - BreakpointAddress breakpoint; - - if (next_breakpoint != p.end()) { - breakpoint.address = next_breakpoint->first; - breakpoint.type = type; - } else { - breakpoint.address = 0; - breakpoint.type = BreakpointType::None; - } - - return breakpoint; -} - -bool CheckBreakpoint(VAddr addr, BreakpointType type) { - if (!IsConnected()) { - return false; - } - - const BreakpointMap& p = GetBreakpointMap(type); - const auto bp = p.find(addr); - - if (bp == p.end()) { - return false; - } - - u64 len = bp->second.len; - - // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints - // 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)) { - LOG_DEBUG(Debug_GDBStub, - "Found breakpoint type {} @ {:016X}, range: {:016X}" - " - {:016X} ({:X} bytes)", - static_cast(type), addr, bp->second.addr, bp->second.addr + len, len); - return true; - } - - return false; -} - -/** - * Send packet to gdb client. - * - * @param packet Packet to be sent to client. - */ -static void SendPacket(const char packet) { - std::size_t sent_size = send(gdbserver_socket, &packet, 1, 0); - if (sent_size != 1) { - LOG_ERROR(Debug_GDBStub, "send failed"); - } -} - -/** - * Send reply to gdb client. - * - * @param reply Reply to be sent to client. - */ -static void SendReply(const char* reply) { - if (!IsConnected()) { - return; - } - - LOG_DEBUG(Debug_GDBStub, "Reply: {}", reply); - - memset(command_buffer, 0, sizeof(command_buffer)); - - command_length = static_cast(strlen(reply)); - if (command_length + 4 > sizeof(command_buffer)) { - LOG_ERROR(Debug_GDBStub, "command_buffer overflow in SendReply"); - return; - } - - memcpy(command_buffer + 1, reply, command_length); - - const u8 checksum = CalculateChecksum(command_buffer, command_length + 1); - command_buffer[0] = GDB_STUB_START; - command_buffer[command_length + 1] = GDB_STUB_END; - command_buffer[command_length + 2] = NibbleToHex(static_cast(checksum >> 4)); - command_buffer[command_length + 3] = NibbleToHex(checksum); - - u8* ptr = command_buffer; - u32 left = command_length + 4; - while (left > 0) { - const auto sent_size = send(gdbserver_socket, reinterpret_cast(ptr), left, 0); - if (sent_size < 0) { - LOG_ERROR(Debug_GDBStub, "gdb: send failed"); - return Shutdown(); - } - - left -= static_cast(sent_size); - ptr += sent_size; - } -} - -/// Handle query command from gdb client. -static void HandleQuery() { - LOG_DEBUG(Debug_GDBStub, "gdb: query '{}'", command_buffer + 1); - - const char* query = reinterpret_cast(command_buffer + 1); - - if (strcmp(query, "TStatus") == 0) { - SendReply("T0"); - } else if (strncmp(query, "Supported", strlen("Supported")) == 0) { - // PacketSize needs to be large enough for target xml - std::string buffer = "PacketSize=2000;qXfer:features:read+;qXfer:threads:read+"; - if (!modules.empty()) { - buffer += ";qXfer:libraries:read+"; - } - SendReply(buffer.c_str()); - } else if (strncmp(query, "Xfer:features:read:target.xml:", - strlen("Xfer:features:read:target.xml:")) == 0) { - SendReply(target_xml); - } else if (strncmp(query, "Offsets", strlen("Offsets")) == 0) { - const VAddr base_address = - Core::System::GetInstance().CurrentProcess()->PageTable().GetCodeRegionStart(); - std::string buffer = fmt::format("TextSeg={:0x}", base_address); - SendReply(buffer.c_str()); - } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { - std::string val = "m"; - const auto& threads = Core::System::GetInstance().GlobalScheduler().GetThreadList(); - for (const auto& thread : threads) { - val += fmt::format("{:x},", thread->GetThreadID()); - } - val.pop_back(); - SendReply(val.c_str()); - } else if (strncmp(query, "sThreadInfo", strlen("sThreadInfo")) == 0) { - SendReply("l"); - } else if (strncmp(query, "Xfer:threads:read", strlen("Xfer:threads:read")) == 0) { - std::string buffer; - buffer += "l"; - buffer += ""; - const auto& threads = Core::System::GetInstance().GlobalScheduler().GetThreadList(); - for (const auto& thread : threads) { - buffer += - fmt::format(R"*()*", - thread->GetThreadID(), thread->GetProcessorID(), thread->GetThreadID()); - } - buffer += ""; - SendReply(buffer.c_str()); - } else if (strncmp(query, "Xfer:libraries:read", strlen("Xfer:libraries:read")) == 0) { - std::string buffer; - buffer += "l"; - buffer += ""; - for (const auto& module : modules) { - buffer += - fmt::format(R"*(")*", - module.name, module.beg); - } - buffer += ""; - SendReply(buffer.c_str()); - } else { - SendReply(""); - } -} - -/// Handle set thread command from gdb client. -static void HandleSetThread() { - int thread_id = -1; - if (command_buffer[2] != '-') { - thread_id = static_cast(HexToInt(command_buffer + 2, command_length - 2)); - } - if (thread_id >= 1) { - current_thread = FindThreadById(thread_id); - } - if (!current_thread) { - thread_id = 1; - current_thread = FindThreadById(thread_id); - } - if (current_thread) { - SendReply("OK"); - return; - } - SendReply("E01"); -} - -/// Handle thread alive command from gdb client. -static void HandleThreadAlive() { - int thread_id = static_cast(HexToInt(command_buffer + 1, command_length - 1)); - if (thread_id == 0) { - thread_id = 1; - } - if (FindThreadById(thread_id)) { - SendReply("OK"); - return; - } - SendReply("E01"); -} - -/** - * Send signal packet to client. - * - * @param signal Signal to be sent to client. - */ -static void SendSignal(Kernel::Thread* thread, u32 signal, bool full = true) { - if (gdbserver_socket == -1) { - return; - } - - latest_signal = signal; - - if (!thread) { - full = false; - } - - std::string buffer; - if (full) { - buffer = fmt::format("T{:02x}{:02x}:{:016x};{:02x}:{:016x};{:02x}:{:016x}", latest_signal, - PC_REGISTER, Common::swap64(RegRead(PC_REGISTER, thread)), SP_REGISTER, - Common::swap64(RegRead(SP_REGISTER, thread)), LR_REGISTER, - Common::swap64(RegRead(LR_REGISTER, thread))); - } else { - buffer = fmt::format("T{:02x}", latest_signal); - } - - if (thread) { - buffer += fmt::format(";thread:{:x};", thread->GetThreadID()); - } - - SendReply(buffer.c_str()); -} - -/// Read command from gdb client. -static void ReadCommand() { - command_length = 0; - memset(command_buffer, 0, sizeof(command_buffer)); - - u8 c = ReadByte(); - if (c == '+') { - // ignore ack - return; - } else if (c == 0x03) { - LOG_INFO(Debug_GDBStub, "gdb: found break command"); - halt_loop = true; - SendSignal(current_thread, SIGTRAP); - return; - } else if (c != GDB_STUB_START) { - LOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte {:02X}", c); - return; - } - - while ((c = ReadByte()) != GDB_STUB_END) { - if (command_length >= sizeof(command_buffer)) { - LOG_ERROR(Debug_GDBStub, "gdb: command_buffer overflow"); - SendPacket(GDB_STUB_NACK); - return; - } - command_buffer[command_length++] = c; - } - - auto checksum_received = static_cast(HexCharToValue(ReadByte()) << 4); - checksum_received |= static_cast(HexCharToValue(ReadByte())); - - const u32 checksum_calculated = CalculateChecksum(command_buffer, command_length); - - if (checksum_received != checksum_calculated) { - LOG_ERROR(Debug_GDBStub, - "gdb: invalid checksum: calculated {:02X} and read {:02X} for ${}# (length: {})", - checksum_calculated, checksum_received, command_buffer, command_length); - - command_length = 0; - - SendPacket(GDB_STUB_NACK); - return; - } - - SendPacket(GDB_STUB_ACK); -} - -/// Check if there is data to be read from the gdb client. -static bool IsDataAvailable() { - if (!IsConnected()) { - return false; - } - - fd_set fd_socket; - - FD_ZERO(&fd_socket); - FD_SET(static_cast(gdbserver_socket), &fd_socket); - - struct timeval t; - t.tv_sec = 0; - t.tv_usec = 0; - - if (select(gdbserver_socket + 1, &fd_socket, nullptr, nullptr, &t) < 0) { - LOG_ERROR(Debug_GDBStub, "select failed"); - return false; - } - - return FD_ISSET(gdbserver_socket, &fd_socket) != 0; -} - -/// Send requested register to gdb client. -static void ReadRegister() { - static u8 reply[64]; - memset(reply, 0, sizeof(reply)); - - u32 id = HexCharToValue(command_buffer[1]); - if (command_buffer[2] != '\0') { - id <<= 4; - id |= HexCharToValue(command_buffer[2]); - } - - if (id <= SP_REGISTER) { - LongToGdbHex(reply, RegRead(id, current_thread)); - } else if (id == PC_REGISTER) { - LongToGdbHex(reply, RegRead(id, current_thread)); - } else if (id == PSTATE_REGISTER) { - IntToGdbHex(reply, static_cast(RegRead(id, current_thread))); - } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - u128 r = FpuRead(id, current_thread); - LongToGdbHex(reply, r[0]); - LongToGdbHex(reply + 16, r[1]); - } else if (id == FPCR_REGISTER) { - u128 r = FpuRead(id, current_thread); - IntToGdbHex(reply, static_cast(r[0])); - } else if (id == FPCR_REGISTER + 1) { - u128 r = FpuRead(id, current_thread); - IntToGdbHex(reply, static_cast(r[0] >> 32)); - } - - SendReply(reinterpret_cast(reply)); -} - -/// Send all registers to the gdb client. -static void ReadRegisters() { - static u8 buffer[GDB_BUFFER_SIZE - 4]; - memset(buffer, 0, sizeof(buffer)); - - u8* bufptr = buffer; - - for (u32 reg = 0; reg <= SP_REGISTER; reg++) { - LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread)); - } - - bufptr += 32 * 16; - - LongToGdbHex(bufptr, RegRead(PC_REGISTER, current_thread)); - - bufptr += 16; - - IntToGdbHex(bufptr, static_cast(RegRead(PSTATE_REGISTER, current_thread))); - - bufptr += 8; - - u128 r; - - for (u32 reg = UC_ARM64_REG_Q0; reg < FPCR_REGISTER; reg++) { - r = FpuRead(reg, current_thread); - LongToGdbHex(bufptr + reg * 32, r[0]); - LongToGdbHex(bufptr + reg * 32 + 16, r[1]); - } - - bufptr += 32 * 32; - - r = FpuRead(FPCR_REGISTER, current_thread); - IntToGdbHex(bufptr, static_cast(r[0])); - - bufptr += 8; - - SendReply(reinterpret_cast(buffer)); -} - -/// Modify data of register specified by gdb client. -static void WriteRegister() { - const u8* buffer_ptr = command_buffer + 3; - - u32 id = HexCharToValue(command_buffer[1]); - if (command_buffer[2] != '=') { - ++buffer_ptr; - id <<= 4; - id |= HexCharToValue(command_buffer[2]); - } - - if (id <= SP_REGISTER) { - RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); - } else if (id == PC_REGISTER) { - RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); - } else if (id == PSTATE_REGISTER) { - RegWrite(id, GdbHexToInt(buffer_ptr), current_thread); - } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - FpuWrite(id, GdbHexToU128(buffer_ptr), current_thread); - } else if (id == FPCR_REGISTER) { - } else if (id == FPCR_REGISTER + 1) { - } - - // Update ARM context, skipping scheduler - no running threads at this point - Core::System::GetInstance() - .ArmInterface(current_core) - .LoadContext(current_thread->GetContext64()); - - SendReply("OK"); -} - -/// Modify all registers with data received from the client. -static void WriteRegisters() { - const u8* buffer_ptr = command_buffer + 1; - - if (command_buffer[0] != 'G') - return SendReply("E01"); - - for (u32 i = 0, reg = 0; reg <= FPCR_REGISTER; i++, reg++) { - if (reg <= SP_REGISTER) { - RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == PC_REGISTER) { - RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == PSTATE_REGISTER) { - RegWrite(PSTATE_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread); - } else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) { - RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == FPCR_REGISTER) { - RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == FPCR_REGISTER + 1) { - RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } - } - - // Update ARM context, skipping scheduler - no running threads at this point - Core::System::GetInstance() - .ArmInterface(current_core) - .LoadContext(current_thread->GetContext64()); - - SendReply("OK"); -} - -/// Read location in memory specified by gdb client. -static void ReadMemory() { - static u8 reply[GDB_BUFFER_SIZE - 4]; - - auto start_offset = command_buffer + 1; - const auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - const VAddr addr = HexToLong(start_offset, static_cast(addr_pos - start_offset)); - - start_offset = addr_pos + 1; - const u64 len = - HexToLong(start_offset, static_cast((command_buffer + command_length) - start_offset)); - - LOG_DEBUG(Debug_GDBStub, "gdb: addr: {:016X} len: {:016X}", addr, len); - - if (len * 2 > sizeof(reply)) { - SendReply("E01"); - } - - auto& memory = Core::System::GetInstance().Memory(); - if (!memory.IsValidVirtualAddress(addr)) { - return SendReply("E00"); - } - - std::vector data(len); - memory.ReadBlock(addr, data.data(), len); - - MemToGdbHex(reply, data.data(), len); - reply[len * 2] = '\0'; - SendReply(reinterpret_cast(reply)); -} - -/// Modify location in memory with data received from the gdb client. -static void WriteMemory() { - auto start_offset = command_buffer + 1; - const auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - const VAddr addr = HexToLong(start_offset, static_cast(addr_pos - start_offset)); - - start_offset = addr_pos + 1; - const auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); - const u64 len = HexToLong(start_offset, static_cast(len_pos - start_offset)); - - auto& system = Core::System::GetInstance(); - auto& memory = system.Memory(); - if (!memory.IsValidVirtualAddress(addr)) { - return SendReply("E00"); - } - - std::vector data(len); - GdbHexToMem(data.data(), len_pos + 1, len); - memory.WriteBlock(addr, data.data(), len); - system.InvalidateCpuInstructionCaches(); - SendReply("OK"); -} - -void Break(bool is_memory_break) { - send_trap = true; - - memory_break = is_memory_break; -} - -/// Tell the CPU that it should perform a single step. -static void Step() { - if (command_length > 1) { - RegWrite(PC_REGISTER, GdbHexToLong(command_buffer + 1), current_thread); - // Update ARM context, skipping scheduler - no running threads at this point - Core::System::GetInstance() - .ArmInterface(current_core) - .LoadContext(current_thread->GetContext64()); - } - step_loop = true; - halt_loop = true; - send_trap = true; - Core::System::GetInstance().InvalidateCpuInstructionCaches(); -} - -/// Tell the CPU if we hit a memory breakpoint. -bool IsMemoryBreak() { - if (!IsConnected()) { - return false; - } - - return memory_break; -} - -/// Tell the CPU to continue executing. -static void Continue() { - memory_break = false; - step_loop = false; - halt_loop = false; - Core::System::GetInstance().InvalidateCpuInstructionCaches(); -} - -/** - * Commit breakpoint to list of breakpoints. - * - * @param type Type of breakpoint. - * @param addr Address of breakpoint. - * @param len Length of breakpoint. - */ -static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) { - BreakpointMap& p = GetBreakpointMap(type); - - Breakpoint breakpoint; - breakpoint.active = true; - breakpoint.addr = addr; - breakpoint.len = len; - - auto& system = Core::System::GetInstance(); - auto& memory = system.Memory(); - memory.ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); - - static constexpr std::array btrap{0x00, 0x7d, 0x20, 0xd4}; - if (type == BreakpointType::Execute) { - memory.WriteBlock(addr, btrap.data(), btrap.size()); - system.InvalidateCpuInstructionCaches(); - } - p.insert({addr, breakpoint}); - - LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}", - static_cast(type), breakpoint.len, breakpoint.addr); - - return true; -} - -/// Handle add breakpoint command from gdb client. -static void AddBreakpoint() { - BreakpointType type; - - u8 type_id = HexCharToValue(command_buffer[1]); - switch (type_id) { - case 0: - case 1: - type = BreakpointType::Execute; - break; - case 2: - type = BreakpointType::Write; - break; - case 3: - type = BreakpointType::Read; - break; - case 4: - type = BreakpointType::Access; - break; - default: - return SendReply("E01"); - } - - auto start_offset = command_buffer + 3; - auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - VAddr addr = HexToLong(start_offset, static_cast(addr_pos - start_offset)); - - start_offset = addr_pos + 1; - u64 len = - HexToLong(start_offset, static_cast((command_buffer + command_length) - start_offset)); - - if (type == BreakpointType::Access) { - // Access is made up of Read and Write types, so add both breakpoints - type = BreakpointType::Read; - - if (!CommitBreakpoint(type, addr, len)) { - return SendReply("E02"); - } - - type = BreakpointType::Write; - } - - if (!CommitBreakpoint(type, addr, len)) { - return SendReply("E02"); - } - - SendReply("OK"); -} - -/// Handle remove breakpoint command from gdb client. -static void RemoveBreakpoint() { - BreakpointType type; - - u8 type_id = HexCharToValue(command_buffer[1]); - switch (type_id) { - case 0: - case 1: - type = BreakpointType::Execute; - break; - case 2: - type = BreakpointType::Write; - break; - case 3: - type = BreakpointType::Read; - break; - case 4: - type = BreakpointType::Access; - break; - default: - return SendReply("E01"); - } - - auto start_offset = command_buffer + 3; - auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - VAddr addr = HexToLong(start_offset, static_cast(addr_pos - start_offset)); - - if (type == BreakpointType::Access) { - // Access is made up of Read and Write types, so add both breakpoints - type = BreakpointType::Read; - RemoveBreakpoint(type, addr); - - type = BreakpointType::Write; - } - - RemoveBreakpoint(type, addr); - SendReply("OK"); -} - -void HandlePacket() { - if (!IsConnected()) { - if (defer_start) { - ToggleServer(true); - } - return; - } - - if (!IsDataAvailable()) { - return; - } - - ReadCommand(); - if (command_length == 0) { - return; - } - - LOG_DEBUG(Debug_GDBStub, "Packet: {}", command_buffer); - - switch (command_buffer[0]) { - case 'q': - HandleQuery(); - break; - case 'H': - HandleSetThread(); - break; - case '?': - SendSignal(current_thread, latest_signal); - break; - case 'k': - Shutdown(); - LOG_INFO(Debug_GDBStub, "killed by gdb"); - return; - case 'g': - ReadRegisters(); - break; - case 'G': - WriteRegisters(); - break; - case 'p': - ReadRegister(); - break; - case 'P': - WriteRegister(); - break; - case 'm': - ReadMemory(); - break; - case 'M': - WriteMemory(); - break; - case 's': - Step(); - return; - case 'C': - case 'c': - Continue(); - return; - case 'z': - RemoveBreakpoint(); - break; - case 'Z': - AddBreakpoint(); - break; - case 'T': - HandleThreadAlive(); - break; - default: - SendReply(""); - break; - } -} - -void SetServerPort(u16 port) { - gdbstub_port = port; -} - -void ToggleServer(bool status) { - if (status) { - server_enabled = status; - - // Start server - if (!IsConnected() && Core::System::GetInstance().IsPoweredOn()) { - Init(); - } - } else { - // Stop server - if (IsConnected()) { - Shutdown(); - } - - server_enabled = status; - } -} - -void DeferStart() { - defer_start = true; -} - -static void Init(u16 port) { - if (!server_enabled) { - // Set the halt loop to false in case the user enabled the gdbstub mid-execution. - // This way the CPU can still execute normally. - halt_loop = false; - step_loop = false; - return; - } - - // Setup initial gdbstub status - halt_loop = true; - step_loop = false; - - breakpoints_execute.clear(); - breakpoints_read.clear(); - breakpoints_write.clear(); - - modules.clear(); - - // Start gdb server - LOG_INFO(Debug_GDBStub, "Starting GDB server on port {}...", port); - - sockaddr_in saddr_server = {}; - saddr_server.sin_family = AF_INET; - saddr_server.sin_port = htons(port); - saddr_server.sin_addr.s_addr = INADDR_ANY; - -#ifdef _WIN32 - WSAStartup(MAKEWORD(2, 2), &InitData); -#endif - - int tmpsock = static_cast(socket(PF_INET, SOCK_STREAM, 0)); - if (tmpsock == -1) { - LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); - } - - // Set socket to SO_REUSEADDR so it can always bind on the same port - int reuse_enabled = 1; - if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, - sizeof(reuse_enabled)) < 0) { - LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); - } - - const sockaddr* server_addr = reinterpret_cast(&saddr_server); - socklen_t server_addrlen = sizeof(saddr_server); - if (bind(tmpsock, server_addr, server_addrlen) < 0) { - LOG_ERROR(Debug_GDBStub, "Failed to bind gdb socket"); - } - - if (listen(tmpsock, 1) < 0) { - LOG_ERROR(Debug_GDBStub, "Failed to listen to gdb socket"); - } - - // Wait for gdb to connect - LOG_INFO(Debug_GDBStub, "Waiting for gdb to connect..."); - sockaddr_in saddr_client; - sockaddr* client_addr = reinterpret_cast(&saddr_client); - socklen_t client_addrlen = sizeof(saddr_client); - gdbserver_socket = static_cast(accept(tmpsock, client_addr, &client_addrlen)); - if (gdbserver_socket < 0) { - // In the case that we couldn't start the server for whatever reason, just start CPU - // execution like normal. - halt_loop = false; - step_loop = false; - - LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); - } else { - LOG_INFO(Debug_GDBStub, "Client connected."); - saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); - } - - // Clean up temporary socket if it's still alive at this point. - if (tmpsock != -1) { - shutdown(tmpsock, SHUT_RDWR); - } -} - -void Init() { - Init(gdbstub_port); -} - -void Shutdown() { - if (!server_enabled) { - return; - } - defer_start = false; - - LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); - if (gdbserver_socket != -1) { - shutdown(gdbserver_socket, SHUT_RDWR); - gdbserver_socket = -1; - } - -#ifdef _WIN32 - WSACleanup(); -#endif - - LOG_INFO(Debug_GDBStub, "GDB stopped."); -} - -bool IsServerEnabled() { - return server_enabled; -} - -bool IsConnected() { - return IsServerEnabled() && gdbserver_socket != -1; -} - -bool GetCpuHaltFlag() { - return halt_loop; -} - -bool GetCpuStepFlag() { - return step_loop; -} - -void SetCpuStepFlag(bool is_step) { - step_loop = is_step; -} - -void SendTrap(Kernel::Thread* thread, int trap) { - if (!send_trap) { - return; - } - - current_thread = thread; - SendSignal(thread, trap); - - halt_loop = true; - send_trap = false; -} -}; // namespace GDBStub diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h deleted file mode 100644 index 8fe3c320bd..0000000000 --- a/src/core/gdbstub/gdbstub.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -// Originally written by Sven Peter for anergistic. - -#pragma once - -#include -#include "common/common_types.h" -#include "core/hle/kernel/thread.h" - -namespace GDBStub { - -/// Breakpoint Method -enum class BreakpointType { - None, ///< None - Execute, ///< Execution Breakpoint - Read, ///< Read Breakpoint - Write, ///< Write Breakpoint - Access ///< Access (R/W) Breakpoint -}; - -struct BreakpointAddress { - VAddr address; - BreakpointType type; -}; - -/** - * Set the port the gdbstub should use to listen for connections. - * - * @param port Port to listen for connection - */ -void SetServerPort(u16 port); - -/** - * Starts or stops the server if possible. - * - * @param status Set the server to enabled or disabled. - */ -void ToggleServer(bool status); - -/// Start the gdbstub server. -void Init(); - -/** - * Defer initialization of the gdbstub to the first packet processing functions. - * This avoids a case where the gdbstub thread is frozen after initialization - * and fails to respond in time to packets. - */ -void DeferStart(); - -/// Stop gdbstub server. -void Shutdown(); - -/// Checks if the gdbstub server is enabled. -bool IsServerEnabled(); - -/// Returns true if there is an active socket connection. -bool IsConnected(); - -/// Register module. -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. - * - * @param is_memory_break If true, the break resulted from a memory breakpoint. - */ -void Break(bool is_memory_break = false); - -/// Determine if there was a memory breakpoint. -bool IsMemoryBreak(); - -/// Read and handle packet from gdb client. -void HandlePacket(); - -/** - * Get the nearest breakpoint of the specified type at the given address. - * - * @param addr Address to search from. - * @param type Type of breakpoint. - */ -BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, GDBStub::BreakpointType type); - -/** - * Check if a breakpoint of the specified type exists at the given address. - * - * @param addr Address of breakpoint. - * @param type Type of breakpoint. - */ -bool CheckBreakpoint(VAddr addr, GDBStub::BreakpointType type); - -/// If set to true, the CPU will halt at the beginning of the next CPU loop. -bool GetCpuHaltFlag(); - -/// If set to true and the CPU is halted, the CPU will step one instruction. -bool GetCpuStepFlag(); - -/** - * When set to true, the CPU will step one instruction when the CPU is halted next. - * - * @param is_step - */ -void SetCpuStepFlag(bool is_step); - -/** - * Send trap signal from thread back to the gdbstub server. - * - * @param thread Sending thread. - * @param trap Trap no. - */ -void SendTrap(Kernel::Thread* thread, int trap); -} // namespace GDBStub diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 2002dc4f28..79ebf11dea 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -12,7 +12,6 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/romfs_factory.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" @@ -180,8 +179,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect next_load_addr = *tentative_next_load_addr; modules.insert_or_assign(load_addr, module); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); - // Register module with GDBStub - GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); } // Find the RomFS by searching for a ".romfs" file in this directory diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 2a905d3e48..e162c4ff09 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -5,7 +5,6 @@ #include #include "core/file_sys/kernel_executable.h" #include "core/file_sys/program_metadata.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" @@ -91,8 +90,6 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process, program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize()); codeset.DataSegment().size += kip->GetBSSSize(); - GDBStub::RegisterModule(kip->GetName(), base_address, base_address + program_image.size()); - codeset.memory = std::move(program_image); process.LoadModule(std::move(codeset), base_address); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 5f4b3104b6..ccf8cc153d 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -14,10 +14,10 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/vfs_offset.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/thread.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/loader/nro.h" #include "core/loader/nso.h" @@ -197,10 +197,6 @@ static bool LoadNroImpl(Kernel::Process& process, const std::vector& data, codeset.memory = std::move(program_image); process.LoadModule(std::move(codeset), process.PageTable().GetCodeRegionStart()); - // Register module with GDBStub - GDBStub::RegisterModule(name, process.PageTable().GetCodeRegionStart(), - process.PageTable().GetCodeRegionEnd()); - return true; } diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index aa85c1a299..95b6f339ab 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -14,10 +14,10 @@ #include "common/swap.h" #include "core/core.h" #include "core/file_sys/patch_manager.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/thread.h" #include "core/loader/nso.h" #include "core/memory.h" #include "core/settings.h" @@ -159,9 +159,6 @@ std::optional AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S codeset.memory = std::move(program_image); process.LoadModule(std::move(codeset), load_base); - // Register module with GDBStub - GDBStub::RegisterModule(file.GetName(), load_base, load_base); - return load_base + image_size; } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index aadbc3932d..e9997a2637 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -4,9 +4,10 @@ #include +#include "common/assert.h" #include "common/file_util.h" +#include "common/logging/log.h" #include "core/core.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/service/hid/hid.h" #include "core/settings.h" #include "video_core/renderer_base.h" @@ -31,13 +32,9 @@ std::string GetTimeZoneString() { return timezones[time_zone_index]; } -void Apply() { - GDBStub::SetServerPort(values.gdbstub_port); - GDBStub::ToggleServer(values.use_gdbstub); - - auto& system_instance = Core::System::GetInstance(); - if (system_instance.IsPoweredOn()) { - system_instance.Renderer().RefreshBaseSettings(); +void Apply(Core::System& system) { + if (system.IsPoweredOn()) { + system.Renderer().RefreshBaseSettings(); } Service::HID::ReloadInputDevices(); @@ -106,9 +103,9 @@ float Volume() { return values.volume.GetValue(); } -void RestoreGlobalState() { +void RestoreGlobalState(bool is_powered_on) { // If a game is running, DO NOT restore the global settings state - if (Core::System::GetInstance().IsPoweredOn()) { + if (is_powered_on) { return; } diff --git a/src/core/settings.h b/src/core/settings.h index 1143aba5d9..3df611d5b9 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -14,6 +14,10 @@ #include "common/common_types.h" #include "input_common/settings.h" +namespace Core { +class System; +} + namespace Settings { enum class RendererBackend { @@ -247,11 +251,11 @@ float Volume(); std::string GetTimeZoneString(); -void Apply(); +void Apply(Core::System& system); void LogSettings(); // Restore the global state of all applicable settings in the Values struct -void RestoreGlobalState(); +void RestoreGlobalState(bool is_powered_on); // Fixes settings that are known to cause issues with the emulator void Sanitize(); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 3c423a2710..8be9e93c3d 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -7,6 +7,7 @@ #include #include "common/common_paths.h" #include "common/file_util.h" +#include "core/core.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/hid/controllers/npad.h" #include "input_common/main.h" @@ -1598,7 +1599,7 @@ void Config::Reload() { Settings::Sanitize(); // To apply default value changes SaveValues(); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } void Config::Save() { diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 5041e0bf89..b33f8437af 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "core/core.h" #include "core/settings.h" #include "ui_configure.h" #include "yuzu/configuration/config.h" @@ -54,7 +55,7 @@ void ConfigureDialog::ApplyConfiguration() { ui->debugTab->ApplyConfiguration(); ui->webTab->ApplyConfiguration(); ui->serviceTab->ApplyConfiguration(); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); Settings::LogSettings(); } diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 8eac3bd9dc..f598513df8 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -57,7 +57,7 @@ void ConfigurePerGame::ApplyConfiguration() { ui->graphicsAdvancedTab->ApplyConfiguration(); ui->audioTab->ApplyConfiguration(); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); Settings::LogSettings(); game_config->Save(); diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 6334c4c50d..13d9a4757e 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -180,7 +180,7 @@ void ConfigureProfileManager::ApplyConfiguration() { return; } - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } void ConfigureProfileManager::SelectUser(const QModelIndex& index) { diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 59a58d92cd..6cf2032da0 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -105,16 +105,18 @@ void ConfigureSystem::SetConfiguration() { void ConfigureSystem::ReadSystemSettings() {} void ConfigureSystem::ApplyConfiguration() { - // Allow setting custom RTC even if system is powered on, to allow in-game time to be fast - // forwared + auto& system = Core::System::GetInstance(); + + // Allow setting custom RTC even if system is powered on, + // to allow in-game time to be fast forwarded if (Settings::values.custom_rtc.UsingGlobal()) { if (ui->custom_rtc_checkbox->isChecked()) { Settings::values.custom_rtc.SetValue( std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); - if (Core::System::GetInstance().IsPoweredOn()) { + if (system.IsPoweredOn()) { const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() + Service::Time::TimeManager::GetExternalTimeZoneOffset()}; - Core::System::GetInstance().GetTimeManager().UpdateLocalSystemClockTime(posix_time); + system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); } } else { Settings::values.custom_rtc.SetValue(std::nullopt); @@ -197,7 +199,7 @@ void ConfigureSystem::ApplyConfiguration() { } } - Settings::Apply(); + Settings::Apply(system); } void ConfigureSystem::RefreshConsoleID() { diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index dbe3f78c89..aed8760087 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -9,6 +9,7 @@ #include #include "common/common_types.h" #include "common/file_util.h" +#include "core/core.h" #include "core/settings.h" #include "ui_configure_ui.h" #include "yuzu/configuration/configure_ui.h" @@ -84,7 +85,7 @@ void ConfigureUi::ApplyConfiguration() { UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir, ui->screenshot_path_edit->text().toStdString()); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } void ConfigureUi::RequestGameListUpdate() { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 07fa85741e..871ff4ae42 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -172,7 +172,7 @@ void GMainWindow::ShowTelemetryCallout() { "

Would you like to share your usage data with us?"); if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { Settings::values.enable_telemetry = false; - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } } @@ -302,7 +302,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers( emit ControllerSelectorReconfigureFinished(); // Don't forget to apply settings. - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); config->Save(); UpdateStatusButtons(); @@ -571,11 +571,11 @@ void GMainWindow::InitializeWidgets() { if (emulation_running) { return; } - bool is_async = !Settings::values.use_asynchronous_gpu_emulation.GetValue() || - Settings::values.use_multi_core.GetValue(); + const bool is_async = !Settings::values.use_asynchronous_gpu_emulation.GetValue() || + Settings::values.use_multi_core.GetValue(); Settings::values.use_asynchronous_gpu_emulation.SetValue(is_async); async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); }); async_status_button->setText(tr("ASYNC")); async_status_button->setCheckable(true); @@ -590,12 +590,12 @@ void GMainWindow::InitializeWidgets() { return; } Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue()); - bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue() || - Settings::values.use_multi_core.GetValue(); + const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue() || + Settings::values.use_multi_core.GetValue(); Settings::values.use_asynchronous_gpu_emulation.SetValue(is_async); async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); }); multicore_status_button->setText(tr("MULTICORE")); multicore_status_button->setCheckable(true); @@ -630,7 +630,7 @@ void GMainWindow::InitializeWidgets() { Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); } - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); }); #endif // HAS_VULKAN statusBar()->insertPermanentWidget(0, renderer_status_button); @@ -2130,14 +2130,14 @@ void GMainWindow::OnPauseGame() { } void GMainWindow::OnStopGame() { - Core::System& system{Core::System::GetInstance()}; + auto& system{Core::System::GetInstance()}; if (system.GetExitLock() && !ConfirmForceLockedExit()) { return; } ShutdownGame(); - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(system.IsPoweredOn()); UpdateStatusButtons(); } @@ -2312,10 +2312,11 @@ void GMainWindow::OnConfigurePerGame() { void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { const auto v_file = Core::GetGameFileFromPath(vfs, file_name); + const auto& system = Core::System::GetInstance(); ConfigurePerGame dialog(this, title_id); dialog.LoadFromFile(v_file); - auto result = dialog.exec(); + const auto result = dialog.exec(); if (result == QDialog::Accepted) { dialog.ApplyConfiguration(); @@ -2325,13 +2326,14 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file } // Do not cause the global config to write local settings into the config file - Settings::RestoreGlobalState(); + const bool is_powered_on = system.IsPoweredOn(); + Settings::RestoreGlobalState(is_powered_on); - if (!Core::System::GetInstance().IsPoweredOn()) { + if (!is_powered_on) { config->Save(); } } else { - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(system.IsPoweredOn()); } } @@ -2602,7 +2604,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det if (emu_thread) { ShutdownGame(); - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(Core::System::GetInstance().IsPoweredOn()); UpdateStatusButtons(); } } else { @@ -2774,7 +2776,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { if (emu_thread != nullptr) { ShutdownGame(); - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(Core::System::GetInstance().IsPoweredOn()); UpdateStatusButtons(); } diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index ba6e89249b..c2efe1ee60 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -25,7 +25,6 @@ #include "core/crypto/key_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/vfs_real.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/process.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/loader/loader.h" @@ -174,13 +173,13 @@ int main(int argc, char** argv) { return -1; } + auto& system{Core::System::GetInstance()}; + InputCommon::InputSubsystem input_subsystem; + // Apply the command line arguments Settings::values.gdbstub_port = gdb_port; Settings::values.use_gdbstub = use_gdbstub; - Settings::Apply(); - - Core::System& system{Core::System::GetInstance()}; - InputCommon::InputSubsystem input_subsystem; + Settings::Apply(system); std::unique_ptr emu_window; switch (Settings::values.renderer_backend.GetValue()) { diff --git a/src/yuzu_tester/yuzu.cpp b/src/yuzu_tester/yuzu.cpp index ea94a65370..50bd7ae417 100644 --- a/src/yuzu_tester/yuzu.cpp +++ b/src/yuzu_tester/yuzu.cpp @@ -160,10 +160,12 @@ int main(int argc, char** argv) { return -1; } - Settings::values.use_gdbstub = false; - Settings::Apply(); + Core::System& system{Core::System::GetInstance()}; - std::unique_ptr emu_window{std::make_unique()}; + Settings::values.use_gdbstub = false; + Settings::Apply(system); + + const auto emu_window{std::make_unique()}; bool finished = false; int return_value = 0; @@ -212,7 +214,6 @@ int main(int argc, char** argv) { return_value = -1; }; - Core::System& system{Core::System::GetInstance()}; system.SetContentProvider(std::make_unique()); system.SetFilesystem(std::make_shared()); system.GetFileSystemController().CreateFactories(*system.GetFilesystem());