This is the mail archive of the gdb-prs@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]
Other format: [Raw text]

mi/1369: gdb corrupts signal types on solaris


>Number:         1369
>Category:       mi
>Synopsis:       gdb corrupts signal types on solaris
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Sep 05 13:28:01 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     roberts@tellink.net
>Release:        5.X
>Organization:
>Environment:
SunOs 5.8
gcc -v
sparc-sun-solaris2.8
>Description:
GDB on solaris starting in the 5.X release corrupts the different signal types.  They are mostly getting mapped to SIGSEGV.  For several of the signals where the registered signal handler of the program being debugged are having the arguments supplied to the signal handler corrupted.

In the fix location is a diff of what is required to fix several issues with the signal handling in the file gdb/procfs.c.  Two new routines where added to derive the correct signal number and information to pass to the programs registered SIGILL signal handler.

The routine procfs_wait() was updated to properly work with the signals  SIGBUS, SIGILL, SIGEMT.

In the How-to-repeat section is a hacked up program that will use a sigbus handler to repair a bad pointer.  Outside of gdb 5.X it will work with solaris's ansi C "cc -g -xs" and gnu's gcc 3.X "gcc -g".  If you run the program under the unpatched gdb the expected SIGBUS will turn into a SIGSEGV.

The fix section contains a patch again a cvs checked out 5.3 version of gdb.  The file is src/gdb/procfs.c
>How-To-Repeat:
solaris ansi cc:  cc -g -xs -o testbus testbus.c
gcc 3.1/3.2:     gcc -g -o testbus testbus.c

./testbus
gdb ./testbus

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>
#include <sys/stack.h>
#include <sys/regset.h>
#include <sys/ucontext.h>
 
static struct sigaction sv_busvec;
 
long *goodboy= NULL;
long *foo;
 
static long
get__reg(ucontext_t *scp, long regnum)
{
  long retval = 0;
  struct rwindow *sp = (struct rwindow *)(((char *)(scp->uc_mcontext.gregs[REG_SP]))+STACK_BIAS);
   
  if ((regnum >=0) && (regnum <=15))
    retval = scp->uc_mcontext.gregs[regnum];
  else if ((regnum >= 16) && (regnum <= 23))
    {
      if (scp->uc_mcontext.gwins != NULL)
        {
          return scp->uc_mcontext.gwins->wbuf->rw_local[regnum-16];
        }
      else
        {
          return sp->rw_local[regnum-16];
        }
    }
  else if (regnum == -4)
    {
      assert(0);
    }
  else
    {
      fprintf(stderr, "what the!  (%d)\n", regnum);
      assert(0);
    }
     
  return(retval);
}
 
static void
put__reg(ucontext_t *scp, long regnum, long val)
{
   struct rwindow *sp = (struct rwindow *)(((char *)(scp->uc_mcontext.gregs[REG_SP]))+STACK_BIAS);
   
  if ((regnum >=0) && (regnum <=15))
    {
      scp->uc_mcontext.gregs[regnum] = val;
    }
  else if ((regnum >= 16) && (regnum <= 23))
    {
      if (scp->uc_mcontext.gwins != NULL)
        {
          scp->uc_mcontext.gwins->wbuf->rw_local[regnum-16] = val;
        }
      else
        {
          sp->rw_local[regnum-16] = val;
        }
    }
  else if (regnum == -4)
    {
      assert(0);
    }
  else
    {
      fprintf(stderr, "put__reg:  what the!  (%d)\n", regnum);
      assert(0);
    }
}
 
static void
sv_bushandler(int sig, siginfo_t *siginf, void *xscp)
{
  int *pc;
  int rf, r2;
  int op;
  long *val = NULL;
  int instr;
  ucontext_t *scp = (ucontext_t *) xscp;
 
  pc = (int *)get__reg(scp, REG_PC);
  fprintf(stdout, "we are here! pc = %lx\n", pc);
 
  instr = *pc;
  op = ((instr)>>19)&0x3f;
  rf = ((instr)>>14)&0x1f;
  r2 = ((instr))&0x1f;
  /* Fixup reg rf (hack) */
  switch(rf)
    {
      case 8: /* gcc will be O0 */
        rf = REG_O0;
      case 16: /* Solaris cc will be l0 */
        break;
      default:
        break;
    }
  /*  val = get_pc(scp, -4);*/
  fprintf(stdout, "instr = %x, regnum = %d  r2 = %d op = %d  bad addr = %lx\n",
instr, rf, r2, op, val);
 
  /* fix the pointer */
  val = (long *)get__reg(scp, rf);
  fprintf(stdout, "address was = %lx  goodboy = %lx\n", val, goodboy);
  put__reg(scp, rf, (long)goodboy);
}
 
int
main()
{
  long bar;
 
  struct sigaction nvec;
 
#ifdef _LP64
  printf("LP64\n");
#endif
 
  /* Set up the busfault handler */
  nvec.sa_flags = 0;
  nvec.sa_flags = SA_RESTART | SA_SIGINFO ;
 
  nvec.sa_sigaction = sv_bushandler;
  sigemptyset (&(sv_busvec.sa_mask));
  sigemptyset (&(nvec.sa_mask));
   
  if (sigaction (SIGBUS, &nvec, &sv_busvec) == -1)
    {
      fprintf(stderr, "failed to setup the busfault\n");
      assert(0);
    }
 
  /* Lets generate a busfault */
  goodboy = (long *)malloc(sizeof(long));
  *goodboy = 0x00109;
  foo = (long *)(((long)goodboy)|0x1L);
printf("sizeof(long)=%d  malloc returned 0x%lx foo = 0x%lx\n", sizeof(long), goodboy, foo);
  bar = *foo;
  printf("bar = %ld\n", bar);
  return(0);
}
>Fix:
cvs diff -c procfs.c
Index: procfs.c
===================================================================
RCS file: /cvs/src/src/gdb/procfs.c,v
retrieving revision 1.40
diff -c -r1.40 procfs.c
*** procfs.c    26 Aug 2002 19:18:33 -0000      1.40
--- procfs.c    5 Sep 2003 11:31:13 -0000
***************
*** 42,47 ****
--- 42,48 ----
  #include <sys/wait.h>
  #include <signal.h>
  #include <ctype.h>
+ #include <assert.h>
   
  /*
   * PROCFS.C
***************
675
  static procinfo *
  create_procinfo (int pid, int tid)
  {
!   procinfo *pi, *parent;
   
    if ((pi = find_procinfo (pid, tid)))
      return pi;                        /* Already exists, nothing to do. */
--- 670,676 ----
  static procinfo *
  create_procinfo (int pid, int tid)
  {
!   procinfo *pi, *parent = NULL;
   
    if ((pi = find_procinfo (pid, tid)))
      return pi;                        /* Already exists, nothing to do. */
***************
*** 1339,1344 ****
--- 1340,1380 ----
  }
   
  /*
+  * Function: proc_cursig:
+  *
+  * returns the pr_cursig field (current signal).
+  */
+
+
+ int
+ proc_curilltrapno (struct procinfo *pi)
+ {
+   if (!pi->status_valid)
+     if (!proc_get_status (pi))
+       return 0;       /* FIXME: not a good failure value (but what is?) */
+
+ #ifdef NEW_PROC_API
+   return pi->prstatus.pr_lwp.pr_info.si_trapno;
+ #else
+   assert(0);
+ #endif
+ }
+
+ void *
+ proc_curilladdr (struct procinfo *pi)
+ {
+   if (!pi->status_valid)
+     if (!proc_get_status (pi))
+       return 0;       /* FIXME: not a good failure value (but what is?) */
+
+ #ifdef NEW_PROC_API
+   return pi->prstatus.pr_lwp.pr_info.si_addr;
+ #else
+   assert(0);
+ #endif
+ }
+
+ /*
   * Function: proc_modify_flag
   *
   *  === I appologize for the messiness of this function.
***************
*** 1672,1679 ****
--- 1708,1718 ----
  #ifdef NEW_PROC_API
    {
      procfs_ctl_t cmd = PCWSTOP;
+
+     immediate_quit++;
      win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
      /* We been runnin' and we stopped -- need to update status.  */
+     immediate_quit--;
      pi->status_valid = 0;
    }
  #else /* ioctl method */
***************
2505
    mysinfo = (gdb_siginfo_t *) &arg.sinfo;
    mysinfo->si_signo = signo;
    mysinfo->si_code  = 0;
    mysinfo->si_pid   = getpid ();       /* ?why? */
    mysinfo->si_uid   = getuid ();       /* ?why? */
!
  #ifdef NEW_PROC_API
    arg.cmd = PCSSIG;
    win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg))  == sizeof (arg));
--- 2536,2570 ----
    mysinfo = (gdb_siginfo_t *) &arg.sinfo;
    mysinfo->si_signo = signo;
    mysinfo->si_code  = 0;
+   switch(signo)
+
+   {
+ #ifdef SIGEMT
+   case SIGEMT:
+         /* Need to setup trapno and address */
+         mysinfo->si_trapno = proc_curilltrapno(pi);
+         mysinfo->si_addr = proc_curilladdr(pi);
+         break;
+ #endif
+ #ifdef SIGSEGV
+   case SIGSEGV:
+         /* Need to setup trapno and address */
+         mysinfo->si_trapno = proc_curilltrapno(pi);
+         mysinfo->si_addr = proc_curilladdr(pi);
+         break;
+ #endif
+ #ifdef SIGILL
+   case SIGILL:
+         /* Need to setup trapno and address */
+         mysinfo->si_trapno = proc_curilltrapno(pi);
+         mysinfo->si_addr = proc_curilladdr(pi);
+         break;
+ #endif
+   default:
    mysinfo->si_pid   = getpid ();       /* ?why? */
    mysinfo->si_uid   = getuid ();       /* ?why? */
!   break;
!   }
  #ifdef NEW_PROC_API
    arg.cmd = PCSSIG;
    win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg))  == sizeof (arg));
***************
3631
        query ("Was stopped when attached, make it runnable again? "))
        {
        /* Clear any pending signal.  */
!       if (!proc_clear_current_fault (pi))
!         proc_warn (pi, "do_detach, clear_current_fault", __LINE__);
   
        if (!proc_set_run_on_last_close (pi))
          proc_warn (pi, "do_detach, set_rlc", __LINE__);
--- 3689,3696 ----
        query ("Was stopped when attached, make it runnable again? "))
        {
        /* Clear any pending signal.  */
!       if ((signo == 0) && !proc_clear_current_signal (pi))
!         proc_warn (pi, "do_detach, clear_current_signal", __LINE__);
   
        if (!proc_set_run_on_last_close (pi))
          proc_warn (pi, "do_detach, set_rlc", __LINE__);
***************
4174
  #endif
                  wstat = (SIGTRAP << 8) | 0177;
                  break;
-               case FLTSTACK:
                case FLTACCESS:
  #if (FLTBOUNDS != FLTSTACK)   /* avoid "duplicate case" error */
                case FLTBOUNDS:
  #endif
                  wstat = (SIGSEGV << 8) | 0177;
                  break;
                case FLTIOVF:
                case FLTIZDIV:
4246
  #endif
                  wstat = (SIGTRAP << 8) | 0177;
                  break;
                case FLTACCESS:
+ #if 0 /* ###djr what */
+                 wstat = (SIGBUS << 8) | 0177;
+                 break;
+ #endif
+               case FLTSTACK:
  #if (FLTBOUNDS != FLTSTACK)   /* avoid "duplicate case" error */
                case FLTBOUNDS:
  #endif
+ #if 0 /* solution from  Woody LaRue */
                  wstat = (SIGSEGV << 8) | 0177;
+ #else
+                 wstat = ((pi->prstatus.pr_lwp.pr_info.si_signo) << 8) | 0177;
+ #endif
                  break;
                case FLTIOVF:
                case FLTIZDIV:
>Release-Note:
>Audit-Trail:
>Unformatted:


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