* solib-svr4.c (LM_ADDR_FROM_LINK_MAP): Use builtin types of
[deliverable/binutils-gdb.git] / gdb / hppa-hpux-nat.c
CommitLineData
eeb8076c
MK
1/* Native-dependent code for PA-RISC HP-UX.
2
9b254dd1 3 Copyright (C) 2004, 2005, 2007, 2008 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
56be3814 146hppa_hpux_fetch_inferior_registers (struct regcache *regcache, int regnum)
eeb8076c
MK
147{
148 if (regnum == -1)
464963c9
UW
149 for (regnum = 0;
150 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
151 regnum++)
56be3814 152 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c 153 else
56be3814 154 hppa_hpux_fetch_register (regcache, regnum);
eeb8076c
MK
155}
156
157/* Store register REGNUM into the inferior. */
158
159static void
56be3814 160hppa_hpux_store_register (struct regcache *regcache, int regnum)
eeb8076c 161{
464963c9 162 struct gdbarch *gdbarch = get_regcache_arch (regcache);
261224b2 163 CORE_ADDR addr;
eeb8076c
MK
164 size_t size;
165 PTRACE_TYPE_RET *buf;
166 pid_t pid;
eeb8076c 167
eee22bf8 168 pid = ptid_get_pid (inferior_ptid);
eeb8076c 169
eeca586f 170 /* This isn't really an address, but ptrace thinks of it as one. */
56be3814 171 addr = hppa_hpux_save_state_offset (regcache, regnum);
464963c9 172 size = register_size (gdbarch, regnum);
eeb8076c 173
eee22bf8 174 gdb_assert (size == 4 || size == 8);
eeb8076c
MK
175 buf = alloca (size);
176
56be3814 177 regcache_raw_collect (regcache, regnum, buf);
eeb8076c 178
eeca586f
MK
179 /* Take care with the "flags" register. It's stored as an `int' in
180 `struct save_state', even for 64-bit code. */
181 if (regnum == HPPA_FLAGS_REGNUM && size == 8)
182 {
0d559b99
MK
183 ULONGEST flags = extract_unsigned_integer ((gdb_byte *)buf, 8);
184 store_unsigned_integer ((gdb_byte *)buf, 4, flags);
eeca586f
MK
185 size = 4;
186 }
187
eee22bf8
MK
188#ifdef HAVE_TTRACE
189 {
190 lwpid_t lwp = ptid_get_lwp (inferior_ptid);
191
192 if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
8a3fe4f8 193 error (_("Couldn't write register %s (#%d): %s"),
464963c9 194 gdbarch_register_name (gdbarch, regnum),
c9f4d572 195 regnum, safe_strerror (errno));
eee22bf8
MK
196 }
197#else
198 {
199 int i;
200
201 /* Write the register contents into the inferior a chunk at the time. */
202 for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
203 {
204 errno = 0;
205 ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
206 if (errno != 0)
8a3fe4f8 207 error (_("Couldn't write register %s (#%d): %s"),
464963c9 208 gdbarch_register_name (gdbarch, regnum),
c9f4d572 209 regnum, safe_strerror (errno));
eee22bf8
MK
210
211 addr += sizeof (PTRACE_TYPE_RET);
212 }
213 }
214#endif
eeb8076c
MK
215}
216
217/* Store register REGNUM back into the inferior. If REGNUM is -1, do
218 this for all registers (including the floating point registers). */
219
220static void
56be3814 221hppa_hpux_store_inferior_registers (struct regcache *regcache, int regnum)
eeb8076c
MK
222{
223 if (regnum == -1)
464963c9
UW
224 for (regnum = 0;
225 regnum < gdbarch_num_regs (get_regcache_arch (regcache));
226 regnum++)
56be3814 227 hppa_hpux_store_register (regcache, regnum);
eeb8076c 228 else
56be3814 229 hppa_hpux_store_register (regcache, regnum);
eeb8076c 230}
3f6306ec
DA
231
232static int
233hppa_hpux_child_can_run (void)
234{
eeca586f 235 /* This variable is controlled by modules that layer their own
0d9b270c
MK
236 process structure atop that provided here. The code in
237 hpux-thread.c does this to support the HP-UX user-mode DCE
238 threads. */
3f6306ec
DA
239 return !child_suppress_run;
240}
eeb8076c
MK
241\f
242
243/* Prevent warning from -Wmissing-prototypes. */
244void _initialize_hppa_hpux_nat (void);
245
246void
247_initialize_hppa_hpux_nat (void)
248{
249 struct target_ops *t;
250
eee22bf8
MK
251#ifdef HAVE_TTRACE
252 t = inf_ttrace_target ();
253#else
eeb8076c 254 t = inf_ptrace_target ();
eee22bf8
MK
255#endif
256
eeb8076c
MK
257 t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
258 t->to_store_registers = hppa_hpux_store_inferior_registers;
3f6306ec 259 t->to_can_run = hppa_hpux_child_can_run;
eee22bf8 260
eeb8076c
MK
261 add_target (t);
262}
This page took 0.278578 seconds and 4 git commands to generate.