From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10945 invoked by alias); 24 Feb 2008 14:51:00 -0000 Received: (qmail 10933 invoked by uid 22791); 24 Feb 2008 14:50:58 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 24 Feb 2008 14:50:41 +0000 Received: (qmail 18315 invoked from network); 24 Feb 2008 14:50:38 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 24 Feb 2008 14:50:38 -0000 From: Vladimir Prus Date: Sun, 24 Feb 2008 14:58:00 -0000 Subject: [RFA] Try2: Ignore breakpoints when reading memory. To: gdb-patches@sources.redhat.com X-TUID: 1b901f9fb44272d0 X-Length: 10008 X-UID: 135 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200802241750.41264.vladimir@codesourcery.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-02/txt/msg00366.txt.bz2 This a second attempt at making gdb always ignore any memory breakpoints that are inserted and show the original memory content. This patch is the immediate prerequisite for the patch that makes breakpoints always inserted. Unlike the previous patch, there's a mechanism to: 1. Control the new behaviour from command line. 2. Temporary force specific behavior, if some code needs it. OK? - Volodya * breakpoint.h (breakpoint_restore_shadows): New declaration. * breakpoint.c (breakpoint_restore_shadows): New. (read_memory_nobpt): Use breakpoint_restore_shadows. * target.c (memory_xfer_partial): Call breakpoint_restore_shadows. (restore_show_memory_breakpoints) (make_show_memory_beakpoints_cleanup): New. (show_memory_breakpoints, show_show_memory_breakpoints): New. (initialize_targets): Register set/show 'show-memory-breakpoints'. * target.h (make_show_memory_beakpoints_cleanup): Declare. * ppc-linux-tdep.c (ppc_linux_memory_remove_breakpoint): Make sure we see memory breakpoints when checking if breakpoint is still there. --- gdb/breakpoint.c | 83 +++++++++++++++++++++---------------------------- gdb/breakpoint.h | 4 ++ gdb/ppc-linux-tdep.c | 4 ++ gdb/target.c | 52 +++++++++++++++++++++++++++++-- gdb/target.h | 5 +++ 5 files changed, 98 insertions(+), 50 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index dca4ca1..9a7800c 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -712,14 +712,26 @@ commands_from_control_command (char *arg, struct command_line *cmd) int read_memory_nobpt (CORE_ADDR memaddr, gdb_byte *myaddr, unsigned len) { - int status; - const struct bp_location *b; + int status = 0; + /* Make sure the following read will ignore memory breakpoints. */ + struct cleanup *cleanup = make_show_memory_breakpoints_cleanup (0); + + status = target_read_memory (memaddr, myaddr, len); + + do_cleanups (cleanup); + + return status; +} + +void +breakpoint_restore_shadows (gdb_byte *buf, + ULONGEST memaddr, + LONGEST len) +{ + struct bp_location *b; CORE_ADDR bp_addr = 0; int bp_size = 0; - - if (gdbarch_breakpoint_from_pc (current_gdbarch, &bp_addr, &bp_size) == NULL) - /* No breakpoints on this machine. */ - return target_read_memory (memaddr, myaddr, len); + int bptoffset = 0; ALL_BP_LOCATIONS (b) { @@ -738,60 +750,37 @@ read_memory_nobpt (CORE_ADDR memaddr, gdb_byte *myaddr, unsigned len) if (bp_size == 0) /* bp isn't valid, or doesn't shadow memory. */ continue; + if (bp_addr + bp_size <= memaddr) /* The breakpoint is entirely before the chunk of memory we are reading. */ continue; + if (bp_addr >= memaddr + len) /* The breakpoint is entirely after the chunk of memory we are reading. */ continue; - /* Copy the breakpoint from the shadow contents, and recurse for - the things before and after. */ - { - /* Offset within shadow_contents. */ - int bptoffset = 0; - - if (bp_addr < memaddr) - { - /* Only copy the second part of the breakpoint. */ - bp_size -= memaddr - bp_addr; - bptoffset = memaddr - bp_addr; - bp_addr = memaddr; - } - if (bp_addr + bp_size > memaddr + len) - { - /* Only copy the first part of the breakpoint. */ - bp_size -= (bp_addr + bp_size) - (memaddr + len); - } - - memcpy (myaddr + bp_addr - memaddr, - b->target_info.shadow_contents + bptoffset, bp_size); + /* Offset within shadow_contents. */ + if (bp_addr < memaddr) + { + /* Only copy the second part of the breakpoint. */ + bp_size -= memaddr - bp_addr; + bptoffset = memaddr - bp_addr; + bp_addr = memaddr; + } - if (bp_addr > memaddr) - { - /* Copy the section of memory before the breakpoint. */ - status = read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr); - if (status != 0) - return status; - } + if (bp_addr + bp_size > memaddr + len) + { + /* Only copy the first part of the breakpoint. */ + bp_size -= (bp_addr + bp_size) - (memaddr + len); + } - if (bp_addr + bp_size < memaddr + len) - { - /* Copy the section of memory after the breakpoint. */ - status = read_memory_nobpt (bp_addr + bp_size, - myaddr + bp_addr + bp_size - memaddr, - memaddr + len - (bp_addr + bp_size)); - if (status != 0) - return status; - } - return 0; - } + memcpy (buf + bp_addr - memaddr, + b->target_info.shadow_contents + bptoffset, bp_size); } - /* Nothing overlaps. Just call read_memory_noerr. */ - return target_read_memory (memaddr, myaddr, len); } + /* A wrapper function for inserting catchpoints. */ diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 41730c0..159c406 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -854,4 +854,8 @@ extern int deprecated_remove_raw_breakpoint (void *); target. */ int watchpoints_triggered (struct target_waitstatus *); +extern void breakpoint_restore_shadows (gdb_byte *buf, + ULONGEST memaddr, + LONGEST len); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 4b35f7f..bf084f5 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -280,12 +280,15 @@ ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt) int val; int bplen; gdb_byte old_contents[BREAKPOINT_MAX]; + struct cleanup *cleanup; /* Determine appropriate breakpoint contents and size for this address. */ bp = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &bplen); if (bp == NULL) error (_("Software breakpoints not implemented for this target.")); + /* Make sure we see the memory breakpoints. */ + cleanup = make_show_memory_breakpoints_cleanup (1); val = target_read_memory (addr, old_contents, bplen); /* If our breakpoint is no longer at the address, this means that the @@ -294,6 +297,7 @@ ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt) if (val == 0 && memcmp (bp, old_contents, bplen) == 0) val = target_write_memory (addr, bp_tgt->shadow_contents, bplen); + do_cleanups (cleanup); return val; } diff --git a/gdb/target.c b/gdb/target.c index 87ddf24..32271eb 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -203,6 +203,18 @@ int attach_flag; static int trust_readonly = 0; +/* Nonzero if we should show true memory content including + memory breakpoint inserted by gdb. */ + +static int show_memory_breakpoints = 0; + +static void +show_show_memory_breakpoints (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Memory breakpoints show mode is %s.\n"), value); +} + /* Non-zero if we want to see trace of target level stuff. */ static int targetdebug = 0; @@ -1064,7 +1076,11 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf if (res <= 0) return -1; else - return res; + { + if (readbuf && !show_memory_breakpoints) + breakpoint_restore_shadows (readbuf, memaddr, reg_len); + return res; + } } /* If none of those methods found the memory we wanted, fall back @@ -1082,22 +1098,40 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL, readbuf, writebuf, memaddr, reg_len); if (res > 0) - return res; + break; /* We want to continue past core files to executables, but not past a running target's memory. */ if (ops->to_has_all_memory) - return res; + break; ops = ops->beneath; } while (ops != NULL); + if (readbuf && !show_memory_breakpoints) + breakpoint_restore_shadows (readbuf, memaddr, reg_len); + /* If we still haven't got anything, return the last error. We give up. */ return res; } +static void +restore_show_memory_breakpoints (void *arg) +{ + show_memory_breakpoints = (int)arg; +} + +struct cleanup * +make_show_memory_breakpoints_cleanup (int show) +{ + int current = show_memory_breakpoints; + show_memory_breakpoints = show; + + return make_cleanup (restore_show_memory_breakpoints, (void *)current); +} + static LONGEST target_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, @@ -2798,6 +2832,18 @@ result in significant performance improvement for remote targets."), show_trust_readonly, &setlist, &showlist); + add_setshow_boolean_cmd ("show-memory-breakpoints", class_support, + &show_memory_breakpoints, _("\ +Set mode for showing memory breakpoints."), _("\ +Show mode for showing memory breakpoints."), _("\ +When this mode is off (which is default), all memory reads will return\n\ +memory content as if no memory breakpoint were inserted. When this mode\n\ +if on, memory reads will see inserted memory breakpoints. In particular,\n\ +the disassemble command will show the breakpoint instructions."), + NULL, + show_show_memory_breakpoints, + &setlist, &showlist); + add_com ("monitor", class_obscure, do_monitor_command, _("Send a command to the remote monitor (remote targets only).")); diff --git a/gdb/target.h b/gdb/target.h index 3f332fd..dcc5cee 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1248,6 +1248,11 @@ extern enum target_signal target_signal_from_command (int); /* Any target can call this to switch to remote protocol (in remote.c). */ extern void push_remote_target (char *name, int from_tty); + +/* Set the show memory breakpoints mode to show, and installs a cleanup + to restore it back to the current value. */ +extern struct cleanup * make_show_memory_breakpoints_cleanup (int show); + /* Imported from machine dependent code */ -- 1.5.3.5