[patch] gdbserver: Detect and return errors reading memory

Nathan J. Williams
2004-03-01T20:55:57Z

As I promised last week, here is a patch to check for errors reading
memory in gdbserver and propagate that error back to the host gdb.

- Nathan

2004-03-01 Nathan J. Williams <nathanw@wasabisystems.com>

* linux-low.c (linux_read_memory): Change return type to
int. Check for and return error from ptrace().
* target.c (read_inferior_memory): Change return type to int. Pass
back return status from the_target->read_memory().
* target.h (struct target_ops): Adapt *read_memory() prototype.
Update comment.
(read_inferior_memory): Adapt prototype.
* server.c (main): Return an error packet if
read_inferior_memory() returns an error.

Index: linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.29
diff -u -p -r1.29 linux-low.c
--- linux-low.c 29 Feb 2004 16:47:15 -0000 1.29
+++ linux-low.c 1 Mar 2004 20:47:58 -0000
@@ -1281,7 +1281,7 @@ linux_store_registers (int regno)
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */

-static void
+static int
linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
register int i;
@@ -1298,11 +1298,16 @@ linux_read_memory (CORE_ADDR memaddr, ch
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
+ errno = 0;
buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
+ if (errno)
+ return errno;
}

/* Copy appropriate bytes out of the buffer. */
memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);
+
+ return 0;
}

/* Copy LEN bytes of data from debugger memory at MYADDR
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.c,v
retrieving revision 1.3
diff -u -p -r1.3 target.c
--- target.c 11 Jun 2002 17:32:40 -0000 1.3
+++ target.c 1 Mar 2004 20:47:58 -0000
@@ -57,11 +57,13 @@ set_desired_inferior (int use_general)
current_inferior = found;
}

-void
+int
read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
- (*the_target->read_memory) (memaddr, myaddr, len);
+ int res;
+ res = (*the_target->read_memory) (memaddr, myaddr, len);
check_mem_read (memaddr, myaddr, len);
+ return res;
}

int
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.10
diff -u -p -r1.10 target.h
--- target.h 26 Feb 2004 15:08:47 -0000 1.10
+++ target.h 1 Mar 2004 20:47:58 -0000
@@ -102,9 +102,11 @@ struct target_ops
/* Read memory from the inferior process. This should generally be
called through read_inferior_memory, which handles breakpoint shadowing.

- Read LEN bytes at MEMADDR into a buffer at MYADDR. */
+ Read LEN bytes at MEMADDR into a buffer at MYADDR.
+
+ Returns 0 on success and errno on failure. */

- void (*read_memory) (CORE_ADDR memaddr, char *myaddr, int len);
+ int (*read_memory) (CORE_ADDR memaddr, char *myaddr, int len);

/* Write memory to the inferior process. This should generally be
called through write_inferior_memory, which handles breakpoint shadowing.
@@ -160,7 +162,7 @@ void set_target_ops (struct target_ops *

unsigned char mywait (char *statusp, int connected_wait);

-void read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
+int read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);

int write_inferior_memory (CORE_ADDR memaddr, const char *myaddr, int len);

Index: server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.20
diff -u -p -r1.20 server.c
--- server.c 29 Feb 2004 16:49:38 -0000 1.20
+++ server.c 1 Mar 2004 20:47:58 -0000
@@ -462,8 +462,10 @@ main (int argc, char *argv[])
break;
case 'm':
decode_m_packet (&own_buf[1], &mem_addr, &len);
- read_inferior_memory (mem_addr, mem_buf, len);
- convert_int_to_ascii (mem_buf, own_buf, len);
+ if (read_inferior_memory (mem_addr, mem_buf, len) == 0)
+ convert_int_to_ascii (mem_buf, own_buf, len);
+ else
+ write_enn (own_buf);
break;
case 'M':
decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);