Further fix the documentation in struct quick_symbol_functions
[deliverable/binutils-gdb.git] / gdb / s390-nat.c
1 /* S390 native-dependent code for GDB, the GNU debugger.
2 Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2009
3 Free Software Foundation, Inc
4
5 Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6 for IBM Deutschland Entwicklung GmbH, IBM Corporation.
7
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
12 the Free Software Foundation; either version 3 of the License, or
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
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22
23 #include "defs.h"
24 #include "regcache.h"
25 #include "inferior.h"
26 #include "target.h"
27 #include "linux-nat.h"
28 #include "auxv.h"
29
30 #include "s390-tdep.h"
31
32 #include <asm/ptrace.h>
33 #include <sys/ptrace.h>
34 #include <asm/types.h>
35 #include <sys/procfs.h>
36 #include <sys/ucontext.h>
37 #include <elf.h>
38
39 #ifndef HWCAP_S390_HIGH_GPRS
40 #define HWCAP_S390_HIGH_GPRS 512
41 #endif
42
43
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
49 #else
50 #define regmap_gregset s390_regmap_gregset
51 #endif
52
53 #define regmap_fpregset s390_regmap_fpregset
54
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__
59 #define SUBOFF(gdbarch, i) \
60 ((gdbarch_ptr_bit (gdbarch) == 32 \
61 && ((i) == S390_PSWA_REGNUM \
62 || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
63 #else
64 #define SUBOFF(gdbarch, i) 0
65 #endif
66
67
68 /* Fill GDB's register array with the general-purpose register values
69 in *REGP. */
70 void
71 supply_gregset (struct regcache *regcache, const gregset_t *regp)
72 {
73 struct gdbarch *gdbarch = get_regcache_arch (regcache);
74 int i;
75 for (i = 0; i < S390_NUM_REGS; i++)
76 if (regmap_gregset[i] != -1)
77 regcache_raw_supply (regcache, i,
78 (const char *)regp + regmap_gregset[i]
79 + SUBOFF (gdbarch, i));
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. */
85 void
86 fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
87 {
88 struct gdbarch *gdbarch = get_regcache_arch (regcache);
89 int i;
90 for (i = 0; i < S390_NUM_REGS; i++)
91 if (regmap_gregset[i] != -1)
92 if (regno == -1 || regno == i)
93 regcache_raw_collect (regcache, i,
94 (char *)regp + regmap_gregset[i]
95 + SUBOFF (gdbarch, i));
96 }
97
98 /* Fill GDB's register array with the floating-point register values
99 in *REGP. */
100 void
101 supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
102 {
103 int i;
104 for (i = 0; i < S390_NUM_REGS; i++)
105 if (regmap_fpregset[i] != -1)
106 regcache_raw_supply (regcache, i,
107 (const char *)regp + regmap_fpregset[i]);
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. */
113 void
114 fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
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)
120 regcache_raw_collect (regcache, i,
121 (char *)regp + regmap_fpregset[i]);
122 }
123
124 /* Find the TID for the current inferior thread to use with ptrace. */
125 static int
126 s390_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. */
138 static void
139 fetch_regs (struct regcache *regcache, int tid)
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)
148 perror_with_name (_("Couldn't get registers"));
149
150 supply_gregset (regcache, (const gregset_t *) &regs);
151 }
152
153 /* Store all valid general-purpose registers in GDB's register cache
154 into the process/thread specified by TID. */
155 static void
156 store_regs (const struct regcache *regcache, int tid, int regnum)
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)
165 perror_with_name (_("Couldn't get registers"));
166
167 fill_gregset (regcache, &regs, regnum);
168
169 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
170 perror_with_name (_("Couldn't write registers"));
171 }
172
173 /* Fetch all floating-point registers from process/thread TID and store
174 their values in GDB's register cache. */
175 static void
176 fetch_fpregs (struct regcache *regcache, int tid)
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)
185 perror_with_name (_("Couldn't get floating point status"));
186
187 supply_fpregset (regcache, (const fpregset_t *) &fpregs);
188 }
189
190 /* Store all valid floating-point registers in GDB's register cache
191 into the process/thread specified by TID. */
192 static void
193 store_fpregs (const struct regcache *regcache, int tid, int regnum)
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)
202 perror_with_name (_("Couldn't get floating point status"));
203
204 fill_fpregset (regcache, &fpregs, regnum);
205
206 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
207 perror_with_name (_("Couldn't write floating point status"));
208 }
209
210 /* Fetch register REGNUM from the child process. If REGNUM is -1, do
211 this for all registers. */
212 static void
213 s390_linux_fetch_inferior_registers (struct target_ops *ops,
214 struct regcache *regcache, int regnum)
215 {
216 int tid = s390_inferior_tid ();
217
218 if (regnum == -1
219 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
220 fetch_regs (regcache, tid);
221
222 if (regnum == -1
223 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
224 fetch_fpregs (regcache, tid);
225 }
226
227 /* Store register REGNUM back into the child process. If REGNUM is
228 -1, do this for all registers. */
229 static void
230 s390_linux_store_inferior_registers (struct target_ops *ops,
231 struct regcache *regcache, int regnum)
232 {
233 int tid = s390_inferior_tid ();
234
235 if (regnum == -1
236 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
237 store_regs (regcache, tid, regnum);
238
239 if (regnum == -1
240 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
241 store_fpregs (regcache, tid, regnum);
242 }
243
244
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
253 struct watch_area
254 {
255 struct watch_area *next;
256 CORE_ADDR lo_addr;
257 CORE_ADDR hi_addr;
258 };
259
260 static struct watch_area *watch_base = NULL;
261
262 static int
263 s390_stopped_by_watchpoint (void)
264 {
265 per_lowcore_bits per_lowcore;
266 ptrace_area parea;
267 int result;
268
269 /* Speed up common case. */
270 if (!watch_base)
271 return 0;
272
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);
276 if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
277 perror_with_name (_("Couldn't retrieve watchpoint status"));
278
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;
291 }
292
293 static void
294 s390_fix_watch_points (ptid_t ptid)
295 {
296 int tid;
297
298 per_struct per_info;
299 ptrace_area parea;
300
301 CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
302 struct watch_area *area;
303
304 tid = TIDGET (ptid);
305 if (tid == 0)
306 tid = PIDGET (ptid);
307
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
314 parea.len = sizeof (per_info);
315 parea.process_addr = (addr_t) & per_info;
316 parea.kernel_addr = offsetof (struct user_regs_struct, per_info);
317 if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
318 perror_with_name (_("Couldn't retrieve watchpoint status"));
319
320 if (watch_base)
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;
332
333 if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
334 perror_with_name (_("Couldn't modify watchpoint status"));
335 }
336
337 static int
338 s390_insert_watchpoint (CORE_ADDR addr, int len, int type,
339 struct expression *cond)
340 {
341 struct lwp_info *lp;
342 struct watch_area *area = xmalloc (sizeof (struct watch_area));
343
344 if (!area)
345 return -1;
346
347 area->lo_addr = addr;
348 area->hi_addr = addr + len - 1;
349
350 area->next = watch_base;
351 watch_base = area;
352
353 ALL_LWPS (lp)
354 s390_fix_watch_points (lp->ptid);
355 return 0;
356 }
357
358 static int
359 s390_remove_watchpoint (CORE_ADDR addr, int len, int type,
360 struct expression *cond)
361 {
362 struct lwp_info *lp;
363 struct watch_area *area, **parea;
364
365 for (parea = &watch_base; *parea; parea = &(*parea)->next)
366 if ((*parea)->lo_addr == addr
367 && (*parea)->hi_addr == addr + len - 1)
368 break;
369
370 if (!*parea)
371 {
372 fprintf_unfiltered (gdb_stderr,
373 "Attempt to remove nonexistent watchpoint.\n");
374 return -1;
375 }
376
377 area = *parea;
378 *parea = area->next;
379 xfree (area);
380
381 ALL_LWPS (lp)
382 s390_fix_watch_points (lp->ptid);
383 return 0;
384 }
385
386 static int
387 s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
388 {
389 return type == bp_hardware_watchpoint;
390 }
391
392 static int
393 s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
394 {
395 return 1;
396 }
397
398 static int
399 s390_target_wordsize (void)
400 {
401 int wordsize = 4;
402
403 /* Check for 64-bit inferior process. This is the case when the host is
404 64-bit, and in addition bit 32 of the PSW mask is set. */
405 #ifdef __s390x__
406 long pswm;
407
408 errno = 0;
409 pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
410 if (errno == 0 && (pswm & 0x100000000ul) != 0)
411 wordsize = 8;
412 #endif
413
414 return wordsize;
415 }
416
417 static int
418 s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
419 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
420 {
421 int sizeof_auxv_field = s390_target_wordsize ();
422 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
423 gdb_byte *ptr = *readptr;
424
425 if (endptr == ptr)
426 return 0;
427
428 if (endptr - ptr < sizeof_auxv_field * 2)
429 return -1;
430
431 *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
432 ptr += sizeof_auxv_field;
433 *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
434 ptr += sizeof_auxv_field;
435
436 *readptr = ptr;
437 return 1;
438 }
439
440 #ifdef __s390x__
441 static unsigned long
442 s390_get_hwcap (void)
443 {
444 CORE_ADDR field;
445
446 if (target_auxv_search (&current_target, AT_HWCAP, &field))
447 return (unsigned long) field;
448
449 return 0;
450 }
451 #endif
452
453 static const struct target_desc *
454 s390_read_description (struct target_ops *ops)
455 {
456 #ifdef __s390x__
457 /* If GDB itself is compiled as 64-bit, we are running on a machine in
458 z/Architecture mode. If the target is running in 64-bit addressing
459 mode, report s390x architecture. If the target is running in 31-bit
460 addressing mode, but the kernel supports using 64-bit registers in
461 that mode, report s390 architecture with 64-bit GPRs. */
462
463 if (s390_target_wordsize () == 8)
464 return tdesc_s390x_linux64;
465
466 if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
467 return tdesc_s390_linux64;
468 #endif
469
470 /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior
471 on a 64-bit kernel that does not support using 64-bit registers in 31-bit
472 mode, report s390 architecture with 32-bit GPRs. */
473 return tdesc_s390_linux32;
474 }
475
476 void _initialize_s390_nat (void);
477
478 void
479 _initialize_s390_nat (void)
480 {
481 struct target_ops *t;
482
483 /* Fill in the generic GNU/Linux methods. */
484 t = linux_target ();
485
486 /* Add our register access methods. */
487 t->to_fetch_registers = s390_linux_fetch_inferior_registers;
488 t->to_store_registers = s390_linux_store_inferior_registers;
489
490 /* Add our watchpoint methods. */
491 t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
492 t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
493 t->to_have_continuable_watchpoint = 1;
494 t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
495 t->to_insert_watchpoint = s390_insert_watchpoint;
496 t->to_remove_watchpoint = s390_remove_watchpoint;
497
498 /* Detect target architecture. */
499 t->to_read_description = s390_read_description;
500 t->to_auxv_parse = s390_auxv_parse;
501
502 /* Register the target. */
503 linux_nat_add_target (t);
504 linux_nat_set_new_thread (t, s390_fix_watch_points);
505 }
This page took 0.040823 seconds and 4 git commands to generate.