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