No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gdb6 / gdb / s390-nat.c
blob8a38eb112b7371391dcf5e590ed2b783f28d2934
1 /* S390 native-dependent code for GDB, the GNU debugger.
2 Copyright (C) 2001, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc
5 Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6 for IBM Deutschland Entwicklung GmbH, IBM Corporation.
8 This file is part of GDB.
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.
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.
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. */
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"
32 #include "s390-tdep.h"
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>
41 /* Map registers to gregset/ptrace offsets.
42 These arrays are defined in s390-tdep.c. */
44 #ifdef __s390x__
45 #define regmap_gregset s390x_regmap_gregset
46 #else
47 #define regmap_gregset s390_regmap_gregset
48 #endif
50 #define regmap_fpregset s390_regmap_fpregset
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
65 /* Fill GDB's register array with the general-purpose register values
66 in *REGP. */
67 void
68 supply_gregset (gregset_t *regp)
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));
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)
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));
91 /* Fill GDB's register array with the floating-point register values
92 in *REGP. */
93 void
94 supply_fpregset (fpregset_t *regp)
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]);
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)
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]);
117 /* Find the TID for the current inferior thread to use with ptrace. */
118 static int
119 s390_inferior_tid (void)
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. */
126 return tid;
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)
134 gregset_t regs;
135 ptrace_area parea;
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"));
143 supply_gregset (&regs);
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)
151 gregset_t regs;
152 ptrace_area parea;
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"));
160 fill_gregset (&regs, regnum);
162 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
163 perror_with_name (_("Couldn't write registers"));
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)
171 fpregset_t fpregs;
172 ptrace_area parea;
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"));
180 supply_fpregset (&fpregs);
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)
188 fpregset_t fpregs;
189 ptrace_area parea;
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"));
197 fill_fpregset (&fpregs, regnum);
199 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
200 perror_with_name (_("Couldn't write floating point status"));
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)
208 int tid = s390_inferior_tid ();
210 if (regnum == -1
211 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
212 fetch_regs (tid);
214 if (regnum == -1
215 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
216 fetch_fpregs (tid);
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)
224 int tid = s390_inferior_tid ();
226 if (regnum == -1
227 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
228 store_regs (tid, regnum);
230 if (regnum == -1
231 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
232 store_fpregs (tid, regnum);
236 /* Hardware-assisted watchpoint handling. */
238 /* We maintain a list of all currently active watchpoints in order
239 to properly handle watchpoint removal.
241 The only thing we actually need is the total address space area
242 spanned by the watchpoints. */
244 struct watch_area
246 struct watch_area *next;
247 CORE_ADDR lo_addr;
248 CORE_ADDR hi_addr;
251 static struct watch_area *watch_base = NULL;
253 static int
254 s390_stopped_by_watchpoint (void)
256 per_lowcore_bits per_lowcore;
257 ptrace_area parea;
259 /* Speed up common case. */
260 if (!watch_base)
261 return 0;
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"));
269 return per_lowcore.perc_storage_alteration == 1
270 && per_lowcore.perc_store_real_address == 0;
273 static void
274 s390_fix_watch_points (void)
276 int tid = s390_inferior_tid ();
278 per_struct per_info;
279 ptrace_area parea;
281 CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
282 struct watch_area *area;
284 for (area = watch_base; area; area = area->next)
286 watch_lo_addr = min (watch_lo_addr, area->lo_addr);
287 watch_hi_addr = max (watch_hi_addr, area->hi_addr);
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"));
296 if (watch_base)
298 per_info.control_regs.bits.em_storage_alteration = 1;
299 per_info.control_regs.bits.storage_alt_space_ctl = 1;
301 else
303 per_info.control_regs.bits.em_storage_alteration = 0;
304 per_info.control_regs.bits.storage_alt_space_ctl = 0;
306 per_info.starting_addr = watch_lo_addr;
307 per_info.ending_addr = watch_hi_addr;
309 if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
310 perror_with_name (_("Couldn't modify watchpoint status"));
313 static int
314 s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
316 struct watch_area *area = xmalloc (sizeof (struct watch_area));
317 if (!area)
318 return -1;
320 area->lo_addr = addr;
321 area->hi_addr = addr + len - 1;
323 area->next = watch_base;
324 watch_base = area;
326 s390_fix_watch_points ();
327 return 0;
330 static int
331 s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
333 struct watch_area *area, **parea;
335 for (parea = &watch_base; *parea; parea = &(*parea)->next)
336 if ((*parea)->lo_addr == addr
337 && (*parea)->hi_addr == addr + len - 1)
338 break;
340 if (!*parea)
342 fprintf_unfiltered (gdb_stderr,
343 "Attempt to remove nonexistent watchpoint.\n");
344 return -1;
347 area = *parea;
348 *parea = area->next;
349 xfree (area);
351 s390_fix_watch_points ();
352 return 0;
355 static int
356 s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
358 return 1;
361 static int
362 s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
364 return 1;
368 void _initialize_s390_nat (void);
370 void
371 _initialize_s390_nat (void)
373 struct target_ops *t;
375 /* Fill in the generic GNU/Linux methods. */
376 t = linux_target ();
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;
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;
390 /* Register the target. */
391 linux_nat_add_target (t);