2012-05-11 Yao Qi <yao@codesourcery.com>
[external/binutils.git] / gdb / ia64-hpux-tdep.c
1 /* Target-dependent code for the IA-64 for GDB, the GNU debugger.
2
3    Copyright (C) 2010, 2012 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "ia64-tdep.h"
22 #include "ia64-hpux-tdep.h"
23 #include "osabi.h"
24 #include "gdbtypes.h"
25 #include "solib.h"
26 #include "target.h"
27 #include "frame.h"
28 #include "regcache.h"
29 #include "gdbcore.h"
30 #include "inferior.h"
31
32 /* A sequence of instructions pushed on the stack when we want to perform
33    an inferior function call.  The main purpose of this code is to save
34    the output region of the register frame belonging to the function
35    from which we are making the call.  Normally, all registers are saved
36    prior to the call, but this does not include stacked registers because
37    they are seen by GDB as pseudo registers.
38
39    With Linux kernels, these stacked registers can be saved by simply
40    creating a new register frame, or in other words by moving the BSP.
41    But the HP/UX kernel does not allow this.  So we rely on this code
42    instead, that makes functions calls whose only purpose is to create
43    new register frames.
44
45    The array below is the result obtained after assembling the code
46    shown below. It's an array of bytes in order to make it independent
47    of the host endianess, in case it ends up being used on more than
48    one target.
49
50    start:
51         // Save b0 before using it (into preserved reg: r4).
52         mov r4 = b0
53         ;;
54
55         br.call.dptk.few b0 = stub#
56         ;;
57
58         // Add a nop bundle where we can insert our dummy breakpoint.
59         nop.m 0
60         nop.i 0
61         nop.i 0
62         ;;
63
64    stub:
65         // Alloc a new register stack frame.  Here, we set the size
66         // of all regions to zero.  Eventually, GDB will manually
67         // change the instruction to set the size of the local region
68         // to match size of the output region of the function from
69         // which we are making the function call.  This is to protect
70         // the value of the output registers of the function from
71         // which we are making the call.
72         alloc r6 = ar.pfs, 0, 0, 0, 0
73
74         // Save b0 before using it again (into preserved reg: r5).
75         mov r5 = b0
76         ;;
77
78         //  Now that we have protected the entire output region of the
79         //  register stack frame, we can call our function that will
80         //  setup the arguments, and call our target function.
81         br.call.dptk.few b0 = call_dummy#
82         ;;
83
84         //  Restore b0, ar.pfs, and return
85         mov b0 = r5
86         mov.i ar.pfs = r6
87         ;;
88         br.ret.dptk.few b0
89         ;;
90
91    call_dummy:
92         //  Alloc a new frame, with 2 local registers, and 8 output registers
93         //  (8 output registers for the maximum of 8 slots passed by register).
94         alloc r32 = ar.pfs, 2, 0, 8, 0
95
96         //  Save b0 before using it to call our target function.
97         mov r33 = b0
98
99         // Load the argument values placed by GDB inside r14-r21 in their
100         // proper registers.
101         or r34 = r14, r0
102         or r35 = r15, r0
103         or r36 = r16, r0
104         or r37 = r17, r0
105         or r38 = r18, r0
106         or r39 = r19, r0
107         or r40 = r20, r0
108         or r41 = r21, r0
109         ;;
110
111         // actual call
112         br.call.dptk.few b0 = b1
113         ;;
114
115         mov.i ar.pfs=r32
116         mov b0=r33
117         ;;
118
119         br.ret.dptk.few b0
120         ;;
121
122 */
123
124 static const gdb_byte ia64_hpux_dummy_code[] =
125 {
126   0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00,
127   0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
128   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
129   0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x52,
130   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
131   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
132   0x02, 0x30, 0x00, 0x00, 0x80, 0x05, 0x50, 0x00,
133   0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
134   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
135   0x00, 0x02, 0x00, 0x00, 0x30, 0x00, 0x00, 0x52,
136   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x28,
137   0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0xaa, 0x00,
138   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
139   0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02,
140   0x00, 0x00, 0x29, 0x04, 0x80, 0x05, 0x10, 0x02,
141   0x00, 0x62, 0x00, 0x40, 0xe4, 0x00, 0x38, 0x80,
142   0x00, 0x18, 0x3d, 0x00, 0x0e, 0x20, 0x40, 0x82,
143   0x00, 0x1c, 0x40, 0xa0, 0x14, 0x01, 0x38, 0x80,
144   0x00, 0x30, 0x49, 0x00, 0x0e, 0x20, 0x70, 0x9a,
145   0x00, 0x1c, 0x40, 0x00, 0x45, 0x01, 0x38, 0x80,
146   0x0a, 0x48, 0x55, 0x00, 0x0e, 0x20, 0x00, 0x00,
147   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
148   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
149   0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x12,
150   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
151   0x01, 0x55, 0x00, 0x00, 0x10, 0x0a, 0x00, 0x07,
152   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
153   0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02
154 };
155
156 /* The offset to be used in order to get the __reason pseudo-register
157    when using one of the *UREGS ttrace requests (see system header file
158    /usr/include/ia64/sys/uregs.h for more details).
159
160    The documentation for this pseudo-register says that a nonzero value
161    indicates that the thread stopped due to a fault, trap, or interrupt.
162    A null value indicates a stop inside a syscall.  */
163 #define IA64_HPUX_UREG_REASON 0x00070000
164
165 /* Return nonzero if the value of the register identified by REGNUM
166    can be modified.  */
167
168 static int
169 ia64_hpux_can_store_ar_register (int regnum)
170 {
171   switch (regnum)
172     {
173       case IA64_RSC_REGNUM:
174       case IA64_RNAT_REGNUM:
175       case IA64_CSD_REGNUM:
176       case IA64_SSD_REGNUM:
177       case IA64_CCV_REGNUM:
178       case IA64_UNAT_REGNUM:
179       case IA64_FPSR_REGNUM:
180       case IA64_PFS_REGNUM:
181       case IA64_LC_REGNUM:
182       case IA64_EC_REGNUM:
183          return 1;
184          break;
185
186       default:
187          return 0;
188          break;
189     }
190 }
191
192 /* The "cannot_store_register" target_ops method.  */
193
194 static int
195 ia64_hpux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
196 {
197   /* General registers.  */
198
199   if (regnum == IA64_GR0_REGNUM)
200     return 1;
201
202   /* FP register.  */
203
204   if (regnum == IA64_FR0_REGNUM || regnum == IA64_FR1_REGNUM)
205     return 1;
206
207   /* Application registers.  */
208   if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_AR0_REGNUM + 127)
209     return (!ia64_hpux_can_store_ar_register (regnum));
210
211   /* We can store all other registers.  */
212   return 0;
213 }
214
215 /* Return nonzero if the inferior is stopped inside a system call.  */
216
217 static int
218 ia64_hpux_stopped_in_syscall (struct gdbarch *gdbarch)
219 {
220   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
221   struct target_ops *ops = &current_target;
222   gdb_byte buf[8];
223   int len;
224
225   len = target_read (ops, TARGET_OBJECT_HPUX_UREGS, NULL,
226                      buf, IA64_HPUX_UREG_REASON, sizeof (buf));
227   if (len == -1)
228     /* The target wasn't able to tell us.  Assume we are not stopped
229        in a system call, which is the normal situation.  */
230     return 0;
231   gdb_assert (len == 8);
232
233   return (extract_unsigned_integer (buf, len, byte_order) == 0);
234 }
235
236 /* The "size_of_register_frame" gdbarch_tdep routine for ia64-hpux.  */
237
238 static int
239 ia64_hpux_size_of_register_frame (struct frame_info *this_frame,
240                                   ULONGEST cfm)
241 {
242   int sof;
243
244   if (frame_relative_level (this_frame) == 0
245       && ia64_hpux_stopped_in_syscall (get_frame_arch (this_frame)))
246     /* If the inferior stopped in a system call, the base address
247        of the register frame is at BSP - SOL instead of BSP - SOF.
248        This is an HP-UX exception.  */
249     sof = (cfm & 0x3f80) >> 7;
250   else
251     sof = (cfm & 0x7f);
252
253   return sof;
254 }
255
256 /* Implement the push_dummy_code gdbarch method.
257
258    This function assumes that the SP is already 16-byte-aligned.  */
259
260 static CORE_ADDR
261 ia64_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
262                            CORE_ADDR funaddr, struct value **args, int nargs,
263                            struct type *value_type, CORE_ADDR *real_pc,
264                            CORE_ADDR *bp_addr, struct regcache *regcache)
265 {
266   ULONGEST cfm;
267   int sof, sol, sor, soo;
268   char buf[16];
269
270   regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
271   sof = cfm & 0x7f;
272   sol = (cfm >> 7) & 0x7f;
273   sor = (cfm >> 14) & 0xf;
274   soo = sof - sol - sor;
275
276   /* Reserve some space on the stack to hold the dummy code.  */
277   sp = sp - sizeof (ia64_hpux_dummy_code);
278
279   /* Set the breakpoint address at the first instruction of the bundle
280      in the dummy code that has only nops.  This is where the dummy code
281      expects us to break.  */
282   *bp_addr = sp + 0x20;
283
284   /* Start the inferior function call from the dummy code.  The dummy
285      code will then call our function.  */
286   *real_pc = sp;
287
288   /* Transfer the dummy code to the inferior.  */
289   write_memory (sp, ia64_hpux_dummy_code, sizeof (ia64_hpux_dummy_code));
290
291   /* Update the size of the local portion of the register frame allocated
292      by ``stub'' to match the size of the output region of the current
293      register frame.  This allows us to save the stacked registers.
294
295      The "alloc" instruction is located at slot 0 of the bundle at +0x30.
296      Update the "sof" and "sol" portion of that instruction which are
297      respectively at bits 18-24 and 25-31 of the bundle.  */
298   memcpy (buf, ia64_hpux_dummy_code + 0x30, sizeof (buf));
299
300   buf[2] |= ((soo & 0x3f) << 2);
301   buf[3] |= (soo << 1);
302   if (soo > 63)
303     buf[3] |= 1;
304
305   write_memory (sp + 0x30, buf, sizeof (buf));
306
307   /* Return the new (already properly aligned) SP.  */
308   return sp;
309 }
310
311 /* The "allocate_new_rse_frame" ia64_infcall_ops routine for ia64-hpux.  */
312
313 static void
314 ia64_hpux_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp,
315                                   int sof)
316 {
317   /* We cannot change the value of the BSP register on HP-UX,
318      so we can't allocate a new RSE frame.  */
319 }
320
321 /* The "store_argument_in_slot" ia64_infcall_ops routine for ia64-hpux.  */
322
323 static void
324 ia64_hpux_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp,
325                                   int slotnum, gdb_byte *buf)
326 {
327   /* The call sequence on this target expects us to place the arguments
328      inside r14 - r21.  */
329   regcache_cooked_write (regcache, IA64_GR0_REGNUM + 14 + slotnum, buf);
330 }
331
332 /* The "set_function_addr" ia64_infcall_ops routine for ia64-hpux.  */
333
334 static void
335 ia64_hpux_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr)
336 {
337   /* The calling sequence calls the function whose address is placed
338      in register b1.  */
339   regcache_cooked_write_unsigned (regcache, IA64_BR1_REGNUM, func_addr);
340 }
341
342 /* The ia64_infcall_ops structure for ia64-hpux.  */
343
344 static const struct ia64_infcall_ops ia64_hpux_infcall_ops =
345 {
346   ia64_hpux_allocate_new_rse_frame,
347   ia64_hpux_store_argument_in_slot,
348   ia64_hpux_set_function_addr
349 };
350
351 /* The "dummy_id" gdbarch routine for ia64-hpux.  */
352
353 static struct frame_id
354 ia64_hpux_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
355 {
356   CORE_ADDR sp, pc, bp_addr, bsp;
357
358   sp = get_frame_register_unsigned (this_frame, IA64_GR12_REGNUM);
359
360   /* Just double-check that the frame PC is within a certain region
361      of the stack that would be plausible for our dummy code (the dummy
362      code was pushed at SP + 16).  If not, then return a null frame ID.
363      This is necessary in our case, because it is possible to produce
364      the same frame ID for a normal frame, if that frame corresponds
365      to the function called by our dummy code, and the function has not
366      modified the registers that we use to build the dummy frame ID.  */
367   pc = get_frame_pc (this_frame);
368   if (pc < sp + 16 || pc >= sp + 16 + sizeof (ia64_hpux_dummy_code))
369     return null_frame_id;
370
371   /* The call sequence is such that the address of the dummy breakpoint
372      we inserted is stored in r5.  */
373   bp_addr = get_frame_register_unsigned (this_frame, IA64_GR5_REGNUM);
374
375   bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM);
376
377   return frame_id_build_special (sp, bp_addr, bsp);
378 }
379
380 /* Should be set to non-NULL if the ia64-hpux solib module is linked in.
381    This may not be the case because the shared library support code can
382    only be compiled on ia64-hpux.  */
383
384 struct target_so_ops *ia64_hpux_so_ops = NULL;
385
386 /* The "find_global_pointer_from_solib" gdbarch_tdep routine for
387    ia64-hpux.  */
388
389 static CORE_ADDR
390 ia64_hpux_find_global_pointer_from_solib (struct gdbarch *gdbarch,
391                                           CORE_ADDR faddr)
392 {
393   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
394   struct target_ops *ops = &current_target;
395   gdb_byte buf[8];
396   LONGEST len;
397
398   len = target_read (ops, TARGET_OBJECT_HPUX_SOLIB_GOT,
399                      paddress (gdbarch, faddr), buf, 0, sizeof (buf));
400
401   return extract_unsigned_integer (buf, len, byte_order);
402 }
403
404 static void
405 ia64_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
406 {
407   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
408
409   tdep->size_of_register_frame = ia64_hpux_size_of_register_frame;
410
411   set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
412   set_gdbarch_cannot_store_register (gdbarch, ia64_hpux_cannot_store_register);
413
414   /* Inferior functions must be called from stack. */
415   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
416   set_gdbarch_push_dummy_code (gdbarch, ia64_hpux_push_dummy_code);
417   tdep->infcall_ops = ia64_hpux_infcall_ops;
418   tdep->find_global_pointer_from_solib
419       = ia64_hpux_find_global_pointer_from_solib;
420   set_gdbarch_dummy_id (gdbarch, ia64_hpux_dummy_id);
421
422   if (ia64_hpux_so_ops)
423     set_solib_ops (gdbarch, ia64_hpux_so_ops);
424 }
425
426 /* Provide a prototype to silence -Wmissing-prototypes.  */
427 extern initialize_file_ftype _initialize_ia64_hpux_tdep;
428
429 void
430 _initialize_ia64_hpux_tdep (void)
431 {
432   gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_HPUX_ELF,
433                           ia64_hpux_init_abi);
434 }