home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / GDB / GDB-4.13 / GDB-4 / gdb-4.13 / gdb / i386v-nat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  8.6 KB  |  360 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_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
  105.                        int));
  106.  
  107. static int
  108. i386_insert_aligned_watchpoint PARAMS ((pid, addr, len, rw));
  109.  
  110. /* Insert a watchpoint.  */
  111.  
  112. int
  113. i386_insert_watchpoint (pid, addr, len, rw)
  114.      int pid;
  115.      CORE_ADDR addr;
  116.      int len;
  117.      int rw;
  118. {
  119.   return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
  120. }
  121.  
  122. static int
  123. i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
  124.      int pid;
  125.      CORE_ADDR waddr;
  126.      CORE_ADDR addr;
  127.      int len;
  128.      int rw;
  129. {
  130.   int i;
  131.   int read_write_bits, len_bits;
  132.   int free_debug_register;
  133.   int register_number;
  134.   
  135.   /* Look for a free debug register.  */
  136.   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  137.     {
  138.       if (address_lookup[i - DR_FIRSTADDR] == 0)
  139.     break;
  140.     }
  141.  
  142.   /* No more debug registers!  */
  143.   if (i > DR_LASTADDR)
  144.     return -1;
  145.  
  146.   read_write_bits = ((rw & 1) ? DR_RW_READ : 0) | ((rw & 2) ? DR_RW_WRITE : 0);
  147.  
  148.   if (len == 1)
  149.     len_bits = DR_LEN_1;
  150.   else if (len == 2)
  151.     {
  152.       if (addr % 2)
  153.     return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
  154.       len_bits = DR_LEN_2;
  155.     }
  156.  
  157.   else if (len == 4)
  158.     {
  159.       if (addr % 4)
  160.     return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
  161.       len_bits = DR_LEN_4;
  162.     }
  163.   else
  164.     return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
  165.   
  166.   free_debug_register = i;
  167.   register_number = free_debug_register - DR_FIRSTADDR;
  168.   debug_control_mirror |=
  169.     ((read_write_bits | len_bits)
  170.      << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
  171.   debug_control_mirror |=
  172.     (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
  173.   debug_control_mirror |= DR_LOCAL_SLOWDOWN;
  174.   debug_control_mirror &= ~DR_CONTROL_RESERVED;
  175.   
  176.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
  177.       debug_control_mirror);
  178.   ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
  179.       addr);
  180.  
  181.   /* Record where we came from.  */
  182.   address_lookup[register_number] = addr;
  183.   return 0;
  184. }
  185.  
  186. static int
  187. i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
  188.      int pid;
  189.      CORE_ADDR waddr;
  190.      CORE_ADDR addr;
  191.      int len;
  192.      int rw;
  193. {
  194.   int align;
  195.   int size;
  196.   int rv;
  197.  
  198.   static int size_try_array[16] = {
  199.     1, 1, 1, 1,            /* trying size one */
  200.     2, 1, 2, 1,            /* trying size two */
  201.     2, 1, 2, 1,            /* trying size three */
  202.     4, 1, 2, 1            /* trying size four */
  203.   };
  204.  
  205.   rv = 0;
  206.   while (len > 0)
  207.     {
  208.       align = addr % 4;
  209.       /* Four is the maximum length for 386.  */
  210.       size = (len > 4) ? 3 : len - 1;
  211.       size = size_try_array[size * 4 + align];
  212.  
  213.       rv = i386_insert_watchpoint (pid, waddr, addr, size, rw);
  214.       if (rv)
  215.     {
  216.       i386_remove_watchpoint (pid, waddr, size);
  217.       return rv;
  218.     }
  219.       addr += size;
  220.       len -= size;
  221.     }
  222.   return rv;
  223. }
  224.  
  225. /* Remove a watchpoint.  */
  226.  
  227. int
  228. i386_remove_watchpoint (pid, addr, len)
  229.      int pid;
  230.      CORE_ADDR addr;
  231.      int len;
  232. {
  233.   int i;
  234.   int register_number;
  235.  
  236.   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  237.     {
  238.       register_number = i - DR_FIRSTADDR;
  239.       if (address_lookup[register_number] == addr)
  240.     {
  241.       debug_control_mirror &=
  242.         ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
  243.       address_lookup[register_number] = 0;
  244.     }
  245.     }
  246.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
  247.       debug_control_mirror);
  248.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  249.  
  250.   return 0;
  251. }
  252.  
  253. /* Check if stopped by a watchpoint.  */
  254.  
  255. CORE_ADDR
  256. i386_stopped_by_watchpoint (pid)
  257.     int pid;
  258. {
  259.   int i;
  260.   int status;
  261.  
  262.   status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  263.   ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  264.  
  265.   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  266.     {
  267.       if (status & (1 << (i - DR_FIRSTADDR)))
  268.     return address_lookup[i - DR_FIRSTADDR];
  269.     }
  270.  
  271.   return 0;
  272. }
  273.  
  274. #endif /* TARGET_CAN_USE_HARDWARE_WATCHPOINT */
  275.  
  276. #if 0
  277. /* using FLOAT_INFO as is would be a problem.  FLOAT_INFO is called
  278.    via a command xxx and eventually calls ptrace without ever having
  279.    traversed the target vector.  This would be terribly impolite
  280.    behaviour for a sun4 hosted remote gdb.
  281.  
  282.    A fix might be to move this code into the "info registers" command.
  283.    rich@cygnus.com 15 Sept 92. */
  284. i386_float_info ()
  285. {
  286.   struct user u; /* just for address computations */
  287.   int i;
  288.   /* fpstate defined in <sys/user.h> */
  289.   struct fpstate *fpstatep;
  290.   char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
  291.   unsigned int uaddr;
  292.   char fpvalid = 0;
  293.   unsigned int rounded_addr;
  294.   unsigned int rounded_size;
  295.   extern int corechan;
  296.   int skip;
  297.   
  298.   uaddr = (char *)&u.u_fpvalid - (char *)&u;
  299.   if (target_has_execution)
  300.     {
  301.       unsigned int data;
  302.       unsigned int mask;
  303.       
  304.       rounded_addr = uaddr & -sizeof (int);
  305.       data = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  306.       mask = 0xff << ((uaddr - rounded_addr) * 8);
  307.       
  308.       fpvalid = ((data & mask) != 0);
  309.     } 
  310. #if 0
  311.   else 
  312.     {
  313.       if (lseek (corechan, uaddr, 0) < 0)
  314.     perror ("seek on core file");
  315.       if (myread (corechan, &fpvalid, 1) < 0) 
  316.     perror ("read on core file");
  317.       
  318.     }
  319. #endif    /* no core support yet */
  320.   
  321.   if (fpvalid == 0) 
  322.     {
  323.       printf_unfiltered ("no floating point status saved\n");
  324.       return;
  325.     }
  326.   
  327.   uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
  328.   if (target_has_execution)
  329.     {
  330.       int *ip;
  331.       
  332.       rounded_addr = uaddr & -sizeof (int);
  333.       rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
  334.               sizeof (int) - 1) / sizeof (int);
  335.       skip = uaddr - rounded_addr;
  336.       
  337.       ip = (int *)buf;
  338.       for (i = 0; i < rounded_size; i++) 
  339.     {
  340.       *ip++ = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  341.       rounded_addr += sizeof (int);
  342.     }
  343.     } 
  344. #if 0
  345.   else 
  346.     {
  347.       if (lseek (corechan, uaddr, 0) < 0)
  348.     perror_with_name ("seek on core file");
  349.       if (myread (corechan, buf, sizeof (struct fpstate)) < 0) 
  350.     perror_with_name ("read from core file");
  351.       skip = 0;
  352.     }
  353. #endif    /* 0 */ 
  354.  
  355.   fpstatep = (struct fpstate *)(buf + skip);
  356.   print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
  357. }
  358.  
  359. #endif /* never */
  360.