support PTRACE_SINGLESTEP.

support debug/int3 exception.
This commit is contained in:
Susumu Komae
2015-01-29 15:48:05 +09:00
committed by postpeta
parent f97f8dbab3
commit bd5f43b119
5 changed files with 95 additions and 3 deletions

View File

@ -107,6 +107,7 @@ void reload_idt(void)
static struct list_head handlers[256 - 32];
extern char page_fault[], general_protection_exception[];
extern char debug_exception[], int3_exception[];
static void init_idt(void)
{
@ -125,6 +126,9 @@ static void init_idt(void)
set_idt_entry(13, (unsigned long)general_protection_exception);
set_idt_entry(14, (unsigned long)page_fault);
set_idt_entry_trap_gate(1, (unsigned long)debug_exception);
set_idt_entry_trap_gate(3, (unsigned long)int3_exception);
reload_idt();
}
@ -467,6 +471,50 @@ void gpe_handler(struct x86_regs *regs)
// panic("GPF");
}
void debug_handler(struct x86_regs *regs)
{
unsigned long db6;
int si_code = 0;
struct siginfo info;
#ifdef DEBUG_PRINT_CPU
kprintf("debug exception (err: %lx, %lx:%lx)\n",
regs->error, regs->cs, regs->rip);
arch_show_interrupt_context(regs);
#endif
asm("mov %%db6, %0" :"=r" (db6));
if (db6 & DB6_BS) {
regs->rflags &= ~RFLAGS_TF;
si_code = TRAP_TRACE;
} else if (db6 & (DB6_B3|DB6_B2|DB6_B1|DB6_B0)) {
si_code = TRAP_HWBKPT;
}
memset(&info, '\0', sizeof info);
info.si_code = si_code;
set_signal(SIGTRAP, regs, &info);
check_signal(0, regs);
check_need_resched();
}
void int3_handler(struct x86_regs *regs)
{
struct siginfo info;
#ifdef DEBUG_PRINT_CPU
kprintf("int3 exception (err: %lx, %lx:%lx)\n",
regs->error, regs->cs, regs->rip);
arch_show_interrupt_context(regs);
#endif
memset(&info, '\0', sizeof info);
info.si_code = TRAP_BRKPT;
set_signal(SIGTRAP, regs, &info);
check_signal(0, regs);
check_need_resched();
}
void x86_issue_ipi(unsigned int apicid, unsigned int low)
{
lapic_icr_write(apicid << LAPIC_ICR_ID_SHIFT, low);

View File

@ -34,6 +34,14 @@
#define RFLAGS_VIP (1 << 20)
#define RFLAGS_ID (1 << 21)
#define DB6_B0 (1 << 0)
#define DB6_B1 (1 << 1)
#define DB6_B2 (1 << 2)
#define DB6_B3 (1 << 3)
#define DB6_BD (1 << 13)
#define DB6_BS (1 << 14)
#define DB6_BT (1 << 15)
#define MSR_EFER 0xc0000080
#define MSR_STAR 0xc0000081
#define MSR_LSTAR 0xc0000082

View File

@ -154,3 +154,25 @@ enter_user_mode:
POP_ALL_REGS
addq $8, %rsp
iretq
.globl debug_exception
debug_exception:
cld
pushq $0 /* error */
PUSH_ALL_REGS
movq %rsp, %rdi
call debug_handler
POP_ALL_REGS
addq $8, %rsp
iretq
.globl int3_exception
int3_exception:
cld
pushq $0 /* error */
PUSH_ALL_REGS
movq %rsp, %rdi
call int3_handler
POP_ALL_REGS
addq $8, %rsp
iretq

View File

@ -384,6 +384,11 @@ void clear_single_step(struct process *proc)
proc->uctx->rflags &= ~RFLAGS_TF;
}
void set_single_step(struct process *proc)
{
proc->uctx->rflags |= RFLAGS_TF;
}
extern void coredump(struct process *proc, void *regs);
static void ptrace_report_signal(struct process *proc, struct x86_regs *regs, int sig)

View File

@ -2557,6 +2557,8 @@ SYSCALL_DECLARE(getrlimit)
}
extern int ptrace_traceme(void);
extern void clear_single_step(struct process *proc);
extern void set_single_step(struct process *proc);
static int ptrace_wakeup_sig(int pid, long request, long data) {
dkprintf("ptrace_wakeup_sig,pid=%d,data=%08x\n", pid, data);
@ -2588,6 +2590,14 @@ static int ptrace_wakeup_sig(int pid, long request, long data) {
}
break;
case PTRACE_CONT:
case PTRACE_SINGLESTEP:
case PTRACE_SYSCALL:
if (request == PTRACE_SINGLESTEP) {
set_single_step(child);
}
if (request == PTRACE_SYSCALL) {
/* TODO: may set PTRACE_SYSCALL flag */
}
if(data != 0 && data != SIGSTOP) {
struct process *proc;
@ -2823,8 +2833,6 @@ out:
return ret;
}
extern void clear_single_step(struct process *proc);
static int ptrace_detach(int pid, int data)
{
int error;
@ -2991,7 +2999,8 @@ SYSCALL_DECLARE(ptrace)
dkprintf("PTRACE_POKEDATA: addr=%p data=%p\n", addr, data);
break;
case PTRACE_SINGLESTEP:
dkprintf("ptrace: unimplemented ptrace(PTRACE_SINGLESTEP) called.\n");
dkprintf("ptrace: PTRACE_SINGLESTEP: data=%d\n", data);
error = ptrace_wakeup_sig(pid, request, data);
break;
case PTRACE_GETFPREGS:
dkprintf("ptrace: unimplemented ptrace(PTRACE_GETFPREGS) called.\n");