* lib/gdb.exp (standard_output_file): Use "file join".
[deliverable/binutils-gdb.git] / gdb / hppa-hpux-nat.c
CommitLineData
eeb8076c
MK
1/* Native-dependent code for PA-RISC HP-UX.
2
0b302171 3 Copyright (C) 2004-2005, 2007-2012 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>
7b64a93b 27#include <sys/utsname.h>
eeb8076c
MK
28#include <machine/save_state.h>
29
eee22bf8
MK
30#ifdef HAVE_TTRACE
31#include <sys/ttrace.h>
32#endif
33
eeb8076c 34#include "hppa-tdep.h"
7b64a93b 35#include "solib-som.h"
eeb8076c 36#include "inf-ptrace.h"
eee22bf8
MK
37#include "inf-ttrace.h"
38
eeca586f
MK
39/* Return the offset of register REGNUM within `struct save_state'.
40 The offset returns depends on the flags in the "flags" register and
41 the register size (32-bit or 64-bit). These are taken from
42 REGCACHE. */
3f6306ec 43
eeca586f
MK
44LONGEST
45hppa_hpux_save_state_offset (struct regcache *regcache, int regnum)
eeb8076c 46{
eeca586f 47 LONGEST offset;
eeb8076c 48
eeca586f
MK
49 if (regnum == HPPA_FLAGS_REGNUM)
50 return ssoff (ss_flags);
eeb8076c 51
eeca586f
MK
52 if (HPPA_R0_REGNUM < regnum && regnum < HPPA_FP0_REGNUM)
53 {
54 struct gdbarch *arch = get_regcache_arch (regcache);
55 size_t size = register_size (arch, HPPA_R1_REGNUM);
56 ULONGEST flags;
57
58 gdb_assert (size == 4 || size == 8);
59
60 regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
61 if (flags & SS_WIDEREGS)
62 offset = ssoff (ss_wide) + (8 - size) + (regnum - HPPA_R0_REGNUM) * 8;
63 else
64 offset = ssoff (ss_narrow) + (regnum - HPPA_R1_REGNUM) * 4;
65 }
66 else
67 {
68 struct gdbarch *arch = get_regcache_arch (regcache);
69 size_t size = register_size (arch, HPPA_FP0_REGNUM);
70
71 gdb_assert (size == 4 || size == 8);
72 gdb_assert (regnum >= HPPA_FP0_REGNUM);
73 offset = ssoff(ss_fpblock) + (regnum - HPPA_FP0_REGNUM) * size;
74 }
75
76 gdb_assert (offset < sizeof (save_state_t));
77 return offset;
eeb8076c
MK
78}
79
eee22bf8
MK
80/* Just in case a future version of PA-RISC HP-UX won't have ptrace(2)
81 at all. */
82#ifndef PTRACE_TYPE_RET
83#define PTRACE_TYPE_RET void
84#endif
85
eeb8076c 86static void
56be3814 87hppa_hpux_fetch_register (struct regcache *regcache, int regnum)
eeb8076c 88{
464963c9 89 struct gdbarch *gdbarch = get_regcache_arch (regcache);
e17a4113 90 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
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 {
e17a4113
UW
138 ULONGEST flags;
139 flags = extract_unsigned_integer ((gdb_byte *)buf, 4, byte_order);
140 store_unsigned_integer ((gdb_byte *)buf, 8, byte_order, flags);
eeca586f
MK
141 }
142
56be3814 143 regcache_raw_supply (regcache, regnum, buf);
eeb8076c
MK
144}
145
146static void
28439f5e
PA
147hppa_hpux_fetch_inferior_registers (struct target_ops *ops,
148 struct regcache *regcache, int regnum)
eeb8076c
MK
149{
150 if (regnum == -1)
464963c9
UW
151 for (regnum = 0;
152 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
153 regnum++)
56be3814 154 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c 155 else
56be3814 156 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c
MK
157}
158
159/* Store register REGNUM into the inferior. */
160
161static void
56be3814 162hppa_hpux_store_register (struct regcache *regcache, int regnum)
eeb8076c 163{
464963c9 164 struct gdbarch *gdbarch = get_regcache_arch (regcache);
e17a4113 165 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
261224b2 166 CORE_ADDR addr;
eeb8076c
MK
167 size_t size;
168 PTRACE_TYPE_RET *buf;
169 pid_t pid;
eeb8076c 170
eee22bf8 171 pid = ptid_get_pid (inferior_ptid);
eeb8076c 172
eeca586f 173 /* This isn't really an address, but ptrace thinks of it as one. */
56be3814 174 addr = hppa_hpux_save_state_offset (regcache, regnum);
464963c9 175 size = register_size (gdbarch, regnum);
eeb8076c 176
eee22bf8 177 gdb_assert (size == 4 || size == 8);
eeb8076c
MK
178 buf = alloca (size);
179
56be3814 180 regcache_raw_collect (regcache, regnum, buf);
eeb8076c 181
eeca586f
MK
182 /* Take care with the "flags" register. It's stored as an `int' in
183 `struct save_state', even for 64-bit code. */
184 if (regnum == HPPA_FLAGS_REGNUM && size == 8)
185 {
e17a4113
UW
186 ULONGEST flags;
187 flags = extract_unsigned_integer ((gdb_byte *)buf, 8, byte_order);
188 store_unsigned_integer ((gdb_byte *)buf, 4, byte_order, flags);
eeca586f
MK
189 size = 4;
190 }
191
eee22bf8
MK
192#ifdef HAVE_TTRACE
193 {
194 lwpid_t lwp = ptid_get_lwp (inferior_ptid);
195
196 if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
8a3fe4f8 197 error (_("Couldn't write register %s (#%d): %s"),
464963c9 198 gdbarch_register_name (gdbarch, regnum),
c9f4d572 199 regnum, safe_strerror (errno));
eee22bf8
MK
200 }
201#else
202 {
203 int i;
204
205 /* Write the register contents into the inferior a chunk at the time. */
206 for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
207 {
208 errno = 0;
209 ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
210 if (errno != 0)
8a3fe4f8 211 error (_("Couldn't write register %s (#%d): %s"),
464963c9 212 gdbarch_register_name (gdbarch, regnum),
c9f4d572 213 regnum, safe_strerror (errno));
eee22bf8
MK
214
215 addr += sizeof (PTRACE_TYPE_RET);
216 }
217 }
218#endif
eeb8076c
MK
219}
220
221/* Store register REGNUM back into the inferior. If REGNUM is -1, do
222 this for all registers (including the floating point registers). */
223
224static void
28439f5e
PA
225hppa_hpux_store_inferior_registers (struct target_ops *ops,
226 struct regcache *regcache, int regnum)
eeb8076c
MK
227{
228 if (regnum == -1)
464963c9
UW
229 for (regnum = 0;
230 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
231 regnum++)
56be3814 232 hppa_hpux_store_register (regcache, regnum);
eeb8076c 233 else
56be3814 234 hppa_hpux_store_register (regcache, regnum);
eeb8076c 235}
3f6306ec 236
7b64a93b
PM
237/* Set hpux_major_release variable to the value retrieved from a call to
238 uname function. */
239
240static void
241set_hpux_major_release (void)
242{
243 struct utsname x;
244 char *p;
245
246 uname (&x);
247 p = strchr (x.release, '.');
248 if (p)
249 hpux_major_release = atoi (p + 1);
250}
251
eeb8076c
MK
252\f
253
254/* Prevent warning from -Wmissing-prototypes. */
255void _initialize_hppa_hpux_nat (void);
256
257void
258_initialize_hppa_hpux_nat (void)
259{
260 struct target_ops *t;
261
7b64a93b
PM
262 set_hpux_major_release ();
263
eee22bf8
MK
264#ifdef HAVE_TTRACE
265 t = inf_ttrace_target ();
266#else
eeb8076c 267 t = inf_ptrace_target ();
eee22bf8
MK
268#endif
269
eeb8076c
MK
270 t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
271 t->to_store_registers = hppa_hpux_store_inferior_registers;
eee22bf8 272
eeb8076c
MK
273 add_target (t);
274}
This page took 0.551743 seconds and 4 git commands to generate.