GDB (API)
/home/stan/gdb/src/gdb/ia64-hpux-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for the IA-64 for GDB, the GNU debugger.
00002 
00003    Copyright (C) 2010-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "ia64-tdep.h"
00022 #include "ia64-hpux-tdep.h"
00023 #include "osabi.h"
00024 #include "gdbtypes.h"
00025 #include "solib.h"
00026 #include "target.h"
00027 #include "frame.h"
00028 #include "regcache.h"
00029 #include "gdbcore.h"
00030 #include "inferior.h"
00031 
00032 /* A sequence of instructions pushed on the stack when we want to perform
00033    an inferior function call.  The main purpose of this code is to save
00034    the output region of the register frame belonging to the function
00035    from which we are making the call.  Normally, all registers are saved
00036    prior to the call, but this does not include stacked registers because
00037    they are seen by GDB as pseudo registers.
00038 
00039    With Linux kernels, these stacked registers can be saved by simply
00040    creating a new register frame, or in other words by moving the BSP.
00041    But the HP/UX kernel does not allow this.  So we rely on this code
00042    instead, that makes functions calls whose only purpose is to create
00043    new register frames.
00044 
00045    The array below is the result obtained after assembling the code
00046    shown below. It's an array of bytes in order to make it independent
00047    of the host endianess, in case it ends up being used on more than
00048    one target.
00049 
00050    start:
00051         // Save b0 before using it (into preserved reg: r4).
00052         mov r4 = b0
00053         ;;
00054 
00055         br.call.dptk.few b0 = stub#
00056         ;;
00057 
00058         // Add a nop bundle where we can insert our dummy breakpoint.
00059         nop.m 0
00060         nop.i 0
00061         nop.i 0
00062         ;;
00063 
00064    stub:
00065         // Alloc a new register stack frame.  Here, we set the size
00066         // of all regions to zero.  Eventually, GDB will manually
00067         // change the instruction to set the size of the local region
00068         // to match size of the output region of the function from
00069         // which we are making the function call.  This is to protect
00070         // the value of the output registers of the function from
00071         // which we are making the call.
00072         alloc r6 = ar.pfs, 0, 0, 0, 0
00073 
00074         // Save b0 before using it again (into preserved reg: r5).
00075         mov r5 = b0
00076         ;;
00077 
00078         //  Now that we have protected the entire output region of the
00079         //  register stack frame, we can call our function that will
00080         //  setup the arguments, and call our target function.
00081         br.call.dptk.few b0 = call_dummy#
00082         ;;
00083 
00084         //  Restore b0, ar.pfs, and return
00085         mov b0 = r5
00086         mov.i ar.pfs = r6
00087         ;;
00088         br.ret.dptk.few b0
00089         ;;
00090 
00091    call_dummy:
00092         //  Alloc a new frame, with 2 local registers, and 8 output registers
00093         //  (8 output registers for the maximum of 8 slots passed by register).
00094         alloc r32 = ar.pfs, 2, 0, 8, 0
00095 
00096         //  Save b0 before using it to call our target function.
00097         mov r33 = b0
00098 
00099         // Load the argument values placed by GDB inside r14-r21 in their
00100         // proper registers.
00101         or r34 = r14, r0
00102         or r35 = r15, r0
00103         or r36 = r16, r0
00104         or r37 = r17, r0
00105         or r38 = r18, r0
00106         or r39 = r19, r0
00107         or r40 = r20, r0
00108         or r41 = r21, r0
00109         ;;
00110 
00111         // actual call
00112         br.call.dptk.few b0 = b1
00113         ;;
00114 
00115         mov.i ar.pfs=r32
00116         mov b0=r33
00117         ;;
00118 
00119         br.ret.dptk.few b0
00120         ;;
00121 
00122 */
00123 
00124 static const gdb_byte ia64_hpux_dummy_code[] =
00125 {
00126   0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00,
00127   0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
00128   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00129   0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x52,
00130   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00131   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
00132   0x02, 0x30, 0x00, 0x00, 0x80, 0x05, 0x50, 0x00,
00133   0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
00134   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00135   0x00, 0x02, 0x00, 0x00, 0x30, 0x00, 0x00, 0x52,
00136   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x28,
00137   0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0xaa, 0x00,
00138   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00139   0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02,
00140   0x00, 0x00, 0x29, 0x04, 0x80, 0x05, 0x10, 0x02,
00141   0x00, 0x62, 0x00, 0x40, 0xe4, 0x00, 0x38, 0x80,
00142   0x00, 0x18, 0x3d, 0x00, 0x0e, 0x20, 0x40, 0x82,
00143   0x00, 0x1c, 0x40, 0xa0, 0x14, 0x01, 0x38, 0x80,
00144   0x00, 0x30, 0x49, 0x00, 0x0e, 0x20, 0x70, 0x9a,
00145   0x00, 0x1c, 0x40, 0x00, 0x45, 0x01, 0x38, 0x80,
00146   0x0a, 0x48, 0x55, 0x00, 0x0e, 0x20, 0x00, 0x00,
00147   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
00148   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00149   0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x12,
00150   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00151   0x01, 0x55, 0x00, 0x00, 0x10, 0x0a, 0x00, 0x07,
00152   0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00153   0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02
00154 };
00155 
00156 /* The offset to be used in order to get the __reason pseudo-register
00157    when using one of the *UREGS ttrace requests (see system header file
00158    /usr/include/ia64/sys/uregs.h for more details).
00159 
00160    The documentation for this pseudo-register says that a nonzero value
00161    indicates that the thread stopped due to a fault, trap, or interrupt.
00162    A null value indicates a stop inside a syscall.  */
00163 #define IA64_HPUX_UREG_REASON 0x00070000
00164 
00165 /* Return nonzero if the value of the register identified by REGNUM
00166    can be modified.  */
00167 
00168 static int
00169 ia64_hpux_can_store_ar_register (int regnum)
00170 {
00171   switch (regnum)
00172     {
00173       case IA64_RSC_REGNUM:
00174       case IA64_RNAT_REGNUM:
00175       case IA64_CSD_REGNUM:
00176       case IA64_SSD_REGNUM:
00177       case IA64_CCV_REGNUM:
00178       case IA64_UNAT_REGNUM:
00179       case IA64_FPSR_REGNUM:
00180       case IA64_PFS_REGNUM:
00181       case IA64_LC_REGNUM:
00182       case IA64_EC_REGNUM:
00183          return 1;
00184          break;
00185 
00186       default:
00187          return 0;
00188          break;
00189     }
00190 }
00191 
00192 /* The "cannot_store_register" target_ops method.  */
00193 
00194 static int
00195 ia64_hpux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
00196 {
00197   /* General registers.  */
00198 
00199   if (regnum == IA64_GR0_REGNUM)
00200     return 1;
00201 
00202   /* FP register.  */
00203 
00204   if (regnum == IA64_FR0_REGNUM || regnum == IA64_FR1_REGNUM)
00205     return 1;
00206 
00207   /* Application registers.  */
00208   if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_AR0_REGNUM + 127)
00209     return (!ia64_hpux_can_store_ar_register (regnum));
00210 
00211   /* We can store all other registers.  */
00212   return 0;
00213 }
00214 
00215 /* Return nonzero if the inferior is stopped inside a system call.  */
00216 
00217 static int
00218 ia64_hpux_stopped_in_syscall (struct gdbarch *gdbarch)
00219 {
00220   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00221   struct target_ops *ops = &current_target;
00222   gdb_byte buf[8];
00223   int len;
00224 
00225   len = target_read (ops, TARGET_OBJECT_HPUX_UREGS, NULL,
00226                      buf, IA64_HPUX_UREG_REASON, sizeof (buf));
00227   if (len == -1)
00228     /* The target wasn't able to tell us.  Assume we are not stopped
00229        in a system call, which is the normal situation.  */
00230     return 0;
00231   gdb_assert (len == 8);
00232 
00233   return (extract_unsigned_integer (buf, len, byte_order) == 0);
00234 }
00235 
00236 /* The "size_of_register_frame" gdbarch_tdep routine for ia64-hpux.  */
00237 
00238 static int
00239 ia64_hpux_size_of_register_frame (struct frame_info *this_frame,
00240                                   ULONGEST cfm)
00241 {
00242   int sof;
00243 
00244   if (frame_relative_level (this_frame) == 0
00245       && ia64_hpux_stopped_in_syscall (get_frame_arch (this_frame)))
00246     /* If the inferior stopped in a system call, the base address
00247        of the register frame is at BSP - SOL instead of BSP - SOF.
00248        This is an HP-UX exception.  */
00249     sof = (cfm & 0x3f80) >> 7;
00250   else
00251     sof = (cfm & 0x7f);
00252 
00253   return sof;
00254 }
00255 
00256 /* Implement the push_dummy_code gdbarch method.
00257 
00258    This function assumes that the SP is already 16-byte-aligned.  */
00259 
00260 static CORE_ADDR
00261 ia64_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
00262                            CORE_ADDR funaddr, struct value **args, int nargs,
00263                            struct type *value_type, CORE_ADDR *real_pc,
00264                            CORE_ADDR *bp_addr, struct regcache *regcache)
00265 {
00266   ULONGEST cfm;
00267   int sof, sol, sor, soo;
00268   gdb_byte buf[16];
00269 
00270   regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
00271   sof = cfm & 0x7f;
00272   sol = (cfm >> 7) & 0x7f;
00273   sor = (cfm >> 14) & 0xf;
00274   soo = sof - sol - sor;
00275 
00276   /* Reserve some space on the stack to hold the dummy code.  */
00277   sp = sp - sizeof (ia64_hpux_dummy_code);
00278 
00279   /* Set the breakpoint address at the first instruction of the bundle
00280      in the dummy code that has only nops.  This is where the dummy code
00281      expects us to break.  */
00282   *bp_addr = sp + 0x20;
00283 
00284   /* Start the inferior function call from the dummy code.  The dummy
00285      code will then call our function.  */
00286   *real_pc = sp;
00287 
00288   /* Transfer the dummy code to the inferior.  */
00289   write_memory (sp, ia64_hpux_dummy_code, sizeof (ia64_hpux_dummy_code));
00290 
00291   /* Update the size of the local portion of the register frame allocated
00292      by ``stub'' to match the size of the output region of the current
00293      register frame.  This allows us to save the stacked registers.
00294 
00295      The "alloc" instruction is located at slot 0 of the bundle at +0x30.
00296      Update the "sof" and "sol" portion of that instruction which are
00297      respectively at bits 18-24 and 25-31 of the bundle.  */
00298   memcpy (buf, ia64_hpux_dummy_code + 0x30, sizeof (buf));
00299 
00300   buf[2] |= ((soo & 0x3f) << 2);
00301   buf[3] |= (soo << 1);
00302   if (soo > 63)
00303     buf[3] |= 1;
00304 
00305   write_memory (sp + 0x30, buf, sizeof (buf));
00306 
00307   /* Return the new (already properly aligned) SP.  */
00308   return sp;
00309 }
00310 
00311 /* The "allocate_new_rse_frame" ia64_infcall_ops routine for ia64-hpux.  */
00312 
00313 static void
00314 ia64_hpux_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp,
00315                                   int sof)
00316 {
00317   /* We cannot change the value of the BSP register on HP-UX,
00318      so we can't allocate a new RSE frame.  */
00319 }
00320 
00321 /* The "store_argument_in_slot" ia64_infcall_ops routine for ia64-hpux.  */
00322 
00323 static void
00324 ia64_hpux_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp,
00325                                   int slotnum, gdb_byte *buf)
00326 {
00327   /* The call sequence on this target expects us to place the arguments
00328      inside r14 - r21.  */
00329   regcache_cooked_write (regcache, IA64_GR0_REGNUM + 14 + slotnum, buf);
00330 }
00331 
00332 /* The "set_function_addr" ia64_infcall_ops routine for ia64-hpux.  */
00333 
00334 static void
00335 ia64_hpux_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr)
00336 {
00337   /* The calling sequence calls the function whose address is placed
00338      in register b1.  */
00339   regcache_cooked_write_unsigned (regcache, IA64_BR1_REGNUM, func_addr);
00340 }
00341 
00342 /* The ia64_infcall_ops structure for ia64-hpux.  */
00343 
00344 static const struct ia64_infcall_ops ia64_hpux_infcall_ops =
00345 {
00346   ia64_hpux_allocate_new_rse_frame,
00347   ia64_hpux_store_argument_in_slot,
00348   ia64_hpux_set_function_addr
00349 };
00350 
00351 /* The "dummy_id" gdbarch routine for ia64-hpux.  */
00352 
00353 static struct frame_id
00354 ia64_hpux_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
00355 {
00356   CORE_ADDR sp, pc, bp_addr, bsp;
00357 
00358   sp = get_frame_register_unsigned (this_frame, IA64_GR12_REGNUM);
00359 
00360   /* Just double-check that the frame PC is within a certain region
00361      of the stack that would be plausible for our dummy code (the dummy
00362      code was pushed at SP + 16).  If not, then return a null frame ID.
00363      This is necessary in our case, because it is possible to produce
00364      the same frame ID for a normal frame, if that frame corresponds
00365      to the function called by our dummy code, and the function has not
00366      modified the registers that we use to build the dummy frame ID.  */
00367   pc = get_frame_pc (this_frame);
00368   if (pc < sp + 16 || pc >= sp + 16 + sizeof (ia64_hpux_dummy_code))
00369     return null_frame_id;
00370 
00371   /* The call sequence is such that the address of the dummy breakpoint
00372      we inserted is stored in r5.  */
00373   bp_addr = get_frame_register_unsigned (this_frame, IA64_GR5_REGNUM);
00374 
00375   bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM);
00376 
00377   return frame_id_build_special (sp, bp_addr, bsp);
00378 }
00379 
00380 /* Should be set to non-NULL if the ia64-hpux solib module is linked in.
00381    This may not be the case because the shared library support code can
00382    only be compiled on ia64-hpux.  */
00383 
00384 struct target_so_ops *ia64_hpux_so_ops = NULL;
00385 
00386 /* The "find_global_pointer_from_solib" gdbarch_tdep routine for
00387    ia64-hpux.  */
00388 
00389 static CORE_ADDR
00390 ia64_hpux_find_global_pointer_from_solib (struct gdbarch *gdbarch,
00391                                           CORE_ADDR faddr)
00392 {
00393   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00394   struct target_ops *ops = &current_target;
00395   gdb_byte buf[8];
00396   LONGEST len;
00397 
00398   len = target_read (ops, TARGET_OBJECT_HPUX_SOLIB_GOT,
00399                      paddress (gdbarch, faddr), buf, 0, sizeof (buf));
00400 
00401   return extract_unsigned_integer (buf, len, byte_order);
00402 }
00403 
00404 static void
00405 ia64_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00406 {
00407   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00408 
00409   tdep->size_of_register_frame = ia64_hpux_size_of_register_frame;
00410 
00411   set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
00412   set_gdbarch_cannot_store_register (gdbarch, ia64_hpux_cannot_store_register);
00413 
00414   /* Inferior functions must be called from stack. */
00415   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
00416   set_gdbarch_push_dummy_code (gdbarch, ia64_hpux_push_dummy_code);
00417   tdep->infcall_ops = ia64_hpux_infcall_ops;
00418   tdep->find_global_pointer_from_solib
00419       = ia64_hpux_find_global_pointer_from_solib;
00420   set_gdbarch_dummy_id (gdbarch, ia64_hpux_dummy_id);
00421 
00422   if (ia64_hpux_so_ops)
00423     set_solib_ops (gdbarch, ia64_hpux_so_ops);
00424 }
00425 
00426 /* Provide a prototype to silence -Wmissing-prototypes.  */
00427 extern initialize_file_ftype _initialize_ia64_hpux_tdep;
00428 
00429 void
00430 _initialize_ia64_hpux_tdep (void)
00431 {
00432   gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_HPUX_ELF,
00433                           ia64_hpux_init_abi);
00434 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines