* defs.h (extract_signed_integer, extract_unsigned_integer,
[deliverable/binutils-gdb.git] / gdb / hppa-hpux-nat.c
CommitLineData
eeb8076c
MK
1/* Native-dependent code for PA-RISC HP-UX.
2
0fb0cc75 3 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
eeb8076c
MK
4
5 This file is part of GDB.
6
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
eeb8076c
MK
10 (at your option) any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
eeb8076c
MK
19
20#include "defs.h"
21#include "inferior.h"
22#include "regcache.h"
23#include "target.h"
24
25#include "gdb_assert.h"
26#include <sys/ptrace.h>
27#include <machine/save_state.h>
28
eee22bf8
MK
29#ifdef HAVE_TTRACE
30#include <sys/ttrace.h>
31#endif
32
eeb8076c
MK
33#include "hppa-tdep.h"
34#include "inf-ptrace.h"
eee22bf8
MK
35#include "inf-ttrace.h"
36
eeca586f
MK
37/* Non-zero if we should pretend not to be a runnable target. */
38int child_suppress_run = 0;
eeb8076c 39
eeca586f
MK
40/* Return the offset of register REGNUM within `struct save_state'.
41 The offset returns depends on the flags in the "flags" register and
42 the register size (32-bit or 64-bit). These are taken from
43 REGCACHE. */
3f6306ec 44
eeca586f
MK
45LONGEST
46hppa_hpux_save_state_offset (struct regcache *regcache, int regnum)
eeb8076c 47{
eeca586f 48 LONGEST offset;
eeb8076c 49
eeca586f
MK
50 if (regnum == HPPA_FLAGS_REGNUM)
51 return ssoff (ss_flags);
eeb8076c 52
eeca586f
MK
53 if (HPPA_R0_REGNUM < regnum && regnum < HPPA_FP0_REGNUM)
54 {
55 struct gdbarch *arch = get_regcache_arch (regcache);
56 size_t size = register_size (arch, HPPA_R1_REGNUM);
57 ULONGEST flags;
58
59 gdb_assert (size == 4 || size == 8);
60
61 regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
62 if (flags & SS_WIDEREGS)
63 offset = ssoff (ss_wide) + (8 - size) + (regnum - HPPA_R0_REGNUM) * 8;
64 else
65 offset = ssoff (ss_narrow) + (regnum - HPPA_R1_REGNUM) * 4;
66 }
67 else
68 {
69 struct gdbarch *arch = get_regcache_arch (regcache);
70 size_t size = register_size (arch, HPPA_FP0_REGNUM);
71
72 gdb_assert (size == 4 || size == 8);
73 gdb_assert (regnum >= HPPA_FP0_REGNUM);
74 offset = ssoff(ss_fpblock) + (regnum - HPPA_FP0_REGNUM) * size;
75 }
76
77 gdb_assert (offset < sizeof (save_state_t));
78 return offset;
eeb8076c
MK
79}
80
eee22bf8
MK
81/* Just in case a future version of PA-RISC HP-UX won't have ptrace(2)
82 at all. */
83#ifndef PTRACE_TYPE_RET
84#define PTRACE_TYPE_RET void
85#endif
86
eeb8076c 87static void
56be3814 88hppa_hpux_fetch_register (struct regcache *regcache, int regnum)
eeb8076c 89{
464963c9 90 struct gdbarch *gdbarch = get_regcache_arch (regcache);
e17a4113 91 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
eeb8076c
MK
92 CORE_ADDR addr;
93 size_t size;
94 PTRACE_TYPE_RET *buf;
95 pid_t pid;
96 int i;
97
eee22bf8 98 pid = ptid_get_pid (inferior_ptid);
eeb8076c 99
eeca586f 100 /* This isn't really an address, but ptrace thinks of it as one. */
56be3814 101 addr = hppa_hpux_save_state_offset (regcache, regnum);
464963c9 102 size = register_size (gdbarch, regnum);
eeb8076c 103
eee22bf8 104 gdb_assert (size == 4 || size == 8);
eeb8076c
MK
105 buf = alloca (size);
106
eee22bf8
MK
107#ifdef HAVE_TTRACE
108 {
109 lwpid_t lwp = ptid_get_lwp (inferior_ptid);
110
111 if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
8a3fe4f8 112 error (_("Couldn't read register %s (#%d): %s"),
464963c9 113 gdbarch_register_name (gdbarch, regnum),
c9f4d572 114 regnum, safe_strerror (errno));
eee22bf8
MK
115 }
116#else
117 {
118 int i;
119
120 /* Read the register contents from the inferior a chuck at the time. */
121 for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
122 {
123 errno = 0;
124 buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0);
125 if (errno != 0)
8a3fe4f8 126 error (_("Couldn't read register %s (#%d): %s"),
464963c9 127 gdbarch_register_name (gdbarch, regnum),
c9f4d572 128 regnum, safe_strerror (errno));
eee22bf8
MK
129
130 addr += sizeof (PTRACE_TYPE_RET);
131 }
132 }
133#endif
eeb8076c 134
eeca586f
MK
135 /* Take care with the "flags" register. It's stored as an `int' in
136 `struct save_state', even for 64-bit code. */
137 if (regnum == HPPA_FLAGS_REGNUM && size == 8)
138 {
e17a4113
UW
139 ULONGEST flags;
140 flags = extract_unsigned_integer ((gdb_byte *)buf, 4, byte_order);
141 store_unsigned_integer ((gdb_byte *)buf, 8, byte_order, flags);
eeca586f
MK
142 }
143
56be3814 144 regcache_raw_supply (regcache, regnum, buf);
eeb8076c
MK
145}
146
147static void
28439f5e
PA
148hppa_hpux_fetch_inferior_registers (struct target_ops *ops,
149 struct regcache *regcache, int regnum)
eeb8076c
MK
150{
151 if (regnum == -1)
464963c9
UW
152 for (regnum = 0;
153 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
154 regnum++)
56be3814 155 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c 156 else
56be3814 157 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c
MK
158}
159
160/* Store register REGNUM into the inferior. */
161
162static void
56be3814 163hppa_hpux_store_register (struct regcache *regcache, int regnum)
eeb8076c 164{
464963c9 165 struct gdbarch *gdbarch = get_regcache_arch (regcache);
e17a4113 166 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
261224b2 167 CORE_ADDR addr;
eeb8076c
MK
168 size_t size;
169 PTRACE_TYPE_RET *buf;
170 pid_t pid;
eeb8076c 171
eee22bf8 172 pid = ptid_get_pid (inferior_ptid);
eeb8076c 173
eeca586f 174 /* This isn't really an address, but ptrace thinks of it as one. */
56be3814 175 addr = hppa_hpux_save_state_offset (regcache, regnum);
464963c9 176 size = register_size (gdbarch, regnum);
eeb8076c 177
eee22bf8 178 gdb_assert (size == 4 || size == 8);
eeb8076c
MK
179 buf = alloca (size);
180
56be3814 181 regcache_raw_collect (regcache, regnum, buf);
eeb8076c 182
eeca586f
MK
183 /* Take care with the "flags" register. It's stored as an `int' in
184 `struct save_state', even for 64-bit code. */
185 if (regnum == HPPA_FLAGS_REGNUM && size == 8)
186 {
e17a4113
UW
187 ULONGEST flags;
188 flags = extract_unsigned_integer ((gdb_byte *)buf, 8, byte_order);
189 store_unsigned_integer ((gdb_byte *)buf, 4, byte_order, flags);
eeca586f
MK
190 size = 4;
191 }
192
eee22bf8
MK
193#ifdef HAVE_TTRACE
194 {
195 lwpid_t lwp = ptid_get_lwp (inferior_ptid);
196
197 if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
8a3fe4f8 198 error (_("Couldn't write register %s (#%d): %s"),
464963c9 199 gdbarch_register_name (gdbarch, regnum),
c9f4d572 200 regnum, safe_strerror (errno));
eee22bf8
MK
201 }
202#else
203 {
204 int i;
205
206 /* Write the register contents into the inferior a chunk at the time. */
207 for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
208 {
209 errno = 0;
210 ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
211 if (errno != 0)
8a3fe4f8 212 error (_("Couldn't write register %s (#%d): %s"),
464963c9 213 gdbarch_register_name (gdbarch, regnum),
c9f4d572 214 regnum, safe_strerror (errno));
eee22bf8
MK
215
216 addr += sizeof (PTRACE_TYPE_RET);
217 }
218 }
219#endif
eeb8076c
MK
220}
221
222/* Store register REGNUM back into the inferior. If REGNUM is -1, do
223 this for all registers (including the floating point registers). */
224
225static void
28439f5e
PA
226hppa_hpux_store_inferior_registers (struct target_ops *ops,
227 struct regcache *regcache, int regnum)
eeb8076c
MK
228{
229 if (regnum == -1)
464963c9
UW
230 for (regnum = 0;
231 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
232 regnum++)
56be3814 233 hppa_hpux_store_register (regcache, regnum);
eeb8076c 234 else
56be3814 235 hppa_hpux_store_register (regcache, regnum);
eeb8076c 236}
3f6306ec
DA
237
238static int
239hppa_hpux_child_can_run (void)
240{
eeca586f 241 /* This variable is controlled by modules that layer their own
0d9b270c
MK
242 process structure atop that provided here. The code in
243 hpux-thread.c does this to support the HP-UX user-mode DCE
244 threads. */
3f6306ec
DA
245 return !child_suppress_run;
246}
eeb8076c
MK
247\f
248
249/* Prevent warning from -Wmissing-prototypes. */
250void _initialize_hppa_hpux_nat (void);
251
252void
253_initialize_hppa_hpux_nat (void)
254{
255 struct target_ops *t;
256
eee22bf8
MK
257#ifdef HAVE_TTRACE
258 t = inf_ttrace_target ();
259#else
eeb8076c 260 t = inf_ptrace_target ();
eee22bf8
MK
261#endif
262
eeb8076c
MK
263 t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
264 t->to_store_registers = hppa_hpux_store_inferior_registers;
3f6306ec 265 t->to_can_run = hppa_hpux_child_can_run;
eee22bf8 266
eeb8076c
MK
267 add_target (t);
268}
This page took 0.395318 seconds and 4 git commands to generate.