summaryrefslogtreecommitdiff
path: root/src/core/gdbstub/gdbstub.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2018-11-23 23:36:36 -0500
committerGravatar GitHub2018-11-23 23:36:36 -0500
commit69a9bd8187777ed74368f41b2c0806fed66c0ee5 (patch)
tree4755329e624f04efd6d1bee3953566c5562ea6d2 /src/core/gdbstub/gdbstub.cpp
parentMerge pull request #1708 from ogniK5377/res-scale (diff)
parentGDBStub improvements: (diff)
downloadyuzu-69a9bd8187777ed74368f41b2c0806fed66c0ee5.tar.gz
yuzu-69a9bd8187777ed74368f41b2c0806fed66c0ee5.tar.xz
yuzu-69a9bd8187777ed74368f41b2c0806fed66c0ee5.zip
Merge pull request #1692 from Hedges/GDBClean
GDBStub Improvements
Diffstat (limited to 'src/core/gdbstub/gdbstub.cpp')
-rw-r--r--src/core/gdbstub/gdbstub.cpp123
1 files changed, 86 insertions, 37 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index bdcc889e0..687dea409 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -71,10 +71,6 @@ constexpr u32 PSTATE_REGISTER = 33;
71constexpr u32 UC_ARM64_REG_Q0 = 34; 71constexpr u32 UC_ARM64_REG_Q0 = 34;
72constexpr u32 FPCR_REGISTER = 66; 72constexpr u32 FPCR_REGISTER = 66;
73 73
74// TODO/WiP - Used while working on support for FPU
75constexpr u32 TODO_DUMMY_REG_997 = 997;
76constexpr u32 TODO_DUMMY_REG_998 = 998;
77
78// For sample XML files see the GDB source /gdb/features 74// For sample XML files see the GDB source /gdb/features
79// GDB also wants the l character at the start 75// GDB also wants the l character at the start
80// This XML defines what the registers are for this specific ARM device 76// This XML defines what the registers are for this specific ARM device
@@ -260,6 +256,36 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
260 } 256 }
261} 257}
262 258
259static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {
260 if (!thread) {
261 return u128{0};
262 }
263
264 auto& thread_context = thread->GetContext();
265
266 if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
267 return thread_context.vector_registers[id - UC_ARM64_REG_Q0];
268 } else if (id == FPCR_REGISTER) {
269 return u128{thread_context.fpcr, 0};
270 } else {
271 return u128{0};
272 }
273}
274
275static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr) {
276 if (!thread) {
277 return;
278 }
279
280 auto& thread_context = thread->GetContext();
281
282 if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
283 thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
284 } else if (id == FPCR_REGISTER) {
285 thread_context.fpcr = val[0];
286 }
287}
288
263/** 289/**
264 * Turns hex string character into the equivalent byte. 290 * Turns hex string character into the equivalent byte.
265 * 291 *
@@ -409,6 +435,27 @@ static u64 GdbHexToLong(const u8* src) {
409 return output; 435 return output;
410} 436}
411 437
438/**
439 * Convert a gdb-formatted hex string into a u128.
440 *
441 * @param src Pointer to hex string.
442 */
443static u128 GdbHexToU128(const u8* src) {
444 u128 output;
445
446 for (int i = 0; i < 16; i += 2) {
447 output[0] = (output[0] << 4) | HexCharToValue(src[15 - i - 1]);
448 output[0] = (output[0] << 4) | HexCharToValue(src[15 - i]);
449 }
450
451 for (int i = 0; i < 16; i += 2) {
452 output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i - 1]);
453 output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i]);
454 }
455
456 return output;
457}
458
412/// Read a byte from the gdb client. 459/// Read a byte from the gdb client.
413static u8 ReadByte() { 460static u8 ReadByte() {
414 u8 c; 461 u8 c;
@@ -599,8 +646,7 @@ static void HandleQuery() {
599 for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) { 646 for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) {
600 const auto& threads = Core::System::GetInstance().Scheduler(core).GetThreadList(); 647 const auto& threads = Core::System::GetInstance().Scheduler(core).GetThreadList();
601 for (const auto& thread : threads) { 648 for (const auto& thread : threads) {
602 val += fmt::format("{:x}", thread->GetThreadID()); 649 val += fmt::format("{:x},", thread->GetThreadID());
603 val += ",";
604 } 650 }
605 } 651 }
606 val.pop_back(); 652 val.pop_back();
@@ -791,11 +837,15 @@ static void ReadRegister() {
791 } else if (id == PSTATE_REGISTER) { 837 } else if (id == PSTATE_REGISTER) {
792 IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread))); 838 IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread)));
793 } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { 839 } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
794 LongToGdbHex(reply, RegRead(id, current_thread)); 840 u128 r = FpuRead(id, current_thread);
841 LongToGdbHex(reply, r[0]);
842 LongToGdbHex(reply + 16, r[1]);
795 } else if (id == FPCR_REGISTER) { 843 } else if (id == FPCR_REGISTER) {
796 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread)); 844 u128 r = FpuRead(id, current_thread);
797 } else { 845 IntToGdbHex(reply, static_cast<u32>(r[0]));
798 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread)); 846 } else if (id == FPCR_REGISTER + 1) {
847 u128 r = FpuRead(id, current_thread);
848 IntToGdbHex(reply, static_cast<u32>(r[0] >> 32));
799 } 849 }
800 850
801 SendReply(reinterpret_cast<char*>(reply)); 851 SendReply(reinterpret_cast<char*>(reply));
@@ -822,13 +872,18 @@ static void ReadRegisters() {
822 872
823 bufptr += 8; 873 bufptr += 8;
824 874
825 for (u32 reg = UC_ARM64_REG_Q0; reg <= UC_ARM64_REG_Q0 + 31; reg++) { 875 u128 r;
826 LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread)); 876
877 for (u32 reg = UC_ARM64_REG_Q0; reg < FPCR_REGISTER; reg++) {
878 r = FpuRead(reg, current_thread);
879 LongToGdbHex(bufptr + reg * 32, r[0]);
880 LongToGdbHex(bufptr + reg * 32 + 16, r[1]);
827 } 881 }
828 882
829 bufptr += 32 * 32; 883 bufptr += 32 * 32;
830 884
831 LongToGdbHex(bufptr, RegRead(TODO_DUMMY_REG_998, current_thread)); 885 r = FpuRead(FPCR_REGISTER, current_thread);
886 IntToGdbHex(bufptr, static_cast<u32>(r[0]));
832 887
833 bufptr += 8; 888 bufptr += 8;
834 889
@@ -853,14 +908,12 @@ static void WriteRegister() {
853 } else if (id == PSTATE_REGISTER) { 908 } else if (id == PSTATE_REGISTER) {
854 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread); 909 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
855 } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { 910 } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
856 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); 911 FpuWrite(id, GdbHexToU128(buffer_ptr), current_thread);
857 } else if (id == FPCR_REGISTER) { 912 } else if (id == FPCR_REGISTER) {
858 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread); 913 } else if (id == FPCR_REGISTER + 1) {
859 } else {
860 RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread);
861 } 914 }
862 915
863 // Update Unicorn context skipping scheduler, no running threads at this point 916 // Update ARM context, skipping scheduler - no running threads at this point
864 Core::System::GetInstance() 917 Core::System::GetInstance()
865 .ArmInterface(current_core) 918 .ArmInterface(current_core)
866 .LoadContext(current_thread->GetContext()); 919 .LoadContext(current_thread->GetContext());
@@ -885,13 +938,13 @@ static void WriteRegisters() {
885 } else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) { 938 } else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) {
886 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); 939 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
887 } else if (reg == FPCR_REGISTER) { 940 } else if (reg == FPCR_REGISTER) {
888 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread); 941 RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
889 } else { 942 } else if (reg == FPCR_REGISTER + 1) {
890 UNIMPLEMENTED(); 943 RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
891 } 944 }
892 } 945 }
893 946
894 // Update Unicorn context skipping scheduler, no running threads at this point 947 // Update ARM context, skipping scheduler - no running threads at this point
895 Core::System::GetInstance() 948 Core::System::GetInstance()
896 .ArmInterface(current_core) 949 .ArmInterface(current_core)
897 .LoadContext(current_thread->GetContext()); 950 .LoadContext(current_thread->GetContext());
@@ -917,12 +970,6 @@ static void ReadMemory() {
917 SendReply("E01"); 970 SendReply("E01");
918 } 971 }
919 972
920 const auto& vm_manager = Core::CurrentProcess()->VMManager();
921 if (addr < vm_manager.GetCodeRegionBaseAddress() ||
922 addr >= vm_manager.GetMapRegionEndAddress()) {
923 return SendReply("E00");
924 }
925
926 if (!Memory::IsValidVirtualAddress(addr)) { 973 if (!Memory::IsValidVirtualAddress(addr)) {
927 return SendReply("E00"); 974 return SendReply("E00");
928 } 975 }
@@ -967,7 +1014,7 @@ void Break(bool is_memory_break) {
967static void Step() { 1014static void Step() {
968 if (command_length > 1) { 1015 if (command_length > 1) {
969 RegWrite(PC_REGISTER, GdbHexToLong(command_buffer + 1), current_thread); 1016 RegWrite(PC_REGISTER, GdbHexToLong(command_buffer + 1), current_thread);
970 // Update Unicorn context skipping scheduler, no running threads at this point 1017 // Update ARM context, skipping scheduler - no running threads at this point
971 Core::System::GetInstance() 1018 Core::System::GetInstance()
972 .ArmInterface(current_core) 1019 .ArmInterface(current_core)
973 .LoadContext(current_thread->GetContext()); 1020 .LoadContext(current_thread->GetContext());
@@ -1010,7 +1057,7 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
1010 breakpoint.addr = addr; 1057 breakpoint.addr = addr;
1011 breakpoint.len = len; 1058 breakpoint.len = len;
1012 Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); 1059 Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
1013 static constexpr std::array<u8, 4> btrap{{0x00, 0x7d, 0x20, 0xd4}}; 1060 static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4};
1014 Memory::WriteBlock(addr, btrap.data(), btrap.size()); 1061 Memory::WriteBlock(addr, btrap.data(), btrap.size());
1015 Core::System::GetInstance().InvalidateCpuInstructionCaches(); 1062 Core::System::GetInstance().InvalidateCpuInstructionCaches();
1016 p.insert({addr, breakpoint}); 1063 p.insert({addr, breakpoint});
@@ -1321,13 +1368,15 @@ void SetCpuStepFlag(bool is_step) {
1321} 1368}
1322 1369
1323void SendTrap(Kernel::Thread* thread, int trap) { 1370void SendTrap(Kernel::Thread* thread, int trap) {
1324 if (send_trap) { 1371 if (!send_trap) {
1325 if (!halt_loop || current_thread == thread) { 1372 return;
1326 current_thread = thread;
1327 SendSignal(thread, trap);
1328 }
1329 halt_loop = true;
1330 send_trap = false;
1331 } 1373 }
1374
1375 if (!halt_loop || current_thread == thread) {
1376 current_thread = thread;
1377 SendSignal(thread, trap);
1378 }
1379 halt_loop = true;
1380 send_trap = false;
1332} 1381}
1333}; // namespace GDBStub 1382}; // namespace GDBStub