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
12 * J. David Anglin writes:
14 * "You have to adjust the current sp to that at the begining of the function.
15 * There can be up to two stack additions to allocate the frame in the
16 * prologue. Similar things happen in the epilogue. In the presence of
17 * interrupts, you have to be concerned about where you are in the function
18 * and what stack adjustments have taken place."
20 * For now these cases are not handled, but they should be!
23 #include <linux/config.h>
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
28 #include <asm/uaccess.h>
30 #include <asm/unwind.h>
34 #define dbg(x...) printk(x)
39 extern const struct unwind_table_entry __start___unwind[];
40 extern const struct unwind_table_entry __stop___unwind[];
42 static spinlock_t unwind_lock;
44 * the kernel unwind block is not dynamically allocated so that
45 * we can call unwind_init as early in the bootup process as
46 * possible (before the slab allocator is initialized)
48 static struct unwind_table kernel_unwind_table;
49 static struct unwind_table *unwind_tables, *unwind_tables_end;
52 static inline const struct unwind_table_entry *
53 find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
55 const struct unwind_table_entry *e = 0;
56 unsigned long lo, hi, mid;
58 addr -= table->base_addr;
60 for (lo = 0, hi = table->length; lo < hi; )
63 e = &table->table[mid];
64 if (addr < e->region_start)
66 else if (addr > e->region_end)
75 static inline const struct unwind_table_entry *
76 find_unwind_entry(unsigned long addr)
78 struct unwind_table *table = unwind_tables;
79 const struct unwind_table_entry *e = NULL;
81 if (addr >= kernel_unwind_table.start &&
82 addr <= kernel_unwind_table.end)
83 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
85 for (; table; table = table->next)
87 if (addr >= table->start &&
89 e = find_unwind_entry_in_table(table, addr);
98 unwind_table_init(struct unwind_table *table, const char *name,
99 unsigned long base_addr, unsigned long gp,
100 const void *table_start, const void *table_end)
102 const struct unwind_table_entry *start = table_start;
103 const struct unwind_table_entry *end = table_end - 1;
106 table->base_addr = base_addr;
108 table->start = base_addr + start->region_start;
109 table->end = base_addr + end->region_end;
110 table->table = (struct unwind_table_entry *)table_start;
111 table->length = end - start;
116 unwind_table_add(const char *name, unsigned long base_addr,
118 const void *start, const void *end)
120 struct unwind_table *table;
123 table = kmalloc(sizeof(struct unwind_table), GFP_USER);
126 unwind_table_init(table, name, base_addr, gp, start, end);
127 spin_lock_irqsave(&unwind_lock, flags);
130 unwind_tables_end->next = table;
131 unwind_tables_end = table;
135 unwind_tables = unwind_tables_end = table;
137 spin_unlock_irqrestore(&unwind_lock, flags);
142 /* Called from setup_arch to import the kernel unwind info */
143 static int unwind_init(void)
146 register unsigned long gp __asm__ ("r27");
148 start = (long)&__start___unwind[0];
149 stop = (long)&__stop___unwind[0];
151 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
153 (stop - start) / sizeof(struct unwind_table_entry));
155 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
157 &__start___unwind[0], &__stop___unwind[0]);
161 for (i = 0; i < 10; i++)
163 printk("region 0x%x-0x%x\n",
164 __start___unwind[i].region_start,
165 __start___unwind[i].region_end);
172 static void unwind_frame_regs(struct unwind_frame_info *info)
174 const struct unwind_table_entry *e;
178 int looking_for_rp, rpoffset = 0;
180 e = find_unwind_entry(info->ip);
183 extern char _stext[], _etext[];
185 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
187 /* Since we are doing the unwinding blind, we don't know if
188 we are adjusting the stack correctly or extracting the rp
189 correctly. The rp is checked to see if it belongs to the
190 kernel text section, if not we assume we don't have a
191 correct stack frame and we continue to unwind the stack.
192 This is not quite correct, and will fail for loadable
196 info->prev_sp = sp - 64;
198 /* FIXME: what happens if we unwind too far so that
199 sp no longer falls in a mapped kernel page? */
201 info->prev_ip = *(unsigned long *)(info->prev_sp - 20);
203 info->prev_ip = *(unsigned long *)(info->prev_sp - 16);
207 } while (info->prev_ip < (unsigned long)_stext ||
208 info->prev_ip > (unsigned long)_etext);
211 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, Save_RP = %d size = %u\n",
212 e->region_start, e->region_end, e->Save_SP, e->Save_RP, e->Total_frame_size);
214 looking_for_rp = e->Save_RP;
216 for (npc = e->region_start;
217 (frame_size < (e->Total_frame_size << 3) || looking_for_rp) &&
221 insn = *(unsigned int *)npc;
223 if ((insn & 0xffffc000) == 0x37de0000 ||
224 (insn & 0xffe00000) == 0x6fc00000) {
225 /* ldo X(sp), sp, or stwm X,D(sp) */
226 frame_size += (insn & 0x1 ? -1 << 13 : 0) |
227 ((insn & 0x3fff) >> 1);
228 } else if ((insn & 0xffe00008) == 0x7ec00008) {
230 frame_size += (insn & 0x1 ? -1 << 13 : 0) |
231 (((insn >> 4) & 0x3ff) << 3);
232 } else if (insn == 0x6bc23fd9) {
236 } else if (insn == 0x0fc212c1) {
237 /* std rp,-16(sr0,sp) */
243 info->prev_sp = info->sp - frame_size;
245 info->prev_ip = *(unsigned long *)(info->prev_sp - rpoffset);
249 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
250 struct pt_regs *regs)
252 memset(info, 0, sizeof(struct unwind_frame_info));
254 info->sp = regs->ksp;
255 info->ip = regs->kpc;
257 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", (int)t->pid, info->sp, info->ip);
260 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
262 struct pt_regs *regs = &t->thread.regs;
263 unwind_frame_init(info, t, regs);
266 int unwind_once(struct unwind_frame_info *next_frame)
268 unwind_frame_regs(next_frame);
270 if (next_frame->prev_sp == 0 ||
271 next_frame->prev_ip == 0)
274 next_frame->sp = next_frame->prev_sp;
275 next_frame->ip = next_frame->prev_ip;
276 next_frame->prev_sp = 0;
277 next_frame->prev_ip = 0;
279 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", (int)next_frame->t->pid, next_frame->sp, next_frame->ip);
284 int unwind_to_user(struct unwind_frame_info *info)
289 ret = unwind_once(info);
290 } while (!ret && !(info->ip & 3));
295 module_init(unwind_init);