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