ptrace: PTRACE_SINGLESTEP

This commit is contained in:
K. Lange 2021-09-24 14:41:17 +09:00
parent 9e19ebb93a
commit 41ba264cdc
4 changed files with 52 additions and 3 deletions

View File

@ -403,6 +403,11 @@ static void show_commandline(pid_t pid, int status, struct regs * regs) {
if (signum == SIGINT) signum = 0;
ptrace(PTRACE_CONT, pid, NULL, (void*)(uintptr_t)signum);
return;
} else if (!strcmp(buf, "step") || !strcmp(buf,"s")) {
int signum = WSTOPSIG(status);
if (signum == SIGINT) signum = 0;
ptrace(PTRACE_SINGLESTEP, pid, NULL, (void*)(uintptr_t)signum);
return;
} else if (!strcmp(buf, "poke")) {
char * addr = arg;
char * data = strstr(addr, " ");
@ -599,8 +604,19 @@ int main(int argc, char * argv[]) {
if (WIFSTOPPED(status)) {
if (WSTOPSIG(status) == SIGTRAP) {
/* Don't care about TRAP right now */
//ptrace(PTRACE_SIGNALS_ONLY_PLZ, p, NULL, NULL);
ptrace(PTRACE_CONT, p, NULL, NULL);
int event = (status >> 16) & 0xFF;
switch (event) {
case PTRACE_EVENT_SINGLESTEP: {
struct regs regs;
ptrace(PTRACE_GETREGS, res, NULL, &regs);
show_commandline(res, status, &regs);
}
break;
default:
//ptrace(PTRACE_SIGNALS_ONLY_PLZ, p, NULL, NULL);
ptrace(PTRACE_CONT, p, NULL, NULL);
break;
}
} else {
printf("Program received signal %s.\n", sig_to_str(WSTOPSIG(status)));

View File

@ -13,12 +13,14 @@ enum __ptrace_request {
PTRACE_GETREGS,
PTRACE_PEEKDATA,
PTRACE_SIGNALS_ONLY_PLZ,
PTRACE_POKEDATA
PTRACE_POKEDATA,
PTRACE_SINGLESTEP
};
enum __ptrace_event {
PTRACE_EVENT_SYSCALL_ENTER,
PTRACE_EVENT_SYSCALL_EXIT,
PTRACE_EVENT_SINGLESTEP,
};
#ifndef __kernel__

View File

@ -7,9 +7,12 @@
#include <kernel/signal.h>
#include <kernel/misc.h>
#include <kernel/time.h>
#include <kernel/ptrace.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/ptrace.h>
#include <kernel/arch/x86_64/mmu.h>
#include <kernel/arch/x86_64/ports.h>
#include <kernel/arch/x86_64/pml.h>
@ -229,11 +232,21 @@ struct regs * isr_handler(struct regs * r) {
/* Spurious interrupt */
break;
}
case 1: {
/* Debug interrupt */
r->rflags &= ~(1 << 8);
if (this_core->current_process->flags & PROC_FLAG_TRACE_SIGNALS) {
ptrace_signal(SIGTRAP, PTRACE_EVENT_SINGLESTEP);
}
return r;
}
default: {
if (r->int_no < 32) {
if (!this_core->current_process || r->cs == 0x08) {
arch_fatal();
}
printf("int_no %ld in process %d\n",
r->int_no, this_core->current_process->id);
send_signal(this_core->current_process->id, SIGILL, 1);
} else {
for (size_t i = 0; i < IRQ_CHAIN_DEPTH; i++) {

View File

@ -127,6 +127,22 @@ long ptrace_signals_only(pid_t pid) {
return 0;
}
long ptrace_singlestep(pid_t pid, int sig) {
process_t * tracee = process_from_pid(pid);
if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH;
struct regs * target = tracee->interrupt_registers ? tracee->interrupt_registers : tracee->syscall_registers;
/* arch_set_singlestep? */
target->rflags |= (1 << 8);
__sync_and_and_fetch(&tracee->flags, ~(PROC_FLAG_SUSPENDED));
tracee->status = (sig << 8);
make_process_ready(tracee);
return 0;
}
long ptrace_handle(long request, pid_t pid, void * addr, void * data) {
switch (request) {
case PTRACE_ATTACH:
@ -143,6 +159,8 @@ long ptrace_handle(long request, pid_t pid, void * addr, void * data) {
return ptrace_poke(pid,addr,data);
case PTRACE_SIGNALS_ONLY_PLZ:
return ptrace_signals_only(pid);
case PTRACE_SINGLESTEP:
return ptrace_singlestep(pid,(uintptr_t)data);
default:
return -EINVAL;
}