2011-01-05 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / s390-nat.c
CommitLineData
5769d3cd 1/* S390 native-dependent code for GDB, the GNU debugger.
1e061d1a 2 Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2009
c9dd6fef 3 Free Software Foundation, Inc
d0f54f9d 4
5769d3cd
AC
5 Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6 for IBM Deutschland Entwicklung GmbH, IBM Corporation.
d0f54f9d 7
5769d3cd
AC
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
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
5769d3cd
AC
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
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
5769d3cd
AC
22
23#include "defs.h"
3ecc0ae2 24#include "regcache.h"
d0f54f9d 25#include "inferior.h"
10d6c8cd
DJ
26#include "target.h"
27#include "linux-nat.h"
7803799a 28#include "auxv.h"
d0f54f9d
JB
29
30#include "s390-tdep.h"
31
5769d3cd
AC
32#include <asm/ptrace.h>
33#include <sys/ptrace.h>
2d0c7962 34#include <asm/types.h>
5769d3cd 35#include <sys/procfs.h>
5769d3cd 36#include <sys/ucontext.h>
7803799a
UW
37#include <elf.h>
38
39#ifndef HWCAP_S390_HIGH_GPRS
40#define HWCAP_S390_HIGH_GPRS 512
41#endif
5769d3cd
AC
42
43
d0f54f9d
JB
44/* Map registers to gregset/ptrace offsets.
45 These arrays are defined in s390-tdep.c. */
46
47#ifdef __s390x__
48#define regmap_gregset s390x_regmap_gregset
5769d3cd 49#else
d0f54f9d 50#define regmap_gregset s390_regmap_gregset
5769d3cd 51#endif
d0f54f9d
JB
52
53#define regmap_fpregset s390_regmap_fpregset
54
9cbd5950
JB
55/* When debugging a 32-bit executable running under a 64-bit kernel,
56 we have to fix up the 64-bit registers we get from the kernel
57 to make them look like 32-bit registers. */
58#ifdef __s390x__
8fe9ea88
MD
59#define SUBOFF(gdbarch, i) \
60 ((gdbarch_ptr_bit (gdbarch) == 32 \
9cbd5950
JB
61 && ((i) == S390_PSWA_REGNUM \
62 || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
63#else
8fe9ea88 64#define SUBOFF(gdbarch, i) 0
9cbd5950
JB
65#endif
66
d0f54f9d
JB
67
68/* Fill GDB's register array with the general-purpose register values
69 in *REGP. */
70void
7f7fe91e 71supply_gregset (struct regcache *regcache, const gregset_t *regp)
d0f54f9d 72{
8fe9ea88 73 struct gdbarch *gdbarch = get_regcache_arch (regcache);
d0f54f9d
JB
74 int i;
75 for (i = 0; i < S390_NUM_REGS; i++)
76 if (regmap_gregset[i] != -1)
7f7fe91e 77 regcache_raw_supply (regcache, i,
8fe9ea88
MD
78 (const char *)regp + regmap_gregset[i]
79 + SUBOFF (gdbarch, i));
d0f54f9d
JB
80}
81
82/* Fill register REGNO (if it is a general-purpose register) in
83 *REGP with the value in GDB's register array. If REGNO is -1,
84 do this for all registers. */
85void
7f7fe91e 86fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
d0f54f9d 87{
8fe9ea88 88 struct gdbarch *gdbarch = get_regcache_arch (regcache);
d0f54f9d
JB
89 int i;
90 for (i = 0; i < S390_NUM_REGS; i++)
91 if (regmap_gregset[i] != -1)
92 if (regno == -1 || regno == i)
7f7fe91e 93 regcache_raw_collect (regcache, i,
8fe9ea88
MD
94 (char *)regp + regmap_gregset[i]
95 + SUBOFF (gdbarch, i));
d0f54f9d
JB
96}
97
98/* Fill GDB's register array with the floating-point register values
99 in *REGP. */
100void
7f7fe91e 101supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
d0f54f9d
JB
102{
103 int i;
104 for (i = 0; i < S390_NUM_REGS; i++)
105 if (regmap_fpregset[i] != -1)
7f7fe91e
UW
106 regcache_raw_supply (regcache, i,
107 (const char *)regp + regmap_fpregset[i]);
d0f54f9d
JB
108}
109
110/* Fill register REGNO (if it is a general-purpose register) in
111 *REGP with the value in GDB's register array. If REGNO is -1,
112 do this for all registers. */
113void
7f7fe91e 114fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
d0f54f9d
JB
115{
116 int i;
117 for (i = 0; i < S390_NUM_REGS; i++)
118 if (regmap_fpregset[i] != -1)
119 if (regno == -1 || regno == i)
7f7fe91e
UW
120 regcache_raw_collect (regcache, i,
121 (char *)regp + regmap_fpregset[i]);
d0f54f9d
JB
122}
123
124/* Find the TID for the current inferior thread to use with ptrace. */
125static int
126s390_inferior_tid (void)
127{
128 /* GNU/Linux LWP ID's are process ID's. */
129 int tid = TIDGET (inferior_ptid);
130 if (tid == 0)
131 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
132
133 return tid;
134}
135
136/* Fetch all general-purpose registers from process/thread TID and
137 store their values in GDB's register cache. */
138static void
56be3814 139fetch_regs (struct regcache *regcache, int tid)
d0f54f9d
JB
140{
141 gregset_t regs;
142 ptrace_area parea;
143
144 parea.len = sizeof (regs);
145 parea.process_addr = (addr_t) &regs;
146 parea.kernel_addr = offsetof (struct user_regs_struct, psw);
147 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
e2e0b3e5 148 perror_with_name (_("Couldn't get registers"));
d0f54f9d 149
56be3814 150 supply_gregset (regcache, (const gregset_t *) &regs);
d0f54f9d
JB
151}
152
153/* Store all valid general-purpose registers in GDB's register cache
154 into the process/thread specified by TID. */
155static void
56be3814 156store_regs (const struct regcache *regcache, int tid, int regnum)
d0f54f9d
JB
157{
158 gregset_t regs;
159 ptrace_area parea;
160
161 parea.len = sizeof (regs);
162 parea.process_addr = (addr_t) &regs;
163 parea.kernel_addr = offsetof (struct user_regs_struct, psw);
164 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
e2e0b3e5 165 perror_with_name (_("Couldn't get registers"));
d0f54f9d 166
56be3814 167 fill_gregset (regcache, &regs, regnum);
d0f54f9d
JB
168
169 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
e2e0b3e5 170 perror_with_name (_("Couldn't write registers"));
d0f54f9d
JB
171}
172
173/* Fetch all floating-point registers from process/thread TID and store
174 their values in GDB's register cache. */
175static void
56be3814 176fetch_fpregs (struct regcache *regcache, int tid)
d0f54f9d
JB
177{
178 fpregset_t fpregs;
179 ptrace_area parea;
180
181 parea.len = sizeof (fpregs);
182 parea.process_addr = (addr_t) &fpregs;
183 parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
184 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
e2e0b3e5 185 perror_with_name (_("Couldn't get floating point status"));
d0f54f9d 186
56be3814 187 supply_fpregset (regcache, (const fpregset_t *) &fpregs);
d0f54f9d
JB
188}
189
190/* Store all valid floating-point registers in GDB's register cache
191 into the process/thread specified by TID. */
192static void
56be3814 193store_fpregs (const struct regcache *regcache, int tid, int regnum)
d0f54f9d
JB
194{
195 fpregset_t fpregs;
196 ptrace_area parea;
197
198 parea.len = sizeof (fpregs);
199 parea.process_addr = (addr_t) &fpregs;
200 parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
201 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
e2e0b3e5 202 perror_with_name (_("Couldn't get floating point status"));
d0f54f9d 203
56be3814 204 fill_fpregset (regcache, &fpregs, regnum);
d0f54f9d
JB
205
206 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
e2e0b3e5 207 perror_with_name (_("Couldn't write floating point status"));
d0f54f9d
JB
208}
209
210/* Fetch register REGNUM from the child process. If REGNUM is -1, do
211 this for all registers. */
10d6c8cd 212static void
28439f5e
PA
213s390_linux_fetch_inferior_registers (struct target_ops *ops,
214 struct regcache *regcache, int regnum)
d0f54f9d
JB
215{
216 int tid = s390_inferior_tid ();
217
218 if (regnum == -1
219 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
56be3814 220 fetch_regs (regcache, tid);
d0f54f9d
JB
221
222 if (regnum == -1
223 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
56be3814 224 fetch_fpregs (regcache, tid);
d0f54f9d
JB
225}
226
227/* Store register REGNUM back into the child process. If REGNUM is
228 -1, do this for all registers. */
10d6c8cd 229static void
28439f5e
PA
230s390_linux_store_inferior_registers (struct target_ops *ops,
231 struct regcache *regcache, int regnum)
d0f54f9d
JB
232{
233 int tid = s390_inferior_tid ();
234
235 if (regnum == -1
236 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
56be3814 237 store_regs (regcache, tid, regnum);
d0f54f9d
JB
238
239 if (regnum == -1
240 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
56be3814 241 store_fpregs (regcache, tid, regnum);
5769d3cd
AC
242}
243
d0f54f9d 244
e1457d83
JB
245/* Hardware-assisted watchpoint handling. */
246
247/* We maintain a list of all currently active watchpoints in order
248 to properly handle watchpoint removal.
249
250 The only thing we actually need is the total address space area
251 spanned by the watchpoints. */
252
5769d3cd
AC
253struct watch_area
254{
e1457d83 255 struct watch_area *next;
5769d3cd
AC
256 CORE_ADDR lo_addr;
257 CORE_ADDR hi_addr;
258};
259
e1457d83 260static struct watch_area *watch_base = NULL;
5769d3cd 261
fd7979d1 262static int
e1457d83 263s390_stopped_by_watchpoint (void)
5769d3cd
AC
264{
265 per_lowcore_bits per_lowcore;
266 ptrace_area parea;
9f0bdab8 267 int result;
5769d3cd 268
e1457d83
JB
269 /* Speed up common case. */
270 if (!watch_base)
271 return 0;
272
5769d3cd
AC
273 parea.len = sizeof (per_lowcore);
274 parea.process_addr = (addr_t) & per_lowcore;
275 parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
e1457d83 276 if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
e2e0b3e5 277 perror_with_name (_("Couldn't retrieve watchpoint status"));
5769d3cd 278
9f0bdab8
DJ
279 result = (per_lowcore.perc_storage_alteration == 1
280 && per_lowcore.perc_store_real_address == 0);
281
282 if (result)
283 {
284 /* Do not report this watchpoint again. */
285 memset (&per_lowcore, 0, sizeof (per_lowcore));
286 if (ptrace (PTRACE_POKEUSR_AREA, s390_inferior_tid (), &parea) < 0)
287 perror_with_name (_("Couldn't clear watchpoint status"));
288 }
289
290 return result;
e1457d83 291}
5769d3cd 292
e1457d83 293static void
9f0bdab8 294s390_fix_watch_points (ptid_t ptid)
5769d3cd 295{
9f0bdab8 296 int tid;
e1457d83 297
5769d3cd
AC
298 per_struct per_info;
299 ptrace_area parea;
300
e1457d83
JB
301 CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
302 struct watch_area *area;
303
9f0bdab8
DJ
304 tid = TIDGET (ptid);
305 if (tid == 0)
306 tid = PIDGET (ptid);
307
e1457d83
JB
308 for (area = watch_base; area; area = area->next)
309 {
310 watch_lo_addr = min (watch_lo_addr, area->lo_addr);
311 watch_hi_addr = max (watch_hi_addr, area->hi_addr);
312 }
313
5769d3cd
AC
314 parea.len = sizeof (per_info);
315 parea.process_addr = (addr_t) & per_info;
e1457d83
JB
316 parea.kernel_addr = offsetof (struct user_regs_struct, per_info);
317 if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
e2e0b3e5 318 perror_with_name (_("Couldn't retrieve watchpoint status"));
e1457d83
JB
319
320 if (watch_base)
5769d3cd
AC
321 {
322 per_info.control_regs.bits.em_storage_alteration = 1;
323 per_info.control_regs.bits.storage_alt_space_ctl = 1;
324 }
325 else
326 {
327 per_info.control_regs.bits.em_storage_alteration = 0;
328 per_info.control_regs.bits.storage_alt_space_ctl = 0;
329 }
330 per_info.starting_addr = watch_lo_addr;
331 per_info.ending_addr = watch_hi_addr;
e1457d83
JB
332
333 if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
e2e0b3e5 334 perror_with_name (_("Couldn't modify watchpoint status"));
5769d3cd
AC
335}
336
fd7979d1 337static int
0cf6dd15
TJB
338s390_insert_watchpoint (CORE_ADDR addr, int len, int type,
339 struct expression *cond)
5769d3cd 340{
9f0bdab8
DJ
341 struct lwp_info *lp;
342 ptid_t ptid;
e1457d83 343 struct watch_area *area = xmalloc (sizeof (struct watch_area));
9f0bdab8 344
e1457d83
JB
345 if (!area)
346 return -1;
347
348 area->lo_addr = addr;
349 area->hi_addr = addr + len - 1;
350
351 area->next = watch_base;
352 watch_base = area;
353
9f0bdab8
DJ
354 ALL_LWPS (lp, ptid)
355 s390_fix_watch_points (ptid);
e1457d83 356 return 0;
5769d3cd
AC
357}
358
fd7979d1 359static int
0cf6dd15
TJB
360s390_remove_watchpoint (CORE_ADDR addr, int len, int type,
361 struct expression *cond)
5769d3cd 362{
9f0bdab8
DJ
363 struct lwp_info *lp;
364 ptid_t ptid;
e1457d83
JB
365 struct watch_area *area, **parea;
366
367 for (parea = &watch_base; *parea; parea = &(*parea)->next)
368 if ((*parea)->lo_addr == addr
369 && (*parea)->hi_addr == addr + len - 1)
370 break;
371
372 if (!*parea)
5769d3cd
AC
373 {
374 fprintf_unfiltered (gdb_stderr,
e1457d83 375 "Attempt to remove nonexistent watchpoint.\n");
5769d3cd
AC
376 return -1;
377 }
e1457d83
JB
378
379 area = *parea;
380 *parea = area->next;
381 xfree (area);
382
9f0bdab8
DJ
383 ALL_LWPS (lp, ptid)
384 s390_fix_watch_points (ptid);
e1457d83 385 return 0;
5769d3cd
AC
386}
387
fd7979d1
UW
388static int
389s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
390{
b1798462 391 return type == bp_hardware_watchpoint;
fd7979d1 392}
e1457d83 393
fd7979d1 394static int
2a3cdf79 395s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
5769d3cd 396{
fd7979d1 397 return 1;
5769d3cd
AC
398}
399
7803799a
UW
400static int
401s390_target_wordsize (void)
402{
403 int wordsize = 4;
404
405 /* Check for 64-bit inferior process. This is the case when the host is
406 64-bit, and in addition bit 32 of the PSW mask is set. */
407#ifdef __s390x__
408 long pswm;
409
410 errno = 0;
411 pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
412 if (errno == 0 && (pswm & 0x100000000ul) != 0)
413 wordsize = 8;
414#endif
415
416 return wordsize;
417}
418
419static int
420s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
421 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
422{
423 int sizeof_auxv_field = s390_target_wordsize ();
424 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
425 gdb_byte *ptr = *readptr;
426
427 if (endptr == ptr)
428 return 0;
429
430 if (endptr - ptr < sizeof_auxv_field * 2)
431 return -1;
432
433 *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
434 ptr += sizeof_auxv_field;
435 *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
436 ptr += sizeof_auxv_field;
437
438 *readptr = ptr;
439 return 1;
440}
441
442#ifdef __s390x__
443static unsigned long
444s390_get_hwcap (void)
445{
446 CORE_ADDR field;
447
448 if (target_auxv_search (&current_target, AT_HWCAP, &field))
449 return (unsigned long) field;
450
451 return 0;
452}
453#endif
454
455static const struct target_desc *
456s390_read_description (struct target_ops *ops)
457{
458#ifdef __s390x__
459 /* If GDB itself is compiled as 64-bit, we are running on a machine in
460 z/Architecture mode. If the target is running in 64-bit addressing
461 mode, report s390x architecture. If the target is running in 31-bit
462 addressing mode, but the kernel supports using 64-bit registers in
463 that mode, report s390 architecture with 64-bit GPRs. */
464
465 if (s390_target_wordsize () == 8)
466 return tdesc_s390x_linux64;
467
468 if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
469 return tdesc_s390_linux64;
470#endif
471
472 /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior
473 on a 64-bit kernel that does not support using 64-bit registers in 31-bit
474 mode, report s390 architecture with 32-bit GPRs. */
475 return tdesc_s390_linux32;
476}
fd7979d1 477
10d6c8cd
DJ
478void _initialize_s390_nat (void);
479
480void
481_initialize_s390_nat (void)
482{
483 struct target_ops *t;
484
485 /* Fill in the generic GNU/Linux methods. */
486 t = linux_target ();
487
488 /* Add our register access methods. */
489 t->to_fetch_registers = s390_linux_fetch_inferior_registers;
490 t->to_store_registers = s390_linux_store_inferior_registers;
491
fd7979d1
UW
492 /* Add our watchpoint methods. */
493 t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
2a3cdf79 494 t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
fd7979d1
UW
495 t->to_have_continuable_watchpoint = 1;
496 t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
497 t->to_insert_watchpoint = s390_insert_watchpoint;
498 t->to_remove_watchpoint = s390_remove_watchpoint;
499
7803799a
UW
500 /* Detect target architecture. */
501 t->to_read_description = s390_read_description;
502 t->to_auxv_parse = s390_auxv_parse;
503
10d6c8cd 504 /* Register the target. */
f973ed9c 505 linux_nat_add_target (t);
9f0bdab8 506 linux_nat_set_new_thread (t, s390_fix_watch_points);
10d6c8cd 507}
This page took 0.911262 seconds and 4 git commands to generate.