OSDN Git Service

add i18n markup in error message (utils.c:parse_escape)
[pf3gnuchains/sourceware.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   ptid_t ptid;
343   struct watch_area *area = xmalloc (sizeof (struct watch_area));
344
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
354   ALL_LWPS (lp, ptid)
355     s390_fix_watch_points (ptid);
356   return 0;
357 }
358
359 static int
360 s390_remove_watchpoint (CORE_ADDR addr, int len, int type,
361                         struct expression *cond)
362 {
363   struct lwp_info *lp;
364   ptid_t ptid;
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)
373     {
374       fprintf_unfiltered (gdb_stderr,
375                           "Attempt to remove nonexistent watchpoint.\n");
376       return -1;
377     }
378
379   area = *parea;
380   *parea = area->next;
381   xfree (area);
382
383   ALL_LWPS (lp, ptid)
384     s390_fix_watch_points (ptid);
385   return 0;
386 }
387
388 static int
389 s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
390 {
391   return type == bp_hardware_watchpoint;
392 }
393
394 static int
395 s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
396 {
397   return 1;
398 }
399
400 static int
401 s390_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
419 static int
420 s390_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__
443 static unsigned long
444 s390_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
455 static const struct target_desc *
456 s390_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 }
477
478 void _initialize_s390_nat (void);
479
480 void
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
492   /* Add our watchpoint methods.  */
493   t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
494   t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
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
500   /* Detect target architecture.  */
501   t->to_read_description = s390_read_description;
502   t->to_auxv_parse = s390_auxv_parse;
503
504   /* Register the target.  */
505   linux_nat_add_target (t);
506   linux_nat_set_new_thread (t, s390_fix_watch_points);
507 }