This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / gdb / mem-break.c
1 /* Simulate breakpoints by patching locations in the target system.
2    Copyright (C) 1990 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 GDB is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GDB is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GDB; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "param.h"
22
23 #ifdef BREAKPOINT
24 /* This file is only useful if BREAKPOINT is set.  If not, we punt.  */
25
26 #include <stdio.h>
27 #include "breakpoint.h"
28 #include "inferior.h"
29 #include "target.h"
30
31 /* This is the sequence of bytes we insert for a breakpoint.  On some
32    machines, breakpoints are handled by the target environment and we
33    don't have to worry about them here.  */
34
35 static char break_insn[] = BREAKPOINT;
36
37 /* This is only to check that BREAKPOINT fits in BREAKPOINT_MAX bytes.  */
38
39 static char check_break_insn_size[BREAKPOINT_MAX] = BREAKPOINT;
40
41 /* Insert a breakpoint on machines that don't have any better breakpoint
42    support.  We read the contents of the target location and stash it,
43    then overwrite it with a breakpoint instruction.  ADDR is the target
44    location in the target machine.  CONTENTS_CACHE is a pointer to 
45    memory allocated for saving the target contents.  It is guaranteed
46    by the caller to be long enough to save sizeof BREAKPOINT bytes.
47    FIXME: This size is target_arch dependent and should be available in
48    the target_arch transfer vector, if we ever have one...  */
49
50 int
51 memory_insert_breakpoint (addr, contents_cache)
52      CORE_ADDR addr;
53      char *contents_cache;
54 {
55   int val;
56
57   val = target_read_memory (addr, contents_cache, sizeof break_insn);
58
59   if (val == 0)
60     val = target_write_memory (addr, break_insn, sizeof break_insn);
61
62   return val;
63 }
64
65
66 int
67 memory_remove_breakpoint (addr, contents_cache)
68      CORE_ADDR addr;
69      char *contents_cache;
70 {
71   return target_write_memory (addr, contents_cache, sizeof break_insn);
72 }
73
74
75 #if 0
76 /* This should move back into breakpoint.c, sad to say.   Encapsulate
77     sizeof (BREAKPOINT) by export it as an int from mem-break.c.  */
78
79 /* Like target_read_memory() but if breakpoints are inserted, return
80    the shadow contents instead of the breakpoints themselves.  */
81 int
82 read_memory_nobpt (memaddr, myaddr, len)
83      CORE_ADDR memaddr;
84      char *myaddr;
85      unsigned len;
86 {
87   int status;
88   struct breakpoint *b;
89   ALL_BREAKPOINTS (b)
90     {
91       if (b->address == NULL || !b->inserted)
92         continue;
93       else if (b->address + sizeof (break_insn) <= memaddr)
94         /* The breakpoint is entirely before the chunk of memory
95            we are reading.  */
96         continue;
97       else if (b->address >= memaddr + len)
98         /* The breakpoint is entirely after the chunk of memory we
99            are reading.  */
100         continue;
101       else
102         {
103           /* Copy the breakpoint from the shadow contents, and recurse
104              for the things before and after.  */
105           
106           /* Addresses and length of the part of the breakpoint that
107              we need to copy.  */
108           CORE_ADDR membpt = b->address;
109           unsigned int bptlen = sizeof (break_insn);
110           /* Offset within shadow_contents.  */
111           int bptoffset = 0;
112           
113           if (membpt < memaddr)
114             {
115               /* Only copy the second part of the breakpoint.  */
116               bptlen -= memaddr - membpt;
117               bptoffset = memaddr - membpt;
118               membpt = memaddr;
119             }
120
121           if (membpt + bptlen > memaddr + len)
122             {
123               /* Only copy the first part of the breakpoint.  */
124               bptlen -= (membpt + bptlen) - (memaddr + len);
125             }
126
127           bcopy (b->shadow_contents + bptoffset,
128                  myaddr + membpt - memaddr, bptlen);
129
130           if (membpt > memaddr)
131             {
132               /* Copy the section of memory before the breakpoint.  */
133               status = read_memory_nobpt (memaddr, myaddr, membpt - memaddr);
134               if (status != 0)
135                 return status;
136             }
137
138           if (membpt + bptlen < memaddr + len)
139             {
140               /* Copy the section of memory after the breakpoint.  */
141               status = read_memory_nobpt
142                 (membpt + bptlen,
143                  myaddr + membpt + bptlen - memaddr,
144                  memaddr + len - (membpt + bptlen));
145               if (status != 0)
146                 return status;
147             }
148           return 0;
149         }
150     }
151   /* Nothing overlaps.  Just call read_memory_noerr.  */
152   return target_read_memory (memaddr, myaddr, len);
153 }
154 #endif /* 0 */
155
156 #else  /* BREAKPOINT */
157
158 char nogo[] = "Breakpoints not implemented for this target.";
159
160 int
161 memory_insert_breakpoint (addr, contents_cache)
162      CORE_ADDR addr;
163      char *contents_cache;
164 {
165   error (nogo);
166   return 0;     /* lint */
167 }
168
169 int
170 memory_remove_breakpoint (addr, contents_cache)
171      CORE_ADDR addr;
172      char *contents_cache;
173 {
174   error (nogo);
175   return 0;     /* lint */
176 }
177
178 #endif /* BREAKPOINT */