summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/string_util.cpp2
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp4
-rw-r--r--src/core/gdbstub/gdbstub.cpp194
-rw-r--r--src/core/gdbstub/gdbstub.h8
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp3
-rw-r--r--src/core/loader/nca.cpp4
-rw-r--r--src/core/loader/nro.cpp4
-rw-r--r--src/core/loader/nso.cpp4
8 files changed, 173 insertions, 50 deletions
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index ea9d8f77c..0027888c7 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -134,7 +134,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
134 size_t dir_end = full_path.find_last_of("/" 134 size_t dir_end = full_path.find_last_of("/"
135// windows needs the : included for something like just "C:" to be considered a directory 135// windows needs the : included for something like just "C:" to be considered a directory
136#ifdef _WIN32 136#ifdef _WIN32
137 ":" 137 "\\:"
138#endif 138#endif
139 ); 139 );
140 if (std::string::npos == dir_end) 140 if (std::string::npos == dir_end)
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index ce6c5616d..f239cf0ea 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -193,11 +193,11 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
193 } 193 }
194 Kernel::Thread* thread = Kernel::GetCurrentThread(); 194 Kernel::Thread* thread = Kernel::GetCurrentThread();
195 SaveContext(thread->context); 195 SaveContext(thread->context);
196 if (last_bkpt_hit) { 196 if (last_bkpt_hit || (num_instructions == 1)) {
197 last_bkpt_hit = false; 197 last_bkpt_hit = false;
198 GDBStub::Break(); 198 GDBStub::Break();
199 GDBStub::SendTrap(thread, 5);
199 } 200 }
200 GDBStub::SendTrap(thread, 5);
201 } 201 }
202} 202}
203 203
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 938852a1a..6062de13c 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -61,10 +61,16 @@ const u32 SIGTERM = 15;
61const u32 MSG_WAITALL = 8; 61const u32 MSG_WAITALL = 8;
62#endif 62#endif
63 63
64const u32 X30_REGISTER = 30; 64const u32 LR_REGISTER = 30;
65const u32 SP_REGISTER = 31; 65const u32 SP_REGISTER = 31;
66const u32 PC_REGISTER = 32; 66const u32 PC_REGISTER = 32;
67const u32 CPSR_REGISTER = 33; 67const u32 CPSR_REGISTER = 33;
68const u32 UC_ARM64_REG_Q0 = 34;
69const u32 FPSCR_REGISTER = 66;
70
71// TODO/WiP - Used while working on support for FPU
72const u32 TODO_DUMMY_REG_997 = 997;
73const u32 TODO_DUMMY_REG_998 = 998;
68 74
69// For sample XML files see the GDB source /gdb/features 75// For sample XML files see the GDB source /gdb/features
70// GDB also wants the l character at the start 76// GDB also wants the l character at the start
@@ -130,6 +136,8 @@ static const char* target_xml =
130 </flags> 136 </flags>
131 <reg name="cpsr" bitsize="32" type="cpsr_flags"/> 137 <reg name="cpsr" bitsize="32" type="cpsr_flags"/>
132 </feature> 138 </feature>
139 <feature name="org.gnu.gdb.aarch64.fpu">
140 </feature>
133</target> 141</target>
134)"; 142)";
135 143
@@ -144,6 +152,7 @@ static u32 latest_signal = 0;
144static bool memory_break = false; 152static bool memory_break = false;
145 153
146static Kernel::Thread* current_thread = nullptr; 154static Kernel::Thread* current_thread = nullptr;
155static u32 current_core = 0;
147 156
148// Binding to a port within the reserved ports range (0-1023) requires root permissions, 157// Binding to a port within the reserved ports range (0-1023) requires root permissions,
149// so default to a port outside of that range. 158// so default to a port outside of that range.
@@ -171,13 +180,34 @@ static std::map<u64, Breakpoint> breakpoints_execute;
171static std::map<u64, Breakpoint> breakpoints_read; 180static std::map<u64, Breakpoint> breakpoints_read;
172static std::map<u64, Breakpoint> breakpoints_write; 181static std::map<u64, Breakpoint> breakpoints_write;
173 182
183struct Module {
184 std::string name;
185 PAddr beg;
186 PAddr end;
187};
188
189static std::vector<Module> modules;
190
191void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext) {
192 Module module;
193 if (add_elf_ext) {
194 Common::SplitPath(name, nullptr, &module.name, nullptr);
195 module.name += ".elf";
196 } else {
197 module.name = std::move(name);
198 }
199 module.beg = beg;
200 module.end = end;
201 modules.push_back(std::move(module));
202}
203
174static Kernel::Thread* FindThreadById(int id) { 204static Kernel::Thread* FindThreadById(int id) {
175 for (int core = 0; core < Core::NUM_CPU_CORES; core++) { 205 for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) {
176 auto threads = Core::System::GetInstance().Scheduler(core)->GetThreadList(); 206 const auto& threads = Core::System::GetInstance().Scheduler(core)->GetThreadList();
177 for (auto thread : threads) { 207 for (auto& thread : threads) {
178 if (thread->GetThreadId() == id) { 208 if (thread->GetThreadId() == id) {
179 current_thread = thread.get(); 209 current_core = core;
180 return current_thread; 210 return thread.get();
181 } 211 }
182 } 212 }
183 } 213 }
@@ -197,6 +227,8 @@ static u64 RegRead(int id, Kernel::Thread* thread = nullptr) {
197 return thread->context.pc; 227 return thread->context.pc;
198 } else if (id == CPSR_REGISTER) { 228 } else if (id == CPSR_REGISTER) {
199 return thread->context.cpsr; 229 return thread->context.cpsr;
230 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
231 return thread->context.fpu_registers[id - UC_ARM64_REG_Q0][0];
200 } else { 232 } else {
201 return 0; 233 return 0;
202 } 234 }
@@ -215,6 +247,8 @@ static void RegWrite(int id, u64 val, Kernel::Thread* thread = nullptr) {
215 thread->context.pc = val; 247 thread->context.pc = val;
216 } else if (id == CPSR_REGISTER) { 248 } else if (id == CPSR_REGISTER) {
217 thread->context.cpsr = val; 249 thread->context.cpsr = val;
250 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
251 thread->context.fpu_registers[id - (CPSR_REGISTER + 1)][0] = val;
218 } 252 }
219} 253}
220 254
@@ -534,7 +568,11 @@ static void HandleQuery() {
534 SendReply("T0"); 568 SendReply("T0");
535 } else if (strncmp(query, "Supported", strlen("Supported")) == 0) { 569 } else if (strncmp(query, "Supported", strlen("Supported")) == 0) {
536 // PacketSize needs to be large enough for target xml 570 // PacketSize needs to be large enough for target xml
537 SendReply("PacketSize=2000;qXfer:features:read+"); 571 std::string buffer = "PacketSize=2000;qXfer:features:read+;qXfer:threads:read+";
572 if (!modules.empty()) {
573 buffer += ";qXfer:libraries:read+";
574 }
575 SendReply(buffer.c_str());
538 } else if (strncmp(query, "Xfer:features:read:target.xml:", 576 } else if (strncmp(query, "Xfer:features:read:target.xml:",
539 strlen("Xfer:features:read:target.xml:")) == 0) { 577 strlen("Xfer:features:read:target.xml:")) == 0) {
540 SendReply(target_xml); 578 SendReply(target_xml);
@@ -543,9 +581,9 @@ static void HandleQuery() {
543 SendReply(buffer.c_str()); 581 SendReply(buffer.c_str());
544 } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { 582 } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) {
545 std::string val = "m"; 583 std::string val = "m";
546 for (int core = 0; core < Core::NUM_CPU_CORES; core++) { 584 for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) {
547 auto threads = Core::System::GetInstance().Scheduler(core)->GetThreadList(); 585 const auto& threads = Core::System::GetInstance().Scheduler(core)->GetThreadList();
548 for (auto thread : threads) { 586 for (const auto& thread : threads) {
549 val += fmt::format("{:x}", thread->GetThreadId()); 587 val += fmt::format("{:x}", thread->GetThreadId());
550 val += ","; 588 val += ",";
551 } 589 }
@@ -554,6 +592,31 @@ static void HandleQuery() {
554 SendReply(val.c_str()); 592 SendReply(val.c_str());
555 } else if (strncmp(query, "sThreadInfo", strlen("sThreadInfo")) == 0) { 593 } else if (strncmp(query, "sThreadInfo", strlen("sThreadInfo")) == 0) {
556 SendReply("l"); 594 SendReply("l");
595 } else if (strncmp(query, "Xfer:threads:read", strlen("Xfer:threads:read")) == 0) {
596 std::string buffer;
597 buffer += "l<?xml version=\"1.0\"?>";
598 buffer += "<threads>";
599 for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) {
600 const auto& threads = Core::System::GetInstance().Scheduler(core)->GetThreadList();
601 for (const auto& thread : threads) {
602 buffer +=
603 fmt::format(R"*(<thread id="{:x}" core="{:d}" name="Thread {:x}"></thread>)*",
604 thread->GetThreadId(), core, thread->GetThreadId());
605 }
606 }
607 buffer += "</threads>";
608 SendReply(buffer.c_str());
609 } else if (strncmp(query, "Xfer:libraries:read", strlen("Xfer:libraries:read")) == 0) {
610 std::string buffer;
611 buffer += "l<?xml version=\"1.0\"?>";
612 buffer += "<library-list>";
613 for (const auto& module : modules) {
614 buffer +=
615 fmt::format(R"*("<library name = "{}"><segment address = "0x{:x}"/></library>)*",
616 module.name, module.beg);
617 }
618 buffer += "</library-list>";
619 SendReply(buffer.c_str());
557 } else { 620 } else {
558 SendReply(""); 621 SendReply("");
559 } 622 }
@@ -561,33 +624,27 @@ static void HandleQuery() {
561 624
562/// Handle set thread command from gdb client. 625/// Handle set thread command from gdb client.
563static void HandleSetThread() { 626static void HandleSetThread() {
564 if (memcmp(command_buffer, "Hc", 2) == 0 || memcmp(command_buffer, "Hg", 2) == 0) { 627 int thread_id = -1;
565 int thread_id = -1; 628 if (command_buffer[2] != '-') {
566 if (command_buffer[2] != '-') { 629 thread_id = static_cast<int>(HexToInt(command_buffer + 2, command_length - 2));
567 thread_id = static_cast<int>(HexToInt( 630 }
568 command_buffer + 2, 631 if (thread_id >= 1) {
569 command_length - 2 /*strlen(reinterpret_cast<char*>(command_buffer) + 2)*/)); 632 current_thread = FindThreadById(thread_id);
570 } 633 }
571 if (thread_id >= 1) { 634 if (!current_thread) {
572 current_thread = FindThreadById(thread_id); 635 thread_id = 1;
573 } 636 current_thread = FindThreadById(thread_id);
574 if (!current_thread) { 637 }
575 thread_id = 1; 638 if (current_thread) {
576 current_thread = FindThreadById(thread_id); 639 SendReply("OK");
577 } 640 return;
578 if (current_thread) {
579 SendReply("OK");
580 return;
581 }
582 } 641 }
583 SendReply("E01"); 642 SendReply("E01");
584} 643}
585 644
586/// Handle thread alive command from gdb client. 645/// Handle thread alive command from gdb client.
587static void HandleThreadAlive() { 646static void HandleThreadAlive() {
588 int thread_id = static_cast<int>( 647 int thread_id = static_cast<int>(HexToInt(command_buffer + 1, command_length - 1));
589 HexToInt(command_buffer + 1,
590 command_length - 1 /*strlen(reinterpret_cast<char*>(command_buffer) + 1)*/));
591 if (thread_id == 0) { 648 if (thread_id == 0) {
592 thread_id = 1; 649 thread_id = 1;
593 } 650 }
@@ -610,16 +667,23 @@ static void SendSignal(Kernel::Thread* thread, u32 signal, bool full = true) {
610 667
611 latest_signal = signal; 668 latest_signal = signal;
612 669
670 if (!thread) {
671 full = false;
672 }
673
613 std::string buffer; 674 std::string buffer;
614 if (full) { 675 if (full) {
615 buffer = fmt::format("T{:02x}{:02x}:{:016x};{:02x}:{:016x};", latest_signal, PC_REGISTER, 676 buffer = fmt::format("T{:02x}{:02x}:{:016x};{:02x}:{:016x};{:02x}:{:016x}", latest_signal,
616 Common::swap64(RegRead(PC_REGISTER, thread)), SP_REGISTER, 677 PC_REGISTER, Common::swap64(RegRead(PC_REGISTER, thread)), SP_REGISTER,
617 Common::swap64(RegRead(SP_REGISTER, thread))); 678 Common::swap64(RegRead(SP_REGISTER, thread)), LR_REGISTER,
679 Common::swap64(RegRead(LR_REGISTER, thread)));
618 } else { 680 } else {
619 buffer = fmt::format("T{:02x};", latest_signal); 681 buffer = fmt::format("T{:02x}", latest_signal);
620 } 682 }
621 683
622 buffer += fmt::format("thread:{:x};", thread->GetThreadId()); 684 if (thread) {
685 buffer += fmt::format(";thread:{:x};", thread->GetThreadId());
686 }
623 687
624 SendReply(buffer.c_str()); 688 SendReply(buffer.c_str());
625} 689}
@@ -711,8 +775,12 @@ static void ReadRegister() {
711 LongToGdbHex(reply, RegRead(id, current_thread)); 775 LongToGdbHex(reply, RegRead(id, current_thread));
712 } else if (id == CPSR_REGISTER) { 776 } else if (id == CPSR_REGISTER) {
713 IntToGdbHex(reply, (u32)RegRead(id, current_thread)); 777 IntToGdbHex(reply, (u32)RegRead(id, current_thread));
778 } else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) {
779 LongToGdbHex(reply, RegRead(id, current_thread));
780 } else if (id == FPSCR_REGISTER) {
781 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread));
714 } else { 782 } else {
715 return SendReply("E01"); 783 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread));
716 } 784 }
717 785
718 SendReply(reinterpret_cast<char*>(reply)); 786 SendReply(reinterpret_cast<char*>(reply));
@@ -729,7 +797,7 @@ static void ReadRegisters() {
729 LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread)); 797 LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread));
730 } 798 }
731 799
732 bufptr += (32 * 16); 800 bufptr += 32 * 16;
733 801
734 LongToGdbHex(bufptr, RegRead(PC_REGISTER, current_thread)); 802 LongToGdbHex(bufptr, RegRead(PC_REGISTER, current_thread));
735 803
@@ -739,6 +807,16 @@ static void ReadRegisters() {
739 807
740 bufptr += 8; 808 bufptr += 8;
741 809
810 for (int reg = UC_ARM64_REG_Q0; reg <= UC_ARM64_REG_Q0 + 31; reg++) {
811 LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread));
812 }
813
814 bufptr += 32 * 32;
815
816 LongToGdbHex(bufptr, RegRead(TODO_DUMMY_REG_998, current_thread));
817
818 bufptr += 8;
819
742 SendReply(reinterpret_cast<char*>(buffer)); 820 SendReply(reinterpret_cast<char*>(buffer));
743} 821}
744 822
@@ -759,10 +837,17 @@ static void WriteRegister() {
759 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); 837 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
760 } else if (id == CPSR_REGISTER) { 838 } else if (id == CPSR_REGISTER) {
761 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread); 839 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
840 } else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) {
841 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
842 } else if (id == FPSCR_REGISTER) {
843 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread);
762 } else { 844 } else {
763 return SendReply("E01"); 845 RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread);
764 } 846 }
765 847
848 // Update Unicorn context skipping scheduler, no running threads at this point
849 Core::System::GetInstance().ArmInterface(current_core).LoadContext(current_thread->context);
850
766 SendReply("OK"); 851 SendReply("OK");
767} 852}
768 853
@@ -773,18 +858,25 @@ static void WriteRegisters() {
773 if (command_buffer[0] != 'G') 858 if (command_buffer[0] != 'G')
774 return SendReply("E01"); 859 return SendReply("E01");
775 860
776 for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) { 861 for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) {
777 if (reg <= SP_REGISTER) { 862 if (reg <= SP_REGISTER) {
778 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); 863 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
779 } else if (reg == PC_REGISTER) { 864 } else if (reg == PC_REGISTER) {
780 RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); 865 RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
781 } else if (reg == CPSR_REGISTER) { 866 } else if (reg == CPSR_REGISTER) {
782 RegWrite(CPSR_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread); 867 RegWrite(CPSR_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread);
868 } else if (reg >= UC_ARM64_REG_Q0 && reg < FPSCR_REGISTER) {
869 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
870 } else if (reg == FPSCR_REGISTER) {
871 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread);
783 } else { 872 } else {
784 UNIMPLEMENTED(); 873 UNIMPLEMENTED();
785 } 874 }
786 } 875 }
787 876
877 // Update Unicorn context skipping scheduler, no running threads at this point
878 Core::System::GetInstance().ArmInterface(current_core).LoadContext(current_thread->context);
879
788 SendReply("OK"); 880 SendReply("OK");
789} 881}
790 882
@@ -806,6 +898,10 @@ static void ReadMemory() {
806 SendReply("E01"); 898 SendReply("E01");
807 } 899 }
808 900
901 if (addr < Memory::PROCESS_IMAGE_VADDR || addr >= Memory::MAP_REGION_VADDR_END) {
902 return SendReply("E00");
903 }
904
809 if (!Memory::IsValidVirtualAddress(addr)) { 905 if (!Memory::IsValidVirtualAddress(addr)) {
810 return SendReply("E00"); 906 return SendReply("E00");
811 } 907 }
@@ -840,16 +936,18 @@ static void WriteMemory() {
840} 936}
841 937
842void Break(bool is_memory_break) { 938void Break(bool is_memory_break) {
843 if (!halt_loop) { 939 send_trap = true;
844 halt_loop = true;
845 send_trap = true;
846 }
847 940
848 memory_break = is_memory_break; 941 memory_break = is_memory_break;
849} 942}
850 943
851/// Tell the CPU that it should perform a single step. 944/// Tell the CPU that it should perform a single step.
852static void Step() { 945static void Step() {
946 if (command_length > 1) {
947 RegWrite(PC_REGISTER, GdbHexToLong(command_buffer + 1), current_thread);
948 // Update Unicorn context skipping scheduler, no running threads at this point
949 Core::System::GetInstance().ArmInterface(current_core).LoadContext(current_thread->context);
950 }
853 step_loop = true; 951 step_loop = true;
854 halt_loop = true; 952 halt_loop = true;
855 send_trap = true; 953 send_trap = true;
@@ -1090,6 +1188,8 @@ static void Init(u16 port) {
1090 breakpoints_read.clear(); 1188 breakpoints_read.clear();
1091 breakpoints_write.clear(); 1189 breakpoints_write.clear();
1092 1190
1191 modules.clear();
1192
1093 // Start gdb server 1193 // Start gdb server
1094 LOG_INFO(Debug_GDBStub, "Starting GDB server on port {}...", port); 1194 LOG_INFO(Debug_GDBStub, "Starting GDB server on port {}...", port);
1095 1195
@@ -1192,8 +1292,12 @@ void SetCpuStepFlag(bool is_step) {
1192 1292
1193void SendTrap(Kernel::Thread* thread, int trap) { 1293void SendTrap(Kernel::Thread* thread, int trap) {
1194 if (send_trap) { 1294 if (send_trap) {
1295 if (!halt_loop || current_thread == thread) {
1296 current_thread = thread;
1297 SendSignal(thread, trap);
1298 }
1299 halt_loop = true;
1195 send_trap = false; 1300 send_trap = false;
1196 SendSignal(thread, trap);
1197 } 1301 }
1198} 1302}
1199}; // namespace GDBStub 1303}; // namespace GDBStub
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h
index f2418c9e4..a6b50c26c 100644
--- a/src/core/gdbstub/gdbstub.h
+++ b/src/core/gdbstub/gdbstub.h
@@ -6,6 +6,7 @@
6 6
7#pragma once 7#pragma once
8 8
9#include <string>
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
11 12
@@ -51,6 +52,9 @@ bool IsServerEnabled();
51/// Returns true if there is an active socket connection. 52/// Returns true if there is an active socket connection.
52bool IsConnected(); 53bool IsConnected();
53 54
55/// Register module.
56void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext = true);
57
54/** 58/**
55 * Signal to the gdbstub server that it should halt CPU execution. 59 * Signal to the gdbstub server that it should halt CPU execution.
56 * 60 *
@@ -80,10 +84,10 @@ BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, GDBStub::BreakpointTy
80 */ 84 */
81bool CheckBreakpoint(PAddr addr, GDBStub::BreakpointType type); 85bool CheckBreakpoint(PAddr addr, GDBStub::BreakpointType type);
82 86
83// If set to true, the CPU will halt at the beginning of the next CPU loop. 87/// If set to true, the CPU will halt at the beginning of the next CPU loop.
84bool GetCpuHaltFlag(); 88bool GetCpuHaltFlag();
85 89
86// If set to true and the CPU is halted, the CPU will step one instruction. 90/// If set to true and the CPU is halted, the CPU will step one instruction.
87bool GetCpuStepFlag(); 91bool GetCpuStepFlag();
88 92
89/** 93/**
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index eb7feb617..5fdb1d289 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -9,6 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "core/file_sys/romfs_factory.h" 11#include "core/file_sys/romfs_factory.h"
12#include "core/gdbstub/gdbstub.h"
12#include "core/hle/kernel/process.h" 13#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/resource_limit.h" 14#include "core/hle/kernel/resource_limit.h"
14#include "core/hle/service/filesystem/filesystem.h" 15#include "core/hle/service/filesystem/filesystem.h"
@@ -133,6 +134,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
133 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr); 134 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr);
134 if (next_load_addr) { 135 if (next_load_addr) {
135 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); 136 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
137 // Register module with GDBStub
138 GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
136 } else { 139 } else {
137 next_load_addr = load_addr; 140 next_load_addr = load_addr;
138 } 141 }
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index da064f8e3..0fd930ae2 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -7,10 +7,12 @@
7#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/string_util.h"
10#include "common/swap.h" 11#include "common/swap.h"
11#include "core/core.h" 12#include "core/core.h"
12#include "core/file_sys/program_metadata.h" 13#include "core/file_sys/program_metadata.h"
13#include "core/file_sys/romfs_factory.h" 14#include "core/file_sys/romfs_factory.h"
15#include "core/gdbstub/gdbstub.h"
14#include "core/hle/kernel/process.h" 16#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/resource_limit.h" 17#include "core/hle/kernel/resource_limit.h"
16#include "core/hle/service/filesystem/filesystem.h" 18#include "core/hle/service/filesystem/filesystem.h"
@@ -259,6 +261,8 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
259 next_load_addr = AppLoader_NSO::LoadModule(module, nca->GetExeFsFile(module), load_addr); 261 next_load_addr = AppLoader_NSO::LoadModule(module, nca->GetExeFsFile(module), load_addr);
260 if (next_load_addr) { 262 if (next_load_addr) {
261 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); 263 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
264 // Register module with GDBStub
265 GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
262 } else { 266 } else {
263 next_load_addr = load_addr; 267 next_load_addr = load_addr;
264 } 268 }
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 3853cfa1a..4d7c69a22 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -9,6 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/swap.h" 10#include "common/swap.h"
11#include "core/core.h" 11#include "core/core.h"
12#include "core/gdbstub/gdbstub.h"
12#include "core/hle/kernel/process.h" 13#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/resource_limit.h" 14#include "core/hle/kernel/resource_limit.h"
14#include "core/loader/nro.h" 15#include "core/loader/nro.h"
@@ -115,6 +116,9 @@ bool AppLoader_NRO::LoadNro(const std::string& path, VAddr load_base) {
115 codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 116 codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
116 Core::CurrentProcess()->LoadModule(codeset, load_base); 117 Core::CurrentProcess()->LoadModule(codeset, load_base);
117 118
119 // Register module with GDBStub
120 GDBStub::RegisterModule(codeset->name, load_base, load_base);
121
118 return true; 122 return true;
119} 123}
120 124
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 7f84e4b1b..1c629e21f 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -10,6 +10,7 @@
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/swap.h" 11#include "common/swap.h"
12#include "core/core.h" 12#include "core/core.h"
13#include "core/gdbstub/gdbstub.h"
13#include "core/hle/kernel/process.h" 14#include "core/hle/kernel/process.h"
14#include "core/hle/kernel/resource_limit.h" 15#include "core/hle/kernel/resource_limit.h"
15#include "core/loader/nso.h" 16#include "core/loader/nso.h"
@@ -147,6 +148,9 @@ VAddr AppLoader_NSO::LoadModule(const std::string& name, const std::vector<u8>&
147 codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 148 codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
148 Core::CurrentProcess()->LoadModule(codeset, load_base); 149 Core::CurrentProcess()->LoadModule(codeset, load_base);
149 150
151 // Register module with GDBStub
152 GDBStub::RegisterModule(codeset->name, load_base, load_base);
153
150 return load_base + image_size; 154 return load_base + image_size;
151} 155}
152 156