sys_process.c (84483) | sys_process.c (84637) |
---|---|
1/* 2 * Copyright (c) 1994, Sean Eric Fagan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * | 1/* 2 * Copyright (c) 1994, Sean Eric Fagan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * |
31 * $FreeBSD: head/sys/kern/sys_process.c 84483 2001-10-04 16:35:44Z des $ | 31 * $FreeBSD: head/sys/kern/sys_process.c 84637 2001-10-07 20:08:42Z des $ |
32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/lock.h> 37#include <sys/mutex.h> 38#include <sys/sysproto.h> 39#include <sys/proc.h> 40#include <sys/vnode.h> 41#include <sys/ptrace.h> 42#include <sys/sx.h> 43#include <sys/user.h> 44 45#include <machine/reg.h> 46 47#include <vm/vm.h> | 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/lock.h> 37#include <sys/mutex.h> 38#include <sys/sysproto.h> 39#include <sys/proc.h> 40#include <sys/vnode.h> 41#include <sys/ptrace.h> 42#include <sys/sx.h> 43#include <sys/user.h> 44 45#include <machine/reg.h> 46 47#include <vm/vm.h> |
48#include <vm/vm_param.h> |
|
48#include <vm/pmap.h> | 49#include <vm/pmap.h> |
50#include <vm/vm_extern.h> |
|
49#include <vm/vm_map.h> | 51#include <vm/vm_map.h> |
52#include <vm/vm_kern.h> 53#include <vm/vm_object.h> |
|
50#include <vm/vm_page.h> 51 | 54#include <vm/vm_page.h> 55 |
52#include <fs/procfs/procfs.h> 53 54/* use the equivalent procfs code */ 55#if 0 56static int 57pread(struct proc *procp, unsigned int addr, unsigned int *retval) | 56int 57proc_rwmem(struct proc *p, struct uio *uio) |
58{ | 58{ |
59 int rv; 60 vm_map_t map, tmap; 61 vm_object_t object; 62 vm_offset_t kva = 0; 63 int page_offset; /* offset into page */ 64 vm_offset_t pageno; /* page number */ 65 vm_map_entry_t out_entry; 66 vm_prot_t out_prot; 67 boolean_t wired; 68 vm_pindex_t pindex; | 59 struct vmspace *vm; 60 vm_map_t map; 61 vm_object_t object = NULL; 62 vm_offset_t pageno = 0; /* page number */ 63 vm_prot_t reqprot; 64 vm_offset_t kva; 65 int error; 66 int writing; |
69 | 67 |
70 /* Map page into kernel space */ | 68 GIANT_REQUIRED; |
71 | 69 |
72 map = &procp->p_vmspace->vm_map; | 70 /* 71 * if the vmspace is in the midst of being deallocated or the 72 * process is exiting, don't try to grab anything. The page table 73 * usage in that process can be messed up. 74 */ 75 vm = p->p_vmspace; 76 if ((p->p_flag & P_WEXIT)) 77 return (EFAULT); 78 if (vm->vm_refcnt < 1) 79 return (EFAULT); 80 ++vm->vm_refcnt; 81 /* 82 * The map we want... 83 */ 84 map = &vm->vm_map; |
73 | 85 |
74 page_offset = addr - trunc_page(addr); 75 pageno = trunc_page(addr); | 86 writing = uio->uio_rw == UIO_WRITE; 87 reqprot = writing ? (VM_PROT_WRITE | VM_PROT_OVERRIDE_WRITE) : 88 VM_PROT_READ; |
76 | 89 |
77 tmap = map; 78 rv = vm_map_lookup(&tmap, pageno, VM_PROT_READ, &out_entry, 79 &object, &pindex, &out_prot, &wired); | 90 kva = kmem_alloc_pageable(kernel_map, PAGE_SIZE); |
80 | 91 |
81 if (rv != KERN_SUCCESS) 82 return (EINVAL); | 92 /* 93 * Only map in one page at a time. We don't have to, but it 94 * makes things easier. This way is trivial - right? 95 */ 96 do { 97 vm_map_t tmap; 98 vm_offset_t uva; 99 int page_offset; /* offset into page */ 100 vm_map_entry_t out_entry; 101 vm_prot_t out_prot; 102 boolean_t wired; 103 vm_pindex_t pindex; 104 u_int len; 105 vm_page_t m; |
83 | 106 |
84 vm_map_lookup_done(tmap, out_entry); | 107 object = NULL; |
85 | 108 |
86 /* Find space in kernel_map for the page we're interested in */ 87 rv = vm_map_find(kernel_map, object, IDX_TO_OFF(pindex), 88 &kva, PAGE_SIZE, 0, VM_PROT_ALL, VM_PROT_ALL, 0); | 109 uva = (vm_offset_t)uio->uio_offset; |
89 | 110 |
90 if (!rv) { 91 vm_object_reference(object); | 111 /* 112 * Get the page number of this segment. 113 */ 114 pageno = trunc_page(uva); 115 page_offset = uva - pageno; |
92 | 116 |
93 rv = vm_map_pageable(kernel_map, kva, kva + PAGE_SIZE, 0); 94 if (!rv) { 95 *retval = 0; 96 bcopy((caddr_t)kva + page_offset, 97 retval, sizeof *retval); | 117 /* 118 * How many bytes to copy 119 */ 120 len = min(PAGE_SIZE - page_offset, uio->uio_resid); 121 122 /* 123 * Fault the page on behalf of the process 124 */ 125 error = vm_fault(map, pageno, reqprot, VM_FAULT_NORMAL); 126 if (error) { 127 error = EFAULT; 128 break; |
98 } | 129 } |
99 vm_map_remove(kernel_map, kva, kva + PAGE_SIZE); 100 } | |
101 | 130 |
102 return (rv); 103} | 131 /* 132 * Now we need to get the page. out_entry, out_prot, wired, 133 * and single_use aren't used. One would think the vm code 134 * would be a *bit* nicer... We use tmap because 135 * vm_map_lookup() can change the map argument. 136 */ 137 tmap = map; 138 error = vm_map_lookup(&tmap, pageno, reqprot, &out_entry, 139 &object, &pindex, &out_prot, &wired); |
104 | 140 |
105static int 106pwrite(struct proc *procp, unsigned int addr, unsigned int datum) 107{ 108 int rv; 109 vm_map_t map, tmap; 110 vm_object_t object; 111 vm_offset_t kva = 0; 112 int page_offset; /* offset into page */ 113 vm_offset_t pageno; /* page number */ 114 vm_map_entry_t out_entry; 115 vm_prot_t out_prot; 116 boolean_t wired; 117 vm_pindex_t pindex; 118 boolean_t fix_prot = 0; | 141 if (error) { 142 error = EFAULT; |
119 | 143 |
120 /* Map page into kernel space */ | 144 /* 145 * Make sure that there is no residue in 'object' from 146 * an error return on vm_map_lookup. 147 */ 148 object = NULL; |
121 | 149 |
122 map = &procp->p_vmspace->vm_map; | 150 break; 151 } |
123 | 152 |
124 page_offset = addr - trunc_page(addr); 125 pageno = trunc_page(addr); | 153 m = vm_page_lookup(object, pindex); |
126 | 154 |
127 /* 128 * Check the permissions for the area we're interested in. 129 */ | 155 /* Allow fallback to backing objects if we are reading */ |
130 | 156 |
131 if (vm_map_check_protection(map, pageno, pageno + PAGE_SIZE, 132 VM_PROT_WRITE) == FALSE) { | 157 while (m == NULL && !writing && object->backing_object) { 158 159 pindex += OFF_TO_IDX(object->backing_object_offset); 160 object = object->backing_object; 161 162 m = vm_page_lookup(object, pindex); 163 } 164 165 if (m == NULL) { 166 error = EFAULT; 167 168 /* 169 * Make sure that there is no residue in 'object' from 170 * an error return on vm_map_lookup. 171 */ 172 object = NULL; 173 174 vm_map_lookup_done(tmap, out_entry); 175 176 break; 177 } 178 |
133 /* | 179 /* |
134 * If the page was not writable, we make it so. 135 * XXX It is possible a page may *not* be read/executable, 136 * if a process changes that! | 180 * Wire the page into memory |
137 */ | 181 */ |
138 fix_prot = 1; 139 /* The page isn't writable, so let's try making it so... */ 140 if ((rv = vm_map_protect(map, pageno, pageno + PAGE_SIZE, 141 VM_PROT_ALL, 0)) != KERN_SUCCESS) 142 return (EFAULT); /* I guess... */ 143 } | 182 vm_page_wire(m); |
144 | 183 |
145 /* 146 * Now we need to get the page. out_entry, out_prot, wired, and 147 * single_use aren't used. One would think the vm code would be 148 * a *bit* nicer... We use tmap because vm_map_lookup() can 149 * change the map argument. 150 */ | 184 /* 185 * We're done with tmap now. 186 * But reference the object first, so that we won't loose 187 * it. 188 */ 189 vm_object_reference(object); 190 vm_map_lookup_done(tmap, out_entry); |
151 | 191 |
152 tmap = map; 153 rv = vm_map_lookup(&tmap, pageno, VM_PROT_WRITE, &out_entry, 154 &object, &pindex, &out_prot, &wired); 155 if (rv != KERN_SUCCESS) { 156 return (EINVAL); 157 } | 192 pmap_kenter(kva, VM_PAGE_TO_PHYS(m)); |
158 | 193 |
159 /* 160 * Okay, we've got the page. Let's release tmap. 161 */ | 194 /* 195 * Now do the i/o move. 196 */ 197 error = uiomove((caddr_t)(kva + page_offset), len, uio); |
162 | 198 |
163 vm_map_lookup_done(tmap, out_entry); | 199 pmap_kremove(kva); |
164 | 200 |
165 /* 166 * Fault the page in... 167 */ | 201 /* 202 * release the page and the object 203 */ 204 vm_page_unwire(m, 1); 205 vm_object_deallocate(object); |
168 | 206 |
169 rv = vm_fault(map, pageno, VM_PROT_WRITE|VM_PROT_READ, FALSE); 170 if (rv != KERN_SUCCESS) 171 return (EFAULT); | 207 object = NULL; |
172 | 208 |
173 /* Find space in kernel_map for the page we're interested in */ 174 rv = vm_map_find(kernel_map, object, IDX_TO_OFF(pindex), 175 &kva, PAGE_SIZE, 0, 176 VM_PROT_ALL, VM_PROT_ALL, 0); 177 if (!rv) { 178 vm_object_reference(object); | 209 } while (error == 0 && uio->uio_resid > 0); |
179 | 210 |
180 rv = vm_map_pageable(kernel_map, kva, kva + PAGE_SIZE, 0); 181 if (!rv) { 182 bcopy(&datum, (caddr_t)kva + page_offset, sizeof datum); 183 } 184 vm_map_remove(kernel_map, kva, kva + PAGE_SIZE); 185 } | 211 if (object) 212 vm_object_deallocate(object); |
186 | 213 |
187 if (fix_prot) 188 vm_map_protect(map, pageno, pageno + PAGE_SIZE, 189 VM_PROT_READ|VM_PROT_EXECUTE, 0); 190 return (rv); | 214 kmem_free(kernel_map, kva, PAGE_SIZE); 215 vmspace_free(vm); 216 return (error); |
191} | 217} |
192#endif | |
193 194/* 195 * Process debugging system call. 196 */ 197#ifndef _SYS_SYSPROTO_H_ 198struct ptrace_args { 199 int req; 200 pid_t pid; 201 caddr_t addr; 202 int data; 203}; 204#endif 205 206int | 218 219/* 220 * Process debugging system call. 221 */ 222#ifndef _SYS_SYSPROTO_H_ 223struct ptrace_args { 224 int req; 225 pid_t pid; 226 caddr_t addr; 227 int data; 228}; 229#endif 230 231int |
207ptrace(td, uap) 208 struct thread *td; 209 struct ptrace_args *uap; | 232ptrace(struct thread *td, struct ptrace_args *uap) |
210{ 211 struct proc *curp = td->td_proc; 212 struct proc *p; 213 struct iovec iov; 214 struct uio uio; | 233{ 234 struct proc *curp = td->td_proc; 235 struct proc *p; 236 struct iovec iov; 237 struct uio uio; |
238 union { 239 struct reg reg; 240 struct dbreg dbreg; 241 struct fpreg fpreg; 242 } r; |
|
215 int error = 0; 216 int write; 217 218 write = 0; 219 if (uap->req == PT_TRACE_ME) { 220 p = curp; 221 PROC_LOCK(p); 222 } else { 223 if ((p = pfind(uap->pid)) == NULL) 224 return (ESRCH); 225 } 226 if (p_cansee(curp, p)) { 227 PROC_UNLOCK(p); 228 return (ESRCH); 229 } 230 | 243 int error = 0; 244 int write; 245 246 write = 0; 247 if (uap->req == PT_TRACE_ME) { 248 p = curp; 249 PROC_LOCK(p); 250 } else { 251 if ((p = pfind(uap->pid)) == NULL) 252 return (ESRCH); 253 } 254 if (p_cansee(curp, p)) { 255 PROC_UNLOCK(p); 256 return (ESRCH); 257 } 258 |
259 if ((error = p_candebug(curp, p)) != 0) { 260 PROC_UNLOCK(p); 261 return (error); 262 } 263 |
|
231 /* | 264 /* |
265 * Don't debug system processes! 266 */ 267 if ((p->p_flag & P_SYSTEM) != 0) { 268 PROC_UNLOCK(p); 269 return (EINVAL); 270 } 271 272 /* |
|
232 * Permissions check 233 */ 234 switch (uap->req) { 235 case PT_TRACE_ME: 236 /* Always legal. */ 237 break; 238 239 case PT_ATTACH: --- 4 unchanged lines hidden (view full) --- 244 } 245 246 /* Already traced */ 247 if (p->p_flag & P_TRACED) { 248 PROC_UNLOCK(p); 249 return (EBUSY); 250 } 251 | 273 * Permissions check 274 */ 275 switch (uap->req) { 276 case PT_TRACE_ME: 277 /* Always legal. */ 278 break; 279 280 case PT_ATTACH: --- 4 unchanged lines hidden (view full) --- 285 } 286 287 /* Already traced */ 288 if (p->p_flag & P_TRACED) { 289 PROC_UNLOCK(p); 290 return (EBUSY); 291 } 292 |
252 if ((error = p_candebug(curp, p))) { 253 PROC_UNLOCK(p); 254 return (error); 255 } 256 | |
257 /* OK */ 258 break; 259 260 case PT_READ_I: 261 case PT_READ_D: 262 case PT_WRITE_I: 263 case PT_WRITE_D: 264 case PT_CONTINUE: --- 164 unchanged lines hidden (view full) --- 429 iov.iov_len = sizeof(int); 430 uio.uio_iov = &iov; 431 uio.uio_iovcnt = 1; 432 uio.uio_offset = (off_t)(uintptr_t)uap->addr; 433 uio.uio_resid = sizeof(int); 434 uio.uio_segflg = UIO_SYSSPACE; /* ie: the uap */ 435 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 436 uio.uio_td = td; | 293 /* OK */ 294 break; 295 296 case PT_READ_I: 297 case PT_READ_D: 298 case PT_WRITE_I: 299 case PT_WRITE_D: 300 case PT_CONTINUE: --- 164 unchanged lines hidden (view full) --- 465 iov.iov_len = sizeof(int); 466 uio.uio_iov = &iov; 467 uio.uio_iovcnt = 1; 468 uio.uio_offset = (off_t)(uintptr_t)uap->addr; 469 uio.uio_resid = sizeof(int); 470 uio.uio_segflg = UIO_SYSSPACE; /* ie: the uap */ 471 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 472 uio.uio_td = td; |
437 error = procfs_domem(curp, p, NULL, &uio); | 473 error = proc_rwmem(p, &uio); |
438 if (uio.uio_resid != 0) { 439 /* | 474 if (uio.uio_resid != 0) { 475 /* |
440 * XXX procfs_domem() doesn't currently return ENOSPC, | 476 * XXX proc_rwmem() doesn't currently return ENOSPC, |
441 * so I think write() can bogusly return 0. 442 * XXX what happens for short writes? We don't want 443 * to write partial data. | 477 * so I think write() can bogusly return 0. 478 * XXX what happens for short writes? We don't want 479 * to write partial data. |
444 * XXX procfs_domem() returns EPERM for other invalid | 480 * XXX proc_rwmem() returns EPERM for other invalid |
445 * addresses. Convert this to EINVAL. Does this 446 * clobber returns of EPERM for other reasons? 447 */ 448 if (error == 0 || error == ENOSPC || error == EPERM) 449 error = EINVAL; /* EOF */ 450 } 451 return (error); 452 453 case PT_KILL: 454 uap->data = SIGKILL; 455 goto sendsig; /* in PT_CONTINUE above */ 456 457#ifdef PT_SETREGS 458 case PT_SETREGS: | 481 * addresses. Convert this to EINVAL. Does this 482 * clobber returns of EPERM for other reasons? 483 */ 484 if (error == 0 || error == ENOSPC || error == EPERM) 485 error = EINVAL; /* EOF */ 486 } 487 return (error); 488 489 case PT_KILL: 490 uap->data = SIGKILL; 491 goto sendsig; /* in PT_CONTINUE above */ 492 493#ifdef PT_SETREGS 494 case PT_SETREGS: |
459 write = 1; 460 /* fallthrough */ | 495 error = copyin(uap->addr, &r.reg, sizeof r.reg); 496 if (error == 0) { 497 PHOLD(p); 498 error = procfs_write_regs(&p->p_thread, &r.reg); 499 PRELE(p); 500 } 501 return (error); |
461#endif /* PT_SETREGS */ | 502#endif /* PT_SETREGS */ |
503 |
|
462#ifdef PT_GETREGS 463 case PT_GETREGS: | 504#ifdef PT_GETREGS 505 case PT_GETREGS: |
464 /* write = 0 above */ | 506 PHOLD(p); 507 error = procfs_read_regs(&p->p_thread, &r.reg); 508 PRELE(p); 509 if (error == 0) 510 error = copyout(&r.reg, uap->addr, sizeof r.reg); 511 return (error); |
465#endif /* PT_SETREGS */ | 512#endif /* PT_SETREGS */ |
466#if defined(PT_SETREGS) || defined(PT_GETREGS) 467 if (!procfs_validregs(td)) /* no P_SYSTEM procs please */ 468 return (EINVAL); 469 else { 470 iov.iov_base = uap->addr; 471 iov.iov_len = sizeof(struct reg); 472 uio.uio_iov = &iov; 473 uio.uio_iovcnt = 1; 474 uio.uio_offset = 0; 475 uio.uio_resid = sizeof(struct reg); 476 uio.uio_segflg = UIO_USERSPACE; 477 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 478 uio.uio_td = td; 479 return (procfs_doregs(curp, p, NULL, &uio)); 480 } 481#endif /* defined(PT_SETREGS) || defined(PT_GETREGS) */ | |
482 483#ifdef PT_SETFPREGS 484 case PT_SETFPREGS: | 513 514#ifdef PT_SETFPREGS 515 case PT_SETFPREGS: |
485 write = 1; 486 /* fallthrough */ | 516 error = copyin(uap->addr, &r.fpreg, sizeof r.fpreg); 517 if (error == 0) { 518 PHOLD(p); 519 error = procfs_write_fpregs(&p->p_thread, &r.fpreg); 520 PRELE(p); 521 } 522 return (error); |
487#endif /* PT_SETFPREGS */ | 523#endif /* PT_SETFPREGS */ |
524 |
|
488#ifdef PT_GETFPREGS 489 case PT_GETFPREGS: | 525#ifdef PT_GETFPREGS 526 case PT_GETFPREGS: |
490 /* write = 0 above */ | 527 PHOLD(p); 528 error = procfs_read_fpregs(&p->p_thread, &r.fpreg); 529 PRELE(p); 530 if (error == 0) 531 error = copyout(&r.fpreg, uap->addr, sizeof r.fpreg); 532 return (error); |
491#endif /* PT_SETFPREGS */ | 533#endif /* PT_SETFPREGS */ |
492#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) 493 if (!procfs_validfpregs(td)) /* no P_SYSTEM procs please */ 494 return (EINVAL); 495 else { 496 iov.iov_base = uap->addr; 497 iov.iov_len = sizeof(struct fpreg); 498 uio.uio_iov = &iov; 499 uio.uio_iovcnt = 1; 500 uio.uio_offset = 0; 501 uio.uio_resid = sizeof(struct fpreg); 502 uio.uio_segflg = UIO_USERSPACE; 503 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 504 uio.uio_td = td; 505 return (procfs_dofpregs(curp, p, NULL, &uio)); 506 } 507#endif /* defined(PT_SETFPREGS) || defined(PT_GETFPREGS) */ | |
508 509#ifdef PT_SETDBREGS 510 case PT_SETDBREGS: | 534 535#ifdef PT_SETDBREGS 536 case PT_SETDBREGS: |
511 write = 1; 512 /* fallthrough */ | 537 error = copyin(uap->addr, &r.dbreg, sizeof r.dbreg); 538 if (error == 0) { 539 PHOLD(p); 540 error = procfs_write_dbregs(&p->p_thread, &r.dbreg); 541 PRELE(p); 542 } 543 return (error); |
513#endif /* PT_SETDBREGS */ | 544#endif /* PT_SETDBREGS */ |
545 |
|
514#ifdef PT_GETDBREGS 515 case PT_GETDBREGS: | 546#ifdef PT_GETDBREGS 547 case PT_GETDBREGS: |
516 /* write = 0 above */ | 548 PHOLD(p); 549 error = procfs_read_dbregs(&p->p_thread, &r.dbreg); 550 PRELE(p); 551 if (error == 0) 552 error = copyout(&r.dbreg, uap->addr, sizeof r.dbreg); 553 return (error); |
517#endif /* PT_SETDBREGS */ | 554#endif /* PT_SETDBREGS */ |
518#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS) 519 if (!procfs_validdbregs(td)) /* no P_SYSTEM procs please */ 520 return (EINVAL); 521 else { 522 iov.iov_base = uap->addr; 523 iov.iov_len = sizeof(struct dbreg); 524 uio.uio_iov = &iov; 525 uio.uio_iovcnt = 1; 526 uio.uio_offset = 0; 527 uio.uio_resid = sizeof(struct dbreg); 528 uio.uio_segflg = UIO_USERSPACE; 529 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 530 uio.uio_td = td; 531 return (procfs_dodbregs(curp, p, NULL, &uio)); 532 } 533#endif /* defined(PT_SETDBREGS) || defined(PT_GETDBREGS) */ | |
534 535 default: | 555 556 default: |
557 KASSERT(0, ("unreachable code\n")); |
|
536 break; 537 } 538 | 558 break; 559 } 560 |
561 KASSERT(0, ("unreachable code\n")); |
|
539 return (0); 540} 541 542int | 562 return (0); 563} 564 565int |
543trace_req(p) 544 struct proc *p; | 566trace_req(struct proc *p) |
545{ 546 return (1); 547} 548 549/* 550 * stopevent() | 567{ 568 return (1); 569} 570 571/* 572 * stopevent() |
551 * Stop a process because of a procfs event; | 573 * Stop a process because of a debugging event; |
552 * stay stopped until p->p_step is cleared 553 * (cleared by PIOCCONT in procfs). 554 * 555 * Must be called with the proc struct mutex held. 556 */ 557 558void | 574 * stay stopped until p->p_step is cleared 575 * (cleared by PIOCCONT in procfs). 576 * 577 * Must be called with the proc struct mutex held. 578 */ 579 580void |
559stopevent(p, event, val) 560 struct proc *p; 561 unsigned int event; 562 unsigned int val; | 581stopevent(struct proc *p, unsigned int event, unsigned int val) |
563{ 564 565 PROC_LOCK_ASSERT(p, MA_OWNED | MA_NOTRECURSED); 566 p->p_step = 1; 567 568 do { 569 p->p_xstat = val; 570 p->p_stype = event; /* Which event caused the stop? */ 571 wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */ 572 msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0); 573 } while (p->p_step); 574} | 582{ 583 584 PROC_LOCK_ASSERT(p, MA_OWNED | MA_NOTRECURSED); 585 p->p_step = 1; 586 587 do { 588 p->p_xstat = val; 589 p->p_stype = event; /* Which event caused the stop? */ 590 wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */ 591 msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0); 592 } while (p->p_step); 593} |