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