gdb
[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);
eeb8076c
MK
91 CORE_ADDR addr;
92 size_t size;
93 PTRACE_TYPE_RET *buf;
94 pid_t pid;
95 int i;
96
eee22bf8 97 pid = ptid_get_pid (inferior_ptid);
eeb8076c 98
eeca586f 99 /* This isn't really an address, but ptrace thinks of it as one. */
56be3814 100 addr = hppa_hpux_save_state_offset (regcache, regnum);
464963c9 101 size = register_size (gdbarch, regnum);
eeb8076c 102
eee22bf8 103 gdb_assert (size == 4 || size == 8);
eeb8076c
MK
104 buf = alloca (size);
105
eee22bf8
MK
106#ifdef HAVE_TTRACE
107 {
108 lwpid_t lwp = ptid_get_lwp (inferior_ptid);
109
110 if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
8a3fe4f8 111 error (_("Couldn't read register %s (#%d): %s"),
464963c9 112 gdbarch_register_name (gdbarch, regnum),
c9f4d572 113 regnum, safe_strerror (errno));
eee22bf8
MK
114 }
115#else
116 {
117 int i;
118
119 /* Read the register contents from the inferior a chuck at the time. */
120 for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
121 {
122 errno = 0;
123 buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0);
124 if (errno != 0)
8a3fe4f8 125 error (_("Couldn't read register %s (#%d): %s"),
464963c9 126 gdbarch_register_name (gdbarch, regnum),
c9f4d572 127 regnum, safe_strerror (errno));
eee22bf8
MK
128
129 addr += sizeof (PTRACE_TYPE_RET);
130 }
131 }
132#endif
eeb8076c 133
eeca586f
MK
134 /* Take care with the "flags" register. It's stored as an `int' in
135 `struct save_state', even for 64-bit code. */
136 if (regnum == HPPA_FLAGS_REGNUM && size == 8)
137 {
0d559b99
MK
138 ULONGEST flags = extract_unsigned_integer ((gdb_byte *)buf, 4);
139 store_unsigned_integer ((gdb_byte *)buf, 8, flags);
eeca586f
MK
140 }
141
56be3814 142 regcache_raw_supply (regcache, regnum, buf);
eeb8076c
MK
143}
144
145static void
28439f5e
PA
146hppa_hpux_fetch_inferior_registers (struct target_ops *ops,
147 struct regcache *regcache, int regnum)
eeb8076c
MK
148{
149 if (regnum == -1)
464963c9
UW
150 for (regnum = 0;
151 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
152 regnum++)
56be3814 153 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c 154 else
56be3814 155 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c
MK
156}
157
158/* Store register REGNUM into the inferior. */
159
160static void
56be3814 161hppa_hpux_store_register (struct regcache *regcache, int regnum)
eeb8076c 162{
464963c9 163 struct gdbarch *gdbarch = get_regcache_arch (regcache);
261224b2 164 CORE_ADDR addr;
eeb8076c
MK
165 size_t size;
166 PTRACE_TYPE_RET *buf;
167 pid_t pid;
eeb8076c 168
eee22bf8 169 pid = ptid_get_pid (inferior_ptid);
eeb8076c 170
eeca586f 171 /* This isn't really an address, but ptrace thinks of it as one. */
56be3814 172 addr = hppa_hpux_save_state_offset (regcache, regnum);
464963c9 173 size = register_size (gdbarch, regnum);
eeb8076c 174
eee22bf8 175 gdb_assert (size == 4 || size == 8);
eeb8076c
MK
176 buf = alloca (size);
177
56be3814 178 regcache_raw_collect (regcache, regnum, buf);
eeb8076c 179
eeca586f
MK
180 /* Take care with the "flags" register. It's stored as an `int' in
181 `struct save_state', even for 64-bit code. */
182 if (regnum == HPPA_FLAGS_REGNUM && size == 8)
183 {
0d559b99
MK
184 ULONGEST flags = extract_unsigned_integer ((gdb_byte *)buf, 8);
185 store_unsigned_integer ((gdb_byte *)buf, 4, flags);
eeca586f
MK
186 size = 4;
187 }
188
eee22bf8
MK
189#ifdef HAVE_TTRACE
190 {
191 lwpid_t lwp = ptid_get_lwp (inferior_ptid);
192
193 if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
8a3fe4f8 194 error (_("Couldn't write register %s (#%d): %s"),
464963c9 195 gdbarch_register_name (gdbarch, regnum),
c9f4d572 196 regnum, safe_strerror (errno));
eee22bf8
MK
197 }
198#else
199 {
200 int i;
201
202 /* Write the register contents into the inferior a chunk at the time. */
203 for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
204 {
205 errno = 0;
206 ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
207 if (errno != 0)
8a3fe4f8 208 error (_("Couldn't write register %s (#%d): %s"),
464963c9 209 gdbarch_register_name (gdbarch, regnum),
c9f4d572 210 regnum, safe_strerror (errno));
eee22bf8
MK
211
212 addr += sizeof (PTRACE_TYPE_RET);
213 }
214 }
215#endif
eeb8076c
MK
216}
217
218/* Store register REGNUM back into the inferior. If REGNUM is -1, do
219 this for all registers (including the floating point registers). */
220
221static void
28439f5e
PA
222hppa_hpux_store_inferior_registers (struct target_ops *ops,
223 struct regcache *regcache, int regnum)
eeb8076c
MK
224{
225 if (regnum == -1)
464963c9
UW
226 for (regnum = 0;
227 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
228 regnum++)
56be3814 229 hppa_hpux_store_register (regcache, regnum);
eeb8076c 230 else
56be3814 231 hppa_hpux_store_register (regcache, regnum);
eeb8076c 232}
3f6306ec
DA
233
234static int
235hppa_hpux_child_can_run (void)
236{
eeca586f 237 /* This variable is controlled by modules that layer their own
0d9b270c
MK
238 process structure atop that provided here. The code in
239 hpux-thread.c does this to support the HP-UX user-mode DCE
240 threads. */
3f6306ec
DA
241 return !child_suppress_run;
242}
eeb8076c
MK
243\f
244
245/* Prevent warning from -Wmissing-prototypes. */
246void _initialize_hppa_hpux_nat (void);
247
248void
249_initialize_hppa_hpux_nat (void)
250{
251 struct target_ops *t;
252
eee22bf8
MK
253#ifdef HAVE_TTRACE
254 t = inf_ttrace_target ();
255#else
eeb8076c 256 t = inf_ptrace_target ();
eee22bf8
MK
257#endif
258
eeb8076c
MK
259 t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
260 t->to_store_registers = hppa_hpux_store_inferior_registers;
3f6306ec 261 t->to_can_run = hppa_hpux_child_can_run;
eee22bf8 262
eeb8076c
MK
263 add_target (t);
264}
This page took 0.297356 seconds and 4 git commands to generate.