1 /* 2 * Copyright 2003-2009, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler <axeld@pinc-software.de> 7 * Ingo Weinhold <bonefish@cs.tu-berlin.de> 8 * François Revol <revol@free.fr> 9 */ 10 11 12 #include <arch/debug.h> 13 14 #include <arch_cpu.h> 15 #include <debug.h> 16 #include <elf.h> 17 #include <kernel.h> 18 #include <kimage.h> 19 #include <thread.h> 20 21 22 struct stack_frame { 23 struct stack_frame *previous; 24 addr_t return_address; 25 }; 26 27 #define NUM_PREVIOUS_LOCATIONS 32 28 29 extern struct iframe_stack gBootFrameStack; 30 /* 31 32 static bool 33 already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer) 34 { 35 int32 last = *_last; 36 int32 num = *_num; 37 int32 i; 38 39 for (i = 0; i < num; i++) { 40 if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) 41 % NUM_PREVIOUS_LOCATIONS] == framePointer) { 42 return true; 43 } 44 } 45 46 *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS; 47 visited[last] = framePointer; 48 49 if (num < NUM_PREVIOUS_LOCATIONS) 50 *_num = num + 1; 51 52 return false; 53 } 54 55 56 static inline stack_frame * 57 get_current_stack_frame() 58 { 59 stack_frame *frame; 60 asm volatile("move.l %%fp,%0" : "=r"(frame)); 61 return frame; 62 } 63 64 65 static status_t 66 get_next_frame(addr_t framePointer, addr_t *next, addr_t *ip) 67 { 68 struct thread *thread = thread_get_current_thread(); 69 addr_t oldFaultHandler = thread->fault_handler; 70 71 // set fault handler, so that we can safely access user stacks 72 if (thread) { 73 if (m68k_set_fault_handler(&thread->fault_handler, (addr_t)&&error)) 74 goto error; 75 } 76 77 *ip = ((struct stack_frame *)framePointer)->return_address; 78 *next = (addr_t)((struct stack_frame *)framePointer)->previous; 79 80 if (thread) 81 thread->fault_handler = oldFaultHandler; 82 return B_OK; 83 84 error: 85 thread->fault_handler = oldFaultHandler; 86 return B_BAD_ADDRESS; 87 } 88 89 90 static void 91 print_stack_frame(struct thread *thread, addr_t ip, addr_t framePointer, 92 addr_t nextFramePointer) 93 { 94 addr_t diff = nextFramePointer - framePointer; 95 96 // kernel space/user space switch 97 if (diff & 0x80000000) 98 diff = 0; 99 100 // lookup symbol 101 const char *symbol, *image; 102 addr_t baseAddress; 103 bool exactMatch; 104 status_t status = elf_debug_lookup_symbol_address(ip, &baseAddress, &symbol, 105 &image, &exactMatch); 106 if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) { 107 // try to locate the image in the images loaded into user space 108 status = image_debug_lookup_user_symbol_address(thread->team, ip, 109 &baseAddress, &symbol, &image, &exactMatch); 110 } 111 if (status == B_OK) { 112 if (symbol != NULL) { 113 kprintf("%08lx (+%4ld) %08lx <%s>:%s + 0x%04lx%s\n", framePointer, 114 diff, ip, image, symbol, ip - baseAddress, 115 (exactMatch ? "" : " (nearest)")); 116 } else { 117 kprintf("%08lx (+%4ld) %08lx <%s@%p>:unknown + 0x%04lx\n", 118 framePointer, diff, ip, image, (void *)baseAddress, 119 ip - baseAddress); 120 } 121 } else 122 kprintf("%08lx (+%4ld) %08lx\n", framePointer, diff, ip); 123 } 124 125 126 static int 127 stack_trace(int argc, char **argv) 128 { 129 uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; 130 struct iframe_stack *frameStack; 131 struct thread *thread; 132 addr_t framePointer; 133 int32 i, num = 0, last = 0; 134 135 if (argc < 2) { 136 thread = thread_get_current_thread(); 137 framePointer = (addr_t)get_current_stack_frame(); 138 } else { 139 kprintf("Stack traces of other threads not supported yet!\n"); 140 return 0; 141 } 142 143 // We don't have a thread pointer early in the boot process 144 if (thread != NULL) 145 frameStack = &thread->arch_info.iframes; 146 else 147 frameStack = &gBootFrameStack; 148 149 for (i = 0; i < frameStack->index; i++) { 150 kprintf("iframe %p (end = %p)\n", 151 frameStack->frames[i], frameStack->frames[i] + 1); 152 } 153 154 if (thread != NULL) { 155 kprintf("stack trace for thread 0x%lx \"%s\"\n", thread->id, 156 thread->name); 157 158 kprintf(" kernel stack: %p to %p\n", 159 (void *)thread->kernel_stack_base, 160 (void *)(thread->kernel_stack_top)); 161 if (thread->user_stack_base != 0) { 162 kprintf(" user stack: %p to %p\n", 163 (void *)thread->user_stack_base, 164 (void *)(thread->user_stack_base + thread->user_stack_size)); 165 } 166 } 167 168 kprintf("frame caller <image>:function + offset\n"); 169 170 for (;;) { 171 // see if the frame pointer matches the iframe 172 struct iframe *frame = NULL; 173 for (i = 0; i < frameStack->index; i++) { 174 if (framePointer == (addr_t)frameStack->frames[i]) { 175 // it's an iframe 176 frame = frameStack->frames[i]; 177 break; 178 } 179 } 180 181 if (frame) { 182 kprintf("iframe at %p\n", frame); 183 kprintf(" d0 0x%08lx d1 0x%08lx d2 0x%08lx d3 0x%08lx\n", 184 frame->d[0], frame->d[1], frame->d[2], frame->d[3]); 185 kprintf(" d4 0x%08lx d5 0x%08lx d6 0x%08lx d7 0x%08lx\n", 186 frame->d[4], frame->d[5], frame->d[6], frame->d[7]); 187 kprintf(" a0 0x%08lx a1 0x%08lx a2 0x%08lx a3 0x%08lx\n", 188 frame->a[0], frame->a[1], frame->a[2], frame->a[3]); 189 kprintf(" a4 0x%08lx a5 0x%08lx a6 0x%08lx a7 0x%08lx (sp)\n", 190 #warning M68K: a7 in iframe ?? 191 frame->a[4], frame->a[5], frame->a[6], -1L); 192 kprintf(" pc 0x%08lx sr 0x%04x\n", 193 frame->cpu.pc, frame->cpu.sr); 194 #warning M68K: missing regs 195 196 print_stack_frame(thread, frame->cpu.pc, framePointer, frame->a[6]); 197 framePointer = frame->a[6]; 198 } else { 199 addr_t ip, nextFramePointer; 200 201 if (get_next_frame(framePointer, &nextFramePointer, &ip) != B_OK) { 202 kprintf("%08lx -- read fault\n", framePointer); 203 break; 204 } 205 206 if (ip == 0 || framePointer == 0) 207 break; 208 209 print_stack_frame(thread, ip, framePointer, nextFramePointer); 210 framePointer = nextFramePointer; 211 } 212 213 if (already_visited(previousLocations, &last, &num, framePointer)) { 214 kprintf("circular stack frame: %p!\n", (void *)framePointer); 215 break; 216 } 217 if (framePointer == 0) 218 break; 219 } 220 221 222 return 0; 223 } 224 225 */ 226 227 // #pragma mark - 228 229 230 void 231 arch_debug_save_registers(int *regs) 232 { 233 } 234 235 236 bool 237 arch_debug_contains_call(struct thread *thread, const char *symbol, 238 addr_t start, addr_t end) 239 { 240 return false; 241 } 242 243 244 void 245 arch_debug_stack_trace(void) 246 { 247 } 248 249 250 void * 251 arch_debug_get_caller(void) 252 { 253 #warning ARM:IMPLEMENT 254 // TODO: implement me 255 //return __builtin_frame_address(1); 256 // struct stack_frame *frame; 257 //frame = __builtin_frame_address(0); 258 // frame = get_current_stack_frame(); 259 // return (void *)frame->previous->return_address; 260 return NULL; 261 } 262 263 264 /*! Captures a stack trace (the return addresses) of the current thread. 265 \param returnAddresses The array the return address shall be written to. 266 \param maxCount The maximum number of return addresses to be captured. 267 \param skipIframes The number of interrupt frames that shall be skipped. If 268 greater than 0, \a skipFrames is ignored. 269 \param skipFrames The number of stack frames that shall be skipped. 270 \param userOnly If \c true, only userland return addresses are captured. 271 \return The number of return addresses written to the given array. 272 */ 273 int32 274 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, 275 int32 skipIframes, int32 skipFrames, bool userOnly) 276 { 277 /* struct iframe_stack *frameStack; 278 addr_t framePointer; 279 int32 count = 0; 280 int32 i, num = 0, last = 0; 281 282 // Keep skipping normal stack frames until we've skipped the iframes we're 283 // supposed to skip. 284 if (skipIframes > 0) { 285 skipFrames = INT_MAX; 286 } else { 287 // always skip our own frame 288 skipFrames++; 289 } 290 291 struct thread* thread = thread_get_current_thread(); 292 framePointer = (addr_t)get_current_stack_frame(); 293 294 // We don't have a thread pointer early in the boot process 295 if (thread != NULL) 296 frameStack = &thread->arch_info.iframes; 297 else 298 frameStack = &gBootFrameStack; 299 300 while (framePointer != 0 && count < maxCount) { 301 // see if the frame pointer matches the iframe 302 struct iframe *frame = NULL; 303 for (i = 0; i < frameStack->index; i++) { 304 if (framePointer == (addr_t)frameStack->frames[i]) { 305 // it's an iframe 306 frame = frameStack->frames[i]; 307 break; 308 } 309 } 310 311 addr_t ip; 312 addr_t nextFrame; 313 314 if (frame) { 315 ip = frame->cpu.pc; 316 nextFrame = frame->a[6]; 317 318 if (skipIframes > 0) { 319 if (--skipIframes == 0) 320 skipFrames = 0; 321 } 322 } else { 323 if (get_next_frame(framePointer, &nextFrame, &ip) != B_OK) 324 break; 325 } 326 327 if (skipFrames <= 0 && (!userOnly || IS_USER_ADDRESS(framePointer))) 328 returnAddresses[count++] = ip; 329 else 330 skipFrames--; 331 332 framePointer = nextFrame; 333 } 334 335 return count;*/ 336 #warning ARM:IMPLEMENT 337 338 return 0; 339 } 340 341 342 void* 343 arch_debug_get_interrupt_pc(bool* _isSyscall) 344 { 345 // TODO: Implement! 346 return NULL; 347 } 348 349 350 bool 351 arch_is_debug_variable_defined(const char* variableName) 352 { 353 // TODO: Implement! 354 return false; 355 } 356 357 358 status_t 359 arch_set_debug_variable(const char* variableName, uint64 value) 360 { 361 // TODO: Implement! 362 return B_ENTRY_NOT_FOUND; 363 } 364 365 366 status_t 367 arch_get_debug_variable(const char* variableName, uint64* value) 368 { 369 // TODO: Implement! 370 return B_ENTRY_NOT_FOUND; 371 } 372 373 374 status_t 375 arch_debug_init(kernel_args *args) 376 { 377 // add_debugger_command("where", &stack_trace, "Same as \"sc\""); 378 // add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)"); 379 // add_debugger_command("sc", &stack_trace, "Stack crawl for current thread"); 380 #warning ARM:IMPLEMENT 381 382 return B_NO_ERROR; 383 } 384 385 386 void 387 arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, 388 void (*function)(void*), void* parameter) 389 { 390 // TODO: Implement! Most likely in assembly. 391 longjmp(jumpBuffer, 1); 392 } 393 394 395 void 396 arch_debug_unset_current_thread(void) 397 { 398 // TODO: Implement! 399 } 400 401 402