diff options
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 100 |
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 | */ | ||
| 136 | static 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 | */ |
| 136 | static void MemToHex(u8* dest, u8* src, u32 len) { | 152 | static 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 | */ |
| 151 | static void HexToMem(u8* dest, u8* src, u32 len) { | 167 | static 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 | */ |
| 163 | static void IntToHex(u8* dest, u32 v) { | 179 | static 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 | */ |
| 175 | static u32 HexToInt(u8* src) { | 191 | static 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() { | |||
| 581 | static void WriteMemory() { | 597 | static 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 |