home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / gdb / i386v-nat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-03  |  8.7 KB  |  361 lines

  1. /* Intel 386 native support for SYSV systems (pre-SVR4).
  2.    Copyright (C) 1988, 1989, 1991, 1992, 1994 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "defs.h"
  21. #include "frame.h"
  22. #include "inferior.h"
  23. #include "language.h"
  24. #include "gdbcore.h"
  25.  
  26. #ifdef USG
  27. #include <sys/types.h>
  28. #endif
  29.  
  30. #include <sys/param.h>
  31. #include <sys/dir.h>
  32. #include <signal.h>
  33. #include <sys/user.h>
  34. #include <sys/ioctl.h>
  35. #include <fcntl.h>
  36.  
  37. #ifdef TARGET_CAN_USE_HARDWARE_WATCHPOINT
  38. #include <sys/debugreg.h>
  39. #endif
  40.  
  41. #include <sys/file.h>
  42. #include <sys/stat.h>
  43.  
  44. #ifndef NO_SYS_REG_H
  45. #include <sys/reg.h>
  46. #endif
  47.  
  48. #include "floatformat.h"
  49.  
  50. #include "target.h"
  51.  
  52.  
  53. /* this table must line up with REGISTER_NAMES in tm-i386v.h */
  54. /* symbols like 'EAX' come from <sys/reg.h> */
  55. static int regmap[] = 
  56. {
  57.   EAX, ECX, EDX, EBX,
  58.   UESP, EBP, ESI, EDI,
  59.   EIP, EFL, CS, SS,
  60.   DS, ES, FS, GS,
  61. };
  62.  
  63. /* blockend is the value of u.u_ar0, and points to the
  64.  * place where GS is stored
  65.  */
  66.  
  67. int
  68. i386_register_u_addr (blockend, regnum)
  69.      int blockend;
  70.      int regnum;
  71. {
  72. #if 0
  73.   /* this will be needed if fp registers are reinstated */
  74.   /* for now, you can look at them with 'info float'
  75.    * sys5 wont let you change them with ptrace anyway
  76.    */
  77.   if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM) 
  78.     {
  79.       int ubase, fpstate;
  80.       struct user u;
  81.       ubase = blockend + 4 * (SS + 1) - KSTKSZ;
  82.       fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
  83.       return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
  84.     } 
  85.   else
  86. #endif
  87.     return (blockend + 4 * regmap[regnum]);
  88.   
  89. }
  90.  
  91. #ifdef TARGET_CAN_USE_HARDWARE_WATCHPOINT
  92.  
  93. #if !defined (offsetof)
  94. #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
  95. #endif
  96.  
  97. /* Record the value of the debug control register.  */
  98. static int debug_control_mirror;
  99.  
  100. /* Record which address associates with which register.  */
  101. static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
  102.  
  103. static int
  104. i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
  105.                        int));
  106.  
  107. static int
  108. i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
  109.                        int));
  110.  
  111. /* Insert a watchpoint.  */
  112.  
  113. int
  114. i386_insert_watchpoint (pid, addr, len, rw)
  115.      int pid;
  116.      CORE_ADDR addr;
  117.      int len;
  118.      int rw;
  119. {
  120.   return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
  121. }
  122.  
  123. static int
  124. i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
  125.      int pid;
  126.      CORE_ADDR waddr;
  127.      CORE_ADDR addr;
  128.      int len;
  129.      int rw;
  130. {
  131.   int i;
  132.   int read_write_bits, len_bits;
  133.   int free_debug_register;
  134.   int register_number;
  135.   
  136.   /* Look for a free debug register.  */
  137.   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  138.     {
  139.       if (address_lookup[i - DR_FIRSTADDR] == 0)
  140.     break;
  141.     }
  142.  
  143.   /* No more debug registers!  */
  144.   if (i > DR_LASTADDR)
  145.     return -1;
  146.  
  147.   read_write_bits = ((rw & 1) ? DR_RW_READ : 0) | ((rw & 2) ? DR_RW_WRITE : 0);
  148.  
  149.   if (len == 1)
  150.     len_bits = DR_LEN_1;
  151.   else if (len == 2)
  152.     {
  153.       if (addr % 2)
  154.     return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
  155.       len_bits = DR_LEN_2;
  156.     }
  157.  
  158.   else if (len == 4)
  159.     {
  160.       if (addr % 4)
  161.     return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
  162.       len_bits = DR_LEN_4;
  163.     }
  164.   else
  165.     return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
  166.   
  167.   free_debug_register = i;
  168.   register_number = free_debug_register - DR_FIRSTADDR;
  169.   debug_control_mirror |=
  170.     ((read_write_bits | len_bits)
  171.      << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
  172.   debug_control_mirror |=
  173.     (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
  174.   debug_control_mirror |= DR_LOCAL_SLOWDOWN;
  175.   debug_control_mirror &= ~DR_CONTROL_RESERVED;
  176.   
  177.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
  178.       debug_control_mirror);
  179.   ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
  180.       addr);
  181.  
  182.   /* Record where we came from.  */
  183.   address_lookup[register_number] = addr;
  184.   return 0;
  185. }
  186.  
  187. static int
  188. i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
  189.      int pid;
  190.      CORE_ADDR waddr;
  191.      CORE_ADDR addr;
  192.      int len;
  193.      int rw;
  194. {
  195.   int align;
  196.   int size;
  197.   int rv;
  198.  
  199.   static int size_try_array[16] = {
  200.     1, 1, 1, 1,            /* trying size one */
  201.     2, 1, 2, 1,            /* trying size two */
  202.     2, 1, 2, 1,            /* trying size three */
  203.     4, 1, 2, 1            /* trying size four */
  204.   };
  205.  
  206.   rv = 0;
  207.   while (len > 0)
  208.     {
  209.       align = addr % 4;
  210.       /* Four is the maximum length for 386.  */
  211.       size = (len > 4) ? 3 : len - 1;
  212.       size = size_try_array[size * 4 + align];
  213.  
  214.       rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
  215.       if (rv)
  216.     {
  217.       i386_remove_watchpoint (pid, waddr, size);
  218.       return rv;
  219.     }
  220.       addr += size;
  221.       len -= size;
  222.     }
  223.   return rv;
  224. }
  225.  
  226. /* Remove a watchpoint.  */
  227.  
  228. int
  229. i386_remove_watchpoint (pid, addr, len)
  230.      int pid;
  231.      CORE_ADDR addr;
  232.      int len;
  233. {
  234.   int i;
  235.   int register_number;
  236.  
  237.   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  238.     {
  239.       register_number = i - DR_FIRSTADDR;
  240.       if (address_lookup[register_number] == addr)
  241.     {
  242.       debug_control_mirror &=
  243.         ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
  244.       address_lookup[register_number] = 0;
  245.     }
  246.     }
  247.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
  248.       debug_control_mirror);
  249.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  250.  
  251.   return 0;
  252. }
  253.  
  254. /* Check if stopped by a watchpoint.  */
  255.  
  256. CORE_ADDR
  257. i386_stopped_by_watchpoint (pid)
  258.     int pid;
  259. {
  260.   int i;
  261.   int status;
  262.  
  263.   status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  264.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  265.  
  266.   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  267.     {
  268.       if (status & (1 << (i - DR_FIRSTADDR)))
  269.     return address_lookup[i - DR_FIRSTADDR];
  270.     }
  271.  
  272.   return 0;
  273. }
  274.  
  275. #endif /* TARGET_CAN_USE_HARDWARE_WATCHPOINT */
  276.  
  277. #if 0
  278. /* using FLOAT_INFO as is would be a problem.  FLOAT_INFO is called
  279.    via a command xxx and eventually calls ptrace without ever having
  280.    traversed the target vector.  This would be terribly impolite
  281.    behaviour for a sun4 hosted remote gdb.
  282.  
  283.    A fix might be to move this code into the "info registers" command.
  284.    rich@cygnus.com 15 Sept 92. */
  285. i386_float_info ()
  286. {
  287.   struct user u; /* just for address computations */
  288.   int i;
  289.   /* fpstate defined in <sys/user.h> */
  290.   struct fpstate *fpstatep;
  291.   char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
  292.   unsigned int uaddr;
  293.   char fpvalid = 0;
  294.   unsigned int rounded_addr;
  295.   unsigned int rounded_size;
  296.   extern int corechan;
  297.   int skip;
  298.   
  299.   uaddr = (char *)&u.u_fpvalid - (char *)&u;
  300.   if (target_has_execution)
  301.     {
  302.       unsigned int data;
  303.       unsigned int mask;
  304.       
  305.       rounded_addr = uaddr & -sizeof (int);
  306.       data = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  307.       mask = 0xff << ((uaddr - rounded_addr) * 8);
  308.       
  309.       fpvalid = ((data & mask) != 0);
  310.     } 
  311. #if 0
  312.   else 
  313.     {
  314.       if (lseek (corechan, uaddr, 0) < 0)
  315.     perror ("seek on core file");
  316.       if (myread (corechan, &fpvalid, 1) < 0) 
  317.     perror ("read on core file");
  318.       
  319.     }
  320. #endif    /* no core support yet */
  321.   
  322.   if (fpvalid == 0) 
  323.     {
  324.       printf_unfiltered ("no floating point status saved\n");
  325.       return;
  326.     }
  327.   
  328.   uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
  329.   if (target_has_execution)
  330.     {
  331.       int *ip;
  332.       
  333.       rounded_addr = uaddr & -sizeof (int);
  334.       rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
  335.               sizeof (int) - 1) / sizeof (int);
  336.       skip = uaddr - rounded_addr;
  337.       
  338.       ip = (int *)buf;
  339.       for (i = 0; i < rounded_size; i++) 
  340.     {
  341.       *ip++ = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  342.       rounded_addr += sizeof (int);
  343.     }
  344.     } 
  345. #if 0
  346.   else 
  347.     {
  348.       if (lseek (corechan, uaddr, 0) < 0)
  349.     perror_with_name ("seek on core file");
  350.       if (myread (corechan, buf, sizeof (struct fpstate)) < 0) 
  351.     perror_with_name ("read from core file");
  352.       skip = 0;
  353.     }
  354. #endif    /* 0 */ 
  355.  
  356.   fpstatep = (struct fpstate *)(buf + skip);
  357.   print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
  358. }
  359.  
  360. #endif /* never */
  361.