home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / gdb / hppab-nat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-14  |  5.4 KB  |  202 lines

  1. /* Machine-dependent hooks for the unix child process stratum.  This
  2.    code is for the HP PA-RISC cpu.
  3.  
  4.    Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  5.  
  6.    Contributed by the Center for Software Science at the
  7.    University of Utah (pa-gdb-bugs@cs.utah.edu).
  8.  
  9. This file is part of GDB.
  10.  
  11. This program is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  24.  
  25. #include "defs.h"
  26. #include "inferior.h"
  27. #include "target.h"
  28. #include <sys/ptrace.h>
  29.  
  30. /* Use an extra level of indirection for ptrace calls.
  31.    This lets us breakpoint usefully on call_ptrace.   It also
  32.    allows us to pass an extra argument to ptrace without
  33.    using an ANSI-C specific macro.  */
  34.  
  35. #define ptrace call_ptrace
  36.  
  37. #if !defined (offsetof)
  38. #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
  39. #endif
  40.  
  41. /* U_REGS_OFFSET is the offset of the registers within the u area.  */
  42. #if !defined (U_REGS_OFFSET)
  43. #define U_REGS_OFFSET \
  44.   ptrace (PT_READ_U, inferior_pid, \
  45.           (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
  46.     - KERNEL_U_ADDR
  47. #endif
  48.  
  49. /* Fetch one register.  */
  50.  
  51. static void
  52. fetch_register (regno)
  53.      int regno;
  54. {
  55.   register unsigned int regaddr;
  56.   char buf[MAX_REGISTER_RAW_SIZE];
  57.   register int i;
  58.  
  59.   /* Offset of registers within the u area.  */
  60.   unsigned int offset;
  61.  
  62.   offset = U_REGS_OFFSET;
  63.  
  64.   regaddr = register_addr (regno, offset);
  65.   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
  66.     {
  67.       errno = 0;
  68.       *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid,
  69.                  (PTRACE_ARG3_TYPE) regaddr, 0);
  70.       regaddr += sizeof (int);
  71.       if (errno != 0)
  72.     {
  73.       /* Warning, not error, in case we are attached; sometimes the
  74.          kernel doesn't let us at the registers.  */
  75.       char *err = safe_strerror (errno);
  76.       char *msg = alloca (strlen (err) + 128);
  77.       sprintf (msg, "reading register %s: %s", reg_names[regno], err);
  78.       warning (msg);
  79.       goto error_exit;
  80.     }
  81.     }
  82.   supply_register (regno, buf);
  83.  error_exit:;
  84. }
  85.  
  86. /* Fetch all registers, or just one, from the child process.  */
  87.  
  88. void
  89. fetch_inferior_registers (regno)
  90.      int regno;
  91. {
  92.   if (regno == -1)
  93.     for (regno = 0; regno < NUM_REGS; regno++)
  94.       fetch_register (regno);
  95.   else
  96.     fetch_register (regno);
  97. }
  98.  
  99. /* Store our register values back into the inferior.
  100.    If REGNO is -1, do this for all registers.
  101.    Otherwise, REGNO specifies which register (so we can save time).  */
  102.  
  103. void
  104. store_inferior_registers (regno)
  105.      int regno;
  106. {
  107.   register unsigned int regaddr;
  108.   extern char registers[];
  109.   register int i;
  110.  
  111.   unsigned int offset = U_REGS_OFFSET;
  112.  
  113.   if (regno >= 0)
  114.     {
  115.       regaddr = register_addr (regno, offset);
  116.       for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
  117.     {
  118.       errno = 0;
  119.       ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
  120.           *(int *) ®isters[REGISTER_BYTE (regno) + i]);
  121.       if (errno != 0)
  122.         {
  123.           char *err = safe_strerror (errno);
  124.           char *msg = alloca (strlen (err) + 128);
  125.           sprintf (msg, "writing register %s: %s", reg_names[regno], err);
  126.           warning (msg);
  127.         }
  128.       regaddr += sizeof(int);
  129.     }
  130.     }
  131.   else
  132.     {
  133.       for (regno = 0; regno < NUM_REGS; regno++)
  134.     {
  135.       if (CANNOT_STORE_REGISTER (regno))
  136.         continue;
  137.       store_inferior_registers (regno);
  138.     }
  139.     }
  140.   return;
  141. }
  142.  
  143.  
  144. /* PT_PROT is specific to the PA BSD kernel and isn't documented
  145.    anywhere (except here).  
  146.  
  147.    PT_PROT allows one to enable/disable the data memory break bit
  148.    for pages of memory in an inferior process.  This bit is used
  149.    to cause "Data memory break traps" to occur when the appropriate
  150.    page is written to.
  151.  
  152.    The arguments are as follows:
  153.  
  154.       PT_PROT -- The ptrace action to perform.
  155.  
  156.       INFERIOR_PID -- The pid of the process who's page table entries
  157.       will be modified.
  158.  
  159.       PT_ARGS -- The *address* of a 3 word block of memory which has
  160.       additional information:
  161.  
  162.         word 0 -- The start address to watch.  This should be a page-aligned
  163.     address.
  164.  
  165.     word 1 -- The ending address to watch.  Again, this should be a 
  166.     page aligned address.
  167.  
  168.     word 2 -- Nonzero to enable the data memory break bit on the
  169.     given address range or zero to disable the data memory break
  170.     bit on the given address range.
  171.  
  172.   This call may fail if the given addresses are not valid in the inferior
  173.   process.  This most often happens when restarting a program which
  174.   as watchpoints inserted on heap or stack memory.  */
  175.     
  176. #define PT_PROT 21
  177.  
  178. int
  179. hppa_set_watchpoint (addr, len, flag)
  180.      int addr, len, flag;
  181. {
  182.   int pt_args[3];
  183.   pt_args[0] = addr;
  184.   pt_args[1] = addr + len;
  185.   pt_args[2] = flag;
  186.  
  187.   /* Mask off the lower 12 bits since we want to work on a page basis.  */
  188.   pt_args[0] >>= 12; 
  189.   pt_args[1] >>= 12; 
  190.  
  191.   /* Rounding adjustments.  */
  192.   pt_args[1] -= pt_args[0]; 
  193.   pt_args[1]++; 
  194.  
  195.   /* Put the lower 12 bits back as zero.  */
  196.   pt_args[0] <<= 12; 
  197.   pt_args[1] <<= 12; 
  198.  
  199.   /* Do it.  */
  200.   return ptrace (PT_PROT, inferior_pid, (PTRACE_ARG3_TYPE) pt_args, 0);
  201. }
  202.