1 /* Target-dependent code for the IA-64 for GDB, the GNU debugger.
3 Copyright (C) 2010, 2012 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "ia64-tdep.h"
22 #include "ia64-hpux-tdep.h"
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.
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
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
51 // Save b0 before using it (into preserved reg: r4).
55 br.call.dptk.few b0 = stub#
58 // Add a nop bundle where we can insert our dummy breakpoint.
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
74 // Save b0 before using it again (into preserved reg: r5).
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#
84 // Restore b0, ar.pfs, and return
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
96 // Save b0 before using it to call our target function.
99 // Load the argument values placed by GDB inside r14-r21 in their
112 br.call.dptk.few b0 = b1
124 static const gdb_byte ia64_hpux_dummy_code[] =
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
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).
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
165 /* Return nonzero if the value of the register identified by REGNUM
169 ia64_hpux_can_store_ar_register (int regnum)
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:
192 /* The "cannot_store_register" target_ops method. */
195 ia64_hpux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
197 /* General registers. */
199 if (regnum == IA64_GR0_REGNUM)
204 if (regnum == IA64_FR0_REGNUM || regnum == IA64_FR1_REGNUM)
207 /* Application registers. */
208 if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_AR0_REGNUM + 127)
209 return (!ia64_hpux_can_store_ar_register (regnum));
211 /* We can store all other registers. */
215 /* Return nonzero if the inferior is stopped inside a system call. */
218 ia64_hpux_stopped_in_syscall (struct gdbarch *gdbarch)
220 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
221 struct target_ops *ops = ¤t_target;
225 len = target_read (ops, TARGET_OBJECT_HPUX_UREGS, NULL,
226 buf, IA64_HPUX_UREG_REASON, sizeof (buf));
228 /* The target wasn't able to tell us. Assume we are not stopped
229 in a system call, which is the normal situation. */
231 gdb_assert (len == 8);
233 return (extract_unsigned_integer (buf, len, byte_order) == 0);
236 /* The "size_of_register_frame" gdbarch_tdep routine for ia64-hpux. */
239 ia64_hpux_size_of_register_frame (struct frame_info *this_frame,
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;
256 /* Implement the push_dummy_code gdbarch method.
258 This function assumes that the SP is already 16-byte-aligned. */
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)
267 int sof, sol, sor, soo;
270 regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
272 sol = (cfm >> 7) & 0x7f;
273 sor = (cfm >> 14) & 0xf;
274 soo = sof - sol - sor;
276 /* Reserve some space on the stack to hold the dummy code. */
277 sp = sp - sizeof (ia64_hpux_dummy_code);
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;
284 /* Start the inferior function call from the dummy code. The dummy
285 code will then call our function. */
288 /* Transfer the dummy code to the inferior. */
289 write_memory (sp, ia64_hpux_dummy_code, sizeof (ia64_hpux_dummy_code));
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.
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));
300 buf[2] |= ((soo & 0x3f) << 2);
301 buf[3] |= (soo << 1);
305 write_memory (sp + 0x30, buf, sizeof (buf));
307 /* Return the new (already properly aligned) SP. */
311 /* The "allocate_new_rse_frame" ia64_infcall_ops routine for ia64-hpux. */
314 ia64_hpux_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp,
317 /* We cannot change the value of the BSP register on HP-UX,
318 so we can't allocate a new RSE frame. */
321 /* The "store_argument_in_slot" ia64_infcall_ops routine for ia64-hpux. */
324 ia64_hpux_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp,
325 int slotnum, gdb_byte *buf)
327 /* The call sequence on this target expects us to place the arguments
329 regcache_cooked_write (regcache, IA64_GR0_REGNUM + 14 + slotnum, buf);
332 /* The "set_function_addr" ia64_infcall_ops routine for ia64-hpux. */
335 ia64_hpux_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr)
337 /* The calling sequence calls the function whose address is placed
339 regcache_cooked_write_unsigned (regcache, IA64_BR1_REGNUM, func_addr);
342 /* The ia64_infcall_ops structure for ia64-hpux. */
344 static const struct ia64_infcall_ops ia64_hpux_infcall_ops =
346 ia64_hpux_allocate_new_rse_frame,
347 ia64_hpux_store_argument_in_slot,
348 ia64_hpux_set_function_addr
351 /* The "dummy_id" gdbarch routine for ia64-hpux. */
353 static struct frame_id
354 ia64_hpux_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
356 CORE_ADDR sp, pc, bp_addr, bsp;
358 sp = get_frame_register_unsigned (this_frame, IA64_GR12_REGNUM);
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;
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);
375 bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM);
377 return frame_id_build_special (sp, bp_addr, bsp);
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. */
384 struct target_so_ops *ia64_hpux_so_ops = NULL;
386 /* The "find_global_pointer_from_solib" gdbarch_tdep routine for
390 ia64_hpux_find_global_pointer_from_solib (struct gdbarch *gdbarch,
393 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
394 struct target_ops *ops = ¤t_target;
398 len = target_read (ops, TARGET_OBJECT_HPUX_SOLIB_GOT,
399 paddress (gdbarch, faddr), buf, 0, sizeof (buf));
401 return extract_unsigned_integer (buf, len, byte_order);
405 ia64_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
407 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
409 tdep->size_of_register_frame = ia64_hpux_size_of_register_frame;
411 set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
412 set_gdbarch_cannot_store_register (gdbarch, ia64_hpux_cannot_store_register);
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);
422 if (ia64_hpux_so_ops)
423 set_solib_ops (gdbarch, ia64_hpux_so_ops);
426 /* Provide a prototype to silence -Wmissing-prototypes. */
427 extern initialize_file_ftype _initialize_ia64_hpux_tdep;
430 _initialize_ia64_hpux_tdep (void)
432 gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_HPUX_ELF,