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