| 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_ENDPT       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_e = m_ptr->CTL_ENDPT, tr_proc_nr; | 
|---|
| 48 | int i; | 
|---|
| 49 |  | 
|---|
| 50 | if(!isokendpt(tr_proc_nr_e, &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 */ | 
|---|