C'è una chiamata di sistema chiamata ptrace. Richiede 4 parametri:l'operazione, il PID del processo target, un indirizzo nella memoria del processo target e un puntatore dati. Il modo in cui vengono utilizzati gli ultimi 2 parametri dipende dall'operazione.
Ad esempio puoi collegare/scollegare il tuo debugger a un processo:
ptrace(PTRACE_ATTACH, pid, 0, 0);
...
ptrace(PTRACE_DETACH, pid, 0, 0);
Esecuzione a passo singolo:
ptrace(PTRACE_ATTACH, pid, 0, 0);
int status;
waitpid(pid, &status, WSTOPPED);
while (...) {
ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
// give the user a chance to do something
}
ptrace(PTRACE_DETACH, pid, 0, 0);
Puoi anche leggere/scrivere la memoria del processo di destinazione con PTRACE_PEEKDATA e PTRACE_POKEDATA. Se vuoi vedere un esempio reale dai un'occhiata a gdb.