diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/debug/debug_core.h | 2 | ||||
| -rw-r--r-- | kernel/debug/gdbstub.c | 3 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_bp.c | 20 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_debugger.c | 25 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_main.c | 135 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_private.h | 4 | 
6 files changed, 62 insertions, 127 deletions
diff --git a/kernel/debug/debug_core.h b/kernel/debug/debug_core.h index 3494c28a7e7..2235967e78b 100644 --- a/kernel/debug/debug_core.h +++ b/kernel/debug/debug_core.h @@ -72,6 +72,8 @@ extern int dbg_kdb_mode;  #ifdef CONFIG_KGDB_KDB  extern int kdb_stub(struct kgdb_state *ks);  extern int kdb_parse(const char *cmdstr); +extern int kdb_common_init_state(struct kgdb_state *ks); +extern int kdb_common_deinit_state(void);  #else /* ! CONFIG_KGDB_KDB */  static inline int kdb_stub(struct kgdb_state *ks)  { diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 38573f35a5a..19d9a578c75 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c @@ -783,7 +783,10 @@ static void gdb_cmd_query(struct kgdb_state *ks)  			len = len / 2;  			remcom_out_buffer[len++] = 0; +			kdb_common_init_state(ks);  			kdb_parse(remcom_out_buffer); +			kdb_common_deinit_state(); +  			strcpy(remcom_out_buffer, "OK");  		}  		break; diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c index 8418c2f8ec5..70a504601dc 100644 --- a/kernel/debug/kdb/kdb_bp.c +++ b/kernel/debug/kdb/kdb_bp.c @@ -486,11 +486,9 @@ static int kdb_bc(int argc, const char **argv)  /*   * kdb_ss   * - *	Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch) - *	commands. + *	Process the 'ss' (Single Step) command.   *   *	ss - *	ssb   *   * Parameters:   *	argc	Argument count @@ -498,35 +496,23 @@ static int kdb_bc(int argc, const char **argv)   * Outputs:   *	None.   * Returns: - *	KDB_CMD_SS[B] for success, a kdb error if failure. + *	KDB_CMD_SS for success, a kdb error if failure.   * Locking:   *	None.   * Remarks:   *   *	Set the arch specific option to trigger a debug trap after the next   *	instruction. - * - *	For 'ssb', set the trace flag in the debug trap handler - *	after printing the current insn and return directly without - *	invoking the kdb command processor, until a branch instruction - *	is encountered.   */  static int kdb_ss(int argc, const char **argv)  { -	int ssb = 0; - -	ssb = (strcmp(argv[0], "ssb") == 0);  	if (argc != 0)  		return KDB_ARGCOUNT;  	/*  	 * Set trace flag and go.  	 */  	KDB_STATE_SET(DOING_SS); -	if (ssb) { -		KDB_STATE_SET(DOING_SSB); -		return KDB_CMD_SSB; -	}  	return KDB_CMD_SS;  } @@ -561,8 +547,6 @@ void __init kdb_initbptab(void)  	kdb_register_repeat("ss", kdb_ss, "",  		"Single Step", 1, KDB_REPEAT_NO_ARGS); -	kdb_register_repeat("ssb", kdb_ss, "", -		"Single step to branch/call", 0, KDB_REPEAT_NO_ARGS);  	/*  	 * Architecture dependent initialization.  	 */ diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c index be7b33b73d3..328d18ef31e 100644 --- a/kernel/debug/kdb/kdb_debugger.c +++ b/kernel/debug/kdb/kdb_debugger.c @@ -34,6 +34,22 @@ EXPORT_SYMBOL_GPL(kdb_poll_idx);  static struct kgdb_state *kdb_ks; +int kdb_common_init_state(struct kgdb_state *ks) +{ +	kdb_initial_cpu = atomic_read(&kgdb_active); +	kdb_current_task = kgdb_info[ks->cpu].task; +	kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo; +	return 0; +} + +int kdb_common_deinit_state(void) +{ +	kdb_initial_cpu = -1; +	kdb_current_task = NULL; +	kdb_current_regs = NULL; +	return 0; +} +  int kdb_stub(struct kgdb_state *ks)  {  	int error = 0; @@ -94,13 +110,10 @@ int kdb_stub(struct kgdb_state *ks)  	}  	/* Set initial kdb state variables */  	KDB_STATE_CLEAR(KGDB_TRANS); -	kdb_initial_cpu = atomic_read(&kgdb_active); -	kdb_current_task = kgdb_info[ks->cpu].task; -	kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo; +	kdb_common_init_state(ks);  	/* Remove any breakpoints as needed by kdb and clear single step */  	kdb_bp_remove();  	KDB_STATE_CLEAR(DOING_SS); -	KDB_STATE_CLEAR(DOING_SSB);  	KDB_STATE_SET(PAGER);  	/* zero out any offline cpu data */  	for_each_present_cpu(i) { @@ -125,9 +138,7 @@ int kdb_stub(struct kgdb_state *ks)  	 * Upon exit from the kdb main loop setup break points and restart  	 * the system based on the requested continue state  	 */ -	kdb_initial_cpu = -1; -	kdb_current_task = NULL; -	kdb_current_regs = NULL; +	kdb_common_deinit_state();  	KDB_STATE_CLEAR(PAGER);  	kdbnearsym_cleanup();  	if (error == KDB_CMD_KGDB) { diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 8875254120b..00eb8f7fbf4 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -124,7 +124,7 @@ static kdbmsg_t kdbmsgs[] = {  };  #undef KDBMSG -static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t); +static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);  /* @@ -175,7 +175,7 @@ static char *__env[] = {   (char *)0,  }; -static const int __nenv = (sizeof(__env) / sizeof(char *)); +static const int __nenv = ARRAY_SIZE(__env);  struct task_struct *kdb_curr_task(int cpu)  { @@ -681,34 +681,50 @@ static int kdb_defcmd(int argc, const char **argv)  	}  	if (argc != 3)  		return KDB_ARGCOUNT; -	defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), -			     GFP_KDB); -	if (!defcmd_set) { -		kdb_printf("Could not allocate new defcmd_set entry for %s\n", -			   argv[1]); -		defcmd_set = save_defcmd_set; +	if (in_dbg_master()) { +		kdb_printf("Command only available during kdb_init()\n");  		return KDB_NOTIMP;  	} +	defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), +			     GFP_KDB); +	if (!defcmd_set) +		goto fail_defcmd;  	memcpy(defcmd_set, save_defcmd_set,  	       defcmd_set_count * sizeof(*defcmd_set)); -	kfree(save_defcmd_set);  	s = defcmd_set + defcmd_set_count;  	memset(s, 0, sizeof(*s));  	s->usable = 1;  	s->name = kdb_strdup(argv[1], GFP_KDB); +	if (!s->name) +		goto fail_name;  	s->usage = kdb_strdup(argv[2], GFP_KDB); +	if (!s->usage) +		goto fail_usage;  	s->help = kdb_strdup(argv[3], GFP_KDB); +	if (!s->help) +		goto fail_help;  	if (s->usage[0] == '"') { -		strcpy(s->usage, s->usage+1); +		strcpy(s->usage, argv[2]+1);  		s->usage[strlen(s->usage)-1] = '\0';  	}  	if (s->help[0] == '"') { -		strcpy(s->help, s->help+1); +		strcpy(s->help, argv[3]+1);  		s->help[strlen(s->help)-1] = '\0';  	}  	++defcmd_set_count;  	defcmd_in_progress = 1; +	kfree(save_defcmd_set);  	return 0; +fail_help: +	kfree(s->usage); +fail_usage: +	kfree(s->name); +fail_name: +	kfree(defcmd_set); +fail_defcmd: +	kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]); +	defcmd_set = save_defcmd_set; +	return KDB_NOTIMP;  }  /* @@ -1112,7 +1128,6 @@ void kdb_set_current_task(struct task_struct *p)   *	KDB_CMD_GO	User typed 'go'.   *	KDB_CMD_CPU	User switched to another cpu.   *	KDB_CMD_SS	Single step. - *	KDB_CMD_SSB	Single step until branch.   */  static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,  		     kdb_dbtrap_t db_result) @@ -1151,14 +1166,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,  			kdb_printf("due to Debug @ " kdb_machreg_fmt "\n",  				   instruction_pointer(regs));  			break; -		case KDB_DB_SSB: -			/* -			 * In the midst of ssb command. Just return. -			 */ -			KDB_DEBUG_STATE("kdb_local 3", reason); -			return KDB_CMD_SSB;	/* Continue with SSB command */ - -			break;  		case KDB_DB_SS:  			break;  		case KDB_DB_SSBPT: @@ -1281,7 +1288,6 @@ do_full_getstr:  		if (diag == KDB_CMD_GO  		 || diag == KDB_CMD_CPU  		 || diag == KDB_CMD_SS -		 || diag == KDB_CMD_SSB  		 || diag == KDB_CMD_KGDB)  			break; @@ -1368,12 +1374,6 @@ int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,  			break;  		} -		if (result == KDB_CMD_SSB) { -			KDB_STATE_SET(DOING_SS); -			KDB_STATE_SET(DOING_SSB); -			break; -		} -  		if (result == KDB_CMD_KGDB) {  			if (!KDB_STATE(DOING_KGDB))  				kdb_printf("Entering please attach debugger " @@ -2350,69 +2350,6 @@ static int kdb_pid(int argc, const char **argv)  	return 0;  } -/* - * kdb_ll - This function implements the 'll' command which follows a - *	linked list and executes an arbitrary command for each - *	element. - */ -static int kdb_ll(int argc, const char **argv) -{ -	int diag = 0; -	unsigned long addr; -	long offset = 0; -	unsigned long va; -	unsigned long linkoffset; -	int nextarg; -	const char *command; - -	if (argc != 3) -		return KDB_ARGCOUNT; - -	nextarg = 1; -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL); -	if (diag) -		return diag; - -	diag = kdbgetularg(argv[2], &linkoffset); -	if (diag) -		return diag; - -	/* -	 * Using the starting address as -	 * the first element in the list, and assuming that -	 * the list ends with a null pointer. -	 */ - -	va = addr; -	command = kdb_strdup(argv[3], GFP_KDB); -	if (!command) { -		kdb_printf("%s: cannot duplicate command\n", __func__); -		return 0; -	} -	/* Recursive use of kdb_parse, do not use argv after this point */ -	argv = NULL; - -	while (va) { -		char buf[80]; - -		if (KDB_FLAG(CMD_INTERRUPT)) -			goto out; - -		sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va); -		diag = kdb_parse(buf); -		if (diag) -			goto out; - -		addr = va + linkoffset; -		if (kdb_getword(&va, addr, sizeof(va))) -			goto out; -	} - -out: -	kfree(command); -	return diag; -} -  static int kdb_kgdb(int argc, const char **argv)  {  	return KDB_CMD_KGDB; @@ -2430,11 +2367,15 @@ static int kdb_help(int argc, const char **argv)  	kdb_printf("-----------------------------"  		   "-----------------------------\n");  	for_each_kdbcmd(kt, i) { -		if (kt->cmd_name) -			kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name, -				   kt->cmd_usage, kt->cmd_help); +		char *space = "";  		if (KDB_FLAG(CMD_INTERRUPT))  			return 0; +		if (!kt->cmd_name) +			continue; +		if (strlen(kt->cmd_usage) > 20) +			space = "\n                                    "; +		kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name, +			   kt->cmd_usage, space, kt->cmd_help);  	}  	return 0;  } @@ -2739,7 +2680,7 @@ int kdb_register_repeat(char *cmd,  			  (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));  			kfree(kdb_commands);  		} -		memset(new + kdb_max_commands, 0, +		memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,  		       kdb_command_extend * sizeof(*new));  		kdb_commands = new;  		kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX; @@ -2843,15 +2784,13 @@ static void __init kdb_inittab(void)  	  "Stack traceback", 1, KDB_REPEAT_NONE);  	kdb_register_repeat("btp", kdb_bt, "<pid>",  	  "Display stack for process <pid>", 0, KDB_REPEAT_NONE); -	kdb_register_repeat("bta", kdb_bt, "[DRSTCZEUIMA]", -	  "Display stack all processes", 0, KDB_REPEAT_NONE); +	kdb_register_repeat("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]", +	  "Backtrace all processes matching state flag", 0, KDB_REPEAT_NONE);  	kdb_register_repeat("btc", kdb_bt, "",  	  "Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);  	kdb_register_repeat("btt", kdb_bt, "<vaddr>",  	  "Backtrace process given its struct task address", 0,  			    KDB_REPEAT_NONE); -	kdb_register_repeat("ll", kdb_ll, "<first-element> <linkoffset> <cmd>", -	  "Execute cmd for each element in linked list", 0, KDB_REPEAT_NONE);  	kdb_register_repeat("env", kdb_env, "",  	  "Show environment variables", 0, KDB_REPEAT_NONE);  	kdb_register_repeat("set", kdb_set, "", diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 392ec6a2584..7afd3c8c41d 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -19,7 +19,6 @@  #define KDB_CMD_GO	(-1001)  #define KDB_CMD_CPU	(-1002)  #define KDB_CMD_SS	(-1003) -#define KDB_CMD_SSB	(-1004)  #define KDB_CMD_KGDB (-1005)  /* Internal debug flags */ @@ -125,8 +124,6 @@ extern int kdb_state;  						 * kdb control */  #define KDB_STATE_HOLD_CPU	0x00000010	/* Hold this cpu inside kdb */  #define KDB_STATE_DOING_SS	0x00000020	/* Doing ss command */ -#define KDB_STATE_DOING_SSB	0x00000040	/* Doing ssb command, -						 * DOING_SS is also set */  #define KDB_STATE_SSBPT		0x00000080	/* Install breakpoint  						 * after one ss, independent of  						 * DOING_SS */ @@ -191,7 +188,6 @@ extern void kdb_bp_remove(void);  typedef enum {  	KDB_DB_BPT,	/* Breakpoint */  	KDB_DB_SS,	/* Single-step trap */ -	KDB_DB_SSB,	/* Single step to branch */  	KDB_DB_SSBPT,	/* Single step over breakpoint */  	KDB_DB_NOBPT	/* Spurious breakpoint */  } kdb_dbtrap_t;  |