* inf-ttrace.c: New file.
[external/binutils.git] / gdb / hppa-hpux-nat.c
1 /* Native-dependent code for PA-RISC HP-UX.
2
3    Copyright 2004 Free Software Foundation, Inc.
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
9    the Free Software Foundation; either version 2 of the License, or
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
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "inferior.h"
24 #include "regcache.h"
25 #include "target.h"
26
27 #include "gdb_assert.h"
28 #include <sys/ptrace.h>
29 #include <machine/save_state.h>
30
31 #ifdef HAVE_TTRACE
32 #include <sys/ttrace.h>
33 #endif
34
35 #include "hppa-tdep.h"
36 #include "inf-ptrace.h"
37 #include "inf-ttrace.h"
38
39 /* HP-UX 10.20 has a different name than HP-UX 11.00 and later.
40    Apparently, the intended usage changed.  Unfortunately HP didn't
41    care about backwards compatibility.  */
42 #ifdef ss_tlsp
43 #define ss_mpsfu_high ss_tlsp
44 #endif
45
46 int child_suppress_run = 0;     /* Non-zero if we should pretend not to be
47                                    a runnable target.  */
48
49 static int hppa_hpux_save_state_offset[] =
50 {
51   ssoff(ss_flags),
52   ssoff(ss_narrow.ss_gr1),
53   ssoff(ss_narrow.ss_rp),
54   ssoff(ss_narrow.ss_gr3),
55   ssoff(ss_narrow.ss_gr4),
56   ssoff(ss_narrow.ss_gr5),
57   ssoff(ss_narrow.ss_gr6),
58   ssoff(ss_narrow.ss_gr7),
59   ssoff(ss_narrow.ss_gr8),
60   ssoff(ss_narrow.ss_gr9),
61   ssoff(ss_narrow.ss_gr10),
62   ssoff(ss_narrow.ss_gr11),
63   ssoff(ss_narrow.ss_gr12),
64   ssoff(ss_narrow.ss_gr13),
65   ssoff(ss_narrow.ss_gr14),
66   ssoff(ss_narrow.ss_gr15),
67   ssoff(ss_narrow.ss_gr16),
68   ssoff(ss_narrow.ss_gr17),
69   ssoff(ss_narrow.ss_gr18),
70   ssoff(ss_narrow.ss_gr19),
71   ssoff(ss_narrow.ss_gr20),
72   ssoff(ss_narrow.ss_gr21),
73   ssoff(ss_narrow.ss_gr22),
74   ssoff(ss_narrow.ss_arg3),
75   ssoff(ss_narrow.ss_arg2),
76   ssoff(ss_narrow.ss_arg1),
77   ssoff(ss_narrow.ss_arg0),
78   ssoff(ss_narrow.ss_dp),
79   ssoff(ss_narrow.ss_ret0),
80   ssoff(ss_narrow.ss_ret1),
81   ssoff(ss_narrow.ss_sp),
82   ssoff(ss_narrow.ss_gr31),
83   ssoff(ss_narrow.ss_cr11),
84   ssoff(ss_narrow.ss_pcoq_head),
85   ssoff(ss_narrow.ss_pcsq_head),
86   ssoff(ss_narrow.ss_pcoq_tail),
87   ssoff(ss_narrow.ss_pcsq_tail),
88   ssoff(ss_narrow.ss_cr15),
89   ssoff(ss_narrow.ss_cr19),
90   ssoff(ss_narrow.ss_cr20),
91   ssoff(ss_narrow.ss_cr21),
92   ssoff(ss_narrow.ss_cr22),
93   ssoff(ss_narrow.ss_cpustate),
94   ssoff(ss_narrow.ss_sr4),
95   ssoff(ss_narrow.ss_sr0),
96   ssoff(ss_narrow.ss_sr1),
97   ssoff(ss_narrow.ss_sr2),
98   ssoff(ss_narrow.ss_sr3),
99   ssoff(ss_narrow.ss_sr5),
100   ssoff(ss_narrow.ss_sr6),
101   ssoff(ss_narrow.ss_sr7),
102   ssoff(ss_narrow.ss_cr0),
103   ssoff(ss_narrow.ss_cr8),
104   ssoff(ss_narrow.ss_cr9),
105   ssoff(ss_narrow.ss_cr10),
106   ssoff(ss_narrow.ss_cr12),
107   ssoff(ss_narrow.ss_cr13),
108   ssoff(ss_narrow.ss_cr24),
109   ssoff(ss_narrow.ss_cr25),
110   ssoff(ss_narrow.ss_cr26),
111   ssoff(ss_narrow.ss_mpsfu_high),
112   ssoff(ss_narrow.ss_mpsfu_low),
113   ssoff(ss_narrow.ss_mpsfu_ovflo),
114   ssoff(ss_pad),
115   ssoff(ss_frstat),
116   ssoff(ss_frexcp1),
117   ssoff(ss_frexcp2),
118   ssoff(ss_frexcp3),
119   ssoff(ss_frexcp4),
120   ssoff(ss_frexcp5),
121   ssoff(ss_frexcp6),
122   ssoff(ss_frexcp7),
123   ssoff(ss_fr4_hi),
124   ssoff(ss_fr4_lo),
125   ssoff(ss_fr5_hi),
126   ssoff(ss_fr5_lo),
127   ssoff(ss_fr6_hi),
128   ssoff(ss_fr6_lo),
129   ssoff(ss_fr7_hi),
130   ssoff(ss_fr7_lo),
131   ssoff(ss_fr8_hi),
132   ssoff(ss_fr8_lo),
133   ssoff(ss_fr9_hi),
134   ssoff(ss_fr9_lo),
135   ssoff(ss_fr10_hi),
136   ssoff(ss_fr10_lo),
137   ssoff(ss_fr11_hi),
138   ssoff(ss_fr11_lo),
139   ssoff(ss_fr12_hi),
140   ssoff(ss_fr12_lo),
141   ssoff(ss_fr13_hi),
142   ssoff(ss_fr13_lo),
143   ssoff(ss_fr14_hi),
144   ssoff(ss_fr14_lo),
145   ssoff(ss_fr15_hi),
146   ssoff(ss_fr15_lo),
147   ssoff(ss_fr16_hi),
148   ssoff(ss_fr16_lo),
149   ssoff(ss_fr17_hi),
150   ssoff(ss_fr17_lo),
151   ssoff(ss_fr18_hi),
152   ssoff(ss_fr18_lo),
153   ssoff(ss_fr19_hi),
154   ssoff(ss_fr19_lo),
155   ssoff(ss_fr20_hi),
156   ssoff(ss_fr20_lo),
157   ssoff(ss_fr21_hi),
158   ssoff(ss_fr21_lo),
159   ssoff(ss_fr22_hi),
160   ssoff(ss_fr22_lo),
161   ssoff(ss_fr23_hi),
162   ssoff(ss_fr23_lo),
163   ssoff(ss_fr24_hi),
164   ssoff(ss_fr24_lo),
165   ssoff(ss_fr25_hi),
166   ssoff(ss_fr25_lo),
167   ssoff(ss_fr26_hi),
168   ssoff(ss_fr26_lo),
169   ssoff(ss_fr27_hi),
170   ssoff(ss_fr27_lo),
171   ssoff(ss_fr28_hi),
172   ssoff(ss_fr28_lo),
173   ssoff(ss_fr29_hi),
174   ssoff(ss_fr29_lo),
175   ssoff(ss_fr30_hi),
176   ssoff(ss_fr30_lo),
177   ssoff(ss_fr31_hi),
178   ssoff(ss_fr31_lo)
179 };
180
181 static int
182 hppa_hpux_cannot_fetch_register (int regnum)
183 {
184   gdb_assert (regnum >= 0 && regnum < NUM_REGS);
185   return (regnum >= ARRAY_SIZE(hppa_hpux_save_state_offset));
186 }
187
188 static int
189 hppa_hpux_cannot_store_register (int regnum)
190 {
191   return hppa_hpux_cannot_fetch_register (regnum);
192 }
193
194 /* Just in case a future version of PA-RISC HP-UX won't have ptrace(2)
195    at all.  */
196 #ifndef PTRACE_TYPE_RET
197 #define PTRACE_TYPE_RET void
198 #endif
199
200 static void
201 hppa_hpux_fetch_register (int regnum)
202 {
203   CORE_ADDR addr;
204   size_t size;
205   PTRACE_TYPE_RET *buf;
206   pid_t pid;
207   int i;
208
209   if (hppa_hpux_cannot_fetch_register (regnum))
210     {
211       regcache_raw_supply (current_regcache, regnum, NULL);
212       return;
213     }
214
215   pid = ptid_get_pid (inferior_ptid);
216
217   /* This isn't really an address.  But ptrace thinks of it as one.  */
218   addr = hppa_hpux_save_state_offset[regnum];
219   size = register_size (current_gdbarch, regnum);
220
221   gdb_assert (size == 4 || size == 8);
222   buf = alloca (size);
223
224 #ifdef HAVE_TTRACE
225   {
226     lwpid_t lwp = ptid_get_lwp (inferior_ptid);
227
228     if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
229       error ("Couldn't read register %s (#%d): %s",
230              REGISTER_NAME (regnum), regnum, safe_strerror (errno));
231   }
232 #else
233   {
234     int i;
235
236     /* Read the register contents from the inferior a chuck at the time.  */
237     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
238       {
239         errno = 0;
240         buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0);
241         if (errno != 0)
242           error ("Couldn't read register %s (#%d): %s",
243                  REGISTER_NAME (regnum), regnum, safe_strerror (errno));
244
245         addr += sizeof (PTRACE_TYPE_RET);
246       }
247   }
248 #endif
249
250   regcache_raw_supply (current_regcache, regnum, buf);
251 }
252
253 static void
254 hppa_hpux_fetch_inferior_registers (int regnum)
255 {
256   if (regnum == -1)
257     for (regnum = 0; regnum < NUM_REGS; regnum++)
258       hppa_hpux_fetch_register (regnum);
259   else
260     hppa_hpux_fetch_register (regnum);
261 }
262
263 /* Store register REGNUM into the inferior.  */
264
265 static void
266 hppa_hpux_store_register (int regnum)
267 {
268   CORE_ADDR addr;
269   size_t size;
270   PTRACE_TYPE_RET *buf;
271   pid_t pid;
272
273   if (hppa_hpux_cannot_store_register (regnum))
274     return;
275
276   pid = ptid_get_pid (inferior_ptid);
277
278   /* This isn't really an address.  But ptrace thinks of it as one.  */
279   addr = hppa_hpux_save_state_offset[regnum];
280   size = register_size (current_gdbarch, regnum);
281
282   gdb_assert (size == 4 || size == 8);
283   buf = alloca (size);
284
285   regcache_raw_collect (current_regcache, regnum, buf);
286
287 #ifdef HAVE_TTRACE
288   {
289     lwpid_t lwp = ptid_get_lwp (inferior_ptid);
290
291     if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
292       error ("Couldn't write register %s (#%d): %s",
293              REGISTER_NAME (regnum), regnum, safe_strerror (errno));
294   }
295 #else
296   {
297     int i;
298
299     /* Write the register contents into the inferior a chunk at the time.  */
300     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
301       {
302         errno = 0;
303         ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
304         if (errno != 0)
305           error ("Couldn't write register %s (#%d): %s",
306                  REGISTER_NAME (regnum), regnum, safe_strerror (errno));
307
308         addr += sizeof (PTRACE_TYPE_RET);
309       }
310   }
311 #endif
312 }
313
314 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
315    this for all registers (including the floating point registers).  */
316
317 static void
318 hppa_hpux_store_inferior_registers (int regnum)
319 {
320   if (regnum == -1)
321     for (regnum = 0; regnum < NUM_REGS; regnum++)
322       hppa_hpux_store_register (regnum);
323   else
324     hppa_hpux_store_register (regnum);
325 }
326
327 static int
328 hppa_hpux_child_can_run (void)
329 {
330   /* This variable is controlled by modules that layer their own process
331      structure atop that provided here.  hpux-thread.c does this because
332      of the HP-UX user-mode level thread model.  */
333
334   return !child_suppress_run;
335 }
336 \f
337
338 /* Prevent warning from -Wmissing-prototypes.  */
339 void _initialize_hppa_hpux_nat (void);
340
341 void
342 _initialize_hppa_hpux_nat (void)
343 {
344   struct target_ops *t;
345
346 #ifdef HAVE_TTRACE
347   t = inf_ttrace_target ();
348 #else
349   t = inf_ptrace_target ();
350 #endif
351
352   t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
353   t->to_store_registers = hppa_hpux_store_inferior_registers;
354   t->to_can_run = hppa_hpux_child_can_run;
355
356   add_target (t);
357 }