summaryrefslogtreecommitdiff
path: root/src/core/gdbstub/gdbstub.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/gdbstub/gdbstub.cpp')
-rw-r--r--src/core/gdbstub/gdbstub.cpp100
1 files changed, 55 insertions, 45 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index e37a2efd7..003ce4167 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -127,13 +127,29 @@ static u8 NibbleToHex(u8 n) {
127} 127}
128 128
129/** 129/**
130* Converts input hex string characters into an array of equivalent of u8 bytes.
131*
132* @param dest Pointer to buffer to store u8 bytes.
133* @param src Pointer to array of output hex string characters.
134* @param len Length of src array.
135*/
136static u32 HexToInt(u8* src, u32 len) {
137 u32 output = 0;
138 while (len-- > 0) {
139 output = (output << 4) | HexCharToValue(src[0]);
140 src++;
141 }
142 return output;
143}
144
145/**
130 * Converts input array of u8 bytes into their equivalent hex string characters. 146 * Converts input array of u8 bytes into their equivalent hex string characters.
131 * 147 *
132 * @param dest Pointer to buffer to store output hex string characters. 148 * @param dest Pointer to buffer to store output hex string characters.
133 * @param src Pointer to array of u8 bytes. 149 * @param src Pointer to array of u8 bytes.
134 * @param len Length of src array. 150 * @param len Length of src array.
135 */ 151 */
136static void MemToHex(u8* dest, u8* src, u32 len) { 152static void MemToGdbHex(u8* dest, u8* src, u32 len) {
137 while (len-- > 0) { 153 while (len-- > 0) {
138 u8 tmp = *src++; 154 u8 tmp = *src++;
139 *dest++ = NibbleToHex(tmp >> 4); 155 *dest++ = NibbleToHex(tmp >> 4);
@@ -142,13 +158,13 @@ static void MemToHex(u8* dest, u8* src, u32 len) {
142} 158}
143 159
144/** 160/**
145 * Converts input hex string characters into an array of equivalent of u8 bytes. 161 * Converts input gdb-formatted hex string characters into an array of equivalent of u8 bytes.
146 * 162 *
147 * @param dest Pointer to buffer to store u8 bytes. 163 * @param dest Pointer to buffer to store u8 bytes.
148 * @param src Pointer to array of output hex string characters. 164 * @param src Pointer to array of output hex string characters.
149 * @param len Length of src array. 165 * @param len Length of src array.
150 */ 166 */
151static void HexToMem(u8* dest, u8* src, u32 len) { 167static void GdbHexToMem(u8* dest, u8* src, u32 len) {
152 while (len-- > 0) { 168 while (len-- > 0) {
153 *dest++ = (HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]); 169 *dest++ = (HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]);
154 src += 2; 170 src += 2;
@@ -156,11 +172,11 @@ static void HexToMem(u8* dest, u8* src, u32 len) {
156} 172}
157 173
158/** 174/**
159 * Convert a u32 into a hex string. 175 * Convert a u32 into a gdb-formatted hex string.
160 * 176 *
161 * @param dest Pointer to buffer to store output hex string characters. 177 * @param dest Pointer to buffer to store output hex string characters.
162 */ 178 */
163static void IntToHex(u8* dest, u32 v) { 179static void IntToGdbHex(u8* dest, u32 v) {
164 for (int i = 0; i < 8; i += 2) { 180 for (int i = 0; i < 8; i += 2) {
165 dest[i + 1] = NibbleToHex(v >> (4 * i)); 181 dest[i + 1] = NibbleToHex(v >> (4 * i));
166 dest[i] = NibbleToHex(v >> (4 * (i + 1))); 182 dest[i] = NibbleToHex(v >> (4 * (i + 1)));
@@ -168,11 +184,11 @@ static void IntToHex(u8* dest, u32 v) {
168} 184}
169 185
170/** 186/**
171 * Convert a hex string into a u32. 187 * Convert a gdb-formatted hex string into a u32.
172 * 188 *
173 * @param src Pointer to hex string. 189 * @param src Pointer to hex string.
174 */ 190 */
175static u32 HexToInt(u8* src) { 191static u32 GdbHexToInt(u8* src) {
176 u32 output = 0; 192 u32 output = 0;
177 193
178 for (int i = 0; i < 8; i += 2) { 194 for (int i = 0; i < 8; i += 2) {
@@ -455,14 +471,14 @@ static void ReadRegister() {
455 } 471 }
456 472
457 if (id >= R0_REGISTER && id <= R15_REGISTER) { 473 if (id >= R0_REGISTER && id <= R15_REGISTER) {
458 IntToHex(reply, Core::g_app_core->GetReg(id)); 474 IntToGdbHex(reply, Core::g_app_core->GetReg(id));
459 } else if (id == CSPR_REGISTER) { 475 } else if (id == CSPR_REGISTER) {
460 IntToHex(reply, Core::g_app_core->GetCPSR()); 476 IntToGdbHex(reply, Core::g_app_core->GetCPSR());
461 } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) { 477 } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) {
462 IntToHex(reply, Core::g_app_core->GetVFPReg(id - CSPR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER 478 IntToGdbHex(reply, Core::g_app_core->GetVFPReg(id - CSPR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER
463 } else if (id == FPSCR_REGISTER) { 479 } else if (id == FPSCR_REGISTER) {
464 IntToHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR 480 IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
465 IntToHex(reply + 8, 0); 481 IntToGdbHex(reply + 8, 0);
466 } else { 482 } else {
467 return SendReply("E01"); 483 return SendReply("E01");
468 } 484 }
@@ -478,20 +494,20 @@ static void ReadRegisters() {
478 u8* bufptr = buffer; 494 u8* bufptr = buffer;
479 for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) { 495 for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) {
480 if (i <= R15_REGISTER) { 496 if (i <= R15_REGISTER) {
481 IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetReg(reg)); 497 IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetReg(reg));
482 } else if (i == CSPR_REGISTER) { 498 } else if (i == CSPR_REGISTER) {
483 IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetCPSR()); 499 IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetCPSR());
484 } else if (i < CSPR_REGISTER) { 500 } else if (i < CSPR_REGISTER) {
485 IntToHex(bufptr + i * CHAR_BIT, 0); 501 IntToGdbHex(bufptr + i * CHAR_BIT, 0);
486 IntToHex(bufptr + (i + 1) * CHAR_BIT, 0); 502 IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0);
487 i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one 503 i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one
488 reg++; 504 reg++;
489 } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) { 505 } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) {
490 IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPReg(reg - CSPR_REGISTER - 1)); 506 IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPReg(reg - CSPR_REGISTER - 1));
491 IntToHex(bufptr + (i + 1) * CHAR_BIT, 0); 507 IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0);
492 i++; 508 i++;
493 } else if (i == MAX_REGISTERS) { 509 } else if (i == MAX_REGISTERS) {
494 IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); 510 IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR));
495 } 511 }
496 } 512 }
497 513
@@ -510,13 +526,13 @@ static void WriteRegister() {
510 } 526 }
511 527
512 if (id >= R0_REGISTER && id <= R15_REGISTER) { 528 if (id >= R0_REGISTER && id <= R15_REGISTER) {
513 Core::g_app_core->SetReg(id, HexToInt(buffer_ptr)); 529 Core::g_app_core->SetReg(id, GdbHexToInt(buffer_ptr));
514 } else if (id == CSPR_REGISTER) { 530 } else if (id == CSPR_REGISTER) {
515 Core::g_app_core->SetCPSR(HexToInt(buffer_ptr)); 531 Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr));
516 } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) { 532 } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) {
517 Core::g_app_core->SetVFPReg(id - CSPR_REGISTER - 1, HexToInt(buffer_ptr)); 533 Core::g_app_core->SetVFPReg(id - CSPR_REGISTER - 1, GdbHexToInt(buffer_ptr));
518 } else if (id == FPSCR_REGISTER) { 534 } else if (id == FPSCR_REGISTER) {
519 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, HexToInt(buffer_ptr)); 535 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr));
520 } else { 536 } else {
521 return SendReply("E01"); 537 return SendReply("E01");
522 } 538 }
@@ -533,17 +549,17 @@ static void WriteRegisters() {
533 549
534 for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) { 550 for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) {
535 if (i <= R15_REGISTER) { 551 if (i <= R15_REGISTER) {
536 Core::g_app_core->SetReg(reg, HexToInt(buffer_ptr + i * CHAR_BIT)); 552 Core::g_app_core->SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
537 } else if (i == CSPR_REGISTER) { 553 } else if (i == CSPR_REGISTER) {
538 Core::g_app_core->SetCPSR(HexToInt(buffer_ptr + i * CHAR_BIT)); 554 Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT));
539 } else if (i < CSPR_REGISTER) { 555 } else if (i < CSPR_REGISTER) {
540 i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one 556 i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one
541 reg++; 557 reg++;
542 } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) { 558 } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) {
543 Core::g_app_core->SetVFPReg(reg - CSPR_REGISTER - 1, HexToInt(buffer_ptr + i * CHAR_BIT)); 559 Core::g_app_core->SetVFPReg(reg - CSPR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
544 i++; // Skip padding 560 i++; // Skip padding
545 } else if (i == MAX_REGISTERS) { 561 } else if (i == MAX_REGISTERS) {
546 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, HexToInt(buffer_ptr + i * CHAR_BIT)); 562 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
547 } 563 }
548 } 564 }
549 565
@@ -556,12 +572,12 @@ static void ReadMemory() {
556 572
557 auto start_offset = command_buffer+1; 573 auto start_offset = command_buffer+1;
558 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 574 auto addr_pos = std::find(start_offset, command_buffer+command_length, ',');
559 PAddr addr = 0; 575 PAddr addr = HexToInt(start_offset, addr_pos - start_offset);
560 HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2);
561 576
562 start_offset = addr_pos+1; 577 start_offset = addr_pos+1;
563 u32 len = 0; 578 u32 len = HexToInt(start_offset, (command_buffer + command_length) - start_offset);
564 HexToMem((u8*)&len, start_offset, ((command_buffer + command_length) - start_offset) / 2); 579
580 LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len);
565 581
566 if (len * 2 > sizeof(reply)) { 582 if (len * 2 > sizeof(reply)) {
567 SendReply("E01"); 583 SendReply("E01");
@@ -572,7 +588,7 @@ static void ReadMemory() {
572 return SendReply("E0"); 588 return SendReply("E0");
573 } 589 }
574 590
575 MemToHex(reply, data, len); 591 MemToGdbHex(reply, data, len);
576 reply[len * 2] = '\0'; 592 reply[len * 2] = '\0';
577 SendReply(reinterpret_cast<char*>(reply)); 593 SendReply(reinterpret_cast<char*>(reply));
578} 594}
@@ -581,20 +597,18 @@ static void ReadMemory() {
581static void WriteMemory() { 597static void WriteMemory() {
582 auto start_offset = command_buffer+1; 598 auto start_offset = command_buffer+1;
583 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 599 auto addr_pos = std::find(start_offset, command_buffer+command_length, ',');
584 PAddr addr = 0; 600 PAddr addr = HexToInt(start_offset, addr_pos - start_offset);
585 HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2);
586 601
587 start_offset = addr_pos+1; 602 start_offset = addr_pos+1;
588 auto len_pos = std::find(start_offset, command_buffer+command_length, ':'); 603 auto len_pos = std::find(start_offset, command_buffer+command_length, ':');
589 u32 len = 0; 604 u32 len = HexToInt(start_offset, len_pos - start_offset);
590 HexToMem((u8*)&len, start_offset, (len_pos - start_offset) / 2);
591 605
592 u8* dst = Memory::GetPointer(addr); 606 u8* dst = Memory::GetPointer(addr);
593 if (!dst) { 607 if (!dst) {
594 return SendReply("E00"); 608 return SendReply("E00");
595 } 609 }
596 610
597 HexToMem(dst, len_pos + 1, len); 611 GdbHexToMem(dst, len_pos + 1, len);
598 SendReply("OK"); 612 SendReply("OK");
599} 613}
600 614
@@ -677,12 +691,10 @@ static void AddBreakpoint() {
677 691
678 auto start_offset = command_buffer+3; 692 auto start_offset = command_buffer+3;
679 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 693 auto addr_pos = std::find(start_offset, command_buffer+command_length, ',');
680 PAddr addr = 0; 694 PAddr addr = HexToInt(start_offset, addr_pos - start_offset);
681 HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2);
682 695
683 start_offset = addr_pos+1; 696 start_offset = addr_pos+1;
684 u32 len = 0; 697 u32 len = HexToInt(start_offset, (command_buffer + command_length) - start_offset);
685 HexToMem((u8*)&len, start_offset, ((command_buffer + command_length) - start_offset) / 2);
686 698
687 if (type == BreakpointType::Access) { 699 if (type == BreakpointType::Access) {
688 // Access is made up of Read and Write types, so add both breakpoints 700 // Access is made up of Read and Write types, so add both breakpoints
@@ -727,12 +739,10 @@ static void RemoveBreakpoint() {
727 739
728 auto start_offset = command_buffer+3; 740 auto start_offset = command_buffer+3;
729 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 741 auto addr_pos = std::find(start_offset, command_buffer+command_length, ',');
730 PAddr addr = 0; 742 PAddr addr = HexToInt(start_offset, addr_pos - start_offset);
731 HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2);
732 743
733 start_offset = addr_pos+1; 744 start_offset = addr_pos+1;
734 u32 len = 0; 745 u32 len = HexToInt(start_offset, (command_buffer + command_length) - start_offset);
735 HexToMem((u8*)&len, start_offset, ((command_buffer + command_length) - start_offset) / 2);
736 746
737 if (type == BreakpointType::Access) { 747 if (type == BreakpointType::Access) {
738 // Access is made up of Read and Write types, so add both breakpoints 748 // Access is made up of Read and Write types, so add both breakpoints