xref: /freebsd/sys/arm64/arm64/db_trace.c (revision 1c33a94ab06bb8274c8a50257a8b94e209a2e2ee)
1988b7f60SZbigniew Bodek /*-
2988b7f60SZbigniew Bodek  * Copyright (c) 2015 The FreeBSD Foundation
3988b7f60SZbigniew Bodek  *
4988b7f60SZbigniew Bodek  * This software was developed by Semihalf under
5988b7f60SZbigniew Bodek  * the sponsorship of the FreeBSD Foundation.
6988b7f60SZbigniew Bodek  *
7988b7f60SZbigniew Bodek  * Redistribution and use in source and binary forms, with or without
8988b7f60SZbigniew Bodek  * modification, are permitted provided that the following conditions
9988b7f60SZbigniew Bodek  * are met:
10988b7f60SZbigniew Bodek  * 1. Redistributions of source code must retain the above copyright
11988b7f60SZbigniew Bodek  *    notice, this list of conditions and the following disclaimer.
12988b7f60SZbigniew Bodek  * 2. Redistributions in binary form must reproduce the above copyright
13988b7f60SZbigniew Bodek  *    notice, this list of conditions and the following disclaimer in the
14988b7f60SZbigniew Bodek  *    documentation and/or other materials provided with the distribution.
15988b7f60SZbigniew Bodek  *
16988b7f60SZbigniew Bodek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17988b7f60SZbigniew Bodek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18988b7f60SZbigniew Bodek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19988b7f60SZbigniew Bodek  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20988b7f60SZbigniew Bodek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21988b7f60SZbigniew Bodek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22988b7f60SZbigniew Bodek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23988b7f60SZbigniew Bodek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24988b7f60SZbigniew Bodek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25988b7f60SZbigniew Bodek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26988b7f60SZbigniew Bodek  * SUCH DAMAGE.
27988b7f60SZbigniew Bodek  */
28988b7f60SZbigniew Bodek 
296de3c415SAndrew Turner #include "opt_ddb.h"
306de3c415SAndrew Turner 
31988b7f60SZbigniew Bodek #include <sys/cdefs.h>
32988b7f60SZbigniew Bodek __FBSDID("$FreeBSD$");
33988b7f60SZbigniew Bodek #include <sys/param.h>
34988b7f60SZbigniew Bodek #include <sys/proc.h>
35988b7f60SZbigniew Bodek #include <sys/kdb.h>
36a5d295e2SAndrew Turner 
37988b7f60SZbigniew Bodek #include <machine/pcb.h>
38988b7f60SZbigniew Bodek #include <ddb/ddb.h>
39988b7f60SZbigniew Bodek #include <ddb/db_sym.h>
40988b7f60SZbigniew Bodek 
41988b7f60SZbigniew Bodek #include <machine/armreg.h>
42988b7f60SZbigniew Bodek #include <machine/debug_monitor.h>
433f66bd50SRuslan Bukin #include <machine/stack.h>
4405985a7fSJessica Clarke #include <machine/vmparam.h>
4505985a7fSJessica Clarke 
4605985a7fSJessica Clarke #define	FRAME_NORMAL	0
4705985a7fSJessica Clarke #define	FRAME_SYNC	1
4805985a7fSJessica Clarke #define	FRAME_IRQ	2
4905985a7fSJessica Clarke #define	FRAME_SERROR	3
5005985a7fSJessica Clarke #define	FRAME_UNHANDLED	4
51988b7f60SZbigniew Bodek 
52988b7f60SZbigniew Bodek void
5394074089SDimitry Andric db_md_list_watchpoints(void)
54988b7f60SZbigniew Bodek {
55988b7f60SZbigniew Bodek 
56988b7f60SZbigniew Bodek 	dbg_show_watchpoint();
57988b7f60SZbigniew Bodek }
58988b7f60SZbigniew Bodek 
59988b7f60SZbigniew Bodek static void
60ae953968SJohn Baldwin db_stack_trace_cmd(struct thread *td, struct unwind_state *frame)
61988b7f60SZbigniew Bodek {
62988b7f60SZbigniew Bodek 	c_db_sym_t sym;
63988b7f60SZbigniew Bodek 	const char *name;
64988b7f60SZbigniew Bodek 	db_expr_t value;
65988b7f60SZbigniew Bodek 	db_expr_t offset;
6605985a7fSJessica Clarke 	int frame_type;
67988b7f60SZbigniew Bodek 
68988b7f60SZbigniew Bodek 	while (1) {
6905985a7fSJessica Clarke 		sym = db_search_symbol(frame->pc, DB_STGY_ANY, &offset);
70988b7f60SZbigniew Bodek 		if (sym == C_DB_SYM_NULL) {
71988b7f60SZbigniew Bodek 			value = 0;
72988b7f60SZbigniew Bodek 			name = "(null)";
73988b7f60SZbigniew Bodek 		} else
74988b7f60SZbigniew Bodek 			db_symbol_values(sym, &name, &value);
75988b7f60SZbigniew Bodek 
76988b7f60SZbigniew Bodek 		db_printf("%s() at ", name);
77988b7f60SZbigniew Bodek 		db_printsym(frame->pc, DB_STGY_PROC);
78988b7f60SZbigniew Bodek 		db_printf("\n");
79988b7f60SZbigniew Bodek 
8005985a7fSJessica Clarke 		if (strcmp(name, "handle_el0_sync") == 0 ||
8105985a7fSJessica Clarke 		    strcmp(name, "handle_el1h_sync") == 0)
8205985a7fSJessica Clarke 			frame_type = FRAME_SYNC;
8305985a7fSJessica Clarke 		else if (strcmp(name, "handle_el0_irq") == 0 ||
8405985a7fSJessica Clarke 		     strcmp(name, "handle_el1h_irq") == 0)
8505985a7fSJessica Clarke 			frame_type = FRAME_IRQ;
8605985a7fSJessica Clarke 		else if (strcmp(name, "handle_serror") == 0)
8705985a7fSJessica Clarke 			frame_type = FRAME_SERROR;
8805985a7fSJessica Clarke 		else if (strcmp(name, "handle_empty_exception") == 0)
8905985a7fSJessica Clarke 			frame_type = FRAME_UNHANDLED;
9005985a7fSJessica Clarke 		else
9105985a7fSJessica Clarke 			frame_type = FRAME_NORMAL;
9205985a7fSJessica Clarke 
9305985a7fSJessica Clarke 		if (frame_type != FRAME_NORMAL) {
9405985a7fSJessica Clarke 			struct trapframe *tf;
9505985a7fSJessica Clarke 
9605985a7fSJessica Clarke 			tf = (struct trapframe *)(uintptr_t)frame->fp - 1;
9705985a7fSJessica Clarke 			if (!kstack_contains(td, (vm_offset_t)tf,
9805985a7fSJessica Clarke 			    sizeof(*tf))) {
9905985a7fSJessica Clarke 				db_printf("--- invalid trapframe %p\n", tf);
10005985a7fSJessica Clarke 				break;
10105985a7fSJessica Clarke 			}
10205985a7fSJessica Clarke 
10305985a7fSJessica Clarke 			switch (frame_type) {
10405985a7fSJessica Clarke 			case FRAME_SYNC:
10505985a7fSJessica Clarke 				db_printf("--- exception, esr %#x\n",
10605985a7fSJessica Clarke 				    tf->tf_esr);
10705985a7fSJessica Clarke 				break;
10805985a7fSJessica Clarke 			case FRAME_IRQ:
10905985a7fSJessica Clarke 				db_printf("--- interrupt\n");
11005985a7fSJessica Clarke 				break;
11105985a7fSJessica Clarke 			case FRAME_SERROR:
11205985a7fSJessica Clarke 				db_printf("--- system error, esr %#x\n",
11305985a7fSJessica Clarke 				    tf->tf_esr);
11405985a7fSJessica Clarke 				break;
11505985a7fSJessica Clarke 			case FRAME_UNHANDLED:
11605985a7fSJessica Clarke 				db_printf("--- unhandled exception, esr %#x\n",
11705985a7fSJessica Clarke 				    tf->tf_esr);
11805985a7fSJessica Clarke 				break;
11905985a7fSJessica Clarke 			default:
12005985a7fSJessica Clarke 				__assert_unreachable();
12105985a7fSJessica Clarke 				break;
12205985a7fSJessica Clarke 			}
12305985a7fSJessica Clarke 
12405985a7fSJessica Clarke 			frame->fp = tf->tf_x[29];
12585b7c566SAndrew Turner 			frame->pc = ADDR_MAKE_CANONICAL(tf->tf_elr);
12605985a7fSJessica Clarke 			if (!INKERNEL(frame->fp))
12705985a7fSJessica Clarke 				break;
12805985a7fSJessica Clarke 		} else {
12905985a7fSJessica Clarke 			if (strcmp(name, "fork_trampoline") == 0)
13005985a7fSJessica Clarke 				break;
13105985a7fSJessica Clarke 
13205985a7fSJessica Clarke 			if (!unwind_frame(td, frame))
13305985a7fSJessica Clarke 				break;
13405985a7fSJessica Clarke 		}
135988b7f60SZbigniew Bodek 	}
136988b7f60SZbigniew Bodek }
137988b7f60SZbigniew Bodek 
138988b7f60SZbigniew Bodek int
139988b7f60SZbigniew Bodek db_trace_thread(struct thread *thr, int count)
140988b7f60SZbigniew Bodek {
141988b7f60SZbigniew Bodek 	struct unwind_state frame;
142988b7f60SZbigniew Bodek 	struct pcb *ctx;
143988b7f60SZbigniew Bodek 
144988b7f60SZbigniew Bodek 	if (thr != curthread) {
145988b7f60SZbigniew Bodek 		ctx = kdb_thr_ctx(thr);
146988b7f60SZbigniew Bodek 
147*1c33a94aSAndrew Turner 		frame.fp = (uintptr_t)ctx->pcb_x[PCB_FP];
1485f66d5a3Smhorne 		frame.pc = (uintptr_t)ctx->pcb_lr;
149ae953968SJohn Baldwin 		db_stack_trace_cmd(thr, &frame);
150988b7f60SZbigniew Bodek 	} else
151988b7f60SZbigniew Bodek 		db_trace_self();
152988b7f60SZbigniew Bodek 	return (0);
153988b7f60SZbigniew Bodek }
154988b7f60SZbigniew Bodek 
155988b7f60SZbigniew Bodek void
156988b7f60SZbigniew Bodek db_trace_self(void)
157988b7f60SZbigniew Bodek {
158988b7f60SZbigniew Bodek 	struct unwind_state frame;
159988b7f60SZbigniew Bodek 
1604d16f941SJohn Baldwin 	frame.fp = (uintptr_t)__builtin_frame_address(0);
1614d16f941SJohn Baldwin 	frame.pc = (uintptr_t)db_trace_self;
162ae953968SJohn Baldwin 	db_stack_trace_cmd(curthread, &frame);
163988b7f60SZbigniew Bodek }
164