[Pdbg] [PATCH 13/14] gdbserver: use read-modify-write for put_mem that is not 8-byte aligned

Nicholas Piggin npiggin at gmail.com
Mon Mar 14 15:17:34 AEDT 2022


Not all targets have memory access that can support arbitrary byte
writes. Use RMW for put_mem commands that are not 8-byte aligned.

This should really either be done in the target accessor, or at least
an alignment capability should be exposed to the caller. But for now
this will allow sbefifo mem ops to work to set breakpoints (4-byte
writes).

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 src/pdbgproxy.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
index a37e997..e8aab70 100644
--- a/src/pdbgproxy.c
+++ b/src/pdbgproxy.c
@@ -14,6 +14,7 @@
 #include <assert.h>
 #include <getopt.h>
 #include <errno.h>
+#include <byteswap.h>
 #include <ccan/array_size/array_size.h>
 
 #include <bitutils.h>
@@ -281,15 +282,15 @@ out:
 static void put_mem(uint64_t *stack, void *priv)
 {
 	uint64_t addr, len;
+	uint64_t start_addr, end_addr;
+	uint64_t align = 8;
+	uint32_t *insn;
 	uint8_t *data;
+	uint8_t *buf;
 	uint8_t attn_opcode[] = {0x00, 0x00, 0x02, 0x00};
+	uint8_t gdb_break_opcode[] = {0x7d, 0x82, 0x10, 0x08};
 	int err = 0;
 
-	if (littleendian) {
-		attn_opcode[1] = 0x02;
-		attn_opcode[2] = 0x00;
-	}
-
 	addr = stack[0];
 	len = stack[1];
 	data = (uint8_t *) &stack[2];
@@ -301,8 +302,7 @@ static void put_mem(uint64_t *stack, void *priv)
 		goto out;
 	}
 
-
-	if (len == 4 && stack[2] == 0x0810827d) {
+	if (len == 4 && !memcmp(data, gdb_break_opcode, 4)) {
 		/* According to linux-ppc-low.c gdb only uses this
 		 * op-code for sw break points so we replace it with
 		 * the correct attn opcode which is what we need for
@@ -318,17 +318,27 @@ static void put_mem(uint64_t *stack, void *priv)
 			err = 2;
 			goto out;
 		}
-	} else {
-		stack[2] = __builtin_bswap64(stack[2]) >> 32;
 	}
 
-	PR_INFO("put_mem 0x%016" PRIx64 " = 0x%016" PRIx64 "\n", addr, stack[2]);
+	if (len == 4 && littleendian) {
+		insn = (uint32_t *)data;
+		*insn = bswap_32(*insn);
+	}
 
-	if (mem_write(adu_target, addr, data, len, 0, false)) {
+	start_addr = addr & ~(align - 1);
+	end_addr = (addr + len + (align - 1)) & ~(align - 1);
+	if (addr != start_addr || (addr + len) != end_addr) {
+		buf = malloc(end_addr - start_addr);
+		mem_read(adu_target, start_addr, buf, end_addr - start_addr, 0, false);
+		memcpy(buf + (addr - start_addr), data, len);
+	} else {
+		buf = data;
+	}
+
+	if (mem_write(adu_target, start_addr, buf, end_addr - start_addr, 0, false)) {
 		PR_ERROR("Unable to write memory\n");
 		err = 3;
 	}
-
 out:
 	if (err)
 		send_response(fd, ERROR(EPERM));
-- 
2.23.0



More information about the Pdbg mailing list