xref: /freebsd/sys/arm64/arm64/db_trace.c (revision f242c47e)
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/param.h>
32988b7f60SZbigniew Bodek #include <sys/proc.h>
33988b7f60SZbigniew Bodek #include <sys/kdb.h>
34a5d295e2SAndrew Turner 
35988b7f60SZbigniew Bodek #include <machine/pcb.h>
36988b7f60SZbigniew Bodek #include <ddb/ddb.h>
37988b7f60SZbigniew Bodek #include <ddb/db_sym.h>
38988b7f60SZbigniew Bodek 
39988b7f60SZbigniew Bodek #include <machine/armreg.h>
40988b7f60SZbigniew Bodek #include <machine/debug_monitor.h>
413f66bd50SRuslan Bukin #include <machine/stack.h>
4205985a7fSJessica Clarke #include <machine/vmparam.h>
4305985a7fSJessica Clarke 
4405985a7fSJessica Clarke #define	FRAME_NORMAL	0
4505985a7fSJessica Clarke #define	FRAME_SYNC	1
4605985a7fSJessica Clarke #define	FRAME_IRQ	2
4705985a7fSJessica Clarke #define	FRAME_SERROR	3
4805985a7fSJessica Clarke #define	FRAME_UNHANDLED	4
49988b7f60SZbigniew Bodek 
50988b7f60SZbigniew Bodek void
db_md_list_breakpoints(void)51f242c47eSAndrew Turner db_md_list_breakpoints(void)
52f242c47eSAndrew Turner {
53f242c47eSAndrew Turner 
54f242c47eSAndrew Turner 	dbg_show_breakpoint();
55f242c47eSAndrew Turner }
56f242c47eSAndrew Turner 
57f242c47eSAndrew Turner void
db_md_list_watchpoints(void)5894074089SDimitry Andric db_md_list_watchpoints(void)
59988b7f60SZbigniew Bodek {
60988b7f60SZbigniew Bodek 
61988b7f60SZbigniew Bodek 	dbg_show_watchpoint();
62988b7f60SZbigniew Bodek }
63988b7f60SZbigniew Bodek 
6489c52f9dSKyle Evans static void __nosanitizeaddress
db_stack_trace_cmd(struct thread * td,struct unwind_state * frame)65ae953968SJohn Baldwin db_stack_trace_cmd(struct thread *td, struct unwind_state *frame)
66988b7f60SZbigniew Bodek {
67988b7f60SZbigniew Bodek 	c_db_sym_t sym;
68988b7f60SZbigniew Bodek 	const char *name;
69988b7f60SZbigniew Bodek 	db_expr_t value;
70988b7f60SZbigniew Bodek 	db_expr_t offset;
7105985a7fSJessica Clarke 	int frame_type;
72988b7f60SZbigniew Bodek 
73988b7f60SZbigniew Bodek 	while (1) {
7405985a7fSJessica Clarke 		sym = db_search_symbol(frame->pc, DB_STGY_ANY, &offset);
75988b7f60SZbigniew Bodek 		if (sym == C_DB_SYM_NULL) {
76988b7f60SZbigniew Bodek 			value = 0;
77988b7f60SZbigniew Bodek 			name = "(null)";
78988b7f60SZbigniew Bodek 		} else
79988b7f60SZbigniew Bodek 			db_symbol_values(sym, &name, &value);
80988b7f60SZbigniew Bodek 
81988b7f60SZbigniew Bodek 		db_printf("%s() at ", name);
82988b7f60SZbigniew Bodek 		db_printsym(frame->pc, DB_STGY_PROC);
83988b7f60SZbigniew Bodek 		db_printf("\n");
84988b7f60SZbigniew Bodek 
8505985a7fSJessica Clarke 		if (strcmp(name, "handle_el0_sync") == 0 ||
8605985a7fSJessica Clarke 		    strcmp(name, "handle_el1h_sync") == 0)
8705985a7fSJessica Clarke 			frame_type = FRAME_SYNC;
8805985a7fSJessica Clarke 		else if (strcmp(name, "handle_el0_irq") == 0 ||
8905985a7fSJessica Clarke 		     strcmp(name, "handle_el1h_irq") == 0)
9005985a7fSJessica Clarke 			frame_type = FRAME_IRQ;
9105985a7fSJessica Clarke 		else if (strcmp(name, "handle_serror") == 0)
9205985a7fSJessica Clarke 			frame_type = FRAME_SERROR;
9305985a7fSJessica Clarke 		else if (strcmp(name, "handle_empty_exception") == 0)
9405985a7fSJessica Clarke 			frame_type = FRAME_UNHANDLED;
9505985a7fSJessica Clarke 		else
9605985a7fSJessica Clarke 			frame_type = FRAME_NORMAL;
9705985a7fSJessica Clarke 
9805985a7fSJessica Clarke 		if (frame_type != FRAME_NORMAL) {
9905985a7fSJessica Clarke 			struct trapframe *tf;
10005985a7fSJessica Clarke 
10105985a7fSJessica Clarke 			tf = (struct trapframe *)(uintptr_t)frame->fp - 1;
10203d04bf4SMinsoo Choo 			if (!__is_aligned(tf, _Alignof(struct trapframe)) ||
103638c6889SJohn Baldwin 			    !kstack_contains(td, (vm_offset_t)tf,
10405985a7fSJessica Clarke 			    sizeof(*tf))) {
10505985a7fSJessica Clarke 				db_printf("--- invalid trapframe %p\n", tf);
10605985a7fSJessica Clarke 				break;
10705985a7fSJessica Clarke 			}
10805985a7fSJessica Clarke 
10905985a7fSJessica Clarke 			switch (frame_type) {
11005985a7fSJessica Clarke 			case FRAME_SYNC:
1112ecbbcc7SZachary Leaf 				db_printf("--- exception, esr %#lx\n",
11205985a7fSJessica Clarke 				    tf->tf_esr);
11305985a7fSJessica Clarke 				break;
11405985a7fSJessica Clarke 			case FRAME_IRQ:
11505985a7fSJessica Clarke 				db_printf("--- interrupt\n");
11605985a7fSJessica Clarke 				break;
11705985a7fSJessica Clarke 			case FRAME_SERROR:
1182ecbbcc7SZachary Leaf 				db_printf("--- system error, esr %#lx\n",
11905985a7fSJessica Clarke 				    tf->tf_esr);
12005985a7fSJessica Clarke 				break;
12105985a7fSJessica Clarke 			case FRAME_UNHANDLED:
1222ecbbcc7SZachary Leaf 				db_printf("--- unhandled exception, esr %#lx\n",
12305985a7fSJessica Clarke 				    tf->tf_esr);
12405985a7fSJessica Clarke 				break;
12505985a7fSJessica Clarke 			default:
12605985a7fSJessica Clarke 				__assert_unreachable();
12705985a7fSJessica Clarke 				break;
12805985a7fSJessica Clarke 			}
12905985a7fSJessica Clarke 
13005985a7fSJessica Clarke 			frame->fp = tf->tf_x[29];
13185b7c566SAndrew Turner 			frame->pc = ADDR_MAKE_CANONICAL(tf->tf_elr);
13205985a7fSJessica Clarke 			if (!INKERNEL(frame->fp))
13305985a7fSJessica Clarke 				break;
13405985a7fSJessica Clarke 		} else {
13505985a7fSJessica Clarke 			if (strcmp(name, "fork_trampoline") == 0)
13605985a7fSJessica Clarke 				break;
13705985a7fSJessica Clarke 
13805985a7fSJessica Clarke 			if (!unwind_frame(td, frame))
13905985a7fSJessica Clarke 				break;
14005985a7fSJessica Clarke 		}
141988b7f60SZbigniew Bodek 	}
142988b7f60SZbigniew Bodek }
143988b7f60SZbigniew Bodek 
14489c52f9dSKyle Evans int __nosanitizeaddress
db_trace_thread(struct thread * thr,int count)145988b7f60SZbigniew Bodek db_trace_thread(struct thread *thr, int count)
146988b7f60SZbigniew Bodek {
147988b7f60SZbigniew Bodek 	struct unwind_state frame;
148988b7f60SZbigniew Bodek 	struct pcb *ctx;
149988b7f60SZbigniew Bodek 
150988b7f60SZbigniew Bodek 	if (thr != curthread) {
151988b7f60SZbigniew Bodek 		ctx = kdb_thr_ctx(thr);
152988b7f60SZbigniew Bodek 
1531c33a94aSAndrew Turner 		frame.fp = (uintptr_t)ctx->pcb_x[PCB_FP];
1541c1f31a5SAndrew Turner 		frame.pc = (uintptr_t)ctx->pcb_x[PCB_LR];
155ae953968SJohn Baldwin 		db_stack_trace_cmd(thr, &frame);
156988b7f60SZbigniew Bodek 	} else
157988b7f60SZbigniew Bodek 		db_trace_self();
158988b7f60SZbigniew Bodek 	return (0);
159988b7f60SZbigniew Bodek }
160988b7f60SZbigniew Bodek 
16189c52f9dSKyle Evans void __nosanitizeaddress
db_trace_self(void)162988b7f60SZbigniew Bodek db_trace_self(void)
163988b7f60SZbigniew Bodek {
164988b7f60SZbigniew Bodek 	struct unwind_state frame;
165988b7f60SZbigniew Bodek 
1664d16f941SJohn Baldwin 	frame.fp = (uintptr_t)__builtin_frame_address(0);
1674d16f941SJohn Baldwin 	frame.pc = (uintptr_t)db_trace_self;
168ae953968SJohn Baldwin 	db_stack_trace_cmd(curthread, &frame);
169988b7f60SZbigniew Bodek }
170