* s390-nat.c (s390_insert_watchpoint): Add missing argument.
[external/binutils.git] / gdb / s390-nat.c
1 /* S390 native-dependent code for GDB, the GNU debugger.
2    Copyright (C) 2001, 2003, 2004, 2005, 2006
3    Free Software Foundation, Inc
4
5    Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6    for IBM Deutschland Entwicklung GmbH, IBM Corporation.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor,
23    Boston, MA 02110-1301, USA.  */
24
25 #include "defs.h"
26 #include "tm.h"
27 #include "regcache.h"
28 #include "inferior.h"
29 #include "target.h"
30 #include "linux-nat.h"
31
32 #include "s390-tdep.h"
33
34 #include <asm/ptrace.h>
35 #include <sys/ptrace.h>
36 #include <asm/types.h>
37 #include <sys/procfs.h>
38 #include <sys/ucontext.h>
39
40
41 /* Map registers to gregset/ptrace offsets.
42    These arrays are defined in s390-tdep.c.  */
43
44 #ifdef __s390x__
45 #define regmap_gregset s390x_regmap_gregset
46 #else
47 #define regmap_gregset s390_regmap_gregset
48 #endif
49
50 #define regmap_fpregset s390_regmap_fpregset
51
52 /* When debugging a 32-bit executable running under a 64-bit kernel,
53    we have to fix up the 64-bit registers we get from the kernel
54    to make them look like 32-bit registers.  */
55 #ifdef __s390x__
56 #define SUBOFF(i) \
57         ((TARGET_PTR_BIT == 32 \
58           && ((i) == S390_PSWA_REGNUM \
59               || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
60 #else
61 #define SUBOFF(i) 0
62 #endif
63
64
65 /* Fill GDB's register array with the general-purpose register values
66    in *REGP.  */
67 void
68 supply_gregset (gregset_t *regp)
69 {
70   int i;
71   for (i = 0; i < S390_NUM_REGS; i++)
72     if (regmap_gregset[i] != -1)
73       regcache_raw_supply (current_regcache, i, 
74                            (char *)regp + regmap_gregset[i] + SUBOFF (i));
75 }
76
77 /* Fill register REGNO (if it is a general-purpose register) in
78    *REGP with the value in GDB's register array.  If REGNO is -1,
79    do this for all registers.  */
80 void
81 fill_gregset (gregset_t *regp, int regno)
82 {
83   int i;
84   for (i = 0; i < S390_NUM_REGS; i++)
85     if (regmap_gregset[i] != -1)
86       if (regno == -1 || regno == i)
87         regcache_raw_collect (current_regcache, i, 
88                               (char *)regp + regmap_gregset[i] + SUBOFF (i));
89 }
90
91 /* Fill GDB's register array with the floating-point register values
92    in *REGP.  */
93 void
94 supply_fpregset (fpregset_t *regp)
95 {
96   int i;
97   for (i = 0; i < S390_NUM_REGS; i++)
98     if (regmap_fpregset[i] != -1)
99       regcache_raw_supply (current_regcache, i,
100                            ((char *)regp) + regmap_fpregset[i]);
101 }
102
103 /* Fill register REGNO (if it is a general-purpose register) in
104    *REGP with the value in GDB's register array.  If REGNO is -1,
105    do this for all registers.  */
106 void
107 fill_fpregset (fpregset_t *regp, int regno)
108 {
109   int i;
110   for (i = 0; i < S390_NUM_REGS; i++)
111     if (regmap_fpregset[i] != -1)
112       if (regno == -1 || regno == i)
113         regcache_raw_collect (current_regcache, i, 
114                               ((char *)regp) + regmap_fpregset[i]);
115 }
116
117 /* Find the TID for the current inferior thread to use with ptrace.  */
118 static int
119 s390_inferior_tid (void)
120 {
121   /* GNU/Linux LWP ID's are process ID's.  */
122   int tid = TIDGET (inferior_ptid);
123   if (tid == 0)
124     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
125
126   return tid;
127 }
128
129 /* Fetch all general-purpose registers from process/thread TID and
130    store their values in GDB's register cache.  */
131 static void
132 fetch_regs (int tid)
133 {
134   gregset_t regs;
135   ptrace_area parea;
136
137   parea.len = sizeof (regs);
138   parea.process_addr = (addr_t) &regs;
139   parea.kernel_addr = offsetof (struct user_regs_struct, psw);
140   if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
141     perror_with_name (_("Couldn't get registers"));
142
143   supply_gregset (&regs);
144 }
145
146 /* Store all valid general-purpose registers in GDB's register cache
147    into the process/thread specified by TID.  */
148 static void
149 store_regs (int tid, int regnum)
150 {
151   gregset_t regs;
152   ptrace_area parea;
153
154   parea.len = sizeof (regs);
155   parea.process_addr = (addr_t) &regs;
156   parea.kernel_addr = offsetof (struct user_regs_struct, psw);
157   if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
158     perror_with_name (_("Couldn't get registers"));
159
160   fill_gregset (&regs, regnum);
161
162   if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
163     perror_with_name (_("Couldn't write registers"));
164 }
165
166 /* Fetch all floating-point registers from process/thread TID and store
167    their values in GDB's register cache.  */
168 static void
169 fetch_fpregs (int tid)
170 {
171   fpregset_t fpregs;
172   ptrace_area parea;
173
174   parea.len = sizeof (fpregs);
175   parea.process_addr = (addr_t) &fpregs;
176   parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
177   if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
178     perror_with_name (_("Couldn't get floating point status"));
179
180   supply_fpregset (&fpregs);
181 }
182
183 /* Store all valid floating-point registers in GDB's register cache
184    into the process/thread specified by TID.  */
185 static void
186 store_fpregs (int tid, int regnum)
187 {
188   fpregset_t fpregs;
189   ptrace_area parea;
190
191   parea.len = sizeof (fpregs);
192   parea.process_addr = (addr_t) &fpregs;
193   parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
194   if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
195     perror_with_name (_("Couldn't get floating point status"));
196
197   fill_fpregset (&fpregs, regnum);
198
199   if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
200     perror_with_name (_("Couldn't write floating point status"));
201 }
202
203 /* Fetch register REGNUM from the child process.  If REGNUM is -1, do
204    this for all registers.  */
205 static void
206 s390_linux_fetch_inferior_registers (int regnum)
207 {
208   int tid = s390_inferior_tid ();
209
210   if (regnum == -1 
211       || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
212     fetch_regs (tid);
213
214   if (regnum == -1 
215       || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
216     fetch_fpregs (tid);
217 }
218
219 /* Store register REGNUM back into the child process.  If REGNUM is
220    -1, do this for all registers.  */
221 static void
222 s390_linux_store_inferior_registers (int regnum)
223 {
224   int tid = s390_inferior_tid ();
225
226   if (regnum == -1 
227       || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
228     store_regs (tid, regnum);
229
230   if (regnum == -1 
231       || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
232     store_fpregs (tid, regnum);
233 }
234
235
236 /* Hardware-assisted watchpoint handling.  */
237
238 /* We maintain a list of all currently active watchpoints in order
239    to properly handle watchpoint removal.
240
241    The only thing we actually need is the total address space area
242    spanned by the watchpoints.  */
243
244 struct watch_area
245 {
246   struct watch_area *next;
247   CORE_ADDR lo_addr;
248   CORE_ADDR hi_addr;
249 };
250
251 static struct watch_area *watch_base = NULL;
252
253 static int
254 s390_stopped_by_watchpoint (void)
255 {
256   per_lowcore_bits per_lowcore;
257   ptrace_area parea;
258
259   /* Speed up common case.  */
260   if (!watch_base)
261     return 0;
262
263   parea.len = sizeof (per_lowcore);
264   parea.process_addr = (addr_t) & per_lowcore;
265   parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
266   if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
267     perror_with_name (_("Couldn't retrieve watchpoint status"));
268
269   return per_lowcore.perc_storage_alteration == 1
270          && per_lowcore.perc_store_real_address == 0;
271 }
272
273 static void
274 s390_fix_watch_points (void)
275 {
276   int tid = s390_inferior_tid ();
277
278   per_struct per_info;
279   ptrace_area parea;
280
281   CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
282   struct watch_area *area;
283
284   for (area = watch_base; area; area = area->next)
285     {
286       watch_lo_addr = min (watch_lo_addr, area->lo_addr);
287       watch_hi_addr = max (watch_hi_addr, area->hi_addr);
288     }
289
290   parea.len = sizeof (per_info);
291   parea.process_addr = (addr_t) & per_info;
292   parea.kernel_addr = offsetof (struct user_regs_struct, per_info);
293   if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
294     perror_with_name (_("Couldn't retrieve watchpoint status"));
295
296   if (watch_base)
297     {
298       per_info.control_regs.bits.em_storage_alteration = 1;
299       per_info.control_regs.bits.storage_alt_space_ctl = 1;
300     }
301   else
302     {
303       per_info.control_regs.bits.em_storage_alteration = 0;
304       per_info.control_regs.bits.storage_alt_space_ctl = 0;
305     }
306   per_info.starting_addr = watch_lo_addr;
307   per_info.ending_addr = watch_hi_addr;
308
309   if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
310     perror_with_name (_("Couldn't modify watchpoint status"));
311 }
312
313 static int
314 s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
315 {
316   struct watch_area *area = xmalloc (sizeof (struct watch_area));
317   if (!area)
318     return -1; 
319
320   area->lo_addr = addr;
321   area->hi_addr = addr + len - 1;
322  
323   area->next = watch_base;
324   watch_base = area;
325
326   s390_fix_watch_points ();
327   return 0;
328 }
329
330 static int
331 s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
332 {
333   struct watch_area *area, **parea;
334
335   for (parea = &watch_base; *parea; parea = &(*parea)->next)
336     if ((*parea)->lo_addr == addr
337         && (*parea)->hi_addr == addr + len - 1)
338       break;
339
340   if (!*parea)
341     {
342       fprintf_unfiltered (gdb_stderr,
343                           "Attempt to remove nonexistent watchpoint.\n");
344       return -1;
345     }
346
347   area = *parea;
348   *parea = area->next;
349   xfree (area);
350
351   s390_fix_watch_points ();
352   return 0;
353 }
354
355 static int
356 s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
357 {
358   return 1;
359 }
360
361 static int
362 s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
363 {
364   return 1;
365 }
366
367
368 void _initialize_s390_nat (void);
369
370 void
371 _initialize_s390_nat (void)
372 {
373   struct target_ops *t;
374
375   /* Fill in the generic GNU/Linux methods.  */
376   t = linux_target ();
377
378   /* Add our register access methods.  */
379   t->to_fetch_registers = s390_linux_fetch_inferior_registers;
380   t->to_store_registers = s390_linux_store_inferior_registers;
381
382   /* Add our watchpoint methods.  */
383   t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
384   t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
385   t->to_have_continuable_watchpoint = 1;
386   t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
387   t->to_insert_watchpoint = s390_insert_watchpoint;
388   t->to_remove_watchpoint = s390_remove_watchpoint;
389
390   /* Register the target.  */
391   linux_nat_add_target (t);
392 }