mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-13 10:02:38 +00:00
Add support for ptrace() and gdb breakpoints.
This commit is contained in:
parent
8b64f2f5ad
commit
9026d36c6e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=140001
@ -64,8 +64,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/buf.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/uio.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/trap.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
@ -289,17 +291,68 @@ set_dbregs(struct thread *td, struct dbreg *regs)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct uio uio;
|
||||
iov.iov_base = (caddr_t) v;
|
||||
iov.iov_len = sizeof(u_int32_t);
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_offset = (off_t)addr;
|
||||
uio.uio_resid = sizeof(u_int32_t);
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_rw = UIO_READ;
|
||||
uio.uio_td = td;
|
||||
return proc_rwmem(td->td_proc, &uio);
|
||||
}
|
||||
|
||||
static int
|
||||
ptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct uio uio;
|
||||
iov.iov_base = (caddr_t) &v;
|
||||
iov.iov_len = sizeof(u_int32_t);
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_offset = (off_t)addr;
|
||||
uio.uio_resid = sizeof(u_int32_t);
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_rw = UIO_WRITE;
|
||||
uio.uio_td = td;
|
||||
return proc_rwmem(td->td_proc, &uio);
|
||||
}
|
||||
|
||||
int
|
||||
ptrace_single_step(struct thread *td)
|
||||
{
|
||||
/* XXX */
|
||||
return (0);
|
||||
int error;
|
||||
|
||||
KASSERT(td->td_md.md_ptrace_instr == 0,
|
||||
("Didn't clear single step"));
|
||||
error = ptrace_read_int(td, td->td_frame->tf_pc + 4,
|
||||
&td->td_md.md_ptrace_instr);
|
||||
if (error)
|
||||
return (error);
|
||||
error = ptrace_write_int(td, td->td_frame->tf_pc + 4,
|
||||
PTRACE_BREAKPOINT);
|
||||
if (error)
|
||||
td->td_md.md_ptrace_instr = 0;
|
||||
td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ptrace_clear_single_step(struct thread *td)
|
||||
{
|
||||
/* XXX */
|
||||
if (td->td_md.md_ptrace_instr) {
|
||||
ptrace_write_int(td, td->td_md.md_ptrace_addr,
|
||||
td->td_md.md_ptrace_instr);
|
||||
td->td_md.md_ptrace_instr = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/uio.h>
|
||||
#include <sys/ktrace.h>
|
||||
#endif
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/pioctl.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
@ -919,6 +921,8 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
|
||||
if (error == 0) {
|
||||
td->td_retval[0] = 0;
|
||||
td->td_retval[1] = 0;
|
||||
STOPEVENT(p, S_SCE, (callp->sy_narg & SYF_ARGMASK));
|
||||
PTRACESTOP_SC(p, td, S_PT_SCE);
|
||||
error = (*callp->sy_call)(td, args);
|
||||
}
|
||||
switch (error) {
|
||||
@ -952,6 +956,8 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
|
||||
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
|
||||
td->td_proc->p_pid, td->td_proc->p_comm, code);
|
||||
|
||||
STOPEVENT(p, S_SCX, code);
|
||||
PTRACESTOP_SC(p, td, S_PT_SCX);
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(td, KTR_SYSRET))
|
||||
ktrsysret(code, error, td->td_retval[0]);
|
||||
|
@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/ptrace.h>
|
||||
#ifdef KDB
|
||||
#include <sys/kdb.h>
|
||||
#endif
|
||||
@ -135,26 +136,17 @@ gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
|
||||
struct thread *td;
|
||||
td = (curthread == NULL) ? &thread0 : curthread;
|
||||
|
||||
#if 0
|
||||
if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) {
|
||||
if (code == FAULT_USER) {
|
||||
ksiginfo_t ksi;
|
||||
|
||||
KSI_INIT_TRAP(&ksi);
|
||||
ksi.ksi_signo = SIGTRAP;
|
||||
ksi.ksi_code = TRAP_BRKPT;
|
||||
ksi.ksi_addr = (u_int32_t *)addr;
|
||||
ksi.ksi_trap = 0;
|
||||
PROC_LOCK(td->td_proc);
|
||||
trapsignal(td, &ksi);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
trapsignal(td, SIGTRAP, 0);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
#ifdef KGDB
|
||||
return !kgdb_trap(T_BREAKPOINT, frame);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -257,6 +249,11 @@ undefinedinstruction(trapframe_t *frame)
|
||||
fault_code) == 0)
|
||||
break;
|
||||
|
||||
if (fault_code & FAULT_USER && fault_instruction == PTRACE_BREAKPOINT) {
|
||||
ptrace_clear_single_step(td);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uh == NULL && (fault_code & FAULT_USER)) {
|
||||
/* Fault has not been handled */
|
||||
trapsignal(td, SIGILL, 0);
|
||||
@ -272,7 +269,7 @@ undefinedinstruction(trapframe_t *frame)
|
||||
return;
|
||||
} else
|
||||
panic("Undefined instruction in kernel.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FAST_FPE
|
||||
/* Optimised exit code */
|
||||
|
@ -47,6 +47,8 @@ struct md_utrap {
|
||||
|
||||
struct mdthread {
|
||||
register_t md_savecrit;
|
||||
int md_ptrace_instr;
|
||||
int md_ptrace_addr;
|
||||
};
|
||||
|
||||
struct mdproc {
|
||||
|
@ -1,4 +1,10 @@
|
||||
/* $NetBSD: trap.h,v 1.1 2001/02/23 03:48:19 ichiro Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#ifndef _MACHINE_TRAP_H_
|
||||
#define _MACHINE_TRAP_H_
|
||||
#define GDB_BREAKPOINT 0xe6000011
|
||||
#define GDB5_BREAKPOINT 0xe7ffdefe
|
||||
#define PTRACE_BREAKPOINT 0xe7fffff0
|
||||
#define KERNEL_BREAKPOINT 0xe7ffffff
|
||||
#endif /* _MACHINE_TRAP_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user