summaryrefslogtreecommitdiff
path: root/src/core/debugger/gdbstub.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/debugger/gdbstub.cpp')
-rw-r--r--src/core/debugger/gdbstub.cpp66
1 files changed, 35 insertions, 31 deletions
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 4051ed4af..80091cc7e 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -108,9 +108,9 @@ static std::string EscapeXML(std::string_view data) {
108 return escaped; 108 return escaped;
109} 109}
110 110
111GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_) 111GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_, Kernel::KProcess* debug_process_)
112 : DebuggerFrontend(backend_), system{system_} { 112 : DebuggerFrontend(backend_), system{system_}, debug_process{debug_process_} {
113 if (system.ApplicationProcess()->Is64Bit()) { 113 if (GetProcess()->Is64Bit()) {
114 arch = std::make_unique<GDBStubA64>(); 114 arch = std::make_unique<GDBStubA64>();
115 } else { 115 } else {
116 arch = std::make_unique<GDBStubA32>(); 116 arch = std::make_unique<GDBStubA32>();
@@ -276,7 +276,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
276 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; 276 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
277 277
278 std::vector<u8> mem(size); 278 std::vector<u8> mem(size);
279 if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) { 279 if (GetMemory().ReadBlock(addr, mem.data(), size)) {
280 // Restore any bytes belonging to replaced instructions. 280 // Restore any bytes belonging to replaced instructions.
281 auto it = replaced_instructions.lower_bound(addr); 281 auto it = replaced_instructions.lower_bound(addr);
282 for (; it != replaced_instructions.end() && it->first < addr + size; it++) { 282 for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
@@ -310,8 +310,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
310 const auto mem_substr{std::string_view(command).substr(mem_sep)}; 310 const auto mem_substr{std::string_view(command).substr(mem_sep)};
311 const auto mem{Common::HexStringToVector(mem_substr, false)}; 311 const auto mem{Common::HexStringToVector(mem_substr, false)};
312 312
313 if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) { 313 if (GetMemory().WriteBlock(addr, mem.data(), size)) {
314 Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, size); 314 Core::InvalidateInstructionCacheRange(GetProcess(), addr, size);
315 SendReply(GDB_STUB_REPLY_OK); 315 SendReply(GDB_STUB_REPLY_OK);
316 } else { 316 } else {
317 SendReply(GDB_STUB_REPLY_ERR); 317 SendReply(GDB_STUB_REPLY_ERR);
@@ -353,7 +353,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
353 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 353 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
354 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; 354 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
355 355
356 if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { 356 if (!GetMemory().IsValidVirtualAddressRange(addr, size)) {
357 SendReply(GDB_STUB_REPLY_ERR); 357 SendReply(GDB_STUB_REPLY_ERR);
358 return; 358 return;
359 } 359 }
@@ -362,22 +362,20 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
362 362
363 switch (type) { 363 switch (type) {
364 case BreakpointType::Software: 364 case BreakpointType::Software:
365 replaced_instructions[addr] = system.ApplicationMemory().Read32(addr); 365 replaced_instructions[addr] = GetMemory().Read32(addr);
366 system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction()); 366 GetMemory().Write32(addr, arch->BreakpointInstruction());
367 Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); 367 Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32));
368 success = true; 368 success = true;
369 break; 369 break;
370 case BreakpointType::WriteWatch: 370 case BreakpointType::WriteWatch:
371 success = system.ApplicationProcess()->InsertWatchpoint(addr, size, 371 success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write);
372 Kernel::DebugWatchpointType::Write);
373 break; 372 break;
374 case BreakpointType::ReadWatch: 373 case BreakpointType::ReadWatch:
375 success = system.ApplicationProcess()->InsertWatchpoint(addr, size, 374 success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read);
376 Kernel::DebugWatchpointType::Read);
377 break; 375 break;
378 case BreakpointType::AccessWatch: 376 case BreakpointType::AccessWatch:
379 success = system.ApplicationProcess()->InsertWatchpoint( 377 success =
380 addr, size, Kernel::DebugWatchpointType::ReadOrWrite); 378 GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
381 break; 379 break;
382 case BreakpointType::Hardware: 380 case BreakpointType::Hardware:
383 default: 381 default:
@@ -400,7 +398,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
400 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 398 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
401 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; 399 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
402 400
403 if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { 401 if (!GetMemory().IsValidVirtualAddressRange(addr, size)) {
404 SendReply(GDB_STUB_REPLY_ERR); 402 SendReply(GDB_STUB_REPLY_ERR);
405 return; 403 return;
406 } 404 }
@@ -411,24 +409,22 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
411 case BreakpointType::Software: { 409 case BreakpointType::Software: {
412 const auto orig_insn{replaced_instructions.find(addr)}; 410 const auto orig_insn{replaced_instructions.find(addr)};
413 if (orig_insn != replaced_instructions.end()) { 411 if (orig_insn != replaced_instructions.end()) {
414 system.ApplicationMemory().Write32(addr, orig_insn->second); 412 GetMemory().Write32(addr, orig_insn->second);
415 Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); 413 Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32));
416 replaced_instructions.erase(addr); 414 replaced_instructions.erase(addr);
417 success = true; 415 success = true;
418 } 416 }
419 break; 417 break;
420 } 418 }
421 case BreakpointType::WriteWatch: 419 case BreakpointType::WriteWatch:
422 success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, 420 success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write);
423 Kernel::DebugWatchpointType::Write);
424 break; 421 break;
425 case BreakpointType::ReadWatch: 422 case BreakpointType::ReadWatch:
426 success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, 423 success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read);
427 Kernel::DebugWatchpointType::Read);
428 break; 424 break;
429 case BreakpointType::AccessWatch: 425 case BreakpointType::AccessWatch:
430 success = system.ApplicationProcess()->RemoveWatchpoint( 426 success =
431 addr, size, Kernel::DebugWatchpointType::ReadOrWrite); 427 GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
432 break; 428 break;
433 case BreakpointType::Hardware: 429 case BreakpointType::Hardware:
434 default: 430 default:
@@ -466,10 +462,10 @@ void GDBStub::HandleQuery(std::string_view command) {
466 const auto target_xml{arch->GetTargetXML()}; 462 const auto target_xml{arch->GetTargetXML()};
467 SendReply(PaginateBuffer(target_xml, command.substr(30))); 463 SendReply(PaginateBuffer(target_xml, command.substr(30)));
468 } else if (command.starts_with("Offsets")) { 464 } else if (command.starts_with("Offsets")) {
469 const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess()); 465 const auto main_offset = Core::FindMainModuleEntrypoint(GetProcess());
470 SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset))); 466 SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset)));
471 } else if (command.starts_with("Xfer:libraries:read::")) { 467 } else if (command.starts_with("Xfer:libraries:read::")) {
472 auto modules = Core::FindModules(system.ApplicationProcess()); 468 auto modules = Core::FindModules(GetProcess());
473 469
474 std::string buffer; 470 std::string buffer;
475 buffer += R"(<?xml version="1.0"?>)"; 471 buffer += R"(<?xml version="1.0"?>)";
@@ -483,7 +479,7 @@ void GDBStub::HandleQuery(std::string_view command) {
483 SendReply(PaginateBuffer(buffer, command.substr(21))); 479 SendReply(PaginateBuffer(buffer, command.substr(21)));
484 } else if (command.starts_with("fThreadInfo")) { 480 } else if (command.starts_with("fThreadInfo")) {
485 // beginning of list 481 // beginning of list
486 const auto& threads = system.ApplicationProcess()->GetThreadList(); 482 const auto& threads = GetProcess()->GetThreadList();
487 std::vector<std::string> thread_ids; 483 std::vector<std::string> thread_ids;
488 for (const auto& thread : threads) { 484 for (const auto& thread : threads) {
489 thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId())); 485 thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId()));
@@ -497,7 +493,7 @@ void GDBStub::HandleQuery(std::string_view command) {
497 buffer += R"(<?xml version="1.0"?>)"; 493 buffer += R"(<?xml version="1.0"?>)";
498 buffer += "<threads>"; 494 buffer += "<threads>";
499 495
500 const auto& threads = system.ApplicationProcess()->GetThreadList(); 496 const auto& threads = GetProcess()->GetThreadList();
501 for (const auto& thread : threads) { 497 for (const auto& thread : threads) {
502 auto thread_name{Core::GetThreadName(&thread)}; 498 auto thread_name{Core::GetThreadName(&thread)};
503 if (!thread_name) { 499 if (!thread_name) {
@@ -613,7 +609,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
613 std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()}; 609 std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
614 std::string reply; 610 std::string reply;
615 611
616 auto* process = system.ApplicationProcess(); 612 auto* process = GetProcess();
617 auto& page_table = process->GetPageTable(); 613 auto& page_table = process->GetPageTable();
618 614
619 const char* commands = "Commands:\n" 615 const char* commands = "Commands:\n"
@@ -714,7 +710,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
714} 710}
715 711
716Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { 712Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
717 auto& threads{system.ApplicationProcess()->GetThreadList()}; 713 auto& threads{GetProcess()->GetThreadList()};
718 for (auto& thread : threads) { 714 for (auto& thread : threads) {
719 if (thread.GetThreadId() == thread_id) { 715 if (thread.GetThreadId() == thread_id) {
720 return std::addressof(thread); 716 return std::addressof(thread);
@@ -783,4 +779,12 @@ void GDBStub::SendStatus(char status) {
783 backend.WriteToClient(buf); 779 backend.WriteToClient(buf);
784} 780}
785 781
782Kernel::KProcess* GDBStub::GetProcess() {
783 return debug_process;
784}
785
786Core::Memory::Memory& GDBStub::GetMemory() {
787 return GetProcess()->GetMemory();
788}
789
786} // namespace Core 790} // namespace Core