fiq_debugger_arm.c revision 3764f68d03b78ba0239fd00f6e98e08bbe4ff2d8
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 <linux/uaccess.h> 18 19#include <asm/stacktrace.h> 20 21#include "fiq_debugger_priv.h" 22 23static char *mode_name(unsigned cpsr) 24{ 25 switch (cpsr & MODE_MASK) { 26 case USR_MODE: return "USR"; 27 case FIQ_MODE: return "FIQ"; 28 case IRQ_MODE: return "IRQ"; 29 case SVC_MODE: return "SVC"; 30 case ABT_MODE: return "ABT"; 31 case UND_MODE: return "UND"; 32 case SYSTEM_MODE: return "SYS"; 33 default: return "???"; 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 %08x cpsr %08x mode %s\n", 41 regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr)); 42} 43 44void fiq_debugger_dump_regs(struct fiq_debugger_state *state, 45 const struct pt_regs *regs) 46{ 47 fiq_debugger_printf(state, 48 " r0 %08x r1 %08x r2 %08x r3 %08x\n", 49 regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); 50 fiq_debugger_printf(state, 51 " r4 %08x r5 %08x r6 %08x r7 %08x\n", 52 regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7); 53 fiq_debugger_printf(state, 54 " r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n", 55 regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp, 56 mode_name(regs->ARM_cpsr)); 57 fiq_debugger_printf(state, 58 " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", 59 regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc, 60 regs->ARM_cpsr); 61} 62 63struct mode_regs { 64 unsigned long sp_svc; 65 unsigned long lr_svc; 66 unsigned long spsr_svc; 67 68 unsigned long sp_abt; 69 unsigned long lr_abt; 70 unsigned long spsr_abt; 71 72 unsigned long sp_und; 73 unsigned long lr_und; 74 unsigned long spsr_und; 75 76 unsigned long sp_irq; 77 unsigned long lr_irq; 78 unsigned long spsr_irq; 79 80 unsigned long r8_fiq; 81 unsigned long r9_fiq; 82 unsigned long r10_fiq; 83 unsigned long r11_fiq; 84 unsigned long r12_fiq; 85 unsigned long sp_fiq; 86 unsigned long lr_fiq; 87 unsigned long spsr_fiq; 88}; 89 90static void __naked get_mode_regs(struct mode_regs *regs) 91{ 92 asm volatile ( 93 "mrs r1, cpsr\n" 94 "msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n" 95 "stmia r0!, {r13 - r14}\n" 96 "mrs r2, spsr\n" 97 "msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n" 98 "stmia r0!, {r2, r13 - r14}\n" 99 "mrs r2, spsr\n" 100 "msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n" 101 "stmia r0!, {r2, r13 - r14}\n" 102 "mrs r2, spsr\n" 103 "msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" 104 "stmia r0!, {r2, r13 - r14}\n" 105 "mrs r2, spsr\n" 106 "msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" 107 "stmia r0!, {r2, r8 - r14}\n" 108 "mrs r2, spsr\n" 109 "stmia r0!, {r2}\n" 110 "msr cpsr_c, r1\n" 111 "bx lr\n"); 112} 113 114 115void fiq_debugger_dump_allregs(struct fiq_debugger_state *state, 116 const struct pt_regs *regs) 117{ 118 struct mode_regs mode_regs; 119 unsigned long mode = regs->ARM_cpsr & MODE_MASK; 120 121 fiq_debugger_dump_regs(state, regs); 122 get_mode_regs(&mode_regs); 123 124 fiq_debugger_printf(state, 125 "%csvc: sp %08x lr %08x spsr %08x\n", 126 mode == SVC_MODE ? '*' : ' ', 127 mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc); 128 fiq_debugger_printf(state, 129 "%cabt: sp %08x lr %08x spsr %08x\n", 130 mode == ABT_MODE ? '*' : ' ', 131 mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt); 132 fiq_debugger_printf(state, 133 "%cund: sp %08x lr %08x spsr %08x\n", 134 mode == UND_MODE ? '*' : ' ', 135 mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und); 136 fiq_debugger_printf(state, 137 "%cirq: sp %08x lr %08x spsr %08x\n", 138 mode == IRQ_MODE ? '*' : ' ', 139 mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq); 140 fiq_debugger_printf(state, 141 "%cfiq: r8 %08x r9 %08x r10 %08x r11 %08x r12 %08x\n", 142 mode == FIQ_MODE ? '*' : ' ', 143 mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq, 144 mode_regs.r11_fiq, mode_regs.r12_fiq); 145 fiq_debugger_printf(state, 146 " fiq: sp %08x lr %08x spsr %08x\n", 147 mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq); 148} 149 150struct stacktrace_state { 151 struct fiq_debugger_state *state; 152 unsigned int depth; 153}; 154 155static int report_trace(struct stackframe *frame, void *d) 156{ 157 struct stacktrace_state *sts = d; 158 159 if (sts->depth) { 160 fiq_debugger_printf(sts->state, 161 " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", 162 frame->pc, frame->pc, frame->lr, frame->lr, 163 frame->sp, frame->fp); 164 sts->depth--; 165 return 0; 166 } 167 fiq_debugger_printf(sts->state, " ...\n"); 168 169 return sts->depth == 0; 170} 171 172struct frame_tail { 173 struct frame_tail *fp; 174 unsigned long sp; 175 unsigned long lr; 176} __attribute__((packed)); 177 178static struct frame_tail *user_backtrace(struct fiq_debugger_state *state, 179 struct frame_tail *tail) 180{ 181 struct frame_tail buftail[2]; 182 183 /* Also check accessibility of one struct frame_tail beyond */ 184 if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) { 185 fiq_debugger_printf(state, " invalid frame pointer %p\n", 186 tail); 187 return NULL; 188 } 189 if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) { 190 fiq_debugger_printf(state, 191 " failed to copy frame pointer %p\n", tail); 192 return NULL; 193 } 194 195 fiq_debugger_printf(state, " %p\n", buftail[0].lr); 196 197 /* frame pointers should strictly progress back up the stack 198 * (towards higher addresses) */ 199 if (tail >= buftail[0].fp) 200 return NULL; 201 202 return buftail[0].fp-1; 203} 204 205void fiq_debugger_dump_stacktrace(struct fiq_debugger_state *state, 206 const struct pt_regs *regs, unsigned int depth, void *ssp) 207{ 208 struct frame_tail *tail; 209 struct thread_info *real_thread_info = THREAD_INFO(ssp); 210 struct stacktrace_state sts; 211 212 sts.depth = depth; 213 sts.state = state; 214 *current_thread_info() = *real_thread_info; 215 216 if (!current) 217 fiq_debugger_printf(state, "current NULL\n"); 218 else 219 fiq_debugger_printf(state, "pid: %d comm: %s\n", 220 current->pid, current->comm); 221 fiq_debugger_dump_regs(state, regs); 222 223 if (!user_mode(regs)) { 224 struct stackframe frame; 225 frame.fp = regs->ARM_fp; 226 frame.sp = regs->ARM_sp; 227 frame.lr = regs->ARM_lr; 228 frame.pc = regs->ARM_pc; 229 fiq_debugger_printf(state, 230 " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", 231 regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr, 232 regs->ARM_sp, regs->ARM_fp); 233 walk_stackframe(&frame, report_trace, &sts); 234 return; 235 } 236 237 tail = ((struct frame_tail *) regs->ARM_fp) - 1; 238 while (depth-- && tail && !((unsigned long) tail & 3)) 239 tail = user_backtrace(state, tail); 240} 241