2 * Copyright (C) 2014 Google, Inc.
3 * Author: Colin Cross <ccross@android.com>
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.
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.
16 #include <linux/ptrace.h>
17 #include <linux/uaccess.h>
19 #include <asm/stacktrace.h>
21 #include "fiq_debugger_priv.h"
23 static char *mode_name(unsigned cpsr)
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 "???";
37 void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
38 const struct pt_regs *regs)
40 output->printf(output, " pc %08x cpsr %08x mode %s\n",
41 regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr));
44 void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
45 const struct pt_regs *regs)
47 output->printf(output,
48 " r0 %08x r1 %08x r2 %08x r3 %08x\n",
49 regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
50 output->printf(output,
51 " r4 %08x r5 %08x r6 %08x r7 %08x\n",
52 regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
53 output->printf(output,
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 output->printf(output,
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,
66 unsigned long spsr_svc;
70 unsigned long spsr_abt;
74 unsigned long spsr_und;
78 unsigned long spsr_irq;
82 unsigned long r10_fiq;
83 unsigned long r11_fiq;
84 unsigned long r12_fiq;
87 unsigned long spsr_fiq;
90 static void __naked get_mode_regs(struct mode_regs *regs)
94 "msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n"
95 "stmia r0!, {r13 - r14}\n"
97 "msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n"
98 "stmia r0!, {r2, r13 - r14}\n"
100 "msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n"
101 "stmia r0!, {r2, r13 - r14}\n"
103 "msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
104 "stmia r0!, {r2, r13 - r14}\n"
106 "msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
107 "stmia r0!, {r2, r8 - r14}\n"
115 void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
116 const struct pt_regs *regs)
118 struct mode_regs mode_regs;
119 unsigned long mode = regs->ARM_cpsr & MODE_MASK;
121 fiq_debugger_dump_regs(output, regs);
122 get_mode_regs(&mode_regs);
124 output->printf(output,
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 output->printf(output,
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 output->printf(output,
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 output->printf(output,
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 output->printf(output,
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 output->printf(output,
146 " fiq: sp %08x lr %08x spsr %08x\n",
147 mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq);
150 struct stacktrace_state {
151 struct fiq_debugger_output *output;
155 static int report_trace(struct stackframe *frame, void *d)
157 struct stacktrace_state *sts = d;
160 sts->output->printf(sts->output,
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);
167 sts->output->printf(sts->output, " ...\n");
169 return sts->depth == 0;
173 struct frame_tail *fp;
176 } __attribute__((packed));
178 static struct frame_tail *user_backtrace(struct fiq_debugger_output *output,
179 struct frame_tail *tail)
181 struct frame_tail buftail[2];
183 /* Also check accessibility of one struct frame_tail beyond */
184 if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) {
185 output->printf(output, " invalid frame pointer %p\n",
189 if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) {
190 output->printf(output,
191 " failed to copy frame pointer %p\n", tail);
195 output->printf(output, " %p\n", buftail[0].lr);
197 /* frame pointers should strictly progress back up the stack
198 * (towards higher addresses) */
199 if (tail >= buftail[0].fp)
202 return buftail[0].fp-1;
205 void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
206 const struct pt_regs *regs, unsigned int depth, void *ssp)
208 struct frame_tail *tail;
209 struct thread_info *real_thread_info = THREAD_INFO(ssp);
210 struct stacktrace_state sts;
214 *current_thread_info() = *real_thread_info;
217 output->printf(output, "current NULL\n");
219 output->printf(output, "pid: %d comm: %s\n",
220 current->pid, current->comm);
221 fiq_debugger_dump_regs(output, regs);
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 output->printf(output,
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);
237 tail = ((struct frame_tail *) regs->ARM_fp) - 1;
238 while (depth-- && tail && !((unsigned long) tail & 3))
239 tail = user_backtrace(output, tail);