gdb/
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-s390-low.c
1 /* GNU/Linux S/390 specific low level interface, for the remote server
2 for GDB.
3 Copyright (C) 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 /* This file is used for both 31-bit and 64-bit S/390 systems. */
22
23 #include "server.h"
24 #include "linux-low.h"
25 #include "elf/common.h"
26
27 #include <asm/ptrace.h>
28 #include <sys/ptrace.h>
29 #include <sys/uio.h>
30 #include <elf.h>
31
32 #ifndef HWCAP_S390_HIGH_GPRS
33 #define HWCAP_S390_HIGH_GPRS 512
34 #endif
35
36 #ifndef PTRACE_GETREGSET
37 #define PTRACE_GETREGSET 0x4204
38 #endif
39
40 #ifndef PTRACE_SETREGSET
41 #define PTRACE_SETREGSET 0x4205
42 #endif
43
44 /* Defined in auto-generated file s390-linux32.c. */
45 void init_registers_s390_linux32 (void);
46 /* Defined in auto-generated file s390-linux32v1.c. */
47 void init_registers_s390_linux32v1 (void);
48 /* Defined in auto-generated file s390-linux32v2.c. */
49 void init_registers_s390_linux32v2 (void);
50 /* Defined in auto-generated file s390-linux64.c. */
51 void init_registers_s390_linux64 (void);
52 /* Defined in auto-generated file s390-linux64v1.c. */
53 void init_registers_s390_linux64v1 (void);
54 /* Defined in auto-generated file s390-linux64v2.c. */
55 void init_registers_s390_linux64v2 (void);
56 /* Defined in auto-generated file s390x-linux64.c. */
57 void init_registers_s390x_linux64 (void);
58 /* Defined in auto-generated file s390x-linux64v1.c. */
59 void init_registers_s390x_linux64v1 (void);
60 /* Defined in auto-generated file s390x-linux64v2.c. */
61 void init_registers_s390x_linux64v2 (void);
62
63 #define s390_num_regs 52
64
65 static int s390_regmap[] = {
66 PT_PSWMASK, PT_PSWADDR,
67
68 PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
69 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
70 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
71 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
72
73 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
74 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
75 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
76 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
77
78 PT_FPC,
79
80 #ifndef __s390x__
81 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
82 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
83 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
84 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
85 #else
86 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
87 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
88 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
89 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
90 #endif
91
92 PT_ORIGGPR2,
93 };
94
95 #ifdef __s390x__
96 #define s390_num_regs_3264 68
97
98 static int s390_regmap_3264[] = {
99 PT_PSWMASK, PT_PSWADDR,
100
101 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1,
102 PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
103 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5,
104 PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
105 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9,
106 PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
107 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13,
108 PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
109
110 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
111 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
112 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
113 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
114
115 PT_FPC,
116
117 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
118 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
119 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
120 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
121
122 PT_ORIGGPR2,
123 };
124 #endif
125
126
127 static int
128 s390_cannot_fetch_register (int regno)
129 {
130 return 0;
131 }
132
133 static int
134 s390_cannot_store_register (int regno)
135 {
136 return 0;
137 }
138
139 static void
140 s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
141 {
142 int size = register_size (regno);
143 if (size < sizeof (long))
144 {
145 int regaddr = the_low_target.regmap[regno];
146
147 memset (buf, 0, sizeof (long));
148
149 if ((regno ^ 1) < the_low_target.num_regs
150 && the_low_target.regmap[regno ^ 1] == regaddr)
151 {
152 collect_register (regcache, regno & ~1, buf);
153 collect_register (regcache, (regno & ~1) + 1,
154 buf + sizeof (long) - size);
155 }
156 else if (regaddr == PT_PSWMASK)
157 {
158 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
159 the basic addressing mode bit from the PSW address. */
160 char *addr = alloca (register_size (regno ^ 1));
161 collect_register (regcache, regno, buf);
162 collect_register (regcache, regno ^ 1, addr);
163 buf[1] &= ~0x8;
164 buf[size] |= (addr[0] & 0x80);
165 }
166 else if (regaddr == PT_PSWADDR)
167 {
168 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
169 mode bit (which gets copied to the PSW mask instead). */
170 collect_register (regcache, regno, buf + sizeof (long) - size);
171 buf[sizeof (long) - size] &= ~0x80;
172 }
173 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
174 || regaddr == PT_ORIGGPR2)
175 collect_register (regcache, regno, buf + sizeof (long) - size);
176 else
177 collect_register (regcache, regno, buf);
178 }
179 else
180 collect_register (regcache, regno, buf);
181 }
182
183 static void
184 s390_supply_ptrace_register (struct regcache *regcache,
185 int regno, const char *buf)
186 {
187 int size = register_size (regno);
188 if (size < sizeof (long))
189 {
190 int regaddr = the_low_target.regmap[regno];
191
192 if ((regno ^ 1) < the_low_target.num_regs
193 && the_low_target.regmap[regno ^ 1] == regaddr)
194 {
195 supply_register (regcache, regno & ~1, buf);
196 supply_register (regcache, (regno & ~1) + 1,
197 buf + sizeof (long) - size);
198 }
199 else if (regaddr == PT_PSWMASK)
200 {
201 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
202 the basic addressing mode into the PSW address. */
203 char *mask = alloca (size);
204 char *addr = alloca (register_size (regno ^ 1));
205 memcpy (mask, buf, size);
206 mask[1] |= 0x8;
207 supply_register (regcache, regno, mask);
208
209 collect_register (regcache, regno ^ 1, addr);
210 addr[0] &= ~0x80;
211 addr[0] |= (buf[size] & 0x80);
212 supply_register (regcache, regno ^ 1, addr);
213 }
214 else if (regaddr == PT_PSWADDR)
215 {
216 /* Convert 8-byte PSW address to 4 bytes by truncating, but
217 keeping the addressing mode bit (which was set from the mask). */
218 char *addr = alloca (size);
219 char amode;
220 collect_register (regcache, regno, addr);
221 amode = addr[0] & 0x80;
222 memcpy (addr, buf + sizeof (long) - size, size);
223 addr[0] &= ~0x80;
224 addr[0] |= amode;
225 supply_register (regcache, regno, addr);
226 }
227 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
228 || regaddr == PT_ORIGGPR2)
229 supply_register (regcache, regno, buf + sizeof (long) - size);
230 else
231 supply_register (regcache, regno, buf);
232 }
233 else
234 supply_register (regcache, regno, buf);
235 }
236
237 /* Provide only a fill function for the general register set. ps_lgetregs
238 will use this for NPTL support. */
239
240 static void s390_fill_gregset (struct regcache *regcache, void *buf)
241 {
242 int i;
243
244 for (i = 0; i < the_low_target.num_regs; i++)
245 {
246 if (the_low_target.regmap[i] < PT_PSWMASK
247 || the_low_target.regmap[i] > PT_ACR15)
248 continue;
249
250 s390_collect_ptrace_register (regcache, i, (char *) buf
251 + the_low_target.regmap[i]);
252 }
253 }
254
255 /* Fill and store functions for extended register sets. */
256
257 static void
258 s390_fill_last_break (struct regcache *regcache, void *buf)
259 {
260 /* Last break address is read-only. */
261 }
262
263 static void
264 s390_store_last_break (struct regcache *regcache, const void *buf)
265 {
266 supply_register_by_name (regcache, "last_break",
267 (const char *)buf + 8 - register_size (0));
268 }
269
270 static void
271 s390_fill_system_call (struct regcache *regcache, void *buf)
272 {
273 collect_register_by_name (regcache, "system_call", buf);
274 }
275
276 static void
277 s390_store_system_call (struct regcache *regcache, const void *buf)
278 {
279 supply_register_by_name (regcache, "system_call", buf);
280 }
281
282 struct regset_info target_regsets[] = {
283 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
284 /* Last break address is read-only; do not attempt PTRACE_SETREGSET. */
285 { PTRACE_GETREGSET, PTRACE_GETREGSET, NT_S390_LAST_BREAK, 0,
286 EXTENDED_REGS, s390_fill_last_break, s390_store_last_break },
287 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
288 EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
289 { 0, 0, 0, -1, -1, NULL, NULL }
290 };
291
292
293 static const unsigned char s390_breakpoint[] = { 0, 1 };
294 #define s390_breakpoint_len 2
295
296 static CORE_ADDR
297 s390_get_pc (struct regcache *regcache)
298 {
299 if (register_size (0) == 4)
300 {
301 unsigned int pswa;
302 collect_register_by_name (regcache, "pswa", &pswa);
303 return pswa & 0x7fffffff;
304 }
305 else
306 {
307 unsigned long pc;
308 collect_register_by_name (regcache, "pswa", &pc);
309 return pc;
310 }
311 }
312
313 static void
314 s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
315 {
316 if (register_size (0) == 4)
317 {
318 unsigned int pswa;
319 collect_register_by_name (regcache, "pswa", &pswa);
320 pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
321 supply_register_by_name (regcache, "pswa", &pswa);
322 }
323 else
324 {
325 unsigned long pc = newpc;
326 supply_register_by_name (regcache, "pswa", &pc);
327 }
328 }
329
330 #ifdef __s390x__
331 static unsigned long
332 s390_get_hwcap (void)
333 {
334 int wordsize = register_size (0);
335 unsigned char *data = alloca (2 * wordsize);
336 int offset = 0;
337
338 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
339 {
340 if (wordsize == 4)
341 {
342 unsigned int *data_p = (unsigned int *)data;
343 if (data_p[0] == AT_HWCAP)
344 return data_p[1];
345 }
346 else
347 {
348 unsigned long *data_p = (unsigned long *)data;
349 if (data_p[0] == AT_HWCAP)
350 return data_p[1];
351 }
352
353 offset += 2 * wordsize;
354 }
355
356 return 0;
357 }
358 #endif
359
360 static int
361 s390_check_regset (int pid, int regset, int regsize)
362 {
363 gdb_byte *buf = alloca (regsize);
364 struct iovec iov;
365
366 iov.iov_base = buf;
367 iov.iov_len = regsize;
368
369 if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) < 0)
370 return 0;
371 else
372 return 1;
373 }
374
375 static void
376 s390_arch_setup (void)
377 {
378 struct regset_info *regset;
379
380 /* Check whether the kernel supports extra register sets. */
381 int pid = pid_of (get_thread_lwp (current_inferior));
382 int have_regset_last_break
383 = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
384 int have_regset_system_call
385 = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
386
387 /* Update target_regsets according to available register sets. */
388 for (regset = target_regsets; regset->fill_function != NULL; regset++)
389 if (regset->get_request == PTRACE_GETREGSET)
390 switch (regset->nt_type)
391 {
392 case NT_S390_LAST_BREAK:
393 regset->size = have_regset_last_break? 8 : 0;
394 break;
395 case NT_S390_SYSTEM_CALL:
396 regset->size = have_regset_system_call? 4 : 0;
397 break;
398 default:
399 break;
400 }
401
402 /* Assume 31-bit inferior process. */
403 if (have_regset_system_call)
404 init_registers_s390_linux32v2 ();
405 else if (have_regset_last_break)
406 init_registers_s390_linux32v1 ();
407 else
408 init_registers_s390_linux32 ();
409
410 the_low_target.num_regs = s390_num_regs;
411 the_low_target.regmap = s390_regmap;
412
413 /* On a 64-bit host, check the low bit of the (31-bit) PSWM
414 -- if this is one, we actually have a 64-bit inferior. */
415 #ifdef __s390x__
416 {
417 unsigned int pswm;
418 struct regcache *regcache = new_register_cache ();
419 fetch_inferior_registers (regcache, find_regno ("pswm"));
420 collect_register_by_name (regcache, "pswm", &pswm);
421 free_register_cache (regcache);
422
423 if (pswm & 1)
424 {
425 if (have_regset_system_call)
426 init_registers_s390x_linux64v2 ();
427 else if (have_regset_last_break)
428 init_registers_s390x_linux64v1 ();
429 else
430 init_registers_s390x_linux64 ();
431 }
432
433 /* For a 31-bit inferior, check whether the kernel supports
434 using the full 64-bit GPRs. */
435 else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
436 {
437 if (have_regset_system_call)
438 init_registers_s390_linux64v2 ();
439 else if (have_regset_last_break)
440 init_registers_s390_linux64v1 ();
441 else
442 init_registers_s390_linux64 ();
443
444 the_low_target.num_regs = s390_num_regs_3264;
445 the_low_target.regmap = s390_regmap_3264;
446 }
447 }
448 #endif
449 }
450
451
452 static int
453 s390_breakpoint_at (CORE_ADDR pc)
454 {
455 unsigned char c[s390_breakpoint_len];
456 read_inferior_memory (pc, c, s390_breakpoint_len);
457 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
458 }
459
460
461 struct linux_target_ops the_low_target = {
462 s390_arch_setup,
463 s390_num_regs,
464 s390_regmap,
465 s390_cannot_fetch_register,
466 s390_cannot_store_register,
467 s390_get_pc,
468 s390_set_pc,
469 s390_breakpoint,
470 s390_breakpoint_len,
471 NULL,
472 s390_breakpoint_len,
473 s390_breakpoint_at,
474 NULL,
475 NULL,
476 NULL,
477 NULL,
478 s390_collect_ptrace_register,
479 s390_supply_ptrace_register,
480 };
This page took 0.052679 seconds and 4 git commands to generate.