GDB (API)
/home/stan/gdb/src/gdb/hppa-hpux-nat.c
Go to the documentation of this file.
00001 /* Native-dependent code for PA-RISC HP-UX.
00002 
00003    Copyright (C) 2004-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 "inferior.h"
00022 #include "regcache.h"
00023 #include "target.h"
00024 
00025 #include "gdb_assert.h"
00026 #include <sys/ptrace.h>
00027 #include <sys/utsname.h>
00028 #include <machine/save_state.h>
00029 
00030 #ifdef HAVE_TTRACE
00031 #include <sys/ttrace.h>
00032 #endif
00033 
00034 #include "hppa-tdep.h"
00035 #include "solib-som.h"
00036 #include "inf-ptrace.h"
00037 #include "inf-ttrace.h"
00038 
00039 /* Return the offset of register REGNUM within `struct save_state'.
00040    The offset returns depends on the flags in the "flags" register and
00041    the register size (32-bit or 64-bit).  These are taken from
00042    REGCACHE.  */
00043 
00044 static LONGEST
00045 hppa_hpux_save_state_offset (struct regcache *regcache, int regnum)
00046 {
00047   LONGEST offset;
00048 
00049   if (regnum == HPPA_FLAGS_REGNUM)
00050     return ssoff (ss_flags);
00051 
00052   if (HPPA_R0_REGNUM < regnum && regnum < HPPA_FP0_REGNUM)
00053     {
00054       struct gdbarch *arch = get_regcache_arch (regcache);
00055       size_t size = register_size (arch, HPPA_R1_REGNUM);
00056       ULONGEST flags;
00057 
00058       gdb_assert (size == 4 || size == 8);
00059 
00060       regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
00061       if (flags & SS_WIDEREGS)
00062         offset = ssoff (ss_wide) + (8 - size) + (regnum - HPPA_R0_REGNUM) * 8;
00063       else
00064         offset = ssoff (ss_narrow) + (regnum - HPPA_R1_REGNUM) * 4;
00065     }
00066   else
00067     {
00068       struct gdbarch *arch = get_regcache_arch (regcache);
00069       size_t size = register_size (arch, HPPA_FP0_REGNUM);
00070 
00071       gdb_assert (size == 4 || size == 8);
00072       gdb_assert (regnum >= HPPA_FP0_REGNUM);
00073       offset = ssoff(ss_fpblock) + (regnum - HPPA_FP0_REGNUM) * size;
00074     }
00075 
00076   gdb_assert (offset < sizeof (save_state_t));
00077   return offset;
00078 }
00079 
00080 /* Just in case a future version of PA-RISC HP-UX won't have ptrace(2)
00081    at all.  */
00082 #ifndef PTRACE_TYPE_RET
00083 #define PTRACE_TYPE_RET void
00084 #endif
00085 
00086 static void
00087 hppa_hpux_fetch_register (struct regcache *regcache, int regnum)
00088 {
00089   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00090   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00091   CORE_ADDR addr;
00092   size_t size;
00093   PTRACE_TYPE_RET *buf;
00094   pid_t pid;
00095   int i;
00096 
00097   pid = ptid_get_pid (inferior_ptid);
00098 
00099   /* This isn't really an address, but ptrace thinks of it as one.  */
00100   addr = hppa_hpux_save_state_offset (regcache, regnum);
00101   size = register_size (gdbarch, regnum);
00102 
00103   gdb_assert (size == 4 || size == 8);
00104   buf = alloca (size);
00105 
00106 #ifdef HAVE_TTRACE
00107   {
00108     lwpid_t lwp = ptid_get_lwp (inferior_ptid);
00109 
00110     if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
00111       error (_("Couldn't read register %s (#%d): %s"),
00112              gdbarch_register_name (gdbarch, regnum),
00113              regnum, safe_strerror (errno));
00114   }
00115 #else
00116   {
00117     int i;
00118 
00119     /* Read the register contents from the inferior a chuck at the time.  */
00120     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
00121       {
00122         errno = 0;
00123         buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0);
00124         if (errno != 0)
00125           error (_("Couldn't read register %s (#%d): %s"),
00126                  gdbarch_register_name (gdbarch, regnum),
00127                  regnum, safe_strerror (errno));
00128 
00129         addr += sizeof (PTRACE_TYPE_RET);
00130       }
00131   }
00132 #endif
00133 
00134   /* Take care with the "flags" register.  It's stored as an `int' in
00135      `struct save_state', even for 64-bit code.  */
00136   if (regnum == HPPA_FLAGS_REGNUM && size == 8)
00137     {
00138       ULONGEST flags;
00139       flags = extract_unsigned_integer ((gdb_byte *)buf, 4, byte_order);
00140       store_unsigned_integer ((gdb_byte *)buf, 8, byte_order, flags);
00141     }
00142 
00143   regcache_raw_supply (regcache, regnum, buf);
00144 }
00145 
00146 static void
00147 hppa_hpux_fetch_inferior_registers (struct target_ops *ops,
00148                                     struct regcache *regcache, int regnum)
00149 {
00150   if (regnum == -1)
00151     for (regnum = 0;
00152          regnum < gdbarch_num_regs (get_regcache_arch (regcache));
00153          regnum++)
00154       hppa_hpux_fetch_register (regcache, regnum);
00155   else
00156     hppa_hpux_fetch_register (regcache, regnum);
00157 }
00158 
00159 /* Store register REGNUM into the inferior.  */
00160 
00161 static void
00162 hppa_hpux_store_register (struct regcache *regcache, int regnum)
00163 {
00164   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00165   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00166   CORE_ADDR addr;
00167   size_t size;
00168   PTRACE_TYPE_RET *buf;
00169   pid_t pid;
00170 
00171   pid = ptid_get_pid (inferior_ptid);
00172 
00173   /* This isn't really an address, but ptrace thinks of it as one.  */
00174   addr = hppa_hpux_save_state_offset (regcache, regnum);
00175   size = register_size (gdbarch, regnum);
00176 
00177   gdb_assert (size == 4 || size == 8);
00178   buf = alloca (size);
00179 
00180   regcache_raw_collect (regcache, regnum, buf);
00181 
00182   /* Take care with the "flags" register.  It's stored as an `int' in
00183      `struct save_state', even for 64-bit code.  */
00184   if (regnum == HPPA_FLAGS_REGNUM && size == 8)
00185     {
00186       ULONGEST flags;
00187       flags = extract_unsigned_integer ((gdb_byte *)buf, 8, byte_order);
00188       store_unsigned_integer ((gdb_byte *)buf, 4, byte_order, flags);
00189       size = 4;
00190     }
00191 
00192 #ifdef HAVE_TTRACE
00193   {
00194     lwpid_t lwp = ptid_get_lwp (inferior_ptid);
00195 
00196     if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
00197       error (_("Couldn't write register %s (#%d): %s"),
00198              gdbarch_register_name (gdbarch, regnum),
00199              regnum, safe_strerror (errno));
00200   }
00201 #else
00202   {
00203     int i;
00204 
00205     /* Write the register contents into the inferior a chunk at the time.  */
00206     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
00207       {
00208         errno = 0;
00209         ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
00210         if (errno != 0)
00211           error (_("Couldn't write register %s (#%d): %s"),
00212                  gdbarch_register_name (gdbarch, regnum),
00213                  regnum, safe_strerror (errno));
00214 
00215         addr += sizeof (PTRACE_TYPE_RET);
00216       }
00217   }
00218 #endif
00219 }
00220 
00221 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
00222    this for all registers (including the floating point registers).  */
00223 
00224 static void
00225 hppa_hpux_store_inferior_registers (struct target_ops *ops,
00226                                     struct regcache *regcache, int regnum)
00227 {
00228   if (regnum == -1)
00229     for (regnum = 0;
00230          regnum < gdbarch_num_regs (get_regcache_arch (regcache));
00231          regnum++)
00232       hppa_hpux_store_register (regcache, regnum);
00233   else
00234     hppa_hpux_store_register (regcache, regnum);
00235 }
00236 
00237 /* Set hpux_major_release variable to the value retrieved from a call to
00238    uname function.  */
00239 
00240 static void
00241 set_hpux_major_release (void)
00242 {
00243   struct utsname x;
00244   char *p;
00245 
00246   uname (&x);
00247   p = strchr (x.release, '.');
00248   if (p)
00249     hpux_major_release = atoi (p + 1);
00250 }
00251 
00252 
00253 
00254 /* Prevent warning from -Wmissing-prototypes.  */
00255 void _initialize_hppa_hpux_nat (void);
00256 
00257 void
00258 _initialize_hppa_hpux_nat (void)
00259 {
00260   struct target_ops *t;
00261 
00262   set_hpux_major_release ();
00263 
00264 #ifdef HAVE_TTRACE
00265   t = inf_ttrace_target ();
00266 #else
00267   t = inf_ptrace_target ();
00268 #endif
00269 
00270   t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
00271   t->to_store_registers = hppa_hpux_store_inferior_registers;
00272 
00273   add_target (t);
00274 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines