summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Hunter <m@lfurio.us>2025-09-03 01:21:34 -0400
committerMatt Hunter <m@lfurio.us>2025-09-07 21:03:26 -0400
commit0096d1896083f0df73e086b1e086ec52f610b7bf (patch)
tree91cc89f685a6dedc7ef57e784ff1c3c80df24b03
parent95364d5a74eb9977b946b4a520eb2624f2c788ab (diff)
downloadmisplays-0096d1896083f0df73e086b1e086ec52f610b7bf.tar.gz
misplays-0096d1896083f0df73e086b1e086ec52f610b7bf.zip
Manually uninstall breakpoints on process forkHEADmaster
Previously, there was a bug on PTRACE_EVENT_FORK in which the forked child process inherits all installed breakpoints due to their interrupt instructions being resident in memory at the time of the fork, but the debugger initializes the new process model with an empty list of breakpoints. There are some differing opinions on what the correct behavior ought to be here, but at a minimum these two realities must be brought into sync to prevent data corruption or any process crash of the fork child. For the time being, manually "uninstall" the residual breakpoint interrupts from a newly forked child that we attach to, leaving it with no breakpoints of any kind. Process model initialization in the debugger is left as-is. Signed-off-by: Matt Hunter <m@lfurio.us>
-rw-r--r--debugger.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/debugger.c b/debugger.c
index 7378298..c3c9fa1 100644
--- a/debugger.c
+++ b/debugger.c
@@ -113,6 +113,15 @@ static void uninstall_breakpoints(struct thread *th) {
}
}
+static void clean_fork_breakpoints(struct thread *th, const struct process *parent) {
+ const struct list *breaks = &parent->breakpoints;
+ for (struct breakpoint *b = breaks->tail; b != breaks->end; b = b->prev) {
+ if (b->installed) {
+ ptrace(PTRACE_POKETEXT, th->id, b->address, b->text);
+ }
+ }
+}
+
static int detect_breakpoint(struct thread *th, int *restart) {
int is_bp = 0; /* at least 1 effective breakpoint at this PC */
int is_user = 0; /* at least 1 user-defined bp at this PC */
@@ -393,6 +402,8 @@ static int wait_thread(struct thread *th) {
//while (!wait_thread(eventth)) {}
dbg_sync(eventproc);
+ clean_fork_breakpoints(eventth, th->proc);
+
th->stopped = 1;
th->signal = 0;
th->doing = 0;