static void exit_wrk( Int status, Bool gdbserver_call_allowed) { static Bool exit_called = False; // avoid recursive exit during gdbserver call. if (gdbserver_call_allowed && !exit_called) { const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv. exit_called = True; if (status != 0 && VgdbStopAtiS(VgdbStopAt_ValgrindAbExit, VG_(clo_vgdb_stop_at))) { if (VG_(gdbserver_init_done)()) { VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n"); VG_(gdbserver) (atid); } else { VG_(umsg)("(action at valgrind abnormal exit)\n" "valgrind exit is too early => vgdb not yet usable\n"); } } if (VG_(gdbserver_init_done)()) { // Always terminate the gdbserver when Valgrind exits, so as // to e.g. cleanup the FIFOs. VG_(gdbserver_exit) (atid, status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig); } } exit_called = True; VG_(exit_now) (status); }
void VG_(gdbserver_prerun_action) (ThreadId tid) { // Using VG_(dyn_vgdb_error) allows the user to control if gdbserver // stops after a fork. if (VG_(dyn_vgdb_error) == 0 || VgdbStopAtiS(VgdbStopAt_Startup, VG_(clo_vgdb_stop_at))) { /* The below call allows gdb to attach at startup before the first guest instruction is executed. */ VG_(umsg)("(action at startup) vgdb me ... \n"); VG_(gdbserver)(tid); } else { /* User has activated gdbserver => initialize now the FIFOs to let vgdb/gdb contact us either via the scheduler poll mechanism or via vgdb ptrace-ing valgrind. */ if (VG_(gdbserver_activity) (tid)) VG_(gdbserver) (tid); } }
Bool VG_(gdbserver_stop_at) (VgdbStopAt stopat) { return gdbserver_called > 0 && VgdbStopAtiS(stopat, VG_(clo_vgdb_stop_at)); }