mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Fix bug with reading addresses and lengths
This commit is contained in:
		
							parent
							
								
									b6422038b5
								
							
						
					
					
						commit
						bcea959910
					
				
					 1 changed files with 55 additions and 45 deletions
				
			
		|  | @ -126,6 +126,22 @@ static u8 NibbleToHex(u8 n) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  | * Converts input hex string characters into an array of equivalent of u8 bytes. | ||||||
|  | * | ||||||
|  | * @param dest Pointer to buffer to store u8 bytes. | ||||||
|  | * @param src Pointer to array of output hex string characters. | ||||||
|  | * @param len Length of src array. | ||||||
|  | */ | ||||||
|  | static u32 HexToInt(u8* src, u32 len) { | ||||||
|  |     u32 output = 0; | ||||||
|  |     while (len-- > 0) { | ||||||
|  |         output = (output << 4) | HexCharToValue(src[0]); | ||||||
|  |         src++; | ||||||
|  |     } | ||||||
|  |     return output; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Converts input array of u8 bytes into their equivalent hex string characters. |  * Converts input array of u8 bytes into their equivalent hex string characters. | ||||||
|  * |  * | ||||||
|  | @ -133,7 +149,7 @@ static u8 NibbleToHex(u8 n) { | ||||||
|  * @param src Pointer to array of u8 bytes. |  * @param src Pointer to array of u8 bytes. | ||||||
|  * @param len Length of src array. |  * @param len Length of src array. | ||||||
|  */ |  */ | ||||||
| static void MemToHex(u8* dest, u8* src, u32 len) { | static void MemToGdbHex(u8* dest, u8* src, u32 len) { | ||||||
|     while (len-- > 0) { |     while (len-- > 0) { | ||||||
|         u8 tmp = *src++; |         u8 tmp = *src++; | ||||||
|         *dest++ = NibbleToHex(tmp >> 4); |         *dest++ = NibbleToHex(tmp >> 4); | ||||||
|  | @ -142,13 +158,13 @@ static void MemToHex(u8* dest, u8* src, u32 len) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Converts input hex string characters into an array of equivalent of u8 bytes. |  * Converts input gdb-formatted hex string characters into an array of equivalent of u8 bytes. | ||||||
|  * |  * | ||||||
|  * @param dest Pointer to buffer to store u8 bytes. |  * @param dest Pointer to buffer to store u8 bytes. | ||||||
|  * @param src Pointer to array of output hex string characters. |  * @param src Pointer to array of output hex string characters. | ||||||
|  * @param len Length of src array. |  * @param len Length of src array. | ||||||
|  */ |  */ | ||||||
| static void HexToMem(u8* dest, u8* src, u32 len) { | static void GdbHexToMem(u8* dest, u8* src, u32 len) { | ||||||
|     while (len-- > 0) { |     while (len-- > 0) { | ||||||
|         *dest++ = (HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]); |         *dest++ = (HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]); | ||||||
|         src += 2; |         src += 2; | ||||||
|  | @ -156,11 +172,11 @@ static void HexToMem(u8* dest, u8* src, u32 len) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Convert a u32 into a hex string. |  * Convert a u32 into a gdb-formatted hex string. | ||||||
|  * |  * | ||||||
|  * @param dest Pointer to buffer to store output hex string characters. |  * @param dest Pointer to buffer to store output hex string characters. | ||||||
|  */ |  */ | ||||||
| static void IntToHex(u8* dest, u32 v) { | static void IntToGdbHex(u8* dest, u32 v) { | ||||||
|     for (int i = 0; i < 8; i += 2) { |     for (int i = 0; i < 8; i += 2) { | ||||||
|         dest[i + 1] = NibbleToHex(v >> (4 * i)); |         dest[i + 1] = NibbleToHex(v >> (4 * i)); | ||||||
|         dest[i] = NibbleToHex(v >> (4 * (i + 1))); |         dest[i] = NibbleToHex(v >> (4 * (i + 1))); | ||||||
|  | @ -168,11 +184,11 @@ static void IntToHex(u8* dest, u32 v) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Convert a hex string into a u32. |  * Convert a gdb-formatted hex string into a u32. | ||||||
|  * |  * | ||||||
|  * @param src Pointer to hex string. |  * @param src Pointer to hex string. | ||||||
|  */ |  */ | ||||||
| static u32 HexToInt(u8* src) { | static u32 GdbHexToInt(u8* src) { | ||||||
|     u32 output = 0; |     u32 output = 0; | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < 8; i += 2) { |     for (int i = 0; i < 8; i += 2) { | ||||||
|  | @ -455,14 +471,14 @@ static void ReadRegister() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (id >= R0_REGISTER && id <= R15_REGISTER) { |     if (id >= R0_REGISTER && id <= R15_REGISTER) { | ||||||
|         IntToHex(reply, Core::g_app_core->GetReg(id)); |         IntToGdbHex(reply, Core::g_app_core->GetReg(id)); | ||||||
|     } else if (id == CSPR_REGISTER) { |     } else if (id == CSPR_REGISTER) { | ||||||
|         IntToHex(reply, Core::g_app_core->GetCPSR()); |         IntToGdbHex(reply, Core::g_app_core->GetCPSR()); | ||||||
|     } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) { |     } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) { | ||||||
|         IntToHex(reply, Core::g_app_core->GetVFPReg(id - CSPR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER
 |         IntToGdbHex(reply, Core::g_app_core->GetVFPReg(id - CSPR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER
 | ||||||
|     } else if (id == FPSCR_REGISTER) { |     } else if (id == FPSCR_REGISTER) { | ||||||
|         IntToHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
 |         IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
 | ||||||
|         IntToHex(reply + 8, 0); |         IntToGdbHex(reply + 8, 0); | ||||||
|     } else { |     } else { | ||||||
|         return SendReply("E01"); |         return SendReply("E01"); | ||||||
|     } |     } | ||||||
|  | @ -478,20 +494,20 @@ static void ReadRegisters() { | ||||||
|     u8* bufptr = buffer; |     u8* bufptr = buffer; | ||||||
|     for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) { |     for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) { | ||||||
|         if (i <= R15_REGISTER) { |         if (i <= R15_REGISTER) { | ||||||
|             IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetReg(reg)); |             IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetReg(reg)); | ||||||
|         } else if (i == CSPR_REGISTER) { |         } else if (i == CSPR_REGISTER) { | ||||||
|             IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetCPSR()); |             IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetCPSR()); | ||||||
|         } else if (i < CSPR_REGISTER) { |         } else if (i < CSPR_REGISTER) { | ||||||
|             IntToHex(bufptr + i * CHAR_BIT, 0); |             IntToGdbHex(bufptr + i * CHAR_BIT, 0); | ||||||
|             IntToHex(bufptr + (i + 1) * CHAR_BIT, 0); |             IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0); | ||||||
|             i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one
 |             i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one
 | ||||||
|             reg++; |             reg++; | ||||||
|         } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) { |         } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) { | ||||||
|             IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPReg(reg - CSPR_REGISTER - 1)); |             IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPReg(reg - CSPR_REGISTER - 1)); | ||||||
|             IntToHex(bufptr + (i + 1) * CHAR_BIT, 0); |             IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0); | ||||||
|             i++; |             i++; | ||||||
|         } else if (i == MAX_REGISTERS) { |         } else if (i == MAX_REGISTERS) { | ||||||
|             IntToHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); |             IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -510,13 +526,13 @@ static void WriteRegister() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (id >= R0_REGISTER && id <= R15_REGISTER) { |     if (id >= R0_REGISTER && id <= R15_REGISTER) { | ||||||
|         Core::g_app_core->SetReg(id, HexToInt(buffer_ptr)); |         Core::g_app_core->SetReg(id, GdbHexToInt(buffer_ptr)); | ||||||
|     } else if (id == CSPR_REGISTER) { |     } else if (id == CSPR_REGISTER) { | ||||||
|         Core::g_app_core->SetCPSR(HexToInt(buffer_ptr)); |         Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr)); | ||||||
|     } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) { |     } else if (id > CSPR_REGISTER && id < FPSCR_REGISTER) { | ||||||
|         Core::g_app_core->SetVFPReg(id - CSPR_REGISTER - 1, HexToInt(buffer_ptr)); |         Core::g_app_core->SetVFPReg(id - CSPR_REGISTER - 1, GdbHexToInt(buffer_ptr)); | ||||||
|     } else if (id == FPSCR_REGISTER) { |     } else if (id == FPSCR_REGISTER) { | ||||||
|         Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, HexToInt(buffer_ptr)); |         Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr)); | ||||||
|     } else { |     } else { | ||||||
|         return SendReply("E01"); |         return SendReply("E01"); | ||||||
|     } |     } | ||||||
|  | @ -533,17 +549,17 @@ static void WriteRegisters() { | ||||||
| 
 | 
 | ||||||
|     for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) { |     for (int i = 0, reg = 0; i <= MAX_REGISTERS; i++, reg++) { | ||||||
|         if (i <= R15_REGISTER) { |         if (i <= R15_REGISTER) { | ||||||
|             Core::g_app_core->SetReg(reg, HexToInt(buffer_ptr + i * CHAR_BIT)); |             Core::g_app_core->SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | ||||||
|         } else if (i == CSPR_REGISTER) { |         } else if (i == CSPR_REGISTER) { | ||||||
|             Core::g_app_core->SetCPSR(HexToInt(buffer_ptr + i * CHAR_BIT)); |             Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | ||||||
|         } else if (i < CSPR_REGISTER) { |         } else if (i < CSPR_REGISTER) { | ||||||
|             i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one
 |             i++; // These registers seem to be all 64bit instead of 32bit, so skip two instead of one
 | ||||||
|             reg++; |             reg++; | ||||||
|         } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) { |         } else if (i > CSPR_REGISTER && i < MAX_REGISTERS) { | ||||||
|             Core::g_app_core->SetVFPReg(reg - CSPR_REGISTER - 1, HexToInt(buffer_ptr + i * CHAR_BIT)); |             Core::g_app_core->SetVFPReg(reg - CSPR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | ||||||
|             i++; // Skip padding
 |             i++; // Skip padding
 | ||||||
|         } else if (i == MAX_REGISTERS) { |         } else if (i == MAX_REGISTERS) { | ||||||
|             Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, HexToInt(buffer_ptr + i * CHAR_BIT)); |             Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -556,12 +572,12 @@ static void ReadMemory() { | ||||||
| 
 | 
 | ||||||
|     auto start_offset = command_buffer+1; |     auto start_offset = command_buffer+1; | ||||||
|     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); |     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | ||||||
|     PAddr addr = 0; |     PAddr addr = HexToInt(start_offset, addr_pos - start_offset); | ||||||
|     HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     start_offset = addr_pos+1; |     start_offset = addr_pos+1; | ||||||
|     u32 len = 0; |     u32 len = HexToInt(start_offset, (command_buffer + command_length) - start_offset); | ||||||
|     HexToMem((u8*)&len, start_offset, ((command_buffer + command_length) - start_offset) / 2); | 
 | ||||||
|  |     LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len); | ||||||
| 
 | 
 | ||||||
|     if (len * 2 > sizeof(reply)) { |     if (len * 2 > sizeof(reply)) { | ||||||
|         SendReply("E01"); |         SendReply("E01"); | ||||||
|  | @ -572,7 +588,7 @@ static void ReadMemory() { | ||||||
|         return SendReply("E0"); |         return SendReply("E0"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MemToHex(reply, data, len); |     MemToGdbHex(reply, data, len); | ||||||
|     reply[len * 2] = '\0'; |     reply[len * 2] = '\0'; | ||||||
|     SendReply(reinterpret_cast<char*>(reply)); |     SendReply(reinterpret_cast<char*>(reply)); | ||||||
| } | } | ||||||
|  | @ -581,20 +597,18 @@ static void ReadMemory() { | ||||||
| static void WriteMemory() { | static void WriteMemory() { | ||||||
|     auto start_offset = command_buffer+1; |     auto start_offset = command_buffer+1; | ||||||
|     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); |     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | ||||||
|     PAddr addr = 0; |     PAddr addr = HexToInt(start_offset, addr_pos - start_offset); | ||||||
|     HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     start_offset = addr_pos+1; |     start_offset = addr_pos+1; | ||||||
|     auto len_pos = std::find(start_offset, command_buffer+command_length, ':'); |     auto len_pos = std::find(start_offset, command_buffer+command_length, ':'); | ||||||
|     u32 len = 0; |     u32 len = HexToInt(start_offset, len_pos - start_offset); | ||||||
|     HexToMem((u8*)&len, start_offset, (len_pos - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     u8* dst = Memory::GetPointer(addr); |     u8* dst = Memory::GetPointer(addr); | ||||||
|     if (!dst) { |     if (!dst) { | ||||||
|         return SendReply("E00"); |         return SendReply("E00"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HexToMem(dst, len_pos + 1, len); |     GdbHexToMem(dst, len_pos + 1, len); | ||||||
|     SendReply("OK"); |     SendReply("OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -677,12 +691,10 @@ static void AddBreakpoint() { | ||||||
| 
 | 
 | ||||||
|     auto start_offset = command_buffer+3; |     auto start_offset = command_buffer+3; | ||||||
|     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); |     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | ||||||
|     PAddr addr = 0; |     PAddr addr = HexToInt(start_offset, addr_pos - start_offset); | ||||||
|     HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     start_offset = addr_pos+1; |     start_offset = addr_pos+1; | ||||||
|     u32 len = 0; |     u32 len = HexToInt(start_offset, (command_buffer + command_length) - start_offset); | ||||||
|     HexToMem((u8*)&len, start_offset, ((command_buffer + command_length) - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     if (type == BreakpointType::Access) { |     if (type == BreakpointType::Access) { | ||||||
|         // Access is made up of Read and Write types, so add both breakpoints
 |         // Access is made up of Read and Write types, so add both breakpoints
 | ||||||
|  | @ -727,12 +739,10 @@ static void RemoveBreakpoint() { | ||||||
| 
 | 
 | ||||||
|     auto start_offset = command_buffer+3; |     auto start_offset = command_buffer+3; | ||||||
|     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); |     auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | ||||||
|     PAddr addr = 0; |     PAddr addr = HexToInt(start_offset, addr_pos - start_offset); | ||||||
|     HexToMem((u8*)&addr, start_offset, (addr_pos - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     start_offset = addr_pos+1; |     start_offset = addr_pos+1; | ||||||
|     u32 len = 0; |     u32 len = HexToInt(start_offset, (command_buffer + command_length) - start_offset); | ||||||
|     HexToMem((u8*)&len, start_offset, ((command_buffer + command_length) - start_offset) / 2); |  | ||||||
| 
 | 
 | ||||||
|     if (type == BreakpointType::Access) { |     if (type == BreakpointType::Access) { | ||||||
|         // Access is made up of Read and Write types, so add both breakpoints
 |         // Access is made up of Read and Write types, so add both breakpoints
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue