The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/system/do_trace.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* The kernel call implemented in this file:
    2  *   m_type:    SYS_TRACE
    3  *
    4  * The parameters for this kernel call are:
    5  *    m2_i1:    CTL_PROC_NR     process that is traced
    6  *    m2_i2:    CTL_REQUEST     trace request
    7  *    m2_l1:    CTL_ADDRESS     address at traced process' space
    8  *    m2_l2:    CTL_DATA        data to be written or returned here
    9  */
   10 
   11 #include "../system.h"
   12 #include <sys/ptrace.h>
   13 
   14 #if USE_TRACE
   15 
   16 /*==========================================================================*
   17  *                              do_trace                                    *
   18  *==========================================================================*/
   19 #define TR_VLSIZE       ((vir_bytes) sizeof(long))
   20 
   21 PUBLIC int do_trace(m_ptr)
   22 register message *m_ptr;
   23 {
   24 /* Handle the debugging commands supported by the ptrace system call
   25  * The commands are:
   26  * T_STOP       stop the process
   27  * T_OK         enable tracing by parent for this process
   28  * T_GETINS     return value from instruction space
   29  * T_GETDATA    return value from data space
   30  * T_GETUSER    return value from user process table
   31  * T_SETINS     set value from instruction space
   32  * T_SETDATA    set value from data space
   33  * T_SETUSER    set value in user process table
   34  * T_RESUME     resume execution
   35  * T_EXIT       exit
   36  * T_STEP       set trace bit
   37  *
   38  * The T_OK and T_EXIT commands are handled completely by the process manager,
   39  * all others come here.
   40  */
   41 
   42   register struct proc *rp;
   43   phys_bytes src, dst;
   44   vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS;
   45   long tr_data = m_ptr->CTL_DATA;
   46   int tr_request = m_ptr->CTL_REQUEST;
   47   int tr_proc_nr = m_ptr->CTL_PROC_NR;
   48   int i;
   49 
   50   if (! isokprocn(tr_proc_nr)) return(EINVAL);
   51   if (iskerneln(tr_proc_nr)) return(EPERM);
   52 
   53   rp = proc_addr(tr_proc_nr);
   54   if (isemptyp(rp)) return(EIO);
   55   switch (tr_request) {
   56   case T_STOP:                  /* stop process */
   57         if (rp->p_rts_flags == 0) lock_dequeue(rp);
   58         rp->p_rts_flags |= P_STOP;
   59         rp->p_reg.psw &= ~TRACEBIT;     /* clear trace bit */
   60         return(OK);
   61 
   62   case T_GETINS:                /* return value from instruction space */
   63         if (rp->p_memmap[T].mem_len != 0) {
   64                 if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
   65                 phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
   66                 m_ptr->CTL_DATA = tr_data;
   67                 break;
   68         }
   69         /* Text space is actually data space - fall through. */
   70 
   71   case T_GETDATA:               /* return value from data space */
   72         if ((src = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
   73         phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
   74         m_ptr->CTL_DATA= tr_data;
   75         break;
   76 
   77   case T_GETUSER:               /* return value from process table */
   78         if ((tr_addr & (sizeof(long) - 1)) != 0 ||
   79             tr_addr > sizeof(struct proc) - sizeof(long))
   80                 return(EIO);
   81         m_ptr->CTL_DATA = *(long *) ((char *) rp + (int) tr_addr);
   82         break;
   83 
   84   case T_SETINS:                /* set value in instruction space */
   85         if (rp->p_memmap[T].mem_len != 0) {
   86                 if ((dst = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
   87                 phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
   88                 m_ptr->CTL_DATA = 0;
   89                 break;
   90         }
   91         /* Text space is actually data space - fall through. */
   92 
   93   case T_SETDATA:                       /* set value in data space */
   94         if ((dst = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
   95         phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
   96         m_ptr->CTL_DATA = 0;
   97         break;
   98 
   99   case T_SETUSER:                       /* set value in process table */
  100         if ((tr_addr & (sizeof(reg_t) - 1)) != 0 ||
  101              tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
  102                 return(EIO);
  103         i = (int) tr_addr;
  104 #if (CHIP == INTEL)
  105         /* Altering segment registers might crash the kernel when it
  106          * tries to load them prior to restarting a process, so do
  107          * not allow it.
  108          */
  109         if (i == (int) &((struct proc *) 0)->p_reg.cs ||
  110             i == (int) &((struct proc *) 0)->p_reg.ds ||
  111             i == (int) &((struct proc *) 0)->p_reg.es ||
  112 #if _WORD_SIZE == 4
  113             i == (int) &((struct proc *) 0)->p_reg.gs ||
  114             i == (int) &((struct proc *) 0)->p_reg.fs ||
  115 #endif
  116             i == (int) &((struct proc *) 0)->p_reg.ss)
  117                 return(EIO);
  118 #endif
  119         if (i == (int) &((struct proc *) 0)->p_reg.psw)
  120                 /* only selected bits are changeable */
  121                 SETPSW(rp, tr_data);
  122         else
  123                 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) tr_data;
  124         m_ptr->CTL_DATA = 0;
  125         break;
  126 
  127   case T_RESUME:                /* resume execution */
  128         rp->p_rts_flags &= ~P_STOP;
  129         if (rp->p_rts_flags == 0) lock_enqueue(rp);
  130         m_ptr->CTL_DATA = 0;
  131         break;
  132 
  133   case T_STEP:                  /* set trace bit */
  134         rp->p_reg.psw |= TRACEBIT;
  135         rp->p_rts_flags &= ~P_STOP;
  136         if (rp->p_rts_flags == 0) lock_enqueue(rp);
  137         m_ptr->CTL_DATA = 0;
  138         break;
  139 
  140   default:
  141         return(EIO);
  142   }
  143   return(OK);
  144 }
  145 
  146 #endif /* USE_TRACE */

Cache object: 2614494747da4d8407d09f56e82e64d4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.