1 /* 2 * Kernel unwinding support 3 * 4 * (c) 2002-2004 Randolph Chung <tausq@debian.org> 5 * 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 9 */ 10 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> 16 17 #include <asm/uaccess.h> 18 #include <asm/assembly.h> 19 #include <asm/asm-offsets.h> 20 #include <asm/ptrace.h> 21 22 #include <asm/unwind.h> 23 24 /* #define DEBUG 1 */ 25 #ifdef DEBUG 26 #define dbg(x...) printk(x) 27 #else 28 #define dbg(x...) 29 #endif 30 31 #define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000) 32 33 extern struct unwind_table_entry __start___unwind[]; 34 extern struct unwind_table_entry __stop___unwind[]; 35 36 static spinlock_t unwind_lock; 37 /* 38 * the kernel unwind block is not dynamically allocated so that 39 * we can call unwind_init as early in the bootup process as 40 * possible (before the slab allocator is initialized) 41 */ 42 static struct unwind_table kernel_unwind_table __read_mostly; 43 static LIST_HEAD(unwind_tables); 44 45 static inline const struct unwind_table_entry * 46 find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr) 47 { 48 const struct unwind_table_entry *e = NULL; 49 unsigned long lo, hi, mid; 50 51 lo = 0; 52 hi = table->length - 1; 53 54 while (lo <= hi) { 55 mid = (hi - lo) / 2 + lo; 56 e = &table->table[mid]; 57 if (addr < e->region_start) 58 hi = mid - 1; 59 else if (addr > e->region_end) 60 lo = mid + 1; 61 else 62 return e; 63 } 64 65 return NULL; 66 } 67 68 static const struct unwind_table_entry * 69 find_unwind_entry(unsigned long addr) 70 { 71 struct unwind_table *table; 72 const struct unwind_table_entry *e = NULL; 73 74 if (addr >= kernel_unwind_table.start && 75 addr <= kernel_unwind_table.end) 76 e = find_unwind_entry_in_table(&kernel_unwind_table, addr); 77 else 78 list_for_each_entry(table, &unwind_tables, list) { 79 if (addr >= table->start && 80 addr <= table->end) 81 e = find_unwind_entry_in_table(table, addr); 82 if (e) 83 break; 84 } 85 86 return e; 87 } 88 89 static void 90 unwind_table_init(struct unwind_table *table, const char *name, 91 unsigned long base_addr, unsigned long gp, 92 void *table_start, void *table_end) 93 { 94 struct unwind_table_entry *start = table_start; 95 struct unwind_table_entry *end = 96 (struct unwind_table_entry *)table_end - 1; 97 98 table->name = name; 99 table->base_addr = base_addr; 100 table->gp = gp; 101 table->start = base_addr + start->region_start; 102 table->end = base_addr + end->region_end; 103 table->table = (struct unwind_table_entry *)table_start; 104 table->length = end - start + 1; 105 INIT_LIST_HEAD(&table->list); 106 107 for (; start <= end; start++) { 108 if (start < end && 109 start->region_end > (start+1)->region_start) { 110 printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1); 111 } 112 113 start->region_start += base_addr; 114 start->region_end += base_addr; 115 } 116 } 117 118 static void 119 unwind_table_sort(struct unwind_table_entry *start, 120 struct unwind_table_entry *finish) 121 { 122 struct unwind_table_entry el, *p, *q; 123 124 for (p = start + 1; p < finish; ++p) { 125 if (p[0].region_start < p[-1].region_start) { 126 el = *p; 127 q = p; 128 do { 129 q[0] = q[-1]; 130 --q; 131 } while (q > start && 132 el.region_start < q[-1].region_start); 133 *q = el; 134 } 135 } 136 } 137 138 struct unwind_table * 139 unwind_table_add(const char *name, unsigned long base_addr, 140 unsigned long gp, 141 void *start, void *end) 142 { 143 struct unwind_table *table; 144 unsigned long flags; 145 struct unwind_table_entry *s = (struct unwind_table_entry *)start; 146 struct unwind_table_entry *e = (struct unwind_table_entry *)end; 147 148 unwind_table_sort(s, e); 149 150 table = kmalloc(sizeof(struct unwind_table), GFP_USER); 151 if (table == NULL) 152 return NULL; 153 unwind_table_init(table, name, base_addr, gp, start, end); 154 spin_lock_irqsave(&unwind_lock, flags); 155 list_add_tail(&table->list, &unwind_tables); 156 spin_unlock_irqrestore(&unwind_lock, flags); 157 158 return table; 159 } 160 161 void unwind_table_remove(struct unwind_table *table) 162 { 163 unsigned long flags; 164 165 spin_lock_irqsave(&unwind_lock, flags); 166 list_del(&table->list); 167 spin_unlock_irqrestore(&unwind_lock, flags); 168 169 kfree(table); 170 } 171 172 /* Called from setup_arch to import the kernel unwind info */ 173 static int unwind_init(void) 174 { 175 long start, stop; 176 register unsigned long gp __asm__ ("r27"); 177 178 start = (long)&__start___unwind[0]; 179 stop = (long)&__stop___unwind[0]; 180 181 spin_lock_init(&unwind_lock); 182 183 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n", 184 start, stop, 185 (stop - start) / sizeof(struct unwind_table_entry)); 186 187 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START, 188 gp, 189 &__start___unwind[0], &__stop___unwind[0]); 190 #if 0 191 { 192 int i; 193 for (i = 0; i < 10; i++) 194 { 195 printk("region 0x%x-0x%x\n", 196 __start___unwind[i].region_start, 197 __start___unwind[i].region_end); 198 } 199 } 200 #endif 201 return 0; 202 } 203 204 #ifdef CONFIG_64BIT 205 #define get_func_addr(fptr) fptr[2] 206 #else 207 #define get_func_addr(fptr) fptr[0] 208 #endif 209 210 static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) 211 { 212 extern void handle_interruption(int, struct pt_regs *); 213 static unsigned long *hi = (unsigned long *)&handle_interruption; 214 215 if (pc == get_func_addr(hi)) { 216 struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); 217 dbg("Unwinding through handle_interruption()\n"); 218 info->prev_sp = regs->gr[30]; 219 info->prev_ip = regs->iaoq[0]; 220 221 return 1; 222 } 223 224 return 0; 225 } 226 227 static void unwind_frame_regs(struct unwind_frame_info *info) 228 { 229 const struct unwind_table_entry *e; 230 unsigned long npc; 231 unsigned int insn; 232 long frame_size = 0; 233 int looking_for_rp, rpoffset = 0; 234 235 e = find_unwind_entry(info->ip); 236 if (e == NULL) { 237 unsigned long sp; 238 extern char _stext[], _etext[]; 239 240 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip); 241 242 #ifdef CONFIG_KALLSYMS 243 /* Handle some frequent special cases.... */ 244 { 245 char symname[KSYM_NAME_LEN]; 246 char *modname; 247 248 kallsyms_lookup(info->ip, NULL, NULL, &modname, 249 symname); 250 251 dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname); 252 253 if (strcmp(symname, "_switch_to_ret") == 0) { 254 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; 255 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); 256 dbg("_switch_to_ret @ %lx - setting " 257 "prev_sp=%lx prev_ip=%lx\n", 258 info->ip, info->prev_sp, 259 info->prev_ip); 260 return; 261 } else if (strcmp(symname, "ret_from_kernel_thread") == 0 || 262 strcmp(symname, "syscall_exit") == 0) { 263 info->prev_ip = info->prev_sp = 0; 264 return; 265 } 266 } 267 #endif 268 269 /* Since we are doing the unwinding blind, we don't know if 270 we are adjusting the stack correctly or extracting the rp 271 correctly. The rp is checked to see if it belongs to the 272 kernel text section, if not we assume we don't have a 273 correct stack frame and we continue to unwind the stack. 274 This is not quite correct, and will fail for loadable 275 modules. */ 276 sp = info->sp & ~63; 277 do { 278 unsigned long tmp; 279 280 info->prev_sp = sp - 64; 281 info->prev_ip = 0; 282 if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) 283 break; 284 info->prev_ip = tmp; 285 sp = info->prev_sp; 286 } while (info->prev_ip < (unsigned long)_stext || 287 info->prev_ip > (unsigned long)_etext); 288 289 info->rp = 0; 290 291 dbg("analyzing func @ %lx with no unwind info, setting " 292 "prev_sp=%lx prev_ip=%lx\n", info->ip, 293 info->prev_sp, info->prev_ip); 294 } else { 295 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, " 296 "Save_RP = %d, Millicode = %d size = %u\n", 297 e->region_start, e->region_end, e->Save_SP, e->Save_RP, 298 e->Millicode, e->Total_frame_size); 299 300 looking_for_rp = e->Save_RP; 301 302 for (npc = e->region_start; 303 (frame_size < (e->Total_frame_size << 3) || 304 looking_for_rp) && 305 npc < info->ip; 306 npc += 4) { 307 308 insn = *(unsigned int *)npc; 309 310 if ((insn & 0xffffc000) == 0x37de0000 || 311 (insn & 0xffe00000) == 0x6fc00000) { 312 /* ldo X(sp), sp, or stwm X,D(sp) */ 313 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 314 ((insn & 0x3fff) >> 1); 315 dbg("analyzing func @ %lx, insn=%08x @ " 316 "%lx, frame_size = %ld\n", info->ip, 317 insn, npc, frame_size); 318 } else if ((insn & 0xffe00008) == 0x73c00008) { 319 /* std,ma X,D(sp) */ 320 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 321 (((insn >> 4) & 0x3ff) << 3); 322 dbg("analyzing func @ %lx, insn=%08x @ " 323 "%lx, frame_size = %ld\n", info->ip, 324 insn, npc, frame_size); 325 } else if (insn == 0x6bc23fd9) { 326 /* stw rp,-20(sp) */ 327 rpoffset = 20; 328 looking_for_rp = 0; 329 dbg("analyzing func @ %lx, insn=stw rp," 330 "-20(sp) @ %lx\n", info->ip, npc); 331 } else if (insn == 0x0fc212c1) { 332 /* std rp,-16(sr0,sp) */ 333 rpoffset = 16; 334 looking_for_rp = 0; 335 dbg("analyzing func @ %lx, insn=std rp," 336 "-16(sp) @ %lx\n", info->ip, npc); 337 } 338 } 339 340 if (!unwind_special(info, e->region_start, frame_size)) { 341 info->prev_sp = info->sp - frame_size; 342 if (e->Millicode) 343 info->rp = info->r31; 344 else if (rpoffset) 345 info->rp = *(unsigned long *)(info->prev_sp - rpoffset); 346 info->prev_ip = info->rp; 347 info->rp = 0; 348 } 349 350 dbg("analyzing func @ %lx, setting prev_sp=%lx " 351 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, 352 info->prev_ip, npc); 353 } 354 } 355 356 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 357 struct pt_regs *regs) 358 { 359 memset(info, 0, sizeof(struct unwind_frame_info)); 360 info->t = t; 361 info->sp = regs->gr[30]; 362 info->ip = regs->iaoq[0]; 363 info->rp = regs->gr[2]; 364 info->r31 = regs->gr[31]; 365 366 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", 367 t ? (int)t->pid : -1, info->sp, info->ip); 368 } 369 370 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t) 371 { 372 struct pt_regs *r = &t->thread.regs; 373 struct pt_regs *r2; 374 375 r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL); 376 if (!r2) 377 return; 378 *r2 = *r; 379 r2->gr[30] = r->ksp; 380 r2->iaoq[0] = r->kpc; 381 unwind_frame_init(info, t, r2); 382 kfree(r2); 383 } 384 385 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs) 386 { 387 unwind_frame_init(info, current, regs); 388 } 389 390 int unwind_once(struct unwind_frame_info *next_frame) 391 { 392 unwind_frame_regs(next_frame); 393 394 if (next_frame->prev_sp == 0 || 395 next_frame->prev_ip == 0) 396 return -1; 397 398 next_frame->sp = next_frame->prev_sp; 399 next_frame->ip = next_frame->prev_ip; 400 next_frame->prev_sp = 0; 401 next_frame->prev_ip = 0; 402 403 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", 404 next_frame->t ? (int)next_frame->t->pid : -1, 405 next_frame->sp, next_frame->ip); 406 407 return 0; 408 } 409 410 int unwind_to_user(struct unwind_frame_info *info) 411 { 412 int ret; 413 414 do { 415 ret = unwind_once(info); 416 } while (!ret && !(info->ip & 3)); 417 418 return ret; 419 } 420 421 module_init(unwind_init); 422