gdb/hppa-hpux-nat.c - gdb

Functions defined

Macros defined

Source code

  1. /* Native-dependent code for PA-RISC HP-UX.

  2.    Copyright (C) 2004-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "inferior.h"
  16. #include "regcache.h"
  17. #include "target.h"

  18. #include <sys/ptrace.h>
  19. #include <sys/utsname.h>
  20. #include <machine/save_state.h>

  21. #ifdef HAVE_TTRACE
  22. #include <sys/ttrace.h>
  23. #endif

  24. #include "hppa-tdep.h"
  25. #include "solib-som.h"
  26. #include "inf-ptrace.h"
  27. #include "inf-ttrace.h"

  28. /* Return the offset of register REGNUM within `struct save_state'.
  29.    The offset returns depends on the flags in the "flags" register and
  30.    the register size (32-bit or 64-bit).  These are taken from
  31.    REGCACHE.  */

  32. static LONGEST
  33. hppa_hpux_save_state_offset (struct regcache *regcache, int regnum)
  34. {
  35.   LONGEST offset;

  36.   if (regnum == HPPA_FLAGS_REGNUM)
  37.     return ssoff (ss_flags);

  38.   if (HPPA_R0_REGNUM < regnum && regnum < HPPA_FP0_REGNUM)
  39.     {
  40.       struct gdbarch *arch = get_regcache_arch (regcache);
  41.       size_t size = register_size (arch, HPPA_R1_REGNUM);
  42.       ULONGEST flags;

  43.       gdb_assert (size == 4 || size == 8);

  44.       regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags);
  45.       if (flags & SS_WIDEREGS)
  46.         offset = ssoff (ss_wide) + (8 - size) + (regnum - HPPA_R0_REGNUM) * 8;
  47.       else
  48.         offset = ssoff (ss_narrow) + (regnum - HPPA_R1_REGNUM) * 4;
  49.     }
  50.   else
  51.     {
  52.       struct gdbarch *arch = get_regcache_arch (regcache);
  53.       size_t size = register_size (arch, HPPA_FP0_REGNUM);

  54.       gdb_assert (size == 4 || size == 8);
  55.       gdb_assert (regnum >= HPPA_FP0_REGNUM);
  56.       offset = ssoff(ss_fpblock) + (regnum - HPPA_FP0_REGNUM) * size;
  57.     }

  58.   gdb_assert (offset < sizeof (save_state_t));
  59.   return offset;
  60. }

  61. /* Just in case a future version of PA-RISC HP-UX won't have ptrace(2)
  62.    at all.  */
  63. #ifndef PTRACE_TYPE_RET
  64. #define PTRACE_TYPE_RET void
  65. #endif

  66. static void
  67. hppa_hpux_fetch_register (struct regcache *regcache, int regnum)
  68. {
  69.   struct gdbarch *gdbarch = get_regcache_arch (regcache);
  70.   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  71.   CORE_ADDR addr;
  72.   size_t size;
  73.   PTRACE_TYPE_RET *buf;
  74.   pid_t pid;
  75.   int i;

  76.   pid = ptid_get_pid (inferior_ptid);

  77.   /* This isn't really an address, but ptrace thinks of it as one.  */
  78.   addr = hppa_hpux_save_state_offset (regcache, regnum);
  79.   size = register_size (gdbarch, regnum);

  80.   gdb_assert (size == 4 || size == 8);
  81.   buf = alloca (size);

  82. #ifdef HAVE_TTRACE
  83.   {
  84.     lwpid_t lwp = ptid_get_lwp (inferior_ptid);

  85.     if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
  86.       error (_("Couldn't read register %s (#%d): %s"),
  87.              gdbarch_register_name (gdbarch, regnum),
  88.              regnum, safe_strerror (errno));
  89.   }
  90. #else
  91.   {
  92.     int i;

  93.     /* Read the register contents from the inferior a chuck at the time.  */
  94.     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
  95.       {
  96.         errno = 0;
  97.         buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0);
  98.         if (errno != 0)
  99.           error (_("Couldn't read register %s (#%d): %s"),
  100.                  gdbarch_register_name (gdbarch, regnum),
  101.                  regnum, safe_strerror (errno));

  102.         addr += sizeof (PTRACE_TYPE_RET);
  103.       }
  104.   }
  105. #endif

  106.   /* Take care with the "flags" register.  It's stored as an `int' in
  107.      `struct save_state', even for 64-bit code.  */
  108.   if (regnum == HPPA_FLAGS_REGNUM && size == 8)
  109.     {
  110.       ULONGEST flags;
  111.       flags = extract_unsigned_integer ((gdb_byte *)buf, 4, byte_order);
  112.       store_unsigned_integer ((gdb_byte *)buf, 8, byte_order, flags);
  113.     }

  114.   regcache_raw_supply (regcache, regnum, buf);
  115. }

  116. static void
  117. hppa_hpux_fetch_inferior_registers (struct target_ops *ops,
  118.                                     struct regcache *regcache, int regnum)
  119. {
  120.   if (regnum == -1)
  121.     for (regnum = 0;
  122.          regnum < gdbarch_num_regs (get_regcache_arch (regcache));
  123.          regnum++)
  124.       hppa_hpux_fetch_register (regcache, regnum);
  125.   else
  126.     hppa_hpux_fetch_register (regcache, regnum);
  127. }

  128. /* Store register REGNUM into the inferior.  */

  129. static void
  130. hppa_hpux_store_register (struct regcache *regcache, int regnum)
  131. {
  132.   struct gdbarch *gdbarch = get_regcache_arch (regcache);
  133.   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  134.   CORE_ADDR addr;
  135.   size_t size;
  136.   PTRACE_TYPE_RET *buf;
  137.   pid_t pid;

  138.   pid = ptid_get_pid (inferior_ptid);

  139.   /* This isn't really an address, but ptrace thinks of it as one.  */
  140.   addr = hppa_hpux_save_state_offset (regcache, regnum);
  141.   size = register_size (gdbarch, regnum);

  142.   gdb_assert (size == 4 || size == 8);
  143.   buf = alloca (size);

  144.   regcache_raw_collect (regcache, regnum, buf);

  145.   /* Take care with the "flags" register.  It's stored as an `int' in
  146.      `struct save_state', even for 64-bit code.  */
  147.   if (regnum == HPPA_FLAGS_REGNUM && size == 8)
  148.     {
  149.       ULONGEST flags;
  150.       flags = extract_unsigned_integer ((gdb_byte *)buf, 8, byte_order);
  151.       store_unsigned_integer ((gdb_byte *)buf, 4, byte_order, flags);
  152.       size = 4;
  153.     }

  154. #ifdef HAVE_TTRACE
  155.   {
  156.     lwpid_t lwp = ptid_get_lwp (inferior_ptid);

  157.     if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1)
  158.       error (_("Couldn't write register %s (#%d): %s"),
  159.              gdbarch_register_name (gdbarch, regnum),
  160.              regnum, safe_strerror (errno));
  161.   }
  162. #else
  163.   {
  164.     int i;

  165.     /* Write the register contents into the inferior a chunk at the time.  */
  166.     for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
  167.       {
  168.         errno = 0;
  169.         ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0);
  170.         if (errno != 0)
  171.           error (_("Couldn't write register %s (#%d): %s"),
  172.                  gdbarch_register_name (gdbarch, regnum),
  173.                  regnum, safe_strerror (errno));

  174.         addr += sizeof (PTRACE_TYPE_RET);
  175.       }
  176.   }
  177. #endif
  178. }

  179. /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
  180.    this for all registers (including the floating point registers).  */

  181. static void
  182. hppa_hpux_store_inferior_registers (struct target_ops *ops,
  183.                                     struct regcache *regcache, int regnum)
  184. {
  185.   if (regnum == -1)
  186.     for (regnum = 0;
  187.          regnum < gdbarch_num_regs (get_regcache_arch (regcache));
  188.          regnum++)
  189.       hppa_hpux_store_register (regcache, regnum);
  190.   else
  191.     hppa_hpux_store_register (regcache, regnum);
  192. }

  193. /* Set hpux_major_release variable to the value retrieved from a call to
  194.    uname function.  */

  195. static void
  196. set_hpux_major_release (void)
  197. {
  198.   struct utsname x;
  199.   char *p;

  200.   uname (&x);
  201.   p = strchr (x.release, '.');
  202.   if (p)
  203.     hpux_major_release = atoi (p + 1);
  204. }



  205. /* Prevent warning from -Wmissing-prototypes.  */
  206. void _initialize_hppa_hpux_nat (void);

  207. void
  208. _initialize_hppa_hpux_nat (void)
  209. {
  210.   struct target_ops *t;

  211.   set_hpux_major_release ();

  212. #ifdef HAVE_TTRACE
  213.   t = inf_ttrace_target ();
  214. #else
  215.   t = inf_ptrace_target ();
  216. #endif

  217.   t->to_fetch_registers = hppa_hpux_fetch_inferior_registers;
  218.   t->to_store_registers = hppa_hpux_store_inferior_registers;

  219.   add_target (t);
  220. }