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