forked from Imagelibrary/binutils-gdb
Add common write_memory and read_memory NetBSD routines
Instead of sharing the native-only code with all BSDs with slightly
different semantics of the kernels, share the NetBSD-only behavior beteen
the NetBSD native and gdbserver setup.
NetBSD does not differentiate the address space I and D in the
operations (contrary to OpenBSD). NetBSD handles EACCES that integrates
with NetBSD specific PaX MPROTECT error handling.
Add a verbose message in the native client that an operation could be
cancelled due to PaX MPROTECT setup.
gdb/ChangeLog:
* nat/netbsd-nat.c (write_memory, read_memory): Add.
* nat/netbsd-nat.h (write_memory, read_memory): Likewise.
* nbsd-nat.c (nbsd_nat_target::xfer_partial): Update.
gdbserver/ChangeLog:
* netbsd-low.cc (netbsd_process_target::read_memory)
(netbsd_process_target::write_memory): Update.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2020-10-07 Kamil Rytarowski <n54@gmx.com>
|
||||
|
||||
* nat/netbsd-nat.c (write_memory, read_memory): Add.
|
||||
* nat/netbsd-nat.h (write_memory, read_memory): Likewise.
|
||||
* nbsd-nat.c (nbsd_nat_target::xfer_partial): Update.
|
||||
|
||||
2020-10-07 Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
* break-catch-sig.c (signal_catch_counts): Make a static arrray.
|
||||
|
||||
@@ -210,4 +210,84 @@ qxfer_siginfo (pid_t pid, const char *annex, unsigned char *readbuf,
|
||||
return len;
|
||||
}
|
||||
|
||||
/* See netbsd-nat.h. */
|
||||
|
||||
int
|
||||
write_memory (pid_t pid, unsigned const char *writebuf, CORE_ADDR offset,
|
||||
size_t len, size_t *xfered_len)
|
||||
{
|
||||
struct ptrace_io_desc io;
|
||||
io.piod_op = PIOD_WRITE_D;
|
||||
io.piod_len = len;
|
||||
|
||||
size_t bytes_written = 0;
|
||||
|
||||
/* Zero length write always succeeds. */
|
||||
if (len > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
io.piod_addr = (void *)(writebuf + bytes_written);
|
||||
io.piod_offs = (void *)(offset + bytes_written);
|
||||
|
||||
errno = 0;
|
||||
int rv = ptrace (PT_IO, pid, &io, 0);
|
||||
if (rv == -1)
|
||||
{
|
||||
gdb_assert (errno != 0);
|
||||
return errno;
|
||||
}
|
||||
if (io.piod_len == 0)
|
||||
return 0;
|
||||
|
||||
bytes_written += io.piod_len;
|
||||
io.piod_len = len - bytes_written;
|
||||
}
|
||||
while (bytes_written < len);
|
||||
}
|
||||
|
||||
if (xfered_len != nullptr)
|
||||
*xfered_len = bytes_written;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See netbsd-nat.h. */
|
||||
|
||||
int
|
||||
read_memory (pid_t pid, unsigned char *readbuf, CORE_ADDR offset,
|
||||
size_t len, size_t *xfered_len)
|
||||
{
|
||||
struct ptrace_io_desc io;
|
||||
io.piod_op = PIOD_READ_D;
|
||||
io.piod_len = len;
|
||||
|
||||
size_t bytes_read = 0;
|
||||
|
||||
/* Zero length read always succeeds. */
|
||||
if (len > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
io.piod_offs = (void *)(offset + bytes_read);
|
||||
io.piod_addr = readbuf + bytes_read;
|
||||
|
||||
int rv = ptrace (PT_IO, pid, &io, 0);
|
||||
if (rv == -1)
|
||||
return errno;
|
||||
if (io.piod_len == 0)
|
||||
return 0;
|
||||
|
||||
bytes_read += io.piod_len;
|
||||
io.piod_len = len - bytes_read;
|
||||
}
|
||||
while (bytes_read < len);
|
||||
}
|
||||
|
||||
if (xfered_len != nullptr)
|
||||
*xfered_len = bytes_read;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -67,6 +67,28 @@ extern void enable_proc_events (pid_t pid);
|
||||
extern int qxfer_siginfo (pid_t pid, const char *annex, unsigned char *readbuf,
|
||||
unsigned const char *writebuf, CORE_ADDR offset,
|
||||
int len);
|
||||
|
||||
/* Write gdb's LEN bytes from WRITEBUF and copy it to OFFSET in inferior
|
||||
process' address space. The inferior is specified by PID.
|
||||
Returns 0 on success or errno on failure and the number of bytes
|
||||
on a successful transfer in XFERED_LEN.
|
||||
|
||||
This function assumes internally that the queried process is stopped and
|
||||
traced. */
|
||||
|
||||
extern int write_memory (pid_t pid, unsigned const char *writebuf,
|
||||
CORE_ADDR offset, size_t len, size_t *xfered_len);
|
||||
|
||||
/* Read inferior process's LEN bytes from OFFSET and copy it to WRITEBUF in
|
||||
gdb's address space.
|
||||
Returns 0 on success or errno on failure and the number of bytes
|
||||
on a successful transfer in XFERED_LEN.
|
||||
|
||||
This function assumes internally that the queried process is stopped and
|
||||
traced. */
|
||||
|
||||
extern int read_memory (pid_t pid, unsigned char *readbuf, CORE_ADDR offset,
|
||||
size_t len, size_t *xfered_len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -764,6 +764,29 @@ nbsd_nat_target::xfer_partial (enum target_object object,
|
||||
*xfered_len = len;
|
||||
return TARGET_XFER_OK;
|
||||
}
|
||||
case TARGET_OBJECT_MEMORY:
|
||||
{
|
||||
size_t xfered;
|
||||
int res;
|
||||
if (writebuf != nullptr)
|
||||
res = netbsd_nat::write_memory (pid, writebuf, offset, len, &xfered);
|
||||
else
|
||||
res = netbsd_nat::read_memory (pid, readbuf, offset, len, &xfered);
|
||||
if (res != 0)
|
||||
{
|
||||
if (res == EACCES)
|
||||
fprintf_unfiltered (gdb_stderr, "Cannot %s process at %s (%s). "
|
||||
"Is PaX MPROTECT active? See security(7), "
|
||||
"sysctl(7), paxctl(8)\n",
|
||||
(writebuf ? "write to" : "read from"),
|
||||
pulongest (offset), safe_strerror (errno));
|
||||
return TARGET_XFER_E_IO;
|
||||
}
|
||||
if (xfered == 0)
|
||||
return TARGET_XFER_EOF;
|
||||
*xfered_len = (ULONGEST) xfered;
|
||||
return TARGET_XFER_OK;
|
||||
}
|
||||
default:
|
||||
return inf_ptrace_target::xfer_partial (object, annex,
|
||||
readbuf, writebuf, offset,
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2020-10-07 Kamil Rytarowski <n54@gmx.com>
|
||||
|
||||
* netbsd-low.cc (netbsd_process_target::read_memory)
|
||||
(netbsd_process_target::write_memory): Update.
|
||||
|
||||
2020-10-07 Kamil Rytarowski <n54@gmx.com>
|
||||
|
||||
* netbsd-aarch64-low.cc: Add.
|
||||
|
||||
@@ -556,36 +556,8 @@ int
|
||||
netbsd_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr,
|
||||
int size)
|
||||
{
|
||||
struct ptrace_io_desc io;
|
||||
io.piod_op = PIOD_READ_D;
|
||||
io.piod_len = size;
|
||||
|
||||
pid_t pid = current_process ()->pid;
|
||||
|
||||
int bytes_read = 0;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
/* Zero length write always succeeds. */
|
||||
return 0;
|
||||
}
|
||||
do
|
||||
{
|
||||
io.piod_offs = (void *)(memaddr + bytes_read);
|
||||
io.piod_addr = myaddr + bytes_read;
|
||||
|
||||
int rv = ptrace (PT_IO, pid, &io, 0);
|
||||
if (rv == -1)
|
||||
return errno;
|
||||
if (io.piod_len == 0)
|
||||
return 0;
|
||||
|
||||
bytes_read += io.piod_len;
|
||||
io.piod_len = size - bytes_read;
|
||||
}
|
||||
while (bytes_read < size);
|
||||
|
||||
return 0;
|
||||
return netbsd_nat::read_memory (pid, myaddr, memaddr, size, nullptr);
|
||||
}
|
||||
|
||||
/* Implement the write_memory target_ops method. */
|
||||
@@ -594,37 +566,8 @@ int
|
||||
netbsd_process_target::write_memory (CORE_ADDR memaddr,
|
||||
const unsigned char *myaddr, int size)
|
||||
{
|
||||
struct ptrace_io_desc io;
|
||||
io.piod_op = PIOD_WRITE_D;
|
||||
io.piod_len = size;
|
||||
|
||||
pid_t pid = current_process ()->pid;
|
||||
|
||||
int bytes_written = 0;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
/* Zero length write always succeeds. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
io.piod_addr = (void *)(myaddr + bytes_written);
|
||||
io.piod_offs = (void *)(memaddr + bytes_written);
|
||||
|
||||
int rv = ptrace (PT_IO, pid, &io, 0);
|
||||
if (rv == -1)
|
||||
return errno;
|
||||
if (io.piod_len == 0)
|
||||
return 0;
|
||||
|
||||
bytes_written += io.piod_len;
|
||||
io.piod_len = size - bytes_written;
|
||||
}
|
||||
while (bytes_written < size);
|
||||
|
||||
return 0;
|
||||
return netbsd_nat::write_memory (pid, myaddr, memaddr, size, nullptr);
|
||||
}
|
||||
|
||||
/* Implement the request_interrupt target_ops method. */
|
||||
|
||||
Reference in New Issue
Block a user