fiq_debugger_arm64.c revision e139164eb6468f39be07f58a40b657d2e95e787d
1/* 2 * Copyright (C) 2014 Google, Inc. 3 * Author: Colin Cross <ccross@android.com> 4 * 5 * This software is licensed under the terms of the GNU General Public 6 * License version 2, as published by the Free Software Foundation, and 7 * may be copied, distributed, and modified under those terms. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16#include <linux/ptrace.h> 17#include <asm/stacktrace.h> 18 19#include "fiq_debugger_priv.h" 20 21static char *mode_name(const struct pt_regs *regs) 22{ 23 if (compat_user_mode(regs)) { 24 return "USR"; 25 } else { 26 switch (processor_mode(regs)) { 27 case PSR_MODE_EL0t: return "EL0t"; 28 case PSR_MODE_EL1t: return "EL1t"; 29 case PSR_MODE_EL1h: return "EL1h"; 30 case PSR_MODE_EL2t: return "EL2t"; 31 case PSR_MODE_EL2h: return "EL2h"; 32 default: return "???"; 33 } 34 } 35} 36 37void fiq_debugger_dump_pc(struct fiq_debugger_state *state, 38 const struct pt_regs *regs) 39{ 40 fiq_debugger_printf(state, " pc %016lx cpsr %08lx mode %s\n", 41 regs->pc, regs->pstate, mode_name(regs)); 42} 43 44void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_state *state, 45 const struct pt_regs *regs) 46{ 47 fiq_debugger_printf(state, " r0 %08x r1 %08x r2 %08x r3 %08x\n", 48 regs->compat_usr(0), regs->compat_usr(1), 49 regs->compat_usr(2), regs->compat_usr(3)); 50 fiq_debugger_printf(state, " r4 %08x r5 %08x r6 %08x r7 %08x\n", 51 regs->compat_usr(4), regs->compat_usr(5), 52 regs->compat_usr(6), regs->compat_usr(7)); 53 fiq_debugger_printf(state, " r8 %08x r9 %08x r10 %08x r11 %08x\n", 54 regs->compat_usr(8), regs->compat_usr(9), 55 regs->compat_usr(10), regs->compat_usr(11)); 56 fiq_debugger_printf(state, " ip %08x sp %08x lr %08x pc %08x\n", 57 regs->compat_usr(12), regs->compat_sp, 58 regs->compat_lr, regs->pc); 59 fiq_debugger_printf(state, " cpsr %08x (%s)\n", 60 regs->pstate, mode_name(regs)); 61} 62 63void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_state *state, 64 const struct pt_regs *regs) 65{ 66 67 fiq_debugger_printf(state, " x0 %016lx x1 %016lx\n", 68 regs->regs[0], regs->regs[1]); 69 fiq_debugger_printf(state, " x2 %016lx x3 %016lx\n", 70 regs->regs[2], regs->regs[3]); 71 fiq_debugger_printf(state, " x4 %016lx x5 %016lx\n", 72 regs->regs[4], regs->regs[5]); 73 fiq_debugger_printf(state, " x6 %016lx x7 %016lx\n", 74 regs->regs[6], regs->regs[7]); 75 fiq_debugger_printf(state, " x8 %016lx x9 %016lx\n", 76 regs->regs[8], regs->regs[9]); 77 fiq_debugger_printf(state, " x10 %016lx x11 %016lx\n", 78 regs->regs[10], regs->regs[11]); 79 fiq_debugger_printf(state, " x12 %016lx x13 %016lx\n", 80 regs->regs[12], regs->regs[13]); 81 fiq_debugger_printf(state, " x14 %016lx x15 %016lx\n", 82 regs->regs[14], regs->regs[15]); 83 fiq_debugger_printf(state, " x16 %016lx x17 %016lx\n", 84 regs->regs[16], regs->regs[17]); 85 fiq_debugger_printf(state, " x18 %016lx x19 %016lx\n", 86 regs->regs[18], regs->regs[19]); 87 fiq_debugger_printf(state, " x20 %016lx x21 %016lx\n", 88 regs->regs[20], regs->regs[21]); 89 fiq_debugger_printf(state, " x22 %016lx x23 %016lx\n", 90 regs->regs[22], regs->regs[23]); 91 fiq_debugger_printf(state, " x24 %016lx x25 %016lx\n", 92 regs->regs[24], regs->regs[25]); 93 fiq_debugger_printf(state, " x26 %016lx x27 %016lx\n", 94 regs->regs[26], regs->regs[27]); 95 fiq_debugger_printf(state, " x28 %016lx x29 %016lx\n", 96 regs->regs[28], regs->regs[29]); 97 fiq_debugger_printf(state, " x30 %016lx sp %016lx\n", 98 regs->regs[30], regs->sp); 99 fiq_debugger_printf(state, " pc %016lx cpsr %08x (%s)\n", 100 regs->pc, regs->pstate, mode_name(regs)); 101} 102 103void fiq_debugger_dump_regs(struct fiq_debugger_state *state, 104 const struct pt_regs *regs) 105{ 106 if (compat_user_mode(regs)) 107 fiq_debugger_dump_regs_aarch32(state, regs); 108 else 109 fiq_debugger_dump_regs_aarch64(state, regs); 110} 111 112#define READ_SPECIAL_REG(x) ({ \ 113 u64 val; \ 114 asm volatile ("mrs %0, " # x : "=r"(val)); \ 115 val; \ 116}) 117 118void fiq_debugger_dump_allregs(struct fiq_debugger_state *state, 119 const struct pt_regs *regs) 120{ 121 u32 pstate = READ_SPECIAL_REG(CurrentEl); 122 bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t; 123 124 fiq_debugger_dump_regs(state, regs); 125 126 fiq_debugger_printf(state, " sp_el0 %016lx\n", 127 READ_SPECIAL_REG(sp_el0)); 128 129 if (in_el2) 130 fiq_debugger_printf(state, " sp_el1 %016lx\n", 131 READ_SPECIAL_REG(sp_el1)); 132 133 fiq_debugger_printf(state, " elr_el1 %016lx\n", 134 READ_SPECIAL_REG(elr_el1)); 135 136 fiq_debugger_printf(state, " spsr_el1 %08lx\n", 137 READ_SPECIAL_REG(spsr_el1)); 138 139 if (in_el2) { 140 fiq_debugger_printf(state, " spsr_irq %08lx\n", 141 READ_SPECIAL_REG(spsr_irq)); 142 fiq_debugger_printf(state, " spsr_abt %08lx\n", 143 READ_SPECIAL_REG(spsr_abt)); 144 fiq_debugger_printf(state, " spsr_und %08lx\n", 145 READ_SPECIAL_REG(spsr_und)); 146 fiq_debugger_printf(state, " spsr_fiq %08lx\n", 147 READ_SPECIAL_REG(spsr_fiq)); 148 fiq_debugger_printf(state, " spsr_el2 %08lx\n", 149 READ_SPECIAL_REG(elr_el2)); 150 fiq_debugger_printf(state, " spsr_el2 %08lx\n", 151 READ_SPECIAL_REG(spsr_el2)); 152 } 153} 154 155struct stacktrace_state { 156 struct fiq_debugger_state *state; 157 unsigned int depth; 158}; 159 160static int report_trace(struct stackframe *frame, void *d) 161{ 162 struct stacktrace_state *sts = d; 163 164 if (sts->depth) { 165 fiq_debugger_printf(sts->state, "%pF:\n", frame->pc); 166 fiq_debugger_printf(sts->state, 167 " pc %016lx sp %016lx fp %016lx\n", 168 frame->pc, frame->sp, frame->fp); 169 sts->depth--; 170 return 0; 171 } 172 fiq_debugger_printf(sts->state, " ...\n"); 173 174 return sts->depth == 0; 175} 176 177void fiq_debugger_dump_stacktrace(struct fiq_debugger_state *state, 178 const struct pt_regs *regs, unsigned int depth, void *ssp) 179{ 180 struct thread_info *real_thread_info = THREAD_INFO(ssp); 181 struct stacktrace_state sts; 182 183 sts.depth = depth; 184 sts.state = state; 185 *current_thread_info() = *real_thread_info; 186 187 if (!current) 188 fiq_debugger_printf(state, "current NULL\n"); 189 else 190 fiq_debugger_printf(state, "pid: %d comm: %s\n", 191 current->pid, current->comm); 192 fiq_debugger_dump_regs(state, regs); 193 194 if (!user_mode(regs)) { 195 struct stackframe frame; 196 frame.fp = regs->regs[29]; 197 frame.sp = regs->sp; 198 frame.pc = regs->pc; 199 fiq_debugger_printf(state, "\n"); 200 walk_stackframe(&frame, report_trace, &sts); 201 } 202} 203