minix/kernel/system/tracing.c
Jorrit Herder ec24a0798c Updated function key mapping because of possible changes to NOTIFY.
The TTY driver now only notifies the IS server about function key event,
but does not tell which keys are pressed. The IS servers queries the TTY
driver to find out about this.
2005-06-20 14:23:31 +00:00

140 lines
4.2 KiB
C

/* The system call implemented in this file:
* m_type: SYS_TRACE
*
* The parameters for this system call are:
* m2_i1: CTL_PROC_NR process that is traced
* m2_i2: CTL_REQUEST trace request
* m2_l1: CTL_ADDRESS address at traced process' space
* m2_l2: CTL_DATA data to be written or returned here
*/
#include "../kernel.h"
#include "../system.h"
#include <sys/ptrace.h>
/*==========================================================================*
* do_trace *
*==========================================================================*/
#define TR_VLSIZE ((vir_bytes) sizeof(long))
PUBLIC int do_trace(m_ptr)
register message *m_ptr;
{
/* Handle the debugging commands supported by the ptrace system call
* The commands are:
* T_STOP stop the process
* T_OK enable tracing by parent for this process
* T_GETINS return value from instruction space
* T_GETDATA return value from data space
* T_GETUSER return value from user process table
* T_SETINS set value from instruction space
* T_SETDATA set value from data space
* T_SETUSER set value in user process table
* T_RESUME resume execution
* T_EXIT exit
* T_STEP set trace bit
*
* The T_OK and T_EXIT commands are handled completely by the process manager,
* all others come here.
*/
register struct proc *rp;
phys_bytes src, dst;
vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS;
long tr_data = m_ptr->CTL_DATA;
int tr_request = m_ptr->CTL_REQUEST;
int tr_proc_nr = m_ptr->CTL_PROC_NR;
int i;
rp = proc_addr(tr_proc_nr);
if (isemptyp(rp)) return(EIO);
switch (tr_request) {
case T_STOP: /* stop process */
if (rp->p_flags == 0) lock_unready(rp);
rp->p_flags |= P_STOP;
rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
return(OK);
case T_GETINS: /* return value from instruction space */
if (rp->p_memmap[T].mem_len != 0) {
if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
break;
}
/* Text space is actually data space - fall through. */
case T_GETDATA: /* return value from data space */
if ((src = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
break;
case T_GETUSER: /* return value from process table */
if ((tr_addr & (sizeof(long) - 1)) != 0 ||
tr_addr > sizeof(struct proc) - sizeof(long))
return(EIO);
tr_data = *(long *) ((char *) rp + (int) tr_addr);
break;
case T_SETINS: /* set value in instruction space */
if (rp->p_memmap[T].mem_len != 0) {
if ((dst = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
tr_data = 0;
break;
}
/* Text space is actually data space - fall through. */
case T_SETDATA: /* set value in data space */
if ((dst = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
tr_data = 0;
break;
case T_SETUSER: /* set value in process table */
if ((tr_addr & (sizeof(reg_t) - 1)) != 0 ||
tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
return(EIO);
i = (int) tr_addr;
#if (CHIP == INTEL)
/* Altering segment registers might crash the kernel when it
* tries to load them prior to restarting a process, so do
* not allow it.
*/
if (i == (int) &((struct proc *) 0)->p_reg.cs ||
i == (int) &((struct proc *) 0)->p_reg.ds ||
i == (int) &((struct proc *) 0)->p_reg.es ||
#if _WORD_SIZE == 4
i == (int) &((struct proc *) 0)->p_reg.gs ||
i == (int) &((struct proc *) 0)->p_reg.fs ||
#endif
i == (int) &((struct proc *) 0)->p_reg.ss)
return(EIO);
#endif
if (i == (int) &((struct proc *) 0)->p_reg.psw)
/* only selected bits are changeable */
SETPSW(rp, tr_data);
else
*(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) tr_data;
tr_data = 0;
break;
case T_RESUME: /* resume execution */
rp->p_flags &= ~P_STOP;
if (rp->p_flags == 0) lock_ready(rp);
tr_data = 0;
break;
case T_STEP: /* set trace bit */
rp->p_reg.psw |= TRACEBIT;
rp->p_flags &= ~P_STOP;
if (rp->p_flags == 0) lock_ready(rp);
tr_data = 0;
break;
default:
return(EIO);
}
return(OK);
}