1 /* S390 native-dependent code for GDB, the GNU debugger.
2 Copyright 2001 Free Software Foundation, Inc
3 Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
4 for IBM Deutschland Entwicklung GmbH, IBM Corporation.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 #include <asm/ptrace.h>
26 #include <sys/ptrace.h>
27 #include <asm/processor.h>
28 #include <asm/types.h>
29 #include <sys/procfs.h>
32 #include <sys/ucontext.h>
34 #define offsetof(type,member) ((size_t) &((type *)0)->member)
39 s390_register_u_addr (int blockend
, int regnum
)
43 if (regnum
>= S390_GP0_REGNUM
&& regnum
<= S390_GP_LAST_REGNUM
)
44 retval
= PT_GPR0
+ ((regnum
- S390_GP0_REGNUM
) * S390_GPR_SIZE
);
45 else if (regnum
>= S390_PSWM_REGNUM
&& regnum
<= S390_PC_REGNUM
)
46 retval
= PT_PSWMASK
+ ((regnum
- S390_PSWM_REGNUM
) * S390_PSW_MASK_SIZE
);
47 else if (regnum
== S390_FPC_REGNUM
)
49 else if (regnum
>= S390_FP0_REGNUM
&& regnum
<= S390_FPLAST_REGNUM
)
56 + ((regnum
- S390_FP0_REGNUM
) * S390_FPR_SIZE
);
57 else if (regnum
>= S390_FIRST_ACR
&& regnum
<= S390_LAST_ACR
)
58 retval
= PT_ACR0
+ ((regnum
- S390_FIRST_ACR
) * S390_ACR_SIZE
);
59 else if (regnum
>= (S390_FIRST_CR
+ 9) && regnum
<= (S390_FIRST_CR
+ 11))
60 retval
= PT_CR_9
+ ((regnum
- (S390_FIRST_CR
+ 9)) * S390_CR_SIZE
);
64 error ("s390_register_u_addr invalid regnum %s %d regnum=%d",
65 __FILE__
, (int) __LINE__
, regnum
);
67 internal_error (__FILE__
, __LINE__
,
68 "s390_register_u_addr invalid regnum regnum=%d",
73 return retval
+ blockend
;
77 /* watch_areas are required if you put 2 or more watchpoints on the same
78 address or overlapping areas gdb will call us to delete the watchpoint
79 more than once when we try to delete them.
80 attempted reference counting to reduce the number of areas unfortunately
81 they didn't shrink when areas had to be split overlapping occurs. */
83 typedef struct watch_area watch_area
;
91 static watch_area
*watch_base
= NULL
;
92 int watch_area_cnt
= 0;
93 static CORE_ADDR watch_lo_addr
= 0, watch_hi_addr
= 0;
98 s390_stopped_by_watchpoint (int pid
)
100 per_lowcore_bits per_lowcore
;
103 parea
.len
= sizeof (per_lowcore
);
104 parea
.process_addr
= (addr_t
) & per_lowcore
;
105 parea
.kernel_addr
= offsetof (struct user_regs_struct
, per_info
.lowcore
);
106 ptrace (PTRACE_PEEKUSR_AREA
, pid
, &parea
);
107 return ((per_lowcore
.perc_storage_alteration
== 1) &&
108 (per_lowcore
.perc_store_real_address
== 0));
113 s390_fix_watch_points (int pid
)
118 parea
.len
= sizeof (per_info
);
119 parea
.process_addr
= (addr_t
) & per_info
;
120 parea
.kernel_addr
= PT_CR_9
;
121 ptrace (PTRACE_PEEKUSR_AREA
, pid
, &parea
);
122 /* The kernel automatically sets the psw for per depending */
123 /* on whether the per control registers are set for event recording */
124 /* & sets cr9 & cr10 appropriately also */
127 per_info
.control_regs
.bits
.em_storage_alteration
= 1;
128 per_info
.control_regs
.bits
.storage_alt_space_ctl
= 1;
132 per_info
.control_regs
.bits
.em_storage_alteration
= 0;
133 per_info
.control_regs
.bits
.storage_alt_space_ctl
= 0;
135 per_info
.starting_addr
= watch_lo_addr
;
136 per_info
.ending_addr
= watch_hi_addr
;
137 ptrace (PTRACE_POKEUSR_AREA
, pid
, &parea
);
141 s390_insert_watchpoint (int pid
, CORE_ADDR addr
, int len
, int rw
)
143 CORE_ADDR hi_addr
= addr
+ len
- 1;
144 watch_area
*newarea
= (watch_area
*) xmalloc (sizeof (watch_area
));
149 newarea
->next
= watch_base
;
150 watch_base
= newarea
;
151 watch_lo_addr
= min (watch_lo_addr
, addr
);
152 watch_hi_addr
= max (watch_hi_addr
, hi_addr
);
153 newarea
->lo_addr
= addr
;
154 newarea
->hi_addr
= hi_addr
;
155 if (watch_area_cnt
== 0)
157 watch_lo_addr
= newarea
->lo_addr
;
158 watch_hi_addr
= newarea
->hi_addr
;
161 s390_fix_watch_points (pid
);
163 return newarea
? 0 : -1;
168 s390_remove_watchpoint (int pid
, CORE_ADDR addr
, int len
)
170 watch_area
*curr
= watch_base
, *prev
, *matchCurr
;
171 CORE_ADDR hi_addr
= addr
+ len
- 1;
172 CORE_ADDR watch_second_lo_addr
= 0xffffffffUL
, watch_second_hi_addr
= 0;
173 int lo_addr_ref_cnt
, hi_addr_ref_cnt
;
174 prev
= matchCurr
= NULL
;
175 lo_addr_ref_cnt
= (addr
== watch_lo_addr
);
176 hi_addr_ref_cnt
= (addr
== watch_hi_addr
);
179 if (matchCurr
== NULL
)
181 if (curr
->lo_addr
== addr
&& curr
->hi_addr
== hi_addr
)
185 prev
->next
= curr
->next
;
187 watch_base
= curr
->next
;
193 if (watch_lo_addr
== curr
->lo_addr
)
195 if (curr
->lo_addr
> watch_lo_addr
&&
196 curr
->lo_addr
< watch_second_lo_addr
)
197 watch_second_lo_addr
= curr
->lo_addr
;
201 if (watch_hi_addr
== curr
->hi_addr
)
203 if (curr
->hi_addr
< watch_hi_addr
&&
204 curr
->hi_addr
> watch_second_hi_addr
)
205 watch_second_hi_addr
= curr
->hi_addr
;
215 if (lo_addr_ref_cnt
== 2)
216 watch_lo_addr
= watch_second_lo_addr
;
217 if (hi_addr_ref_cnt
== 2)
218 watch_hi_addr
= watch_second_hi_addr
;
222 watch_lo_addr
= watch_hi_addr
= 0;
224 s390_fix_watch_points (pid
);
229 fprintf_unfiltered (gdb_stderr
,
230 "Attempt to remove nonexistent watchpoint in s390_remove_watchpoint\n");
238 return sizeof (struct user
);
242 #if (defined (S390_FP0_REGNUM) && defined (HAVE_FPREGSET_T) && defined(HAVE_SYS_PROCFS_H) && defined (HAVE_GREGSET_T))
244 supply_gregset (gregset_t
* gregsetp
)
247 greg_t
*gregp
= (greg_t
*) gregsetp
;
249 supply_register (S390_PSWM_REGNUM
, (char *) &gregp
[S390_PSWM_REGNUM
]);
250 supply_register (S390_PC_REGNUM
, (char *) &gregp
[S390_PC_REGNUM
]);
251 for (regi
= 0; regi
< S390_NUM_GPRS
; regi
++)
252 supply_register (S390_GP0_REGNUM
+ regi
,
253 (char *) &gregp
[S390_GP0_REGNUM
+ regi
]);
255 #if defined (CONFIG_ARCH_S390X)
256 /* On the s390x, each element of gregset_t is 8 bytes long, but
257 each access register is still only 32 bits long. So they're
258 packed two per element. It's apparently traditional that
259 gregset_t must be an array, so when the registers it provides
260 have different sizes, something has to get strange
263 unsigned int *acrs
= (unsigned int *) &gregp
[S390_FIRST_ACR
];
265 for (regi
= 0; regi
< S390_NUM_ACRS
; regi
++)
266 supply_register (S390_FIRST_ACR
+ regi
, (char *) &acrs
[regi
]);
269 for (regi
= 0; regi
< S390_NUM_ACRS
; regi
++)
270 supply_register (S390_FIRST_ACR
+ regi
,
271 (char *) &gregp
[S390_FIRST_ACR
+ regi
]);
274 /* unfortunately this isn't in gregsetp */
275 for (regi
= 0; regi
< S390_NUM_CRS
; regi
++)
276 supply_register (S390_FIRST_CR
+ regi
, NULL
);
281 supply_fpregset (fpregset_t
* fpregsetp
)
285 supply_register (S390_FPC_REGNUM
, (char *) &fpregsetp
->fpc
);
286 for (regi
= 0; regi
< S390_NUM_FPRS
; regi
++)
287 supply_register (S390_FP0_REGNUM
+ regi
, (char *) &fpregsetp
->fprs
[regi
]);
292 fill_gregset (gregset_t
* gregsetp
, int regno
)
295 greg_t
*gregp
= (greg_t
*) gregsetp
;
299 regcache_collect (S390_PSWM_REGNUM
, &gregp
[S390_PSWM_REGNUM
]);
300 regcache_collect (S390_PC_REGNUM
, &gregp
[S390_PC_REGNUM
]);
301 for (regi
= 0; regi
< S390_NUM_GPRS
; regi
++)
302 regcache_collect (S390_GP0_REGNUM
+ regi
,
303 &gregp
[S390_GP0_REGNUM
+ regi
]);
304 #if defined (CONFIG_ARCH_S390X)
305 /* See the comments about the access registers in
306 supply_gregset, above. */
308 unsigned int *acrs
= (unsigned int *) &gregp
[S390_FIRST_ACR
];
310 for (regi
= 0; regi
< S390_NUM_ACRS
; regi
++)
311 regcache_collect (S390_FIRST_ACR
+ regi
, &acrs
[regi
]);
314 for (regi
= 0; regi
< S390_NUM_ACRS
; regi
++)
315 regcache_collect (S390_FIRST_ACR
+ regi
,
316 &gregp
[S390_FIRST_ACR
+ regi
]);
319 else if (regno
>= S390_PSWM_REGNUM
&& regno
< S390_FIRST_ACR
)
320 regcache_collect (regno
, &gregp
[regno
]);
321 else if (regno
>= S390_FIRST_ACR
&& regno
<= S390_LAST_ACR
)
323 #if defined (CONFIG_ARCH_S390X)
324 /* See the comments about the access registers in
325 supply_gregset, above. */
326 unsigned int *acrs
= (unsigned int *) &gregp
[S390_FIRST_ACR
];
328 regcache_collect (regno
, &acrs
[regno
- S390_FIRST_ACR
]);
330 regcache_collect (regno
, &gregp
[regno
]);
335 /* Given a pointer to a floating point register set in /proc format
336 (fpregset_t *), update the register specified by REGNO from gdb's idea
337 of the current floating point register set. If REGNO is -1, update
341 fill_fpregset (fpregset_t
* fpregsetp
, int regno
)
347 regcache_collect (S390_FPC_REGNUM
, &fpregsetp
->fpc
);
348 for (regi
= 0; regi
< S390_NUM_FPRS
; regi
++)
349 regcache_collect (S390_FP0_REGNUM
+ regi
, &fpregsetp
->fprs
[regi
]);
351 else if (regno
== S390_FPC_REGNUM
)
352 regcache_collect (S390_FPC_REGNUM
, &fpregsetp
->fpc
);
353 else if (regno
>= S390_FP0_REGNUM
&& regno
<= S390_FPLAST_REGNUM
)
354 regcache_collect (regno
, &fpregsetp
->fprs
[regno
- S390_FP0_REGNUM
]);
359 #error "There are a few possibilities here"
360 #error "1) You aren't compiling for linux & don't need a core dumps to work."
361 #error "2) The header files sys/elf.h sys/user.h sys/ptrace.h & sys/procfs.h"
362 #error "libc files are inconsistent with linux/include/asm-s390/"
363 #error "3) you didn't do a completely clean build & delete config.cache."
365 #endif /* GDBSERVER */