* config/tc-arm.c (arm_cpus): Add entry for ARM Cortex-M0.
[binutils-gdb.git] / gdb / s390-nat.c
bloba6528e736461753770cf859a36b5b0a3bf738b2e
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 3 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, see <http://www.gnu.org/licenses/>. */
23 #include "defs.h"
24 #include "regcache.h"
25 #include "inferior.h"
26 #include "target.h"
27 #include "linux-nat.h"
29 #include "s390-tdep.h"
31 #include <asm/ptrace.h>
32 #include <sys/ptrace.h>
33 #include <asm/types.h>
34 #include <sys/procfs.h>
35 #include <sys/ucontext.h>
38 /* Map registers to gregset/ptrace offsets.
39 These arrays are defined in s390-tdep.c. */
41 #ifdef __s390x__
42 #define regmap_gregset s390x_regmap_gregset
43 #else
44 #define regmap_gregset s390_regmap_gregset
45 #endif
47 #define regmap_fpregset s390_regmap_fpregset
49 /* When debugging a 32-bit executable running under a 64-bit kernel,
50 we have to fix up the 64-bit registers we get from the kernel
51 to make them look like 32-bit registers. */
52 #ifdef __s390x__
53 #define SUBOFF(gdbarch, i) \
54 ((gdbarch_ptr_bit (gdbarch) == 32 \
55 && ((i) == S390_PSWA_REGNUM \
56 || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
57 #else
58 #define SUBOFF(gdbarch, i) 0
59 #endif
62 /* Fill GDB's register array with the general-purpose register values
63 in *REGP. */
64 void
65 supply_gregset (struct regcache *regcache, const gregset_t *regp)
67 struct gdbarch *gdbarch = get_regcache_arch (regcache);
68 int i;
69 for (i = 0; i < S390_NUM_REGS; i++)
70 if (regmap_gregset[i] != -1)
71 regcache_raw_supply (regcache, i,
72 (const char *)regp + regmap_gregset[i]
73 + SUBOFF (gdbarch, i));
76 /* Fill register REGNO (if it is a general-purpose register) in
77 *REGP with the value in GDB's register array. If REGNO is -1,
78 do this for all registers. */
79 void
80 fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
82 struct gdbarch *gdbarch = get_regcache_arch (regcache);
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 (regcache, i,
88 (char *)regp + regmap_gregset[i]
89 + SUBOFF (gdbarch, i));
92 /* Fill GDB's register array with the floating-point register values
93 in *REGP. */
94 void
95 supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
97 int i;
98 for (i = 0; i < S390_NUM_REGS; i++)
99 if (regmap_fpregset[i] != -1)
100 regcache_raw_supply (regcache, i,
101 (const char *)regp + regmap_fpregset[i]);
104 /* Fill register REGNO (if it is a general-purpose register) in
105 *REGP with the value in GDB's register array. If REGNO is -1,
106 do this for all registers. */
107 void
108 fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
110 int i;
111 for (i = 0; i < S390_NUM_REGS; i++)
112 if (regmap_fpregset[i] != -1)
113 if (regno == -1 || regno == i)
114 regcache_raw_collect (regcache, i,
115 (char *)regp + regmap_fpregset[i]);
118 /* Find the TID for the current inferior thread to use with ptrace. */
119 static int
120 s390_inferior_tid (void)
122 /* GNU/Linux LWP ID's are process ID's. */
123 int tid = TIDGET (inferior_ptid);
124 if (tid == 0)
125 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
127 return tid;
130 /* Fetch all general-purpose registers from process/thread TID and
131 store their values in GDB's register cache. */
132 static void
133 fetch_regs (struct regcache *regcache, int tid)
135 gregset_t regs;
136 ptrace_area parea;
138 parea.len = sizeof (regs);
139 parea.process_addr = (addr_t) &regs;
140 parea.kernel_addr = offsetof (struct user_regs_struct, psw);
141 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
142 perror_with_name (_("Couldn't get registers"));
144 supply_gregset (regcache, (const gregset_t *) &regs);
147 /* Store all valid general-purpose registers in GDB's register cache
148 into the process/thread specified by TID. */
149 static void
150 store_regs (const struct regcache *regcache, int tid, int regnum)
152 gregset_t regs;
153 ptrace_area parea;
155 parea.len = sizeof (regs);
156 parea.process_addr = (addr_t) &regs;
157 parea.kernel_addr = offsetof (struct user_regs_struct, psw);
158 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
159 perror_with_name (_("Couldn't get registers"));
161 fill_gregset (regcache, &regs, regnum);
163 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
164 perror_with_name (_("Couldn't write registers"));
167 /* Fetch all floating-point registers from process/thread TID and store
168 their values in GDB's register cache. */
169 static void
170 fetch_fpregs (struct regcache *regcache, int tid)
172 fpregset_t fpregs;
173 ptrace_area parea;
175 parea.len = sizeof (fpregs);
176 parea.process_addr = (addr_t) &fpregs;
177 parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
178 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
179 perror_with_name (_("Couldn't get floating point status"));
181 supply_fpregset (regcache, (const fpregset_t *) &fpregs);
184 /* Store all valid floating-point registers in GDB's register cache
185 into the process/thread specified by TID. */
186 static void
187 store_fpregs (const struct regcache *regcache, int tid, int regnum)
189 fpregset_t fpregs;
190 ptrace_area parea;
192 parea.len = sizeof (fpregs);
193 parea.process_addr = (addr_t) &fpregs;
194 parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
195 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
196 perror_with_name (_("Couldn't get floating point status"));
198 fill_fpregset (regcache, &fpregs, regnum);
200 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
201 perror_with_name (_("Couldn't write floating point status"));
204 /* Fetch register REGNUM from the child process. If REGNUM is -1, do
205 this for all registers. */
206 static void
207 s390_linux_fetch_inferior_registers (struct target_ops *ops,
208 struct regcache *regcache, int regnum)
210 int tid = s390_inferior_tid ();
212 if (regnum == -1
213 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
214 fetch_regs (regcache, tid);
216 if (regnum == -1
217 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
218 fetch_fpregs (regcache, tid);
221 /* Store register REGNUM back into the child process. If REGNUM is
222 -1, do this for all registers. */
223 static void
224 s390_linux_store_inferior_registers (struct target_ops *ops,
225 struct regcache *regcache, int regnum)
227 int tid = s390_inferior_tid ();
229 if (regnum == -1
230 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
231 store_regs (regcache, tid, regnum);
233 if (regnum == -1
234 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
235 store_fpregs (regcache, tid, regnum);
239 /* Hardware-assisted watchpoint handling. */
241 /* We maintain a list of all currently active watchpoints in order
242 to properly handle watchpoint removal.
244 The only thing we actually need is the total address space area
245 spanned by the watchpoints. */
247 struct watch_area
249 struct watch_area *next;
250 CORE_ADDR lo_addr;
251 CORE_ADDR hi_addr;
254 static struct watch_area *watch_base = NULL;
256 static int
257 s390_stopped_by_watchpoint (void)
259 per_lowcore_bits per_lowcore;
260 ptrace_area parea;
261 int result;
263 /* Speed up common case. */
264 if (!watch_base)
265 return 0;
267 parea.len = sizeof (per_lowcore);
268 parea.process_addr = (addr_t) & per_lowcore;
269 parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
270 if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
271 perror_with_name (_("Couldn't retrieve watchpoint status"));
273 result = (per_lowcore.perc_storage_alteration == 1
274 && per_lowcore.perc_store_real_address == 0);
276 if (result)
278 /* Do not report this watchpoint again. */
279 memset (&per_lowcore, 0, sizeof (per_lowcore));
280 if (ptrace (PTRACE_POKEUSR_AREA, s390_inferior_tid (), &parea) < 0)
281 perror_with_name (_("Couldn't clear watchpoint status"));
284 return result;
287 static void
288 s390_fix_watch_points (ptid_t ptid)
290 int tid;
292 per_struct per_info;
293 ptrace_area parea;
295 CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
296 struct watch_area *area;
298 tid = TIDGET (ptid);
299 if (tid == 0)
300 tid = PIDGET (ptid);
302 for (area = watch_base; area; area = area->next)
304 watch_lo_addr = min (watch_lo_addr, area->lo_addr);
305 watch_hi_addr = max (watch_hi_addr, area->hi_addr);
308 parea.len = sizeof (per_info);
309 parea.process_addr = (addr_t) & per_info;
310 parea.kernel_addr = offsetof (struct user_regs_struct, per_info);
311 if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
312 perror_with_name (_("Couldn't retrieve watchpoint status"));
314 if (watch_base)
316 per_info.control_regs.bits.em_storage_alteration = 1;
317 per_info.control_regs.bits.storage_alt_space_ctl = 1;
319 else
321 per_info.control_regs.bits.em_storage_alteration = 0;
322 per_info.control_regs.bits.storage_alt_space_ctl = 0;
324 per_info.starting_addr = watch_lo_addr;
325 per_info.ending_addr = watch_hi_addr;
327 if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
328 perror_with_name (_("Couldn't modify watchpoint status"));
331 static int
332 s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
334 struct lwp_info *lp;
335 ptid_t ptid;
336 struct watch_area *area = xmalloc (sizeof (struct watch_area));
338 if (!area)
339 return -1;
341 area->lo_addr = addr;
342 area->hi_addr = addr + len - 1;
344 area->next = watch_base;
345 watch_base = area;
347 ALL_LWPS (lp, ptid)
348 s390_fix_watch_points (ptid);
349 return 0;
352 static int
353 s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
355 struct lwp_info *lp;
356 ptid_t ptid;
357 struct watch_area *area, **parea;
359 for (parea = &watch_base; *parea; parea = &(*parea)->next)
360 if ((*parea)->lo_addr == addr
361 && (*parea)->hi_addr == addr + len - 1)
362 break;
364 if (!*parea)
366 fprintf_unfiltered (gdb_stderr,
367 "Attempt to remove nonexistent watchpoint.\n");
368 return -1;
371 area = *parea;
372 *parea = area->next;
373 xfree (area);
375 ALL_LWPS (lp, ptid)
376 s390_fix_watch_points (ptid);
377 return 0;
380 static int
381 s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
383 return 1;
386 static int
387 s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
389 return 1;
393 void _initialize_s390_nat (void);
395 void
396 _initialize_s390_nat (void)
398 struct target_ops *t;
400 /* Fill in the generic GNU/Linux methods. */
401 t = linux_target ();
403 /* Add our register access methods. */
404 t->to_fetch_registers = s390_linux_fetch_inferior_registers;
405 t->to_store_registers = s390_linux_store_inferior_registers;
407 /* Add our watchpoint methods. */
408 t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
409 t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
410 t->to_have_continuable_watchpoint = 1;
411 t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
412 t->to_insert_watchpoint = s390_insert_watchpoint;
413 t->to_remove_watchpoint = s390_remove_watchpoint;
415 /* Register the target. */
416 linux_nat_add_target (t);
417 linux_nat_set_new_thread (t, s390_fix_watch_points);