| 459 | #endif |
| 460 | |
| 461 | int |
| 462 | sys_ptrace(struct thread *td, struct ptrace_args *uap) |
| 463 | { |
| 464 | /* |
| 465 | * XXX this obfuscation is to reduce stack usage, but the register |
| 466 | * structs may be too large to put on the stack anyway. |
| 467 | */ |
| 468 | union { |
| 469 | struct ptrace_io_desc piod; |
| 470 | struct ptrace_lwpinfo pl; |
| 471 | struct ptrace_vm_entry pve; |
| 472 | struct dbreg dbreg; |
| 473 | struct fpreg fpreg; |
| 474 | struct reg reg; |
| 475 | char args[sizeof(td->td_sa.args)]; |
| 476 | struct ptrace_sc_ret psr; |
| 477 | int ptevents; |
| 478 | } r; |
| 479 | void *addr; |
| 480 | int error = 0; |
| 481 | |
| 482 | AUDIT_ARG_PID(uap->pid); |
| 483 | AUDIT_ARG_CMD(uap->req); |
| 484 | AUDIT_ARG_VALUE(uap->data); |
| 485 | addr = &r; |
| 486 | switch (uap->req) { |
| 487 | case PT_GET_EVENT_MASK: |
| 488 | case PT_LWPINFO: |
| 489 | case PT_GET_SC_ARGS: |
| 490 | case PT_GET_SC_RET: |
| 491 | break; |
| 492 | case PT_GETREGS: |
| 493 | bzero(&r.reg, sizeof(r.reg)); |
| 494 | break; |
| 495 | case PT_GETFPREGS: |
| 496 | bzero(&r.fpreg, sizeof(r.fpreg)); |
| 497 | break; |
| 498 | case PT_GETDBREGS: |
| 499 | bzero(&r.dbreg, sizeof(r.dbreg)); |
| 500 | break; |
| 501 | case PT_SETREGS: |
| 502 | error = copyin(uap->addr, &r.reg, sizeof(r.reg)); |
| 503 | break; |
| 504 | case PT_SETFPREGS: |
| 505 | error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg)); |
| 506 | break; |
| 507 | case PT_SETDBREGS: |
| 508 | error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg)); |
| 509 | break; |
| 510 | case PT_SET_EVENT_MASK: |
| 511 | if (uap->data != sizeof(r.ptevents)) |
| 512 | error = EINVAL; |
| 513 | else |
| 514 | error = copyin(uap->addr, &r.ptevents, uap->data); |
| 515 | break; |
| 516 | case PT_IO: |
| 517 | error = copyin(uap->addr, &r.piod, sizeof(r.piod)); |
| 518 | break; |
nothing calls this directly
no test coverage detected