1/* Simulate breakpoints by patching locations in the target system, for GDB.
2
3   Copyright (C) 1990-2020 Free Software Foundation, Inc.
4
5   Contributed by Cygnus Support.  Written by John Gilmore.
6
7   This file is part of GDB.
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 3 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22#include "defs.h"
23#include "symtab.h"
24#include "breakpoint.h"
25#include "inferior.h"
26#include "target.h"
27#include "gdbarch.h"
28
29/* Insert a breakpoint on targets that don't have any better
30   breakpoint support.  We read the contents of the target location
31   and stash it, then overwrite it with a breakpoint instruction.
32   BP_TGT->placed_address is the target location in the target
33   machine.  BP_TGT->shadow_contents is some memory allocated for
34   saving the target contents.  It is guaranteed by the caller to be
35   long enough to save BREAKPOINT_LEN bytes (this is accomplished via
36   BREAKPOINT_MAX).  */
37
38int
39default_memory_insert_breakpoint (struct gdbarch *gdbarch,
40				  struct bp_target_info *bp_tgt)
41{
42  CORE_ADDR addr = bp_tgt->placed_address;
43  const unsigned char *bp;
44  gdb_byte *readbuf;
45  int bplen;
46  int val;
47
48  /* Determine appropriate breakpoint contents and size for this address.  */
49  bp = gdbarch_sw_breakpoint_from_kind (gdbarch, bp_tgt->kind, &bplen);
50
51  /* Save the memory contents in the shadow_contents buffer and then
52     write the breakpoint instruction.  */
53  readbuf = (gdb_byte *) alloca (bplen);
54  val = target_read_memory (addr, readbuf, bplen);
55  if (val == 0)
56    {
57      /* These must be set together, either before or after the shadow
58	 read, so that if we're "reinserting" a breakpoint that
59	 doesn't have a shadow yet, the breakpoint masking code inside
60	 target_read_memory doesn't mask out this breakpoint using an
61	 unfilled shadow buffer.  The core may be trying to reinsert a
62	 permanent breakpoint, for targets that support breakpoint
63	 conditions/commands on the target side for some types of
64	 breakpoints, such as target remote.  */
65      bp_tgt->shadow_len = bplen;
66      memcpy (bp_tgt->shadow_contents, readbuf, bplen);
67
68      val = target_write_raw_memory (addr, bp, bplen);
69    }
70
71  return val;
72}
73
74
75int
76default_memory_remove_breakpoint (struct gdbarch *gdbarch,
77				  struct bp_target_info *bp_tgt)
78{
79  int bplen;
80
81  gdbarch_sw_breakpoint_from_kind (gdbarch, bp_tgt->kind, &bplen);
82
83  return target_write_raw_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
84				  bplen);
85}
86
87
88int
89memory_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
90			  struct bp_target_info *bp_tgt)
91{
92  return gdbarch_memory_insert_breakpoint (gdbarch, bp_tgt);
93}
94
95int
96memory_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
97			  struct bp_target_info *bp_tgt,
98			  enum remove_bp_reason reason)
99{
100  return gdbarch_memory_remove_breakpoint (gdbarch, bp_tgt);
101}
102
103int
104memory_validate_breakpoint (struct gdbarch *gdbarch,
105			    struct bp_target_info *bp_tgt)
106{
107  CORE_ADDR addr = bp_tgt->placed_address;
108  const gdb_byte *bp;
109  int val;
110  int bplen;
111  gdb_byte cur_contents[BREAKPOINT_MAX];
112
113  /* Determine appropriate breakpoint contents and size for this
114     address.  */
115  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
116
117  if (bp == NULL)
118    return 0;
119
120  /* Make sure we see the memory breakpoints.  */
121  scoped_restore restore_memory
122    = make_scoped_restore_show_memory_breakpoints (1);
123  val = target_read_memory (addr, cur_contents, bplen);
124
125  /* If our breakpoint is no longer at the address, this means that
126     the program modified the code on us, so it is wrong to put back
127     the old value.  */
128  return (val == 0 && memcmp (bp, cur_contents, bplen) == 0);
129}
130