*BSD News Article 21809


Return to BSD News archive

Newsgroups: comp.os.386bsd.misc
Path: sserve!newshost.anu.edu.au!munnari.oz.au!constellation!osuunx.ucc.okstate.edu!moe.ksu.ksu.edu!vixen.cso.uiuc.edu!howland.reston.ans.net!pipex!uunet!mcsun!hp4at!siemens.co.at!zerberus.gud.siemens.co.at!wirth
From: wirth@zerberus.gud.siemens.co.at (Helmut F. Wirth)
Subject: Enhancement for NetBSD's gdb
Message-ID: <1993Oct4.115028.1017@siemens.co.at>
Sender: wirth@zerberus (Helmut F. Wirth)
Date: Mon, 4 Oct 1993 11:50:28 GMT
Nntp-Posting-Host: zerberus.gud.siemens-austria
Organization: Siemens AG Oesterreich
Keywords: gdb, gdb-3.5, debugging
Lines: 507

Hi

Here are patches to gdb (V3.5, the version that comes originally with
NetBSD).

These changes allow you to read the floating point registers of a 
process under debugging. You can not yet write them. The command 
"info float" under gdb will show you a display like this:

(gdb) i flo
status 0x0020: exceptions: LOS; flags: 0000; top 0
control 0x1272: compute to 53 bits; round NEAREST; mask: DENORM UNDERF LOS;
last exception: opcode 0x55d; pc 0x1f:0x1234; operand 0x27:0xfdbfdbd0
regno  tag  msb              lsb  value
=> 7: empty 4005f6e978d4fdf3b800  123.456
   6: empty 3ffe8000000000000000  0.5
   5: empty 00000000000000000000  0
   4: empty 400081f8299f0aa37800  2.03077
   3: empty 40008000000000000000  2
   2: empty 7fffffffffffffffffff  NaN
   1: empty c0100880239000060220  NaN
   0: empty 58000000080000010000  NaN

The environment including control and status word is displayed, then the
8 coprocessor registers are shown in the internal 10 byte format and in
double format. In the example above none of the registers contains a valid
datum, so you can ignore the small arrow on the left hand side.

(gdb) i flo
status 0x3000: flags: 0000; top 6
control 0x1272: compute to 53 bits; round NEAREST; mask: DENORM UNDERF LOS;
last exception: opcode 0x545; pc 0x1f:0x92; operand 0x27:0xfdbfdbc8
regno  tag  msb              lsb  value
   7: empty 00000000000000000000  0
   6: empty 400081f8299f0aa37800  2.03077
   5: empty 40008000000000000000  2
   4: empty 7fffffffffffffffffff  NaN
   3: empty c0100880239000060220  NaN
   2: empty 58000000080000010000  NaN
=> 1: valid 4000c000000000000000  3
   0: valid 4002a000000000000000  10

In this example you see two values pushed to the NPX-Stack. The arrow on
the left hand side is the internal "NPX stack pointer".

Additionally patches are included for gdb's disassembler to enable
i486 instructions.

The diffs below are against the sources distributed with NetBSD 0.9.
But you should not have much problems with 386BSD or FreeBSD. (I think).

To apply the diffs do the following:

cd to the directory containing the gdb sources. (Usually src/usr.bin/gdb or
src/gnu/usr.bin/gdb).

Apply the patch with patch -p0 -s < ThisFile.

If you want to see patch's progress, leave out the "-s" option in the line
above.

Then do a remake: make all 
and install with: make install

Enjoy!

Helmut F. Wirth		(wirth@zerberus.gud.siemens.co.at)

diff -c --recursive config.orig/i386-pinsn.c config/i386-pinsn.c
*** config.orig/i386-pinsn.c	Sun Oct  3 19:37:29 1993
--- config/i386-pinsn.c	Sat Oct  2 16:07:20 1993
***************
*** 43,48 ****
--- 43,50 ----
  #define Ma OP_E, v_mode
  #define M OP_E, 0
  #define Mp OP_E, 0		/* ? */
+ #define Md OP_E, d_mode
+ 
  #define Gv OP_G, v_mode
  #define Gw OP_G, w_mode
  #define Rw OP_rm, w_mode
***************
*** 475,481 ****
    { "clts" },
    { "(bad)" },  
    /* 08 */
!   { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    /* 10 */
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
--- 477,485 ----
    { "clts" },
    { "(bad)" },  
    /* 08 */
!   { "invd"  },  
!   { "wbinvd" },
!   { "(bad)" },  { "(bad)" },  
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    /* 10 */
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
***************
*** 569,576 ****
    { "btS", Ev, Gv },  
    { "shldS", Ev, Gv, Ib },
    { "shldS", Ev, Gv, CL },
!   { "(bad)" },
!   { "(bad)" },  
    /* a8 */
    { "pushl", gs },
    { "popl", gs },
--- 573,580 ----
    { "btS", Ev, Gv },  
    { "shldS", Ev, Gv, Ib },
    { "shldS", Ev, Gv, CL },
!   { "cmpxchg", Eb, Gb },
!   { "cmpxchg", Ev, Gv },  
    /* a8 */
    { "pushl", gs },
    { "popl", gs },
***************
*** 599,609 ****
    { "movsbS", Gv, Eb },
    { "movswS", Gv, Ew },  
    /* c0 */
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
-   { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    /* c8 */
!   { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
!   { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    /* d0 */
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
--- 603,621 ----
    { "movsbS", Gv, Eb },
    { "movswS", Gv, Ew },  
    /* c0 */
+   { "xadd", Eb, Gb },
+   { "xadd", Ev, Gv },
+   { "(bad)" },  { "(bad)" },  
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    /* c8 */
!   { "bswapS",	eAX },
!   { "bswapS",	eCX },
!   { "bswapS",	eDX },
!   { "bswapS",	eBX },
!   { "bswapS",	eSP },
!   { "bswapS",	eBP },
!   { "bswapS",	eSI },
!   { "bswapS",	eDI },
    /* d0 */
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
    { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
***************
*** 810,816 ****
      { "smsw", Ew },
      { "(bad)" },
      { "lmsw", Ew },
!     { "(bad)" },
    },
    /* GRP8 */
    {
--- 822,828 ----
      { "smsw", Ew },
      { "(bad)" },
      { "lmsw", Ew },
!     { "invlpg", Md }
    },
    /* GRP8 */
    {

diff -c --recursive config.orig/i386bsd-dep.c config/i386bsd-dep.c
*** config.orig/i386bsd-dep.c	Sun Oct  3 19:37:29 1993
--- config/i386bsd-dep.c	Sun Oct  3 19:51:06 1993
***************
*** 69,74 ****
--- 69,78 ----
  #endif
  #include <machine/vmparam.h>
  #include <machine/cpu.h>
+ #include <machine/pcb.h>
+ #ifdef i386
+ #include <machine/npx.h>
+ #endif
  #include <ctype.h>
  #include "symtab.h"	/* XXX */
  
***************
*** 1588,1621 ****
      return (blockend + 4 * regmap[regnum]);
  }
  
! i387_to_double (from, to)
       char *from;
       char *to;
  {
-   long *lp;
    /* push extended mode on 387 stack, then pop in double mode
     *
     * first, set exception masks so no error is generated -
     * number will be rounded to inf or 0, if necessary 
     */
!   asm ("pushl %eax"); 		/* grab a stack slot */
!   asm ("fstcw (%esp)");		/* get 387 control word */
!   asm ("movl (%esp),%eax");	/* save old value */
!   asm ("orl $0x3f,%eax");		/* mask all exceptions */
!   asm ("pushl %eax");
!   asm ("fldcw (%esp)");		/* load new value into 387 */
!   
!   asm ("movl 8(%ebp),%eax");
!   asm ("fldt (%eax)");		/* push extended number on 387 stack */
!   asm ("fwait");
!   asm ("movl 12(%ebp),%eax");
!   asm ("fstpl (%eax)");		/* pop double */
!   asm ("fwait");
!   
!   asm ("popl %eax");		/* flush modified control word */
!   asm ("fnclex");			/* clear exceptions */
!   asm ("fldcw (%esp)");		/* restore original control word */
!   asm ("popl %eax");		/* flush saved copy */
  }
  
  double_to_i387 (from, to)
--- 1592,1620 ----
      return (blockend + 4 * regmap[regnum]);
  }
  
! void i387_to_double (from, to)
       char *from;
       char *to;
  {
    /* push extended mode on 387 stack, then pop in double mode
     *
     * first, set exception masks so no error is generated -
     * number will be rounded to inf or 0, if necessary 
     */
!   asm ("subl  $4,%esp");        /* grab a stack slot */
!   asm ("fstcw (%esp)");         /* get 387 control word */
!   asm ("movw  (%esp),%ax");     /* save old value */
!   asm ("movw  %ax,2(%esp)");
!   asm ("orl   $0x3f,(%esp)");   /* mask all exceptions */
!   asm ("fldcw (%esp)");         /* load new value into 387 */
!   
!   asm ("movl  8(%ebp),%eax");
!   asm ("fldt  (%eax)");         /* push extended number on 387 stack */
!   asm ("movl  12(%ebp),%eax");
!   asm ("fstpl (%eax)");         /* pop double */
!   asm ("fnclex");               /* clear exceptions */
!   asm ("fldcw 2(%esp)");        /* restore original control word */
!   asm ("addl  $4,%esp");
  }
  
  double_to_i387 (from, to)
***************
*** 1628,1639 ****
     */
    asm ("movl 8(%ebp),%eax");
    asm ("fldl (%eax)");
-   asm ("fwait");
    asm ("movl 12(%ebp),%eax");
    asm ("fstpt (%eax)");
    asm ("fwait");
  }
  
  struct env387 
  {
    unsigned short control;
--- 1627,1638 ----
     */
    asm ("movl 8(%ebp),%eax");
    asm ("fldl (%eax)");
    asm ("movl 12(%ebp),%eax");
    asm ("fstpt (%eax)");
    asm ("fwait");
  }
  
+ #ifndef __386BSD__
  struct env387 
  {
    unsigned short control;
***************
*** 1650,1655 ****
--- 1649,1655 ----
    unsigned short r3;
    unsigned char regs[8][10];
  };
+ #endif
  
  static
  print_387_control_word (control)
***************
*** 1715,1731 ****
  }
  
  static
! print_387_status (status, ep)
       unsigned short status;
!      struct env387 *ep;
  {
    int i;
    int bothstatus;
    int top;
    int fpreg;
    unsigned char *p;
    
!   bothstatus = ((status != 0) && (ep->status != 0));
    if (status != 0) 
      {
        if (bothstatus)
--- 1715,1735 ----
  }
  
  static
! print_387_status (status, es)
       unsigned short status;
!      struct save87 *es;
  {
    int i;
    int bothstatus;
    int top;
    int fpreg;
    unsigned char *p;
+   struct env87 *ep = &es->sv_env;
    
! #ifdef __386BSD__
!   print_387_status_word(status);
! #else
!   bothstatus = ((status != 0) && (ep->en_sw != 0));
    if (status != 0) 
      {
        if (bothstatus)
***************
*** 1733,1761 ****
        print_387_status_word (status);
      }
    
!   if (ep->status != 0) 
      {
        if (bothstatus)
  	printf ("e: ");
!       print_387_status_word (ep->status);
      }
!   
!   print_387_control_word (ep->control);
    printf ("last exception: ");
!   printf ("opcode 0x%x; ", ep->opcode);
!   printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
!   printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
    
!   top = (ep->status >> 11) & 7;
    
    printf ("regno  tag  msb              lsb  value\n");
    for (fpreg = 7; fpreg >= 0; fpreg--) 
!     {
        double val;
        
        printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
        
!       switch ((ep->tag >> (fpreg * 2)) & 3) 
  	{
  	case 0: printf ("valid "); break;
  	case 1: printf ("zero  "); break;
--- 1737,1766 ----
        print_387_status_word (status);
      }
    
!   if (ep->en_sw != 0) 
      {
        if (bothstatus)
  	printf ("e: ");
!       print_387_status_word (ep->en_sw);
      }
! #endif
! 
!   print_387_control_word (ep->en_cw);
    printf ("last exception: ");
!   printf ("opcode 0x%x; ", ep->en_opcode);
!   printf ("pc 0x%x:0x%x; ", ep->en_fcs & 0xffff, ep->en_fip);
!   printf ("operand 0x%x:0x%x\n", ep->en_fos & 0xffff, ep->en_foo);
    
!   top = 7 - (ep->en_sw >> 11) & 7;
    
    printf ("regno  tag  msb              lsb  value\n");
    for (fpreg = 7; fpreg >= 0; fpreg--) 
!   {
        double val;
        
        printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
        
!       switch ((ep->en_tw >> ((7 - fpreg) * 2)) & 3) 
  	{
  	case 0: printf ("valid "); break;
  	case 1: printf ("zero  "); break;
***************
*** 1763,1781 ****
  	case 3: printf ("empty "); break;
  	}
        for (i = 9; i >= 0; i--)
! 	printf ("%02x", ep->regs[fpreg][i]);
        
!       i387_to_double (ep->regs[fpreg], (char *)&val);
        printf ("  %g\n", val);
!     }
!   if (ep->r0)
!     printf ("warning: reserved0 is 0x%x\n", ep->r0);
!   if (ep->r1)
!     printf ("warning: reserved1 is 0x%x\n", ep->r1);
!   if (ep->r2)
!     printf ("warning: reserved2 is 0x%x\n", ep->r2);
!   if (ep->r3)
!     printf ("warning: reserved3 is 0x%x\n", ep->r3);
  }
  
  #ifndef U_FPSTATE
--- 1768,1778 ----
  	case 3: printf ("empty "); break;
  	}
        for (i = 9; i >= 0; i--)
! 	printf ("%02x", es->sv_ac[fpreg].fp_bytes[i]);
        
!       i387_to_double (es->sv_ac[fpreg].fp_bytes, (char *)&val);
        printf ("  %g\n", val);
!   }
  }
  
  #ifndef U_FPSTATE
***************
*** 1852,1858 ****
--- 1849,1924 ----
    
    fpstatep = (struct fpstate *)(buf + skip);
    print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+ #else /* __386BSD__ */
+   struct save87 *fpstatep;
+   char buf[sizeof (struct save87) + 2 * sizeof (int)];
+   unsigned int uaddr;
+   char fpvalid;
+   unsigned int rounded_addr;
+   unsigned int rounded_size;
+   extern int corechan;
+   int skip;
+   
+   uaddr = (char *)&u.u_pcb.pcb_flags - (char *)&u;
+   if (have_inferior_p()) 
+     {
+       unsigned int data;
+       unsigned int mask;
+       
+       rounded_addr = uaddr & -sizeof (int);
+       data = ptrace (3, inferior_pid, (caddr_t)rounded_addr, 0);
+       mask = 0xff << ((uaddr - rounded_addr) * 8);
+       
+       fpvalid = (data & mask) >> ((uaddr - rounded_addr) * 8);
+     } 
+   else 
+     {
+       if (lseek (corechan, uaddr, 0) < 0)
+         perror ("seek on core file");
+       if (myread (corechan, &fpvalid, 1) < 0) 
+         perror ("read on core file");
+     }
+ 
+ #ifndef __NetBSD__
+   /* In NetBSD 0.9 this flag is'nt used */
+   if ((fpvalid & FP_WASUSED) == 0)
+ 	printf("Coprocessor not used yet, status may be invalid\n");
+ #endif
+   
+   uaddr = (char *)&u.u_pcb.pcb_savefpu - (char *)&u;
+   if (have_inferior_p ()) 
+     {
+       int *ip;
+       
+       rounded_addr = uaddr & -sizeof (int);
+       rounded_size = (((uaddr + sizeof (struct save87)) - uaddr) +
+                       sizeof (int) - 1) / sizeof (int);
+       skip = uaddr - rounded_addr;
+       
+       ip = (int *)buf;
+       for (i = 0; i < rounded_size; i++) 
+         {
+           *ip++ = ptrace (3, inferior_pid, (caddr_t)rounded_addr, 0);
+           rounded_addr += sizeof (int);
+         }
+     } 
+   else 
+     {
+       if (lseek (corechan, uaddr, 0) < 0)
+         perror_with_name ("seek on core file");
+       if (myread (corechan, buf, sizeof (struct save87)) < 0) 
+         perror_with_name ("read from core file");
+       skip = 0;
+     }
+   
+   fpstatep = (struct save87 *)(buf + skip);
+ #ifdef __NetBSD__
+   /* XXX is there a better way ? */
+   if (fpstatep->sv_env.en_fcs == 0)
+ 	printf("Coprocessor not used yet, status may be invalid\n");
  #endif
+   print_387_status (fpstatep->sv_env.en_sw & 0xffff, fpstatep);
+ #endif /* __386BSD__ */
  }
  
  void
============================= End of patches ==========================