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