2 * Kernel unwinding support
4 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
6 * Derived partially from the IA64 implementation. The PA-RISC
7 * Runtime Architecture Document is also a useful reference to
8 * understand what is happening here
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/sched.h>
14 #include <linux/slab.h>
15 #include <linux/kallsyms.h>
17 #include <asm/uaccess.h>
18 #include <asm/assembly.h>
20 #include <asm/unwind.h>
24 #define dbg(x...) printk(x)
29 #define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000)
31 extern struct unwind_table_entry __start___unwind
[];
32 extern struct unwind_table_entry __stop___unwind
[];
34 static spinlock_t unwind_lock
;
36 * the kernel unwind block is not dynamically allocated so that
37 * we can call unwind_init as early in the bootup process as
38 * possible (before the slab allocator is initialized)
40 static struct unwind_table kernel_unwind_table __read_mostly
;
41 static LIST_HEAD(unwind_tables
);
43 static inline const struct unwind_table_entry
*
44 find_unwind_entry_in_table(const struct unwind_table
*table
, unsigned long addr
)
46 const struct unwind_table_entry
*e
= NULL
;
47 unsigned long lo
, hi
, mid
;
50 hi
= table
->length
- 1;
53 mid
= (hi
- lo
) / 2 + lo
;
54 e
= &table
->table
[mid
];
55 if (addr
< e
->region_start
)
57 else if (addr
> e
->region_end
)
66 static const struct unwind_table_entry
*
67 find_unwind_entry(unsigned long addr
)
69 struct unwind_table
*table
;
70 const struct unwind_table_entry
*e
= NULL
;
72 if (addr
>= kernel_unwind_table
.start
&&
73 addr
<= kernel_unwind_table
.end
)
74 e
= find_unwind_entry_in_table(&kernel_unwind_table
, addr
);
76 list_for_each_entry(table
, &unwind_tables
, list
) {
77 if (addr
>= table
->start
&&
79 e
= find_unwind_entry_in_table(table
, addr
);
88 unwind_table_init(struct unwind_table
*table
, const char *name
,
89 unsigned long base_addr
, unsigned long gp
,
90 void *table_start
, void *table_end
)
92 struct unwind_table_entry
*start
= table_start
;
93 struct unwind_table_entry
*end
=
94 (struct unwind_table_entry
*)table_end
- 1;
97 table
->base_addr
= base_addr
;
99 table
->start
= base_addr
+ start
->region_start
;
100 table
->end
= base_addr
+ end
->region_end
;
101 table
->table
= (struct unwind_table_entry
*)table_start
;
102 table
->length
= end
- start
+ 1;
103 INIT_LIST_HEAD(&table
->list
);
105 for (; start
<= end
; start
++) {
107 start
->region_end
> (start
+1)->region_start
) {
108 printk("WARNING: Out of order unwind entry! %p and %p\n", start
, start
+1);
111 start
->region_start
+= base_addr
;
112 start
->region_end
+= base_addr
;
117 unwind_table_sort(struct unwind_table_entry
*start
,
118 struct unwind_table_entry
*finish
)
120 struct unwind_table_entry el
, *p
, *q
;
122 for (p
= start
+ 1; p
< finish
; ++p
) {
123 if (p
[0].region_start
< p
[-1].region_start
) {
129 } while (q
> start
&&
130 el
.region_start
< q
[-1].region_start
);
136 struct unwind_table
*
137 unwind_table_add(const char *name
, unsigned long base_addr
,
139 void *start
, void *end
)
141 struct unwind_table
*table
;
143 struct unwind_table_entry
*s
= (struct unwind_table_entry
*)start
;
144 struct unwind_table_entry
*e
= (struct unwind_table_entry
*)end
;
146 unwind_table_sort(s
, e
);
148 table
= kmalloc(sizeof(struct unwind_table
), GFP_USER
);
151 unwind_table_init(table
, name
, base_addr
, gp
, start
, end
);
152 spin_lock_irqsave(&unwind_lock
, flags
);
153 list_add_tail(&table
->list
, &unwind_tables
);
154 spin_unlock_irqrestore(&unwind_lock
, flags
);
159 void unwind_table_remove(struct unwind_table
*table
)
163 spin_lock_irqsave(&unwind_lock
, flags
);
164 list_del(&table
->list
);
165 spin_unlock_irqrestore(&unwind_lock
, flags
);
170 /* Called from setup_arch to import the kernel unwind info */
171 static int unwind_init(void)
174 register unsigned long gp
__asm__ ("r27");
176 start
= (long)&__start___unwind
[0];
177 stop
= (long)&__stop___unwind
[0];
179 spin_lock_init(&unwind_lock
);
181 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
183 (stop
- start
) / sizeof(struct unwind_table_entry
));
185 unwind_table_init(&kernel_unwind_table
, "kernel", KERNEL_START
,
187 &__start___unwind
[0], &__stop___unwind
[0]);
191 for (i
= 0; i
< 10; i
++)
193 printk("region 0x%x-0x%x\n",
194 __start___unwind
[i
].region_start
,
195 __start___unwind
[i
].region_end
);
202 static void unwind_frame_regs(struct unwind_frame_info
*info
)
204 const struct unwind_table_entry
*e
;
208 int looking_for_rp
, rpoffset
= 0;
210 e
= find_unwind_entry(info
->ip
);
213 extern char _stext
[], _etext
[];
215 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info
->ip
);
217 #ifdef CONFIG_KALLSYMS
218 /* Handle some frequent special cases.... */
220 char symname
[KSYM_NAME_LEN
+1];
223 kallsyms_lookup(info
->ip
, NULL
, NULL
, &modname
,
226 dbg("info->ip = 0x%lx, name = %s\n", info
->ip
, symname
);
228 if (strcmp(symname
, "_switch_to_ret") == 0) {
229 info
->prev_sp
= info
->sp
- CALLEE_SAVE_FRAME_SIZE
;
230 info
->prev_ip
= *(unsigned long *)(info
->prev_sp
- RP_OFFSET
);
231 dbg("_switch_to_ret @ %lx - setting "
232 "prev_sp=%lx prev_ip=%lx\n",
233 info
->ip
, info
->prev_sp
,
236 } else if (strcmp(symname
, "ret_from_kernel_thread") == 0 ||
237 strcmp(symname
, "syscall_exit") == 0) {
238 info
->prev_ip
= info
->prev_sp
= 0;
244 /* Since we are doing the unwinding blind, we don't know if
245 we are adjusting the stack correctly or extracting the rp
246 correctly. The rp is checked to see if it belongs to the
247 kernel text section, if not we assume we don't have a
248 correct stack frame and we continue to unwind the stack.
249 This is not quite correct, and will fail for loadable
255 info
->prev_sp
= sp
- 64;
257 if (get_user(tmp
, (unsigned long *)(info
->prev_sp
- RP_OFFSET
)))
261 } while (info
->prev_ip
< (unsigned long)_stext
||
262 info
->prev_ip
> (unsigned long)_etext
);
266 dbg("analyzing func @ %lx with no unwind info, setting "
267 "prev_sp=%lx prev_ip=%lx\n", info
->ip
,
268 info
->prev_sp
, info
->prev_ip
);
270 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
271 "Save_RP = %d, Millicode = %d size = %u\n",
272 e
->region_start
, e
->region_end
, e
->Save_SP
, e
->Save_RP
,
273 e
->Millicode
, e
->Total_frame_size
);
275 looking_for_rp
= e
->Save_RP
;
277 for (npc
= e
->region_start
;
278 (frame_size
< (e
->Total_frame_size
<< 3) ||
283 insn
= *(unsigned int *)npc
;
285 if ((insn
& 0xffffc000) == 0x37de0000 ||
286 (insn
& 0xffe00000) == 0x6fc00000) {
287 /* ldo X(sp), sp, or stwm X,D(sp) */
288 frame_size
+= (insn
& 0x1 ? -1 << 13 : 0) |
289 ((insn
& 0x3fff) >> 1);
290 dbg("analyzing func @ %lx, insn=%08x @ "
291 "%lx, frame_size = %ld\n", info
->ip
,
292 insn
, npc
, frame_size
);
293 } else if ((insn
& 0xffe00008) == 0x73c00008) {
295 frame_size
+= (insn
& 0x1 ? -1 << 13 : 0) |
296 (((insn
>> 4) & 0x3ff) << 3);
297 dbg("analyzing func @ %lx, insn=%08x @ "
298 "%lx, frame_size = %ld\n", info
->ip
,
299 insn
, npc
, frame_size
);
300 } else if (insn
== 0x6bc23fd9) {
304 dbg("analyzing func @ %lx, insn=stw rp,"
305 "-20(sp) @ %lx\n", info
->ip
, npc
);
306 } else if (insn
== 0x0fc212c1) {
307 /* std rp,-16(sr0,sp) */
310 dbg("analyzing func @ %lx, insn=std rp,"
311 "-16(sp) @ %lx\n", info
->ip
, npc
);
315 info
->prev_sp
= info
->sp
- frame_size
;
317 info
->rp
= info
->r31
;
319 info
->rp
= *(unsigned long *)(info
->prev_sp
- rpoffset
);
320 info
->prev_ip
= info
->rp
;
323 dbg("analyzing func @ %lx, setting prev_sp=%lx "
324 "prev_ip=%lx npc=%lx\n", info
->ip
, info
->prev_sp
,
329 void unwind_frame_init(struct unwind_frame_info
*info
, struct task_struct
*t
,
330 struct pt_regs
*regs
)
332 memset(info
, 0, sizeof(struct unwind_frame_info
));
334 info
->sp
= regs
->gr
[30];
335 info
->ip
= regs
->iaoq
[0];
336 info
->rp
= regs
->gr
[2];
337 info
->r31
= regs
->gr
[31];
339 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
340 t
? (int)t
->pid
: -1, info
->sp
, info
->ip
);
343 void unwind_frame_init_from_blocked_task(struct unwind_frame_info
*info
, struct task_struct
*t
)
345 struct pt_regs
*r
= &t
->thread
.regs
;
348 r2
= kmalloc(sizeof(struct pt_regs
), GFP_KERNEL
);
353 r2
->iaoq
[0] = r
->kpc
;
354 unwind_frame_init(info
, t
, r2
);
358 void unwind_frame_init_running(struct unwind_frame_info
*info
, struct pt_regs
*regs
)
360 unwind_frame_init(info
, current
, regs
);
363 int unwind_once(struct unwind_frame_info
*next_frame
)
365 unwind_frame_regs(next_frame
);
367 if (next_frame
->prev_sp
== 0 ||
368 next_frame
->prev_ip
== 0)
371 next_frame
->sp
= next_frame
->prev_sp
;
372 next_frame
->ip
= next_frame
->prev_ip
;
373 next_frame
->prev_sp
= 0;
374 next_frame
->prev_ip
= 0;
376 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
377 next_frame
->t
? (int)next_frame
->t
->pid
: -1,
378 next_frame
->sp
, next_frame
->ip
);
383 int unwind_to_user(struct unwind_frame_info
*info
)
388 ret
= unwind_once(info
);
389 } while (!ret
&& !(info
->ip
& 3));
394 module_init(unwind_init
);