/******************************************************** * debug_me -- A module to start the debugger from * * a running proram. * * * * Debugging can be started by: * * a) a debug_me call * * b) a failed assertion * * * * Warning: This code is Linux specific. * ********************************************************/ #include #include #include #include #include "debug_me.h" static int in_gdb = 0; // True if gdb started /******************************************************** * gdb_stop -- A place to stop the debugger * * * * Note: This is not static so that the debugger can * * easily find it. * ********************************************************/ void gdb_stop(void) { printf("Gdb stop\n");fflush(stdout); } /******************************************************** * start_debugger -- Actually start the debugger * ********************************************************/ static void start_debugger(void) { int pid = getpid(); // Our PID char gdb_file_name[MAXPATHLEN]; // The name of the gdb file char flag_file[MAXPATHLEN]; // File that's used as a flag // to signal that gdb is running // FILE *gdb_file; // The file with the gdb information in it char cmd[MAXPATHLEN+100]; // Command to start xterm if (in_gdb) return; /* Prevent double debugs */ /* * Create a command file that contains * attach # Attaches to the process * echo .... # Echos a welcome message * symbol /proc//exe * # Loads the symbol table * break gdb_stop # Set a breakpoint in * shell touch /tmp/gdb.flag. * # Create a file that tells us * # that the debugger is running * continue # Continue the program */ sprintf(gdb_file_name, "/tmp/gdb.%d", pid); gdb_file = fopen(gdb_file_name, "w"); if (gdb_file == NULL) { fprintf(stderr, "ERROR: Unable to open %s\n", gdb_file_name); abort(); } sprintf(flag_file, "/tmp/gdb.flag.%d", pid); fprintf(gdb_file, "attach %d\n", pid); fprintf(gdb_file, "echo \"Assert failed. Debugger gdb started\\n\"\n"); fprintf(gdb_file, "symbol /proc/%d/exe\n", pid); fprintf(gdb_file, "break gdb_stop\n"); fprintf(gdb_file, "shell touch %s\n", flag_file); fprintf(gdb_file, "continue\n"); fclose(gdb_file); /* Start a xterm window with the debugger in it */ sprintf(cmd, "xterm -fg red -e gdb --command=%s &", gdb_file_name); system(cmd); /* Now sleep until the debugger starts and * creates the flag file */ while (access(flag_file, F_OK) != 0) { sleep (1); } in_gdb = 1; gdb_stop(); } /******************************************************** * debug_me -- Start the debugger * ********************************************************/ void debug_me(void) { start_debugger(); gdb_stop(); } /******************************************************** * __assert_fail -- Called when an assert fails. * * Starts the debugger. * * * * Note: gcc specific. Different compilers use * * different internal routines to handle bad * * asserts. * ********************************************************/ void __assert_fail( const char *const what, const char *const file, const int line, const char *const funct ) { printf("Assert failed: %s\n", what); printf("FAILURE at: %s:%d\n", file, line); printf("Function is %s\n", funct); debug_me(); abort(); }