This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Patch for gdb5.0; enable hardware watchpoints on UnixWare


I currently have no idea how to get a cleaner interface to procfs.c.

But all the i386v4-nat.c code has to be conditionalized on UNIXWARE (or better
yet, moved to a new i386sco-nat.c file), as i386v4-nat.c is used by
x86 Solaris as well, and Solaris uses page faulting instead of debug
registers for watchpoints, and would not compile with your patches
installed.

> This is a bit ugly: i386v4-nat.c has to have access to some things only
> known by procfs.c.
> 
> Is there a prettier/recommended way of doing this?
> 
> Anyway here's the patch:
> 
> 2000-10-30  John Hughes  <john@CalvaEDI.COM>
> 
>         * i386v4-nat.c (i386_insert_watchpoint, i386_remove_watchpoint,
>         i386_check_watch_resources, i386_stopped_by_watchpoint,
>         i386_insert_aligned_watchpoint, i386_insert_unaliged_watchpoint):
>         use i386 debug registers to implement hardware watchpoints on
>         UnixWare systems.
> 
>         * procfs.c (proc_family) allow access to family specific
>         information (contains debug registers on UnixWare systems).
> 
>         * procfs.c (proc_command) allow other modules to issue commands
>         to the procfs ctl file.
> 
>         * config/i386/tm-i386v42mp.c (TARGET_HAS_HARDWARE_WATCHPOINTS,
>         TARGET_CAN_USE_HARDWARE_WATCHPOINT, HAVE_CONTINUABLE_WATCHPOINT,
>         HAVE_STEPPABLE_WATCHPOINT, STOPPED_BY_WATCHPOINT,
>         target_insert_watchpoint, target_remove_watchpoint): define.
> 
> -- 
> John Hughes <john@Calva.COM>, 
>         CalvaEDI SA.                            Tel: +33-1-4313-3131
>         66 rue du Moulin de la Pointe,          Fax: +33-1-4313-3139
>         75013 PARIS.
> ------=_NextPart_000_0205_01C0427E.5E2E9EC0
> Content-Type: text/plain;
> 	name="unixware-watch-patch.txt"
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: attachment;
> 	filename="unixware-watch-patch.txt"
> 
> --- config/i386/tm-i386v42mp.h.orig	Tue Jan 11 04:07:28 2000
> +++ config/i386/tm-i386v42mp.h	Sat Oct 28 08:15:21 2000
> @@ -61,4 +61,23 @@
>  /* Return whether PID contains a user-space thread id. */
>  #define ISTID(PID)              ((PID) & 0x40000000)
> =20
> +/* We can also do hardware watchpoints */
> +#define TARGET_HAS_HARDWARE_WATCHPOINTS
> +#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
> +	i386_check_watch_resources (type, cnt, ot)
> +/* After a watchpoint trap, the PC points to the instruction which
> +   caused the trap.  But we can continue over it without disabling the
> +   trap. */
> +#define HAVE_CONTINUABLE_WATCHPOINT
> +#define HAVE_STEPPABLE_WATCHPOINT
> +
> +#define STOPPED_BY_WATCHPOINT(W)  \
> +  i386_stopped_by_watchpoint (inferior_pid)
> +
> +#define target_insert_watchpoint(addr, len, type)  \
> +  i386_insert_watchpoint (inferior_pid, addr, len, type)
> +
> +#define target_remove_watchpoint(addr, len, type)  \
> +  i386_remove_watchpoint (inferior_pid, addr, len)
> +
>  #endif /* ifndef TM_I386V42MP_H */
> --- i386v4-nat.c.orig	Thu Apr 13 20:15:49 2000
> +++ i386v4-nat.c	Mon Oct 30 11:58:38 2000
> @@ -250,4 +250,230 @@
> =20
>  #endif /* defined (HAVE_FPREGSET_T) */
> =20
> +#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
> +
> +#include <sys/debugreg.h>
> +
> +#if !defined (offsetof)
> +#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
> +#endif
> +
> +/* Record which address associates with which register.  */
> +static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
> +
> +static int
> +i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
> +					int));
> +
> +static int
> +i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, =
> int,
> +					   int));
> +
> +/* Insert a watchpoint.  */
> +
> +int
> +i386_insert_watchpoint (pid, addr, len, rw)
> +     int pid;
> +     CORE_ADDR addr;
> +     int len;
> +     int rw;
> +{
> +  return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
> +}
> +
> +pfamily_t *proc_family (int pid);
> +
> +static int
> +i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
> +     int pid;
> +     CORE_ADDR waddr;
> +     CORE_ADDR addr;
> +     int len;
> +     int rw;
> +{
> +  int i;
> +  int read_write_bits, len_bits;
> +  int free_debug_register;
> +  int register_number;
> +  pfamily_t *family;
> +  int control;
> +
> +  if (!(family =3D proc_family (pid))) return -1;
> +
> +  /* Look for a free debug register.  */
> +  for (i =3D DR_FIRSTADDR; i <=3D DR_LASTADDR; i++)
> +    {
> +      if (address_lookup[i - DR_FIRSTADDR] =3D=3D 0)
> +	break;
> +    }
> +
> +  /* No more debug registers!  */
> +  if (i > DR_LASTADDR)
> +    return -1;
> +
> +  read_write_bits =3D (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
> +
> +  if (len =3D=3D 1)
> +    len_bits =3D DR_LEN_1;
> +  else if (len =3D=3D 2)
> +    {
> +      if (addr % 2)
> +	return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
> +      len_bits =3D DR_LEN_2;
> +    }
> +
> +  else if (len =3D=3D 4)
> +    {
> +      if (addr % 4)
> +	return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
> +      len_bits =3D DR_LEN_4;
> +    }
> +  else
> +    return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, =
> rw);
> +
> +  free_debug_register =3D i;
> +  register_number =3D free_debug_register - DR_FIRSTADDR;
> +
> +  control =3D family->pf_dbreg.debugreg[DR_CONTROL];
> +
> +  control |=3D
> +    ((read_write_bits | len_bits)
> +     << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
> +  control |=3D
> +    (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
> +  control |=3D DR_LOCAL_SLOWDOWN;
> +  control &=3D ~DR_CONTROL_RESERVED;
> +
> +  family->pf_dbreg.debugreg[DR_CONTROL] =3D control; =20
> +  family->pf_dbreg.debugreg[free_debug_register] =3D addr;
> +
> +  proc_command (pid, PCSDBREG, &family->pf_dbreg, sizeof =
> family->pf_dbreg);
> +
> +  /* Record where we came from.  */
> +  address_lookup[register_number] =3D waddr;
> +  return 0;
> +}
> +
> +static int
> +i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
> +     int pid;
> +     CORE_ADDR waddr;
> +     CORE_ADDR addr;
> +     int len;
> +     int rw;
> +{
> +  int align;
> +  int size;
> +  int rv;
> +
> +  static int size_try_array[16] =3D
> +  {
> +    1, 1, 1, 1,			/* trying size one */
> +    2, 1, 2, 1,			/* trying size two */
> +    2, 1, 2, 1,			/* trying size three */
> +    4, 1, 2, 1			/* trying size four */
> +  };
> +
> +  rv =3D 0;
> +  while (len > 0)
> +    {
> +      align =3D addr % 4;
> +      /* Four is the maximum length for 386.  */
> +      size =3D (len > 4) ? 3 : len - 1;
> +      size =3D size_try_array[size * 4 + align];
> +
> +      rv =3D i386_insert_aligned_watchpoint (pid, waddr, addr, size, =
> rw);
> +      if (rv)
> +	{
> +	  i386_remove_watchpoint (pid, waddr, size);
> +	  return rv;
> +	}
> +      addr +=3D size;
> +      len -=3D size;
> +    }
> +  return rv;
> +}
> +
> +/* Remove a watchpoint.  */
> +
> +int
> +i386_remove_watchpoint (pid, addr, len)
> +     int pid;
> +     CORE_ADDR addr;
> +     int len;
> +{
> +  int i;
> +  int register_number;
> +  int control;
> +  pfamily_t *family =3D proc_family (pid);
> +
> +  control =3D family->pf_dbreg.debugreg[DR_CONTROL];
> +	 =20
> +  for (i =3D DR_FIRSTADDR; i <=3D DR_LASTADDR; i++)
> +    {
> +      register_number =3D i - DR_FIRSTADDR;
> +      if (address_lookup[register_number] =3D=3D addr)
> +	{
> +	  control &=3D
> +	    ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * =
> register_number));
> +	  address_lookup[register_number] =3D 0;
> +	}
> +    }
> +
> +  family->pf_dbreg.debugreg[DR_CONTROL] =3D control;
> +  family->pf_dbreg.debugreg[DR_STATUS] =3D 0;
> +
> +  proc_command (pid, PCSDBREG, &family->pf_dbreg, sizeof =
> family->pf_dbreg);
> +
> +  return 0;
> +}
> +
> +/* Check if stopped by a watchpoint.  */
> +
> +CORE_ADDR
> +i386_stopped_by_watchpoint (pid)
> +     int pid;
> +{
> +  int i;
> +  int status;
> +  pfamily_t *family;
> +
> +  if (!(family =3D proc_family (pid))) return 0;
> +
> +  if (!(status =3D family->pf_dbreg.debugreg [DR_STATUS])) return 0;
> + =20
> +  family->pf_dbreg.debugreg[DR_STATUS] =3D 0;
> +
> +  proc_command (pid, PCSDBREG, &family->pf_dbreg, sizeof =
> family->pf_dbreg);
> + =20
> +  for (i =3D DR_FIRSTADDR; i <=3D DR_LASTADDR; i++)
> +    {
> +      if (status & (1 << (i - DR_FIRSTADDR)))
> +	return address_lookup[i - DR_FIRSTADDR];
> +    }
> +
> +  return 0;
> +}
> +
> +
> +/*
> + * This is not good enough 'cos non-aligned watchpoints can gobble
> + * up more debug registers.
> + */
> +
> +i386_check_watch_resources (type, cnt, ot)
> +     int type;
> +     int cnt;
> +     int ot;
> +{
> +  if (type =3D=3D bp_hardware_breakpoint) return 0;
> +
> +  if (cnt <=3D DR_LASTADDR - DR_FIRSTADDR + 1) return 1;
> +
> +  return -1;
> +}
> +
> +
> +#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
> +
>  #endif /* HAVE_SYS_PROCFS_H */
> --- procfs.c.orig	Fri Apr  7 06:33:21 2000
> +++ procfs.c	Mon Oct 30 12:01:21 2000
> @@ -5256,3 +5256,43 @@
>    else
>      return -1;
>  }
> +
> +
> +#ifdef UNIXWARE
> +
> +/* Messy debug register interface for UW7 */
> +
> +pfamily_t *
> +proc_family (pid)
> +    int pid;
> +{
> +  procinfo *pi;
> +  pi =3D find_procinfo_or_die (PIDGET (pid), 0);
> +  return &pi->prstatus.pr_lwp.pr_family;
> +}
> +
> +#include <sys/uio.h>
> +
> +int
> +proc_command (pid, cmd, buf, len)
> +    int pid;
> +    int cmd;
> +    void *buf;
> +    int len;
> +{
> +  procinfo *pi;
> +  int res;
> +  struct iovec iov [2];
> +
> +  pi =3D find_procinfo_or_die (PIDGET (pid), 0);
> +
> +  iov [0].iov_len =3D sizeof cmd;
> +  iov [0].iov_base =3D &cmd;
> +  iov [1].iov_len =3D len;
> +  iov [1].iov_base =3D buf;
> + =20
> +  return writev (pi->ctl_fd, iov, 2);
> +}
> +
> +#endif
> +

-- 
Peter Schauer			pes@regent.e-technik.tu-muenchen.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]