summaryrefslogtreecommitdiffstats
path: root/misplays.c
diff options
context:
space:
mode:
authorMalfurious <m@lfurio.us>2023-09-19 11:02:03 -0400
committerMalfurious <m@lfurio.us>2024-04-24 13:31:08 -0400
commitb4abda51217101ceffd19c3d403e40781e15dcec (patch)
tree1418becd7e2d8437fee1f5f3eaa27f7c6e1bb690 /misplays.c
parentd070fde6478431c71fb4a55e783a577439c7cb99 (diff)
downloadmisplays-b4abda51217101ceffd19c3d403e40781e15dcec.tar.gz
misplays-b4abda51217101ceffd19c3d403e40781e15dcec.zip
Multithread version 2
Signed-off-by: Malfurious <m@lfurio.us>
Diffstat (limited to 'misplays.c')
-rw-r--r--misplays.c372
1 files changed, 168 insertions, 204 deletions
diff --git a/misplays.c b/misplays.c
index a1f11a4..4fec040 100644
--- a/misplays.c
+++ b/misplays.c
@@ -1,10 +1,7 @@
-#include <errno.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <sys/ptrace.h>
-#include <sys/wait.h>
-#include <linux/ptrace.h>
#include <unistd.h>
#include <capstone/capstone.h>
@@ -12,85 +9,33 @@
#include "console.h"
#include "debugger.h"
#include "helpers.h"
+#include "list.h"
static PANEL *left, *right;
-static struct console cons;
-static int mode = 0;
-PANEL *consolepan;
-
-/*
-static void describe_status(struct tracee *_dbg, PANEL *pan) {
- struct tracee dbg = *_dbg;
- int status = dbg.status;
- struct ptrace_syscall_info info;
-
- if (WIFEXITED(status)) {
- pprintw(pan, "exited with code: %u\n", WEXITSTATUS(status));
- } else if (WIFSIGNALED(status)) {
- pprintw(pan, "terminated by signal: %s\n", strsignal(WTERMSIG(status)));
- } else {
- unsigned long msg;
- if (ptrace(PTRACE_GETEVENTMSG, dbg.id, NULL, &msg) < 0) {
- perror("PTRACE_GETEVENTMSG");
- }
-
- if (WIFSTOPPED(status)) {
- switch (status >> 8) {
- case ((PTRACE_EVENT_VFORK << 8) | SIGTRAP):
- pprintw(pan, "child vfork()'d to: %lu\n", msg);
- break;
- case ((PTRACE_EVENT_FORK << 8) | SIGTRAP):
- pprintw(pan, "child fork()'d to: %lu\n", msg);
- break;
- case ((PTRACE_EVENT_CLONE << 8) | SIGTRAP):
- pprintw(pan, "child clone()'d to: %lu\n", msg);
- break;
- case ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP):
- pprintw(pan, "finished vfork\n");
- break;
- case ((PTRACE_EVENT_EXEC << 8) | SIGTRAP):
- pprintw(pan, "child exec()'d from: %lu\n", msg);
- break;
- case ((PTRACE_EVENT_EXIT << 8) | SIGTRAP):
- pprintw(pan, "exiting with code: %lu\n", msg);
- break;
- case ((PTRACE_EVENT_STOP << 8) | SIGTRAP):
- pprintw(pan, "child stopped\n");
- break;
- case ((PTRACE_EVENT_SECCOMP << 8) | SIGTRAP):
- pprintw(pan, "child seccomp event\n");
- break;
-
- case (SIGTRAP | 0x80):
- ptrace(PTRACE_GET_SYSCALL_INFO, dbg.id, sizeof(info), &info);
- pprintw(pan, "child entering syscall: %llu (%llx, %llx, %llx, %llx, %llx, %llx)\n",
- info.entry.nr,
- info.entry.args[0],
- info.entry.args[1],
- info.entry.args[2],
- info.entry.args[3],
- info.entry.args[4],
- info.entry.args[5]);
- break;
+static pid_t parse_pid(const char *nptr) {
+ char *endptr;
+ pid_t pid = strtoul(nptr, &endptr, 0);
+ return (*endptr ? 0 : pid);
+}
- case SIGSTOP:
- case SIGTSTP:
- case SIGTTIN:
- case SIGTTOU:
- pprintw(pan, "child group-stopped\n");
- break;
+static pid_t dofork(char **argv, struct console *cons) {
+ pid_t pid = fork();
+ if (pid < 0) {
+ return -1;
+ }
- default:
- pprintw(pan, "received signal: %s\n", strsignal(WSTOPSIG(status)));
- break;
- }
- } else {
- pprintw(pan, "child stop event unrecognized\n");
- }
+ if (pid == 0) {
+ console_configslave(cons);
+ close_range(STDERR_FILENO+1, ~0U, CLOSE_RANGE_UNSHARE);
+ setpgid(0, 0);
+ raise(SIGSTOP); // ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+ execvp(argv[0], argv);
+ exit(EXIT_FAILURE);
}
+
+ return pid;
}
-*/
static void list_breakpoints(struct thread *dbg, PANEL *pan) {
struct list *breaks = &dbg->proc->breakpoints;
@@ -148,7 +93,7 @@ static void disasm(struct thread *dbg, PANEL *pan) {
cs_insn *insn;
if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {
- perror("capstone open");
+ //perror("capstone open");
} else {
uint64_t address = dbg->state->regs.rip;
size_t codez = 128;
@@ -185,83 +130,97 @@ static void disasm(struct thread *dbg, PANEL *pan) {
}
}
-static void info_update(struct thread *dbg, PANEL *pan) {
+static void info_update(struct thread *th, PANEL *pan) {
pclear(pan);
- pprintw(pan, "TID: %li\n", (long)dbg->id);
- //if (!dbg->stopped) {
- // pprintw(pan, "Thread is running...\n");
- //} else {
- //describe_status(dbg, pan);
- pprintw(pan, "%s (%i)\n", dbg->status, dbg->signal);
- list_breakpoints(dbg, pan);
- describe_states(dbg, pan);
- dump_registers(dbg, pan);
- pprintw(pan, "---\n");
- dump_stack(dbg, pan);
- pprintw(pan, "---\n");
- disasm(dbg, pan);
- //}
+ pprintw(pan, "TID: %li\n", (long)th->id);
+ pprintw(pan, "%s (%i)\n", th->status, th->signal);
+ list_breakpoints(th, pan);
+ describe_states(th, pan);
+ dump_registers(th, pan);
+ pprintw(pan, "---\n");
+ dump_stack(th, pan);
+ pprintw(pan, "---\n");
+ disasm(th, pan);
+}
+
+static void wait_all_threads(struct list *processes) {
+ for (struct process *proc = processes->head; proc != processes->end; proc = proc->next) {
+ struct list *threads = &proc->threads;
+ for (struct thread *th = threads->head; th != threads->end; th = th->next) {
+ dbg_wait(th, 0);
+ }
+ }
}
-static void layout(struct process *proc, struct thread *th) {
+static void layout(struct list *processes, struct thread *th) {
int w = COLS/2;
reset_panel(left, LINES-2, w, 1, 0);
reset_panel(right, LINES-2, COLS-w, 1, w);
clear();
attron(COLOR_PAIR(1));
- struct list *threads = &proc->threads;
- for (struct thread *t = threads->head; t != threads->end; t = t->next) {
- if (t == th) {
- printw("**");
- }
- printw("%li (%s)", (long)t->id, t->status);
- if (t == th) {
- printw("**");
+
+ for (struct process *proc = processes->head; proc != processes->end; proc = proc->next) {
+ struct list *threads = &proc->threads;
+ for (struct thread *t = threads->head; t != threads->end; t = t->next) {
+ if (t == th) {
+ printw("**");
+ }
+ printw("%li (%s)", (long)t->id, t->status);
+ if (t == th) {
+ printw("**");
+ }
+ printw(" ");
}
- printw(" ");
}
- attroff(COLOR_PAIR(1));
- //refresh();
-}
-static void wait_all_threads(struct process *proc) {
- struct list *threads = &proc->threads;
- for (struct thread *th = threads->head; th != threads->end; th = th->next) {
- dbg_wait(th, 1);
- }
+ attroff(COLOR_PAIR(1));
}
int main(int argc, char **argv) {
if (argc < 2) {
- fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
- return 1;
+ fprintf(stderr, "Usage: %s <pid | cmdline>\n", argv[0]);
+ return EXIT_FAILURE;
}
- //getchar();
+ getchar();
- cursinit();
- left = newpan(0, 0, 0, 0);
- right = newpan(0, 0, 0, 0);
+ struct console cons = {0};
console_init(&cons);
- consolepan = right;
- struct process proc;
- struct thread *th;
+ struct list processes = {0};
+ struct thread *th = NULL;
+ list_init(&processes);
- pid_t pid = strtoul(argv[1], NULL, 0);
- if (dbg_process(&proc, pid, 0)) {
- pprintw(right, "failed to attach process\n");
+ int child = 0;
+ pid_t pid = parse_pid(argv[1]);
+ argv[argc] = NULL;
+
+ if (pid == 0) {
+ pid = dofork(argv+1, &cons);
+ child = 1;
+ }
+
+ struct process *proc = dbg_attach(pid, child);
+ if (!proc) {
+ fprintf(stderr, "Failed to attach to process %li\n", (long)pid);
+ return EXIT_FAILURE;
}
+ list_insert(processes.end, proc);
+ th = proc->threads.head;
- th = proc.threads.head;
+ cursinit();
+ left = newpan(0, 0, 0, 0);
+ right = newpan(0, 0, 0, 0);
+ layout(&processes, th);
int quit = 0;
+ int mode = 0;
while (!quit) {
- wait_all_threads(&proc);
+ wait_all_threads(&processes);
+ layout(&processes, th);
console_update(&cons, right);
info_update(th, left);
- layout(&proc, th);
cursupdate();
int ch = getch();
@@ -269,7 +228,7 @@ int main(int argc, char **argv) {
if (mode == 0) {
switch (ch) {
case KEY_RESIZE:
- layout(&proc, th);
+ layout(&processes, th);
break;
case 'q':
quit = 1;
@@ -279,53 +238,30 @@ int main(int argc, char **argv) {
console_enter(&cons, right);
break;
case 'j':
- dbg_stepin(th);
- /*
- if (dbg->stopped) {
- if (dbg->state != dbg->states.tail) {
- dbg->state = dbg->state->next;
- } else {
- dbg_stepover(dbg);
- }
+ dbg_step(th, 1);
+ break;
+ case 'k':
+ dbg_pets(th);
+ break;
+ case 'l':
+ dbg_step(th, 0);
+ break;
+ case 'h':
+ /* todo: step out */
+ break;
+ case 'g':
+ if (th->stopped) {
+ th->state = th->states.head;
+ }
+ break;
+ case 'G':
+ if (th->stopped) {
+ th->state = th->states.tail;
}
- */
break;
- //case 'k':
- // if (dbg->stopped) {
- // if (dbg->state != dbg->states.head) {
- // dbg->state = dbg->state->prev;
- // }
- // }
- // break;
- //case 'l':
- // if (dbg->stopped) {
- // if (dbg->state != dbg->states.tail) {
- // //dbg.state = dbg.state->next;
- // } else {
- // dbg_stepin(dbg);
- // }
- // }
- // break;
- //case 'h':
- // if (dbg.stopped) {
- // dbg_stepout(&dbg);
- // }
- // break;
- //case 'g':
- // if (dbg->stopped) {
- // dbg->state = dbg->states.head;
- // }
- // break;
- //case 'G':
- // if (dbg->stopped) {
- // dbg->state = dbg->states.tail;
- // }
- // break;
- //case 's':
- // if (dbg->stopped) {
- // dbg_cont(dbg, PTRACE_SYSCALL);
- // }
- // break;
+ case 's':
+ dbg_cont(th, PTRACE_SYSCALL);
+ break;
case 'c':
dbg_cont(th, PTRACE_CONT);
break;
@@ -333,38 +269,19 @@ int main(int argc, char **argv) {
dbg_intr(th);
break;
case 't':
+ proc = th->proc;
do {
th = th->next;
- } while (th == proc.threads.end);
+ } while (th == proc->threads.end);
+ layout(&processes, th);
break;
case 'T':
+ proc = th->proc;
do {
th = th->prev;
- } while (th == proc.threads.end);
- break;
- //case 'd':
- // if (dbg->stopped) {
- // while (dbg->breaks.head != dbg->breaks.end) {
- // struct breakpoint *b = dbg->breaks.head;
- // list_remove(b);
- // free(b);
- // }
- // }
- // break;
- //case 'D':
- // if (dbg->stopped) {
- // if (ptrace(PTRACE_DETACH, dbg->id, NULL, NULL) < 0) {
- // pprintw(right, "PTRACE_DETACH: %s\n", strerror(errno));
- // }
- // struct tracee *rm = dbg;
- // do {
- // dbg = dbg->next;
- // } while (dbg == tracees.end);
- // list_remove(rm);
- // dbg_free(rm);
- // free(rm);
- // }
- // break;
+ } while (th == proc->threads.end);
+ layout(&processes, th);
+ break; /* todo: next/prev process bindings */
case ':':
mvprintw(LINES-1, 0, ":");
curs_set(TRUE);
@@ -376,24 +293,27 @@ int main(int argc, char **argv) {
noecho();
timeout(25);
clear();
- //refresh();
+ layout(&processes, th);
char *t = cmd;
int en = 1;
if (t[0] == '!') {
en = -1;
t++;
+ } else if (t[0] == '#') {
+ en = 0;
+ t++;
}
- unsigned long addr = strtoul(t, NULL, 0);
- add_breakpoint(&proc, addr, 0, 0, en);
+ unsigned long address = strtoul(t, NULL, 0);
+ add_breakpoint(th->proc, address, 0, 0, en);
break;
}
} else {
switch (ch) {
case KEY_RESIZE:
- layout(&proc, th);
+ layout(&processes, th);
break;
- case 0x1b:
+ case KEY_ESCAPE:
mode = 0;
console_leave(&cons, right);
break;
@@ -406,7 +326,51 @@ int main(int argc, char **argv) {
}
}
- dbg_detach(&proc);
+ dbg_detach(th->proc); /* todo: detach all procs */
endwin();
- return 0;
+ return EXIT_SUCCESS;
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//#include <errno.h>
+//#include <signal.h>
+//#include <string.h>
+//#include <sys/ptrace.h>
+//#include <sys/wait.h>
+//#include <linux/ptrace.h>
+
+// //case 'd':
+// // if (dbg->stopped) {
+// // while (dbg->breaks.head != dbg->breaks.end) {
+// // struct breakpoint *b = dbg->breaks.head;
+// // list_remove(b);
+// // free(b);
+// // }
+// // }
+// // break;
+// //case 'D':
+// // if (dbg->stopped) {
+// // if (ptrace(PTRACE_DETACH, dbg->id, NULL, NULL) < 0) {
+// // pprintw(right, "PTRACE_DETACH: %s\n", strerror(errno));
+// // }
+// // struct tracee *rm = dbg;
+// // do {
+// // dbg = dbg->next;
+// // } while (dbg == tracees.end);
+// // list_remove(rm);
+// // dbg_free(rm);
+// // free(rm);
+// // }
+// // break;