diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 682d8f9378..b31695438e 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,25 @@ +2010-08-26 Pedro Alves + + * linux-low.c (linux_prepare_to_access_memory): New. + (linux_unprepare_to_access_memory): New. + (linux_target_ops): Install them. + * server.c (read_memory): Rename to ... + (gdb_read_memory): ... this. Use + prepare_to_access_memory/prepare_to_access_memory. + (write_memory): Rename to ... + (gdb_write_memory): ... this. Use + prepare_to_access_memory/prepare_to_access_memory. + (handle_search_memory_1): Adjust. + (process_serial_event): Adjust. + * target.h (struct target_ops): New fields + prepare_to_access_memory and unprepare_to_access_memory. + (prepare_to_access_memory, unprepare_to_access_memory): New. + * linux-x86-low.c (x86_insert_point, x86_remove_point): Use + prepare_to_access_memory/prepare_to_access_memory. + * nto-low.c (nto_target_ops): Adjust. + * spu-low.c (spu_target_ops): Adjust. + * win32-low.c (win32_target_ops): Adjust. + 2010-08-26 Pedro Alves * Makefile.in (WARN_CFLAGS): Get it from configure. diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 62d1fb883c..7fa9336e8c 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -5005,6 +5005,25 @@ linux_unpause_all (int unfreeze) unstop_all_lwps (unfreeze, NULL); } +static int +linux_prepare_to_access_memory (void) +{ + /* Neither ptrace nor /proc/PID/mem allow accessing memory through a + running LWP. */ + if (non_stop) + linux_pause_all (1); + return 0; +} + +static void +linux_unprepare_to_access_memory (void) +{ + /* Neither ptrace nor /proc/PID/mem allow accessing memory through a + running LWP. */ + if (non_stop) + linux_unpause_all (1); +} + static int linux_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr, CORE_ADDR collector, @@ -5043,6 +5062,8 @@ static struct target_ops linux_target_ops = { linux_wait, linux_fetch_registers, linux_store_registers, + linux_prepare_to_access_memory, + linux_unprepare_to_access_memory, linux_read_memory, linux_write_memory, linux_look_up_symbols, diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 841f053613..b169b75543 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -546,7 +546,7 @@ i386_dr_low_get_status (void) return x86_linux_dr_get (ptid, DR_STATUS); } -/* Watchpoint support. */ +/* Breakpoint/Watchpoint support. */ static int x86_insert_point (char type, CORE_ADDR addr, int len) @@ -555,7 +555,16 @@ x86_insert_point (char type, CORE_ADDR addr, int len) switch (type) { case '0': - return set_gdb_breakpoint_at (addr); + { + int ret; + + ret = prepare_to_access_memory (); + if (ret) + return -1; + ret = set_gdb_breakpoint_at (addr); + unprepare_to_access_memory (); + return ret; + } case '2': case '3': case '4': @@ -574,7 +583,16 @@ x86_remove_point (char type, CORE_ADDR addr, int len) switch (type) { case '0': - return delete_gdb_breakpoint_at (addr); + { + int ret; + + ret = prepare_to_access_memory (); + if (ret) + return -1; + ret = delete_gdb_breakpoint_at (addr); + unprepare_to_access_memory (); + return ret; + } case '2': case '3': case '4': diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c index 17548a42e1..4502ee7f92 100644 --- a/gdb/gdbserver/nto-low.c +++ b/gdb/gdbserver/nto-low.c @@ -913,6 +913,8 @@ static struct target_ops nto_target_ops = { nto_wait, nto_fetch_registers, nto_store_registers, + NULL, /* prepare_to_access_memory */ + NULL, /* unprepare_to_access_memory */ nto_read_memory, nto_write_memory, NULL, /* nto_look_up_symbols */ diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 9e87b20ae4..5daf4b53f2 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -539,8 +539,10 @@ monitor_show_help (void) /* Read trace frame or inferior memory. */ static int -read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) +gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { + int ret; + if (current_traceframe >= 0) { ULONGEST nbytes; @@ -558,19 +560,36 @@ read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) /* (assume no half-trace half-real blocks for now) */ } - return read_inferior_memory (memaddr, myaddr, len); + ret = prepare_to_access_memory (); + if (ret == 0) + { + ret = read_inferior_memory (memaddr, myaddr, len); + unprepare_to_access_memory (); + } + + return ret; } /* Write trace frame or inferior memory. Actually, writing to trace frames is forbidden. */ static int -write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) +gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) { if (current_traceframe >= 0) return EIO; else - return write_inferior_memory (memaddr, myaddr, len); + { + int ret; + + ret = prepare_to_access_memory (); + if (ret == 0) + { + ret = write_inferior_memory (memaddr, myaddr, len); + unprepare_to_access_memory (); + } + return ret; + } } /* Subroutine of handle_search_memory to simplify it. */ @@ -584,7 +603,7 @@ handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len, { /* Prime the search buffer. */ - if (read_memory (start_addr, search_buf, search_buf_size) != 0) + if (gdb_read_memory (start_addr, search_buf, search_buf_size) != 0) { warning ("Unable to access target memory at 0x%lx, halting search.", (long) start_addr); @@ -635,8 +654,8 @@ handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len, ? search_space_len - keep_len : chunk_size); - if (read_memory (read_addr, search_buf + keep_len, - nr_to_read) != 0) + if (gdb_read_memory (read_addr, search_buf + keep_len, + nr_to_read) != 0) { warning ("Unable to access target memory at 0x%lx, halting search.", (long) read_addr); @@ -2924,7 +2943,7 @@ process_serial_event (void) case 'm': require_running (own_buf); decode_m_packet (&own_buf[1], &mem_addr, &len); - if (read_memory (mem_addr, mem_buf, len) == 0) + if (gdb_read_memory (mem_addr, mem_buf, len) == 0) convert_int_to_ascii (mem_buf, own_buf, len); else write_enn (own_buf); @@ -2932,7 +2951,7 @@ process_serial_event (void) case 'M': require_running (own_buf); decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf); - if (write_memory (mem_addr, mem_buf, len) == 0) + if (gdb_write_memory (mem_addr, mem_buf, len) == 0) write_ok (own_buf); else write_enn (own_buf); @@ -2941,7 +2960,7 @@ process_serial_event (void) require_running (own_buf); if (decode_X_packet (&own_buf[1], packet_len - 1, &mem_addr, &len, &mem_buf) < 0 - || write_memory (mem_addr, mem_buf, len) != 0) + || gdb_write_memory (mem_addr, mem_buf, len) != 0) write_enn (own_buf); else write_ok (own_buf); diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c index 2188d64ede..dc301b2ed1 100644 --- a/gdb/gdbserver/spu-low.c +++ b/gdb/gdbserver/spu-low.c @@ -653,6 +653,8 @@ static struct target_ops spu_target_ops = { spu_wait, spu_fetch_registers, spu_store_registers, + NULL, /* prepare_to_access_memory */ + NULL, /* unprepare_to_access_memory */ spu_read_memory, spu_write_memory, spu_look_up_symbols, diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 1f9f921c68..8126f857f7 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -181,6 +181,23 @@ struct target_ops void (*store_registers) (struct regcache *regcache, int regno); + /* Prepare to read or write memory from the inferior process. + Targets use this to do what is necessary to get the state of the + inferior such that it is possible to access memory. + + This should generally only be called from client facing routines, + such as gdb_read_memory/gdb_write_memory, or the insert_point + callbacks. + + Like `read_memory' and `write_memory' below, returns 0 on success + and errno on failure. */ + + int (*prepare_to_access_memory) (void); + + /* Undo the effects of prepare_to_access_memory. */ + + void (*unprepare_to_access_memory) (void); + /* Read memory from the inferior process. This should generally be called through read_inferior_memory, which handles breakpoint shadowing. @@ -469,6 +486,18 @@ int start_non_stop (int nonstop); ptid_t mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options, int connected_wait); +#define prepare_to_access_memory() \ + (the_target->prepare_to_access_memory \ + ? (*the_target->prepare_to_access_memory) () \ + : 0) + +#define unprepare_to_access_memory() \ + do \ + { \ + if (the_target->unprepare_to_access_memory) \ + (*the_target->unprepare_to_access_memory) (); \ + } while (0) + int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len); int write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr, diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c index 72184f304f..f64673849c 100644 --- a/gdb/gdbserver/win32-low.c +++ b/gdb/gdbserver/win32-low.c @@ -1781,6 +1781,8 @@ static struct target_ops win32_target_ops = { win32_wait, win32_fetch_inferior_registers, win32_store_inferior_registers, + NULL, /* prepare_to_access_memory */ + NULL, /* unprepare_to_access_memory */ win32_read_inferior_memory, win32_write_inferior_memory, NULL, /* lookup_symbols */