ulong_t handle_exception(ulong_t sigcode, CPU_REGISTERS *ctx, struct kdebug_entry *entry) { #ifdef DEBUG_GDB kprintf("Enter KDB exception: Sigcode = %x (EIP=%x)\n", (unsigned)sigcode, ctx->eip); #endif if(!is_watch_entry(entry, ctx->eip) && !WANT_FAULT(sigcode)) { #ifdef DEBUG_GDB kprintf("Skip KDB exception: return %x\n", (unsigned)sigcode); #endif return sigcode; } ctx->efl &= ~X86_PSW_TF; restore_break(); /* * Goto GDB command interpreter. */ gdb_interface(entry, ctx, sigcode); #ifdef DEBUG_GDB kprintf("Leave KDB exception: return 0\n"); #endif return (0); }
/* * Quickest way to gdb -- just pass a command string to pass through. */ int gdb_pass_through(char *cmd, FILE *fptr, ulong flags) { struct gnu_request *req; int retval; if (CRASHDEBUG(1)) console("gdb_pass_through: [%s]\n", cmd); req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request)); req->buf = cmd; if (fptr) req->fp = fptr; req->command = GNU_PASS_THROUGH; req->flags = flags; gdb_interface(req); if ((req->flags & (GNU_RETURN_ON_ERROR|GNU_COMMAND_FAILED)) == (GNU_RETURN_ON_ERROR|GNU_COMMAND_FAILED)) retval = FALSE; else retval = TRUE; FREEBUF(req); return retval; }
/* * Check whether string in args[0] is a valid gdb command. */ int is_gdb_command(int merge_orig_args, ulong flags) { int retval; struct gnu_request *req; if (!args[0]) return FALSE; if (STREQ(args[0], "Q")) { args[0] = "q"; return TRUE; } if (is_restricted_command(args[0], flags)) return FALSE; req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request)); req->buf = GETBUF(strlen(args[0])+1); req->command = GNU_COMMAND_EXISTS; req->name = args[0]; req->flags = GNU_RETURN_ON_ERROR; req->fp = pc->nullfp; gdb_interface(req); if (req->flags & GNU_COMMAND_FAILED) retval = FALSE; else retval = req->value; FREEBUF(req->buf); FREEBUF(req); if (retval && merge_orig_args) { int i; for (i = argcnt; i; i--) args[i] = args[i-1]; args[0] = "gdb"; argcnt++; } return retval; }
void gdb_session_init(void) { struct gnu_request *req; int debug_data_pulled_in; if (!have_partial_symbols() && !have_full_symbols()) no_debugging_data(FATAL); /* * Restore the SIGINT and SIGPIPE handlers, which got temporarily * re-assigned by gdb. The SIGINT call also initializes GDB's * SIGINT sigaction. */ SIGACTION(SIGINT, restart, &pc->sigaction, &pc->gdb_sigaction); SIGACTION(SIGPIPE, SIG_IGN, &pc->sigaction, NULL); if (!(pc->flags & DROP_CORE)) SIGACTION(SIGSEGV, restart, &pc->sigaction, NULL); /* * Set up pointers to gdb variables. */ #if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1) gdb_output_format = &output_format; gdb_print_max = &print_max; gdb_prettyprint_structs = &prettyprint_structs; gdb_prettyprint_arrays = &prettyprint_arrays; gdb_repeat_count_threshold = &repeat_count_threshold; gdb_stop_print_at_null = &stop_print_at_null; gdb_output_radix = &output_radix; #else gdb_output_format = (int *) gdb_user_print_option_address("output_format"); gdb_print_max = (unsigned int *) gdb_user_print_option_address("print_max"); gdb_prettyprint_structs = (int *) gdb_user_print_option_address("prettyprint_structs"); gdb_prettyprint_arrays = (int *) gdb_user_print_option_address("prettyprint_arrays"); gdb_repeat_count_threshold = (int *) gdb_user_print_option_address("repeat_count_threshold"); gdb_stop_print_at_null = (int *) gdb_user_print_option_address("stop_print_at_null"); gdb_output_radix = (unsigned int *) gdb_user_print_option_address("output_radix"); #endif /* * If the output radix is set via the --hex or --dec command line * option, then pc->output_radix will be non-zero; otherwise use * the gdb default. */ if (pc->output_radix) { *gdb_output_radix = pc->output_radix; *gdb_output_format = (*gdb_output_radix == 10) ? 0 : 'x'; } switch (*gdb_output_radix) { case 10: case 16: pc->output_radix = *gdb_output_radix; break; default: pc->output_radix = *gdb_output_radix = 10; *gdb_output_format = 0; } *gdb_prettyprint_structs = 1; *gdb_repeat_count_threshold = 0x7fffffff; *gdb_print_max = 256; #ifdef GDB_5_3 gdb_disassemble_from_exec = 0; #endif pc->flags |= GDB_INIT; /* set here so gdb_interface will work */ req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request)); req->buf = GETBUF(BUFSIZE); /* * Make sure the namelist has symbolic data. Later versions of * gcc may require that debug data be pulled in by printing a * static kernel data structure. */ debug_data_pulled_in = FALSE; retry: BZERO(req->buf, BUFSIZE); req->command = GNU_GET_DATATYPE; req->name = XEN_HYPER_MODE() ? "page_info" : "task_struct"; req->flags = GNU_RETURN_ON_ERROR; gdb_interface(req); if (req->flags & GNU_COMMAND_FAILED) { if (XEN_HYPER_MODE()) no_debugging_data(WARNING); /* just bail out */ if (!debug_data_pulled_in) { if (CRASHDEBUG(1)) error(INFO, "gdb_session_init: pulling in debug data by accessing init_mm.mmap %s\n", symbol_exists("sysfs_mount") ? "and syfs_mount" : ""); debug_data_pulled_in = TRUE; req->command = GNU_PASS_THROUGH; req->flags = GNU_RETURN_ON_ERROR|GNU_NO_READMEM; req->name = NULL; if (symbol_exists("sysfs_mount")) sprintf(req->buf, "print sysfs_mount, init_mm.mmap"); else sprintf(req->buf, "print init_mm.mmap"); gdb_interface(req); if (!(req->flags & GNU_COMMAND_FAILED)) goto retry; } no_debugging_data(WARNING); } if (pc->flags & KERNEL_DEBUG_QUERY) { fprintf(fp, "\n%s: %s: contains debugging data\n\n", pc->program_name, pc->namelist); if (REMOTE()) remote_exit(); clean_exit(0); } /* * Set up any pre-ordained gdb settings here that can't be * accessed directly. */ req->command = GNU_PASS_THROUGH; req->name = NULL, req->flags = 0; sprintf(req->buf, "set height 0"); gdb_interface(req); req->command = GNU_PASS_THROUGH; req->name = NULL, req->flags = 0; sprintf(req->buf, "set width 0"); gdb_interface(req); /* * Patch gdb's symbol values with the correct values from either * the System.map or non-debug vmlinux, whichever is in effect. */ if ((pc->flags & SYSMAP) || (kt->flags & (RELOC_SET|RELOC_FORCE)) || (pc->namelist_debug && !pc->debuginfo_file)) { req->command = GNU_PATCH_SYMBOL_VALUES; req->flags = GNU_RETURN_ON_ERROR; gdb_interface(req); if (req->flags & GNU_COMMAND_FAILED) error(FATAL, "patching of gdb symbol values failed\n"); } else if (!(pc->flags & SILENT)) fprintf(fp, "\n"); FREEBUF(req->buf); FREEBUF(req); }