diff options
Diffstat (limited to 'kernel/debug/kdb/kdb_main.c')
| -rw-r--r-- | kernel/debug/kdb/kdb_main.c | 137 | 
1 files changed, 39 insertions, 98 deletions
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 4d5f8d5612f3..00eb8f7fbf41 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 " @@ -1970,6 +1970,8 @@ static int kdb_lsmod(int argc, const char **argv)  	kdb_printf("Module                  Size  modstruct     Used by\n");  	list_for_each_entry(mod, kdb_modules, list) { +		if (mod->state == MODULE_STATE_UNFORMED) +			continue;  		kdb_printf("%-20s%8u  0x%p ", mod->name,  			   mod->core_size, (void *)mod); @@ -2348,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; @@ -2428,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;  } @@ -2737,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; @@ -2841,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, "",  |