1 /* S390 native-dependent code for GDB, the GNU debugger.
2 Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc
4 Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
5 for IBM Deutschland Entwicklung GmbH, IBM Corporation.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
29 #include "linux-nat.h"
31 #include "s390-tdep.h"
33 #include <asm/ptrace.h>
34 #include <sys/ptrace.h>
35 #include <asm/types.h>
36 #include <sys/procfs.h>
37 #include <sys/ucontext.h>
40 /* Map registers to gregset/ptrace offsets.
41 These arrays are defined in s390-tdep.c. */
44 #define regmap_gregset s390x_regmap_gregset
46 #define regmap_gregset s390_regmap_gregset
49 #define regmap_fpregset s390_regmap_fpregset
51 /* When debugging a 32-bit executable running under a 64-bit kernel,
52 we have to fix up the 64-bit registers we get from the kernel
53 to make them look like 32-bit registers. */
56 ((TARGET_PTR_BIT == 32 \
57 && ((i) == S390_PSWA_REGNUM \
58 || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
64 /* Fill GDB's register array with the general-purpose register values
67 supply_gregset (gregset_t
*regp
)
70 for (i
= 0; i
< S390_NUM_REGS
; i
++)
71 if (regmap_gregset
[i
] != -1)
72 regcache_raw_supply (current_regcache
, i
,
73 (char *)regp
+ regmap_gregset
[i
] + SUBOFF (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. */
80 fill_gregset (gregset_t
*regp
, int regno
)
83 for (i
= 0; i
< S390_NUM_REGS
; i
++)
84 if (regmap_gregset
[i
] != -1)
85 if (regno
== -1 || regno
== i
)
86 regcache_raw_collect (current_regcache
, i
,
87 (char *)regp
+ regmap_gregset
[i
] + SUBOFF (i
));
90 /* Fill GDB's register array with the floating-point register values
93 supply_fpregset (fpregset_t
*regp
)
96 for (i
= 0; i
< S390_NUM_REGS
; i
++)
97 if (regmap_fpregset
[i
] != -1)
98 regcache_raw_supply (current_regcache
, i
,
99 ((char *)regp
) + regmap_fpregset
[i
]);
102 /* Fill register REGNO (if it is a general-purpose register) in
103 *REGP with the value in GDB's register array. If REGNO is -1,
104 do this for all registers. */
106 fill_fpregset (fpregset_t
*regp
, int regno
)
109 for (i
= 0; i
< S390_NUM_REGS
; i
++)
110 if (regmap_fpregset
[i
] != -1)
111 if (regno
== -1 || regno
== i
)
112 regcache_raw_collect (current_regcache
, i
,
113 ((char *)regp
) + regmap_fpregset
[i
]);
116 /* Find the TID for the current inferior thread to use with ptrace. */
118 s390_inferior_tid (void)
120 /* GNU/Linux LWP ID's are process ID's. */
121 int tid
= TIDGET (inferior_ptid
);
123 tid
= PIDGET (inferior_ptid
); /* Not a threaded program. */
128 /* Fetch all general-purpose registers from process/thread TID and
129 store their values in GDB's register cache. */
136 parea
.len
= sizeof (regs
);
137 parea
.process_addr
= (addr_t
) ®s
;
138 parea
.kernel_addr
= offsetof (struct user_regs_struct
, psw
);
139 if (ptrace (PTRACE_PEEKUSR_AREA
, tid
, (long) &parea
) < 0)
140 perror_with_name (_("Couldn't get registers"));
142 supply_gregset (®s
);
145 /* Store all valid general-purpose registers in GDB's register cache
146 into the process/thread specified by TID. */
148 store_regs (int tid
, int regnum
)
153 parea
.len
= sizeof (regs
);
154 parea
.process_addr
= (addr_t
) ®s
;
155 parea
.kernel_addr
= offsetof (struct user_regs_struct
, psw
);
156 if (ptrace (PTRACE_PEEKUSR_AREA
, tid
, (long) &parea
) < 0)
157 perror_with_name (_("Couldn't get registers"));
159 fill_gregset (®s
, regnum
);
161 if (ptrace (PTRACE_POKEUSR_AREA
, tid
, (long) &parea
) < 0)
162 perror_with_name (_("Couldn't write registers"));
165 /* Fetch all floating-point registers from process/thread TID and store
166 their values in GDB's register cache. */
168 fetch_fpregs (int tid
)
173 parea
.len
= sizeof (fpregs
);
174 parea
.process_addr
= (addr_t
) &fpregs
;
175 parea
.kernel_addr
= offsetof (struct user_regs_struct
, fp_regs
);
176 if (ptrace (PTRACE_PEEKUSR_AREA
, tid
, (long) &parea
) < 0)
177 perror_with_name (_("Couldn't get floating point status"));
179 supply_fpregset (&fpregs
);
182 /* Store all valid floating-point registers in GDB's register cache
183 into the process/thread specified by TID. */
185 store_fpregs (int tid
, int regnum
)
190 parea
.len
= sizeof (fpregs
);
191 parea
.process_addr
= (addr_t
) &fpregs
;
192 parea
.kernel_addr
= offsetof (struct user_regs_struct
, fp_regs
);
193 if (ptrace (PTRACE_PEEKUSR_AREA
, tid
, (long) &parea
) < 0)
194 perror_with_name (_("Couldn't get floating point status"));
196 fill_fpregset (&fpregs
, regnum
);
198 if (ptrace (PTRACE_POKEUSR_AREA
, tid
, (long) &parea
) < 0)
199 perror_with_name (_("Couldn't write floating point status"));
202 /* Fetch register REGNUM from the child process. If REGNUM is -1, do
203 this for all registers. */
205 s390_linux_fetch_inferior_registers (int regnum
)
207 int tid
= s390_inferior_tid ();
210 || (regnum
< S390_NUM_REGS
&& regmap_gregset
[regnum
] != -1))
214 || (regnum
< S390_NUM_REGS
&& regmap_fpregset
[regnum
] != -1))
218 /* Store register REGNUM back into the child process. If REGNUM is
219 -1, do this for all registers. */
221 s390_linux_store_inferior_registers (int regnum
)
223 int tid
= s390_inferior_tid ();
226 || (regnum
< S390_NUM_REGS
&& regmap_gregset
[regnum
] != -1))
227 store_regs (tid
, regnum
);
230 || (regnum
< S390_NUM_REGS
&& regmap_fpregset
[regnum
] != -1))
231 store_fpregs (tid
, regnum
);
235 /* Hardware-assisted watchpoint handling. */
237 /* We maintain a list of all currently active watchpoints in order
238 to properly handle watchpoint removal.
240 The only thing we actually need is the total address space area
241 spanned by the watchpoints. */
245 struct watch_area
*next
;
250 static struct watch_area
*watch_base
= NULL
;
253 s390_stopped_by_watchpoint (void)
255 per_lowcore_bits per_lowcore
;
258 /* Speed up common case. */
262 parea
.len
= sizeof (per_lowcore
);
263 parea
.process_addr
= (addr_t
) & per_lowcore
;
264 parea
.kernel_addr
= offsetof (struct user_regs_struct
, per_info
.lowcore
);
265 if (ptrace (PTRACE_PEEKUSR_AREA
, s390_inferior_tid (), &parea
) < 0)
266 perror_with_name (_("Couldn't retrieve watchpoint status"));
268 return per_lowcore
.perc_storage_alteration
== 1
269 && per_lowcore
.perc_store_real_address
== 0;
273 s390_fix_watch_points (void)
275 int tid
= s390_inferior_tid ();
280 CORE_ADDR watch_lo_addr
= (CORE_ADDR
)-1, watch_hi_addr
= 0;
281 struct watch_area
*area
;
283 for (area
= watch_base
; area
; area
= area
->next
)
285 watch_lo_addr
= min (watch_lo_addr
, area
->lo_addr
);
286 watch_hi_addr
= max (watch_hi_addr
, area
->hi_addr
);
289 parea
.len
= sizeof (per_info
);
290 parea
.process_addr
= (addr_t
) & per_info
;
291 parea
.kernel_addr
= offsetof (struct user_regs_struct
, per_info
);
292 if (ptrace (PTRACE_PEEKUSR_AREA
, tid
, &parea
) < 0)
293 perror_with_name (_("Couldn't retrieve watchpoint status"));
297 per_info
.control_regs
.bits
.em_storage_alteration
= 1;
298 per_info
.control_regs
.bits
.storage_alt_space_ctl
= 1;
302 per_info
.control_regs
.bits
.em_storage_alteration
= 0;
303 per_info
.control_regs
.bits
.storage_alt_space_ctl
= 0;
305 per_info
.starting_addr
= watch_lo_addr
;
306 per_info
.ending_addr
= watch_hi_addr
;
308 if (ptrace (PTRACE_POKEUSR_AREA
, tid
, &parea
) < 0)
309 perror_with_name (_("Couldn't modify watchpoint status"));
313 s390_insert_watchpoint (CORE_ADDR addr
, int len
)
315 struct watch_area
*area
= xmalloc (sizeof (struct watch_area
));
319 area
->lo_addr
= addr
;
320 area
->hi_addr
= addr
+ len
- 1;
322 area
->next
= watch_base
;
325 s390_fix_watch_points ();
330 s390_remove_watchpoint (CORE_ADDR addr
, int len
)
332 struct watch_area
*area
, **parea
;
334 for (parea
= &watch_base
; *parea
; parea
= &(*parea
)->next
)
335 if ((*parea
)->lo_addr
== addr
336 && (*parea
)->hi_addr
== addr
+ len
- 1)
341 fprintf_unfiltered (gdb_stderr
,
342 "Attempt to remove nonexistent watchpoint.\n");
350 s390_fix_watch_points ();
355 s390_can_use_hw_breakpoint (int type
, int cnt
, int othertype
)
361 s390_region_size_ok_for_hw_watchpoint (int cnt
)
367 void _initialize_s390_nat (void);
370 _initialize_s390_nat (void)
372 struct target_ops
*t
;
374 /* Fill in the generic GNU/Linux methods. */
377 /* Add our register access methods. */
378 t
->to_fetch_registers
= s390_linux_fetch_inferior_registers
;
379 t
->to_store_registers
= s390_linux_store_inferior_registers
;
381 /* Add our watchpoint methods. */
382 t
->to_can_use_hw_breakpoint
= s390_can_use_hw_breakpoint
;
383 t
->to_region_size_ok_for_hw_watchpoint
= s390_region_size_ok_for_hw_watchpoint
;
384 t
->to_have_continuable_watchpoint
= 1;
385 t
->to_stopped_by_watchpoint
= s390_stopped_by_watchpoint
;
386 t
->to_insert_watchpoint
= s390_insert_watchpoint
;
387 t
->to_remove_watchpoint
= s390_remove_watchpoint
;
389 /* Register the target. */