Update copyright year in most headers.
[platform/upstream/binutils.git] / gdb / hppa-hpux-nat.c
1 /* Native-dependent code for PA-RISC HP-UX.
2
3    Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
4    Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "inferior.h"
23 #include "regcache.h"
24 #include "target.h"
25
26 #include "gdb_assert.h"
27 #include <sys/ptrace.h>
28 #include <machine/save_state.h>
29
30 #ifdef HAVE_TTRACE
31 #include <sys/ttrace.h>
32 #endif
33
34 #include "hppa-tdep.h"
35 #include "inf-ptrace.h"
36 #include "inf-ttrace.h"
37
38 /* Non-zero if we should pretend not to be a runnable target.  */
39 int child_suppress_run = 0;
40
41 /* Return the offset of register REGNUM within `struct save_state'.
42    The offset returns depends on the flags in the "flags" register and
43    the register size (32-bit or 64-bit).  These are taken from
44    REGCACHE.  */
45
46 LONGEST
47 hppa_hpux_save_state_offset (struct regcache *regcache, int regnum)
48 {
49   LONGEST offset;
50
51   if (regnum == HPPA_FLAGS_REGNUM)
52     return ssoff (ss_flags);
53
54   if (HPPA_R0_REGNUM < regnum && regnum < HPPA_FP0_REGNUM)
55     {
56       struct gdbarch *arch = get_regcache_arch (regcache);
57       size_t size = register_size (arch, HPPA_R1_REGNUM);
58       ULONGEST flags;
59
60       gdb_assert (size == 4 || size == 8);
61
62       regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
63       if (flags & SS_WIDEREGS)
64         offset = ssoff (ss_wide) + (8 - size) + (regnum - HPPA_R0_REGNUM) * 8;
65       else
66         offset = ssoff (ss_narrow) + (regnum - HPPA_R1_REGNUM) * 4;
67     }
68   else
69     {
70       struct gdbarch *arch = get_regcache_arch (regcache);
71       size_t size = register_size (arch, HPPA_FP0_REGNUM);
72
73       gdb_assert (size == 4 || size == 8);
74       gdb_assert (regnum >= HPPA_FP0_REGNUM);
75       offset = ssoff(ss_fpblock) + (regnum - HPPA_FP0_REGNUM) * size;
76     }
77
78   gdb_assert (offset < sizeof (save_state_t));
79   return offset;
80 }
81
82 /* Just in case a future version of PA-RISC HP-UX won't have ptrace(2)
83    at all.  */
84 #ifndef PTRACE_TYPE_RET
85 #define PTRACE_TYPE_RET void
86 #endif
87
88 static void
89 hppa_hpux_fetch_register (struct regcache *regcache, int regnum)
90 {
91   struct gdbarch *gdbarch = get_regcache_arch (regcache);
92   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
93   CORE_ADDR addr;
94   size_t size;
95   PTRACE_TYPE_RET *buf;
96   pid_t pid;
97   int i;
98
99   pid = ptid_get_pid (inferior_ptid);
100
101   /* This isn't really an address, but ptrace thinks of it as one.  */
102   addr = hppa_hpux_save_state_offset (regcache, regnum);
103   size = register_size (gdbarch, regnum);
104
105   gdb_assert (size == 4 || size == 8);
106   buf = alloca (size);
107
108 #ifdef HAVE_TTRACE
109   {
110     lwpid_t lwp = ptid_get_lwp (inferior_ptid);
111
112     if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
113       error (_("Couldn't read register %s (#%d): %s"),
114              gdbarch_register_name (gdbarch, regnum),
115              regnum, safe_strerror (errno));
116   }
117 #else
118   {
119     int i;
120
121     /* Read the register contents from the inferior a chuck at the time.  */
122     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
123       {
124         errno = 0;
125         buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0);
126         if (errno != 0)
127           error (_("Couldn't read register %s (#%d): %s"),
128                  gdbarch_register_name (gdbarch, regnum),
129                  regnum, safe_strerror (errno));
130
131         addr += sizeof (PTRACE_TYPE_RET);
132       }
133   }
134 #endif
135
136   /* Take care with the "flags" register.  It's stored as an `int' in
137      `struct save_state', even for 64-bit code.  */
138   if (regnum == HPPA_FLAGS_REGNUM && size == 8)
139     {
140       ULONGEST flags;
141       flags = extract_unsigned_integer ((gdb_byte *)buf, 4, byte_order);
142       store_unsigned_integer ((gdb_byte *)buf, 8, byte_order, flags);
143     }
144
145   regcache_raw_supply (regcache, regnum, buf);
146 }
147
148 static void
149 hppa_hpux_fetch_inferior_registers (struct target_ops *ops,
150                                     struct regcache *regcache, int regnum)
151 {
152   if (regnum == -1)
153     for (regnum = 0;
154          regnum < gdbarch_num_regs (get_regcache_arch (regcache));
155          regnum++)
156       hppa_hpux_fetch_register (regcache, regnum);
157   else
158     hppa_hpux_fetch_register (regcache, regnum);
159 }
160
161 /* Store register REGNUM into the inferior.  */
162
163 static void
164 hppa_hpux_store_register (struct regcache *regcache, int regnum)
165 {
166   struct gdbarch *gdbarch = get_regcache_arch (regcache);
167   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
168   CORE_ADDR addr;
169   size_t size;
170   PTRACE_TYPE_RET *buf;
171   pid_t pid;
172
173   pid = ptid_get_pid (inferior_ptid);
174
175   /* This isn't really an address, but ptrace thinks of it as one.  */
176   addr = hppa_hpux_save_state_offset (regcache, regnum);
177   size = register_size (gdbarch, regnum);
178
179   gdb_assert (size == 4 || size == 8);
180   buf = alloca (size);
181
182   regcache_raw_collect (regcache, regnum, buf);
183
184   /* Take care with the "flags" register.  It's stored as an `int' in
185      `struct save_state', even for 64-bit code.  */
186   if (regnum == HPPA_FLAGS_REGNUM && size == 8)
187     {
188       ULONGEST flags;
189       flags = extract_unsigned_integer ((gdb_byte *)buf, 8, byte_order);
190       store_unsigned_integer ((gdb_byte *)buf, 4, byte_order, flags);
191       size = 4;
192     }
193
194 #ifdef HAVE_TTRACE
195   {
196     lwpid_t lwp = ptid_get_lwp (inferior_ptid);
197
198     if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
199       error (_("Couldn't write register %s (#%d): %s"),
200              gdbarch_register_name (gdbarch, regnum),
201              regnum, safe_strerror (errno));
202   }
203 #else
204   {
205     int i;
206
207     /* Write the register contents into the inferior a chunk at the time.  */
208     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
209       {
210         errno = 0;
211         ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
212         if (errno != 0)
213           error (_("Couldn't write register %s (#%d): %s"),
214                  gdbarch_register_name (gdbarch, regnum),
215                  regnum, safe_strerror (errno));
216
217         addr += sizeof (PTRACE_TYPE_RET);
218       }
219   }
220 #endif
221 }
222
223 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
224    this for all registers (including the floating point registers).  */
225
226 static void
227 hppa_hpux_store_inferior_registers (struct target_ops *ops,
228                                     struct regcache *regcache, int regnum)
229 {
230   if (regnum == -1)
231     for (regnum = 0;
232          regnum < gdbarch_num_regs (get_regcache_arch (regcache));
233          regnum++)
234       hppa_hpux_store_register (regcache, regnum);
235   else
236     hppa_hpux_store_register (regcache, regnum);
237 }
238
239 static int
240 hppa_hpux_child_can_run (void)
241 {
242   /* This variable is controlled by modules that layer their own
243      process structure atop that provided here.  The code in
244      hpux-thread.c does this to support the HP-UX user-mode DCE
245      threads.  */
246   return !child_suppress_run;
247 }
248 \f
249
250 /* Prevent warning from -Wmissing-prototypes.  */
251 void _initialize_hppa_hpux_nat (void);
252
253 void
254 _initialize_hppa_hpux_nat (void)
255 {
256   struct target_ops *t;
257
258 #ifdef HAVE_TTRACE
259   t = inf_ttrace_target ();
260 #else
261   t = inf_ptrace_target ();
262 #endif
263
264   t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
265   t->to_store_registers = hppa_hpux_store_inferior_registers;
266   t->to_can_run = hppa_hpux_child_can_run;
267
268   add_target (t);
269 }