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. */
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. */
45 #define regmap_gregset s390x_regmap_gregset
47 #define regmap_gregset s390_regmap_gregset
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. */
57 ((TARGET_PTR_BIT == 32 \
58 && ((i) == S390_PSWA_REGNUM \
59 || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
65 /* Fill GDB's register array with the general-purpose register values
68 supply_gregset (gregset_t
*regp
)
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. */
81 fill_gregset (gregset_t
*regp
, int regno
)
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
94 supply_fpregset (fpregset_t
*regp
)
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. */
107 fill_fpregset (fpregset_t
*regp
, int regno
)
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. */
119 s390_inferior_tid (void)
121 /* GNU/Linux LWP ID's are process ID's. */
122 int tid
= TIDGET (inferior_ptid
);
124 tid
= PIDGET (inferior_ptid
); /* Not a threaded program. */
129 /* Fetch all general-purpose registers from process/thread TID and
130 store their values in GDB's register cache. */
137 parea
.len
= sizeof (regs
);
138 parea
.process_addr
= (addr_t
) ®s
;
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 (®s
);
146 /* Store all valid general-purpose registers in GDB's register cache
147 into the process/thread specified by TID. */
149 store_regs (int tid
, int regnum
)
154 parea
.len
= sizeof (regs
);
155 parea
.process_addr
= (addr_t
) ®s
;
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 (®s
, 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. */
169 fetch_fpregs (int tid
)
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. */
186 store_fpregs (int tid
, int regnum
)
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. */
206 s390_linux_fetch_inferior_registers (int regnum
)
208 int tid
= s390_inferior_tid ();
211 || (regnum
< S390_NUM_REGS
&& regmap_gregset
[regnum
] != -1))
215 || (regnum
< S390_NUM_REGS
&& regmap_fpregset
[regnum
] != -1))
219 /* Store register REGNUM back into the child process. If REGNUM is
220 -1, do this for all registers. */
222 s390_linux_store_inferior_registers (int regnum
)
224 int tid
= s390_inferior_tid ();
227 || (regnum
< S390_NUM_REGS
&& regmap_gregset
[regnum
] != -1))
228 store_regs (tid
, regnum
);
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. */
246 struct watch_area
*next
;
251 static struct watch_area
*watch_base
= NULL
;
254 s390_stopped_by_watchpoint (void)
256 per_lowcore_bits per_lowcore
;
259 /* Speed up common case. */
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;
274 s390_fix_watch_points (void)
276 int tid
= s390_inferior_tid ();
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"));
298 per_info
.control_regs
.bits
.em_storage_alteration
= 1;
299 per_info
.control_regs
.bits
.storage_alt_space_ctl
= 1;
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"));
314 s390_insert_watchpoint (CORE_ADDR addr
, int len
, int type
)
316 struct watch_area
*area
= xmalloc (sizeof (struct watch_area
));
320 area
->lo_addr
= addr
;
321 area
->hi_addr
= addr
+ len
- 1;
323 area
->next
= watch_base
;
326 s390_fix_watch_points ();
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)
342 fprintf_unfiltered (gdb_stderr
,
343 "Attempt to remove nonexistent watchpoint.\n");
351 s390_fix_watch_points ();
356 s390_can_use_hw_breakpoint (int type
, int cnt
, int othertype
)
362 s390_region_ok_for_hw_watchpoint (CORE_ADDR addr
, int cnt
)
368 void _initialize_s390_nat (void);
371 _initialize_s390_nat (void)
373 struct target_ops
*t
;
375 /* Fill in the generic GNU/Linux methods. */
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
);