* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00137
* -------------------- ----- ----------------------
* 04 Sep 92 Paul Kranenburg Fixed copy-on-write checking for pages
* other than anonymous (text pages, etc.)
* 08 Apr 93 Bruce Evans Several VM system fixes
* The following ptrace calls have been defined in addition to
* the standard ones found in original <sys/ptrace.h>:
* PT_ATTACH - attach to running process
* PT_DETACH - detach from running process
* PT_SYSCALL - trace system calls
* PT_GETREG - get register file
* PT_SETREG - set register file
* PT_BREAD_[IDU] - block read from process (not yet implemented)
* PT_BWRITE_[IDU] - block write " "
* PT_INHERIT - make forked processes inherit trace flags
/* Define to prevent extraneous clutter in source */
* `ipcreg' defined in <machine/reg.h>
* Should we define a structure with all regs?
{ 0,0,sEDI
,sESI
,sEBP
,sEBX
,sEDX
,sECX
,sEAX
,sEIP
,sCS
,sEFLAGS
,sESP
,sSS
};
int req
; /* copy of ptrace request */
int *addr
; /* copy of ptrace address */
int data
; /* copy of ptrace data */
int error
; /* errno from `procxmt' */
int regs
[NIPCREG
]; /* PT_[GS]ETREG */
caddr_t buf
; /* PT_BREAD/WRITE */
* Process debugging system call.
ptrace(curp
, uap
, retval
)
register struct ptrace_args
*uap
;
if (uap
->req
== PT_TRACE_ME
) {
/*p->p_tptr = p->p_pptr; * What shall we do here ? */
if ((p
= pfind(uap
->pid
)) == NULL
) {
if (uap
->req
!= PT_ATTACH
&& (
(p
->p_flag
& STRC
) == 0 ||
(p
->p_tptr
&& curp
!= p
->p_tptr
) ||
(!p
->p_tptr
&& curp
!= p
->p_pptr
)))
if (curp
->p_ucred
->cr_uid
!= 0 && (
curp
->p_ucred
->cr_uid
!= p
->p_ucred
->cr_uid
||
curp
->p_ucred
->cr_uid
!= p
->p_cred
->p_svuid
))
if ((unsigned)uap
->data
>= NSIG
)
p
->p_flag
&= ~(STRC
|SSTRC
|SFTRC
);
psignal(p
->p_pptr
, SIGCHLD
);
wakeup((caddr_t
)p
->p_pptr
);
if (p
->p_stat
== SSTOP
) {
if ((p
->p_flag
& STRC
) == 0)
/* Other ptrace calls require target process to be in stopped state */
if ((p
->p_flag
& STRC
) == 0 || p
->p_stat
!= SSTOP
) {
/* Acquire the ipc structure */
while (ipc
.flag
& IPC_BUSY
) {
error
= tsleep((caddr_t
)&ipc
, PWAIT
|PCATCH
, "ipc", 0);
error
= copyin((char *)ipc
.addr
, (char *)ipc
.regs
, sizeof(ipc
.regs
));
#ifdef notyet /* requires change in number of args to ptrace syscall */
ipc
.buf
= kmem_alloc_wait(kernelmap
, uap
->data
);
error
= copyin((char *)ipc
.addr
, (char *)ipc
.buf
, ipc
.buflen
);
kmem_free_wakeup(kernelmap
, ipc
.buf
, ipc
.buflen
);
while ((ipc
.flag
& IPC_DONE
) == 0) {
error
= tsleep((caddr_t
)&ipc
, PWAIT
|PCATCH
, "ipc", 0);
error
= copyout((char *)ipc
.regs
, (char *)ipc
.addr
, sizeof(ipc
.regs
));
/* Release ipc structure */
if (ipc
.flag
& IPC_WANT
) {
/* Are we still being traced? */
if ((p
->p_flag
& STRC
) == 0)
p
->p_addr
->u_kproc
.kp_proc
= *p
;
fill_eproc(p
, &p
->p_addr
->u_kproc
.kp_eproc
);
if (!useracc(ipc
.addr
, sizeof(ipc
.data
), B_READ
)) {
ipc
.error
= copyin((char *)ipc
.addr
, (char *)&ipc
.data
, sizeof(ipc
.data
));
if ((u_int
)ipc
.addr
> UPAGES
* NBPG
- sizeof(int)) {
ipc
.data
= *(int *)((u_int
)p
->p_addr
+ (u_int
)ipc
.addr
);
case PT_WRITE_D
: { /* 04 Sep 92*/
vm_prot_t prot
; /* current protection of region */
int cow
; /* ensure copy-on-write happens */
if (cow
= (useracc(ipc
.addr
, sizeof(ipc
.data
), B_WRITE
) == 0)) {
vm_offset_t addr
= (vm_offset_t
)ipc
.addr
;
* XXX - the useracc check is stronger than the vm
* checks because the user page tables are in the map.
if (!useracc(ipc
.addr
, sizeof(ipc
.data
), B_READ
) ||
vm_region(&p
->p_vmspace
->vm_map
, &addr
, &size
,
&prot
, &max_prot
, &inh
, &shared
,
&object
, &objoff
) != KERN_SUCCESS
||
vm_protect(&p
->p_vmspace
->vm_map
, ipc
.addr
,
prot
|VM_PROT_WRITE
) != KERN_SUCCESS
||
vm_fault(&p
->p_vmspace
->vm_map
,trunc_page(ipc
.addr
),
VM_PROT_WRITE
, FALSE
) != KERN_SUCCESS
) {
ipc
.error
= copyout((char *)&ipc
.data
,
(char *)ipc
.addr
, sizeof(ipc
.data
));
if (vm_protect(&p
->p_vmspace
->vm_map
, ipc
.addr
,
printf("ptrace: oops\n");
if ((u_int
)ipc
.addr
> UPAGES
* NBPG
- sizeof(int)) {
*(int *)((u_int
)p
->p_addr
+ (u_int
)ipc
.addr
) = ipc
.data
;
if (ipc
.addr
!= (int *)1) {
p
->p_regs
[(curpcb
->pcb_flags
&FM_TRAP
)?tEIP
:sEIP
] = (int)ipc
.addr
;
p
->p_flag
&= ~SSTRC
; /* Only set by PT_SYSCALL */
if ((unsigned)ipc
.data
>= NSIG
) {
p
->p_flag
&= ~SSTRC
; /* Only set by PT_SYSCALL */
if (ipc
.addr
!= (int *)1) {
p
->p_regs
[(curpcb
->pcb_flags
&FM_TRAP
)?tEIP
:sEIP
] = (int)ipc
.addr
;
p
->p_regs
[(curpcb
->pcb_flags
&FM_TRAP
)?tEFLAGS
:sEFLAGS
] |= PSL_T
;
p
->p_flag
&= ~SSTRC
; /* Only set by PT_SYSCALL */
if (ipc
.addr
!= (int *)1) {
p
->p_regs
[(curpcb
->pcb_flags
&FM_TRAP
)?tEIP
:sEIP
] = (int)ipc
.addr
;
xreg
= (curpcb
->pcb_flags
&FM_TRAP
)?ipcreg
:sipcreg
;
for (i
= 0; i
< NIPCREG
; i
++)
ipc
.regs
[i
] = p
->p_regs
[xreg
[i
]];
xreg
= (curpcb
->pcb_flags
&FM_TRAP
)?ipcreg
:sipcreg
;
for (i
= 0; i
< NIPCREG
; i
++)
p
->p_regs
[xreg
[i
]] = ipc
.regs
[i
];
/* Should be able to specify core file name */
* Enable process profiling system call.
short *bufbase
; /* base of data buffer */
unsigned bufsize
; /* size of data buffer */
unsigned pcoffset
; /* pc offset (for subtraction) */
unsigned pcscale
; /* scaling factor for offset pc */
register struct profil_args
*uap
;
/* from looking at man pages, and include files, looks like
* this just sets up the fields of p->p_stats->p_prof...
* and those fields come straight from the args.
* only thing *we* have to do is check the args for validity...
/* check to make sure that the buffer is OK. addupc (in locore)
* checks for faults, but would one be generated, say, writing to
* kernel space? probably not -- it just uses "movl"...
* so we've gotta check to make sure that the info set up for
* addupc is set right... it's gotta be writable by the user...
if (useracc(uap
->bufbase
,uap
->bufsize
*sizeof(short),B_WRITE
) == 0)
p
->p_stats
->p_prof
.pr_base
= uap
->bufbase
;
p
->p_stats
->p_prof
.pr_size
= uap
->bufsize
;
p
->p_stats
->p_prof
.pr_off
= uap
->pcoffset
;
p
->p_stats
->p_prof
.pr_scale
= uap
->pcscale
;