xref: /linux/kernel/debug/kdb/kdb_bt.c (revision b77dbc86)
15d5314d6SJason Wessel /*
25d5314d6SJason Wessel  * Kernel Debugger Architecture Independent Stack Traceback
35d5314d6SJason Wessel  *
45d5314d6SJason Wessel  * This file is subject to the terms and conditions of the GNU General Public
55d5314d6SJason Wessel  * License.  See the file "COPYING" in the main directory of this archive
65d5314d6SJason Wessel  * for more details.
75d5314d6SJason Wessel  *
85d5314d6SJason Wessel  * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
95d5314d6SJason Wessel  * Copyright (c) 2009 Wind River Systems, Inc.  All Rights Reserved.
105d5314d6SJason Wessel  */
115d5314d6SJason Wessel 
125d5314d6SJason Wessel #include <linux/ctype.h>
135d5314d6SJason Wessel #include <linux/string.h>
145d5314d6SJason Wessel #include <linux/kernel.h>
153f07c014SIngo Molnar #include <linux/sched/signal.h>
16b17b0153SIngo Molnar #include <linux/sched/debug.h>
175d5314d6SJason Wessel #include <linux/kdb.h>
185d5314d6SJason Wessel #include <linux/nmi.h>
195d5314d6SJason Wessel #include "kdb_private.h"
205d5314d6SJason Wessel 
215d5314d6SJason Wessel 
kdb_show_stack(struct task_struct * p,void * addr)225d5314d6SJason Wessel static void kdb_show_stack(struct task_struct *p, void *addr)
235d5314d6SJason Wessel {
2477819dafSDmitry Safonov 	kdb_trap_printk++;
2577819dafSDmitry Safonov 
2677819dafSDmitry Safonov 	if (!addr && kdb_task_has_cpu(p)) {
275d5314d6SJason Wessel 		int old_lvl = console_loglevel;
282277b492SDouglas Anderson 
29a8fe19ebSBorislav Petkov 		console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
302277b492SDouglas Anderson 		kdb_dump_stack_on_cpu(kdb_process_cpu(p));
315d5314d6SJason Wessel 		console_loglevel = old_lvl;
3277819dafSDmitry Safonov 	} else {
339cb8f069SDmitry Safonov 		show_stack(p, addr, KERN_EMERG);
3477819dafSDmitry Safonov 	}
3577819dafSDmitry Safonov 
36d37d39aeSJason Wessel 	kdb_trap_printk--;
375d5314d6SJason Wessel }
385d5314d6SJason Wessel 
395d5314d6SJason Wessel /*
405d5314d6SJason Wessel  * kdb_bt
415d5314d6SJason Wessel  *
425d5314d6SJason Wessel  *	This function implements the 'bt' command.  Print a stack
435d5314d6SJason Wessel  *	traceback.
445d5314d6SJason Wessel  *
455d5314d6SJason Wessel  *	bt [<address-expression>]	(addr-exp is for alternate stacks)
465d5314d6SJason Wessel  *	btp <pid>			Kernel stack for <pid>
475d5314d6SJason Wessel  *	btt <address-expression>	Kernel stack for task structure at
485d5314d6SJason Wessel  *					<address-expression>
49*b77dbc86SDaniel Thompson  *	bta [state_chars>|A]		All useful processes, optionally
505d5314d6SJason Wessel  *					filtered by state
515d5314d6SJason Wessel  *	btc [<cpu>]			The current process on one cpu,
525d5314d6SJason Wessel  *					default is all cpus
535d5314d6SJason Wessel  *
545d5314d6SJason Wessel  *	bt <address-expression> refers to a address on the stack, that location
555d5314d6SJason Wessel  *	is assumed to contain a return address.
565d5314d6SJason Wessel  *
575d5314d6SJason Wessel  *	btt <address-expression> refers to the address of a struct task.
585d5314d6SJason Wessel  *
595d5314d6SJason Wessel  * Inputs:
605d5314d6SJason Wessel  *	argc	argument count
615d5314d6SJason Wessel  *	argv	argument vector
625d5314d6SJason Wessel  * Outputs:
635d5314d6SJason Wessel  *	None.
645d5314d6SJason Wessel  * Returns:
655d5314d6SJason Wessel  *	zero for success, a kdb diagnostic if error
665d5314d6SJason Wessel  * Locking:
675d5314d6SJason Wessel  *	none.
685d5314d6SJason Wessel  * Remarks:
695d5314d6SJason Wessel  *	Backtrack works best when the code uses frame pointers.  But even
705d5314d6SJason Wessel  *	without frame pointers we should get a reasonable trace.
715d5314d6SJason Wessel  *
725d5314d6SJason Wessel  *	mds comes in handy when examining the stack to do a manual traceback or
735d5314d6SJason Wessel  *	to get a starting point for bt <address-expression>.
745d5314d6SJason Wessel  */
755d5314d6SJason Wessel 
765d5314d6SJason Wessel static int
kdb_bt1(struct task_struct * p,const char * mask,bool btaprompt)77*b77dbc86SDaniel Thompson kdb_bt1(struct task_struct *p, const char *mask, bool btaprompt)
785d5314d6SJason Wessel {
794f27e824SDaniel Thompson 	char ch;
804f27e824SDaniel Thompson 
814f27e824SDaniel Thompson 	if (kdb_getarea(ch, (unsigned long)p) ||
824f27e824SDaniel Thompson 	    kdb_getarea(ch, (unsigned long)(p+1)-1))
835d5314d6SJason Wessel 		return KDB_BADADDR;
845d5314d6SJason Wessel 	if (!kdb_task_state(p, mask))
855d5314d6SJason Wessel 		return 0;
865d5314d6SJason Wessel 	kdb_printf("Stack traceback for pid %d\n", p->pid);
875d5314d6SJason Wessel 	kdb_ps1(p);
885d5314d6SJason Wessel 	kdb_show_stack(p, NULL);
895d5314d6SJason Wessel 	if (btaprompt) {
904f27e824SDaniel Thompson 		kdb_printf("Enter <q> to end, <cr> or <space> to continue:");
914f27e824SDaniel Thompson 		do {
924f27e824SDaniel Thompson 			ch = kdb_getchar();
934f27e824SDaniel Thompson 		} while (!strchr("\r\n q", ch));
945d5314d6SJason Wessel 		kdb_printf("\n");
954f27e824SDaniel Thompson 
964f27e824SDaniel Thompson 		/* reset the pager */
974f27e824SDaniel Thompson 		kdb_nextline = 1;
984f27e824SDaniel Thompson 
994f27e824SDaniel Thompson 		if (ch == 'q')
1005d5314d6SJason Wessel 			return 1;
1015d5314d6SJason Wessel 	}
1025d5314d6SJason Wessel 	touch_nmi_watchdog();
1035d5314d6SJason Wessel 	return 0;
1045d5314d6SJason Wessel }
1055d5314d6SJason Wessel 
10655a7e23fSDouglas Anderson static void
kdb_bt_cpu(unsigned long cpu)10755a7e23fSDouglas Anderson kdb_bt_cpu(unsigned long cpu)
10855a7e23fSDouglas Anderson {
10955a7e23fSDouglas Anderson 	struct task_struct *kdb_tsk;
11055a7e23fSDouglas Anderson 
11155a7e23fSDouglas Anderson 	if (cpu >= num_possible_cpus() || !cpu_online(cpu)) {
11255a7e23fSDouglas Anderson 		kdb_printf("WARNING: no process for cpu %ld\n", cpu);
11355a7e23fSDouglas Anderson 		return;
11455a7e23fSDouglas Anderson 	}
11555a7e23fSDouglas Anderson 
11655a7e23fSDouglas Anderson 	/* If a CPU failed to round up we could be here */
11755a7e23fSDouglas Anderson 	kdb_tsk = KDB_TSK(cpu);
11855a7e23fSDouglas Anderson 	if (!kdb_tsk) {
11955a7e23fSDouglas Anderson 		kdb_printf("WARNING: no task for cpu %ld\n", cpu);
12055a7e23fSDouglas Anderson 		return;
12155a7e23fSDouglas Anderson 	}
12255a7e23fSDouglas Anderson 
123*b77dbc86SDaniel Thompson 	kdb_bt1(kdb_tsk, "A", false);
12455a7e23fSDouglas Anderson }
12555a7e23fSDouglas Anderson 
1265d5314d6SJason Wessel int
kdb_bt(int argc,const char ** argv)1275d5314d6SJason Wessel kdb_bt(int argc, const char **argv)
1285d5314d6SJason Wessel {
1295d5314d6SJason Wessel 	int diag;
1305d5314d6SJason Wessel 	int btaprompt = 1;
1315d5314d6SJason Wessel 	int nextarg;
1325d5314d6SJason Wessel 	unsigned long addr;
1335d5314d6SJason Wessel 	long offset;
1345d5314d6SJason Wessel 
1353bdb65ecSJason Wessel 	/* Prompt after each proc in bta */
1363bdb65ecSJason Wessel 	kdbgetintenv("BTAPROMPT", &btaprompt);
1375d5314d6SJason Wessel 
1385d5314d6SJason Wessel 	if (strcmp(argv[0], "bta") == 0) {
1395d5314d6SJason Wessel 		struct task_struct *g, *p;
1405d5314d6SJason Wessel 		unsigned long cpu;
141*b77dbc86SDaniel Thompson 		const char *mask = argc ? argv[1] : kdbgetenv("PS");
142*b77dbc86SDaniel Thompson 
1435d5314d6SJason Wessel 		if (argc == 0)
1445d5314d6SJason Wessel 			kdb_ps_suppressed();
1455d5314d6SJason Wessel 		/* Run the active tasks first */
1465d5314d6SJason Wessel 		for_each_online_cpu(cpu) {
1475d5314d6SJason Wessel 			p = kdb_curr_task(cpu);
14854af3e39SDouglas Anderson 			if (kdb_bt1(p, mask, btaprompt))
1495d5314d6SJason Wessel 				return 0;
1505d5314d6SJason Wessel 		}
1515d5314d6SJason Wessel 		/* Now the inactive tasks */
152ece4ceafSDavidlohr Bueso 		for_each_process_thread(g, p) {
153d1871b38SJason Wessel 			if (KDB_FLAG(CMD_INTERRUPT))
154d1871b38SJason Wessel 				return 0;
1555d5314d6SJason Wessel 			if (task_curr(p))
1565d5314d6SJason Wessel 				continue;
15754af3e39SDouglas Anderson 			if (kdb_bt1(p, mask, btaprompt))
1585d5314d6SJason Wessel 				return 0;
159ece4ceafSDavidlohr Bueso 		}
1605d5314d6SJason Wessel 	} else if (strcmp(argv[0], "btp") == 0) {
1615d5314d6SJason Wessel 		struct task_struct *p;
1625d5314d6SJason Wessel 		unsigned long pid;
1635d5314d6SJason Wessel 		if (argc != 1)
1645d5314d6SJason Wessel 			return KDB_ARGCOUNT;
1655d5314d6SJason Wessel 		diag = kdbgetularg((char *)argv[1], &pid);
1665d5314d6SJason Wessel 		if (diag)
1675d5314d6SJason Wessel 			return diag;
1685d5314d6SJason Wessel 		p = find_task_by_pid_ns(pid, &init_pid_ns);
1699441d5f6SDouglas Anderson 		if (p)
170*b77dbc86SDaniel Thompson 			return kdb_bt1(p, "A", false);
1715d5314d6SJason Wessel 		kdb_printf("No process with pid == %ld found\n", pid);
1725d5314d6SJason Wessel 		return 0;
1735d5314d6SJason Wessel 	} else if (strcmp(argv[0], "btt") == 0) {
1745d5314d6SJason Wessel 		if (argc != 1)
1755d5314d6SJason Wessel 			return KDB_ARGCOUNT;
1765d5314d6SJason Wessel 		diag = kdbgetularg((char *)argv[1], &addr);
1775d5314d6SJason Wessel 		if (diag)
1785d5314d6SJason Wessel 			return diag;
179*b77dbc86SDaniel Thompson 		return kdb_bt1((struct task_struct *)addr, "A", false);
1805d5314d6SJason Wessel 	} else if (strcmp(argv[0], "btc") == 0) {
1815d5314d6SJason Wessel 		unsigned long cpu = ~0;
1825d5314d6SJason Wessel 		if (argc > 1)
1835d5314d6SJason Wessel 			return KDB_ARGCOUNT;
1845d5314d6SJason Wessel 		if (argc == 1) {
1855d5314d6SJason Wessel 			diag = kdbgetularg((char *)argv[1], &cpu);
1865d5314d6SJason Wessel 			if (diag)
1875d5314d6SJason Wessel 				return diag;
1885d5314d6SJason Wessel 		}
1895d5314d6SJason Wessel 		if (cpu != ~0) {
19055a7e23fSDouglas Anderson 			kdb_bt_cpu(cpu);
19155a7e23fSDouglas Anderson 		} else {
19255a7e23fSDouglas Anderson 			/*
19355a7e23fSDouglas Anderson 			 * Recursive use of kdb_parse, do not use argv after
19455a7e23fSDouglas Anderson 			 * this point.
19555a7e23fSDouglas Anderson 			 */
19655a7e23fSDouglas Anderson 			argv = NULL;
1975d5314d6SJason Wessel 			kdb_printf("btc: cpu status: ");
1985d5314d6SJason Wessel 			kdb_parse("cpu\n");
1995d5314d6SJason Wessel 			for_each_online_cpu(cpu) {
20055a7e23fSDouglas Anderson 				kdb_bt_cpu(cpu);
2015d5314d6SJason Wessel 				touch_nmi_watchdog();
2025d5314d6SJason Wessel 			}
20355a7e23fSDouglas Anderson 		}
2045d5314d6SJason Wessel 		return 0;
2055d5314d6SJason Wessel 	} else {
2065d5314d6SJason Wessel 		if (argc) {
2075d5314d6SJason Wessel 			nextarg = 1;
2085d5314d6SJason Wessel 			diag = kdbgetaddrarg(argc, argv, &nextarg, &addr,
2095d5314d6SJason Wessel 					     &offset, NULL);
2105d5314d6SJason Wessel 			if (diag)
2115d5314d6SJason Wessel 				return diag;
2125d5314d6SJason Wessel 			kdb_show_stack(kdb_current_task, (void *)addr);
2135d5314d6SJason Wessel 			return 0;
2145d5314d6SJason Wessel 		} else {
215*b77dbc86SDaniel Thompson 			return kdb_bt1(kdb_current_task, "A", false);
2165d5314d6SJason Wessel 		}
2175d5314d6SJason Wessel 	}
2185d5314d6SJason Wessel 
2195d5314d6SJason Wessel 	/* NOTREACHED */
2205d5314d6SJason Wessel 	return 0;
2215d5314d6SJason Wessel }
222