1 /* 2 * Copyright 2003-2011, 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 * Ithamar R. Adema <ithamar@upgrade-android.com> 10 * 11 */ 12 13 14 #include <arch/debug.h> 15 16 #include <arch_cpu.h> 17 #include <debug.h> 18 #include <debug_heap.h> 19 #include <elf.h> 20 #include <kernel.h> 21 #include <kimage.h> 22 #include <thread.h> 23 #include <vm/vm_types.h> 24 #include <vm/VMAddressSpace.h> 25 #include <vm/VMArea.h> 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 fp) 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] == fp) { 42 return true; 43 } 44 } 45 46 *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS; 47 visited[last] = fp; 48 49 if (num < NUM_PREVIOUS_LOCATIONS) 50 *_num = num + 1; 51 52 return false; 53 } 54 55 56 static status_t 57 get_next_frame(addr_t fp, addr_t *next, addr_t *ip) 58 { 59 if (fp != 0) { 60 addr_t _fp = *(((addr_t*)fp) -3); 61 addr_t _sp = *(((addr_t*)fp) -2); 62 addr_t _lr = *(((addr_t*)fp) -1); 63 addr_t _pc = *(((addr_t*)fp) -0); 64 65 *ip = (_fp != 0) ? _lr : _pc; 66 *next = _fp; 67 68 return B_OK; 69 } 70 71 return B_BAD_VALUE; 72 } 73 74 75 static status_t 76 lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress, 77 const char** _symbolName, const char** _imageName, bool* _exactMatch) 78 { 79 status_t status = B_ENTRY_NOT_FOUND; 80 81 if (IS_KERNEL_ADDRESS(address)) { 82 // a kernel symbol 83 status = elf_debug_lookup_symbol_address(address, _baseAddress, 84 _symbolName, _imageName, _exactMatch); 85 } else if (thread != NULL && thread->team != NULL) { 86 // try a lookup using the userland runtime loader structures 87 status = elf_debug_lookup_user_symbol_address(thread->team, address, 88 _baseAddress, _symbolName, _imageName, _exactMatch); 89 90 if (status != B_OK) { 91 // try to locate the image in the images loaded into user space 92 status = image_debug_lookup_user_symbol_address(thread->team, 93 address, _baseAddress, _symbolName, _imageName, _exactMatch); 94 } 95 } 96 97 return status; 98 } 99 100 101 static void 102 set_debug_argument_variable(int32 index, uint64 value) 103 { 104 char name[8]; 105 snprintf(name, sizeof(name), "_arg%ld", index); 106 set_debug_variable(name, value); 107 } 108 109 110 template<typename Type> 111 static Type 112 read_function_argument_value(void* argument, bool& _valueKnown) 113 { 114 Type value; 115 if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) { 116 _valueKnown = true; 117 return value; 118 } 119 120 _valueKnown = false; 121 return 0; 122 } 123 124 125 static status_t 126 print_demangled_call(const char* image, const char* symbol, addr_t args, 127 bool noObjectMethod, bool addDebugVariables) 128 { 129 static const size_t kBufferSize = 256; 130 char* buffer = (char*)debug_malloc(kBufferSize); 131 if (buffer == NULL) 132 return B_NO_MEMORY; 133 134 bool isObjectMethod; 135 const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize, 136 &isObjectMethod); 137 if (name == NULL) { 138 debug_free(buffer); 139 return B_ERROR; 140 } 141 142 uint32* arg = (uint32*)args; 143 144 if (noObjectMethod) 145 isObjectMethod = false; 146 if (isObjectMethod) { 147 const char* lastName = strrchr(name, ':') - 1; 148 int namespaceLength = lastName - name; 149 150 uint32 argValue = 0; 151 if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) { 152 kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image, 153 namespaceLength, name, argValue, lastName); 154 } else 155 kprintf("<%s> %.*s<???>%s", image, namespaceLength, name, lastName); 156 157 if (addDebugVariables) 158 set_debug_variable("_this", argValue); 159 arg++; 160 } else 161 kprintf("<%s> %s", image, name); 162 163 kprintf("("); 164 165 size_t length; 166 int32 type, i = 0; 167 uint32 cookie = 0; 168 while (debug_get_next_demangled_argument(&cookie, symbol, buffer, 169 kBufferSize, &type, &length) == B_OK) { 170 if (i++ > 0) 171 kprintf(", "); 172 173 // retrieve value and type identifier 174 175 uint64 value; 176 bool valueKnown = false; 177 178 switch (type) { 179 case B_INT64_TYPE: 180 value = read_function_argument_value<int64>(arg, valueKnown); 181 if (valueKnown) 182 kprintf("int64: \33[34m%Ld\33[0m", value); 183 break; 184 case B_INT32_TYPE: 185 value = read_function_argument_value<int32>(arg, valueKnown); 186 if (valueKnown) 187 kprintf("int32: \33[34m%ld\33[0m", (int32)value); 188 break; 189 case B_INT16_TYPE: 190 value = read_function_argument_value<int16>(arg, valueKnown); 191 if (valueKnown) 192 kprintf("int16: \33[34m%d\33[0m", (int16)value); 193 break; 194 case B_INT8_TYPE: 195 value = read_function_argument_value<int8>(arg, valueKnown); 196 if (valueKnown) 197 kprintf("int8: \33[34m%d\33[0m", (int8)value); 198 break; 199 case B_UINT64_TYPE: 200 value = read_function_argument_value<uint64>(arg, valueKnown); 201 if (valueKnown) { 202 kprintf("uint64: \33[34m%#Lx\33[0m", value); 203 if (value < 0x100000) 204 kprintf(" (\33[34m%Lu\33[0m)", value); 205 } 206 break; 207 case B_UINT32_TYPE: 208 value = read_function_argument_value<uint32>(arg, valueKnown); 209 if (valueKnown) { 210 kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value); 211 if (value < 0x100000) 212 kprintf(" (\33[34m%lu\33[0m)", (uint32)value); 213 } 214 break; 215 case B_UINT16_TYPE: 216 value = read_function_argument_value<uint16>(arg, valueKnown); 217 if (valueKnown) { 218 kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)", 219 (uint16)value, (uint16)value); 220 } 221 break; 222 case B_UINT8_TYPE: 223 value = read_function_argument_value<uint8>(arg, valueKnown); 224 if (valueKnown) { 225 kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)", 226 (uint8)value, (uint8)value); 227 } 228 break; 229 case B_BOOL_TYPE: 230 value = read_function_argument_value<uint8>(arg, valueKnown); 231 if (valueKnown) 232 kprintf("\33[34m%s\33[0m", value ? "true" : "false"); 233 break; 234 default: 235 if (buffer[0]) 236 kprintf("%s: ", buffer); 237 238 if (length == 4) { 239 value = read_function_argument_value<uint32>(arg, 240 valueKnown); 241 if (valueKnown) { 242 if (value == 0 243 && (type == B_POINTER_TYPE || type == B_REF_TYPE)) 244 kprintf("NULL"); 245 else 246 kprintf("\33[34m%#lx\33[0m", (uint32)value); 247 } 248 break; 249 } 250 251 252 if (length == 8) { 253 value = read_function_argument_value<uint64>(arg, 254 valueKnown); 255 } else 256 value = (uint64)arg; 257 258 if (valueKnown) 259 kprintf("\33[34m%#Lx\33[0m", value); 260 break; 261 } 262 263 if (!valueKnown) 264 kprintf("???"); 265 266 if (valueKnown && type == B_STRING_TYPE) { 267 if (value == 0) 268 kprintf(" \33[31m\"<NULL>\"\33[0m"); 269 else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)(addr_t)value, 270 kBufferSize) < B_OK) { 271 kprintf(" \33[31m\"<???>\"\33[0m"); 272 } else 273 kprintf(" \33[36m\"%s\"\33[0m", buffer); 274 } 275 276 if (addDebugVariables) 277 set_debug_argument_variable(i, value); 278 arg = (uint32*)((uint8*)arg + length); 279 } 280 281 debug_free(buffer); 282 283 kprintf(")"); 284 return B_OK; 285 } 286 287 288 289 static void 290 print_stack_frame(Thread *thread, addr_t ip, addr_t fp, addr_t next, 291 int32 callIndex, bool demangle) 292 { 293 const char* symbol; 294 const char* image; 295 addr_t baseAddress; 296 bool exactMatch; 297 status_t status; 298 addr_t diff; 299 300 diff = next - fp; 301 302 // MSB set = kernel space/user space switch 303 if (diff & ~((addr_t)-1 >> 1)) 304 diff = 0; 305 306 status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image, 307 &exactMatch); 308 309 kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex, 310 B_PRINTF_POINTER_WIDTH, fp, diff, B_PRINTF_POINTER_WIDTH, ip); 311 312 if (status == B_OK) { 313 if (exactMatch && demangle) { 314 status = print_demangled_call(image, symbol, 315 next, false, false); 316 } 317 318 if (!exactMatch || !demangle || status != B_OK) { 319 if (symbol != NULL) { 320 kprintf("<%s> %s%s", image, symbol, 321 exactMatch ? "" : " (nearest)"); 322 } else 323 kprintf("<%s@%p> <unknown>", image, (void*)baseAddress); 324 } 325 326 kprintf(" + %#04lx\n", ip - baseAddress); 327 } else { 328 VMArea *area = NULL; 329 if (thread != NULL && thread->team != NULL 330 && thread->team->address_space != NULL) { 331 area = thread->team->address_space->LookupArea(ip); 332 } 333 if (area != NULL) { 334 kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name, 335 (void*)area->Base(), ip - area->Base()); 336 } else 337 kprintf("\n"); 338 } 339 } 340 341 static int 342 stack_trace(int argc, char **argv) 343 { 344 static const char* usage = "usage: %s [-d] [ <thread id> ]\n" 345 "Prints a stack trace for the current, respectively the specified\n" 346 "thread.\n" 347 " -d - Disables the demangling of the symbols.\n" 348 " <thread id> - The ID of the thread for which to print the stack\n" 349 " trace.\n"; 350 bool demangle = true; 351 int32 threadIndex = 1; 352 if (argc > 1 && !strcmp(argv[1], "-d")) { 353 demangle = false; 354 threadIndex++; 355 } 356 357 if (argc > threadIndex + 1 358 || (argc == 2 && strcmp(argv[1], "--help") == 0)) { 359 kprintf(usage, argv[0]); 360 return 0; 361 } 362 363 addr_t previousLocations[NUM_PREVIOUS_LOCATIONS]; 364 Thread* thread = NULL; 365 phys_addr_t oldPageDirectory = 0; 366 addr_t fp = arm_get_fp(); 367 int32 num = 0, last = 0; 368 struct iframe_stack *frameStack; 369 370 // We don't have a thread pointer early in the boot process 371 if (thread != NULL) 372 frameStack = &thread->arch_info.iframes; 373 else 374 frameStack = &gBootFrameStack; 375 376 int32 i; 377 for (i = 0; i < frameStack->index; i++) { 378 kprintf("iframe %p (end = %p)\n", 379 frameStack->frames[i], frameStack->frames[i] + 1); 380 } 381 382 if (thread != NULL) { 383 kprintf("stack trace for thread 0x%lx \"%s\"\n", thread->id, 384 thread->name); 385 386 kprintf(" kernel stack: %p to %p\n", 387 (void *)thread->kernel_stack_base, 388 (void *)(thread->kernel_stack_top)); 389 if (thread->user_stack_base != 0) { 390 kprintf(" user stack: %p to %p\n", 391 (void *)thread->user_stack_base, 392 (void *)(thread->user_stack_base + thread->user_stack_size)); 393 } 394 } 395 396 kprintf("frame caller <image>:function + offset\n"); 397 398 for (int32 callIndex = 0;; callIndex++) { 399 // see if the frame pointer matches the iframe 400 struct iframe *frame = NULL; 401 for (i = 0; i < frameStack->index; i++) { 402 if (fp == (addr_t)frameStack->frames[i]) { 403 // it's an iframe 404 frame = frameStack->frames[i]; 405 break; 406 } 407 } 408 409 if (frame) { 410 kprintf("iframe at %p\n", frame); 411 kprintf(" r0 0x%08lx r1 0x%08lx r2 0x%08lx r3 0x%08lx\n", 412 frame->r0, frame->r1, frame->r2, frame->r3); 413 kprintf(" r4 0x%08lx r5 0x%08lx r6 0x%08lx r7 0x%08lx\n", 414 frame->r4, frame->r5, frame->r6, frame->r7); 415 kprintf(" r8 0x%08lx r9 0x%08lx r10 0x%08lx r11 0x%08lx\n", 416 frame->r8, frame->r9, frame->r10, frame->r11); 417 kprintf(" r12 0x%08lx sp 0x%08lx lr 0x%08lx pc 0x%08lx\n", 418 frame->r12, frame->svc_sp, frame->svc_lr, frame->pc); 419 420 fp = frame->svc_sp; 421 print_stack_frame(thread, frame->pc, frame->svc_sp, frame->svc_lr, callIndex, demangle); 422 } else { 423 addr_t ip, next; 424 425 if (get_next_frame(fp, &next, &ip) != B_OK) { 426 kprintf("%08lx -- read fault\n", fp); 427 break; 428 } 429 430 if (ip == 0 || fp == 0) 431 break; 432 433 print_stack_frame(thread, ip, fp, next, callIndex, demangle); 434 fp = next; 435 } 436 437 if (already_visited(previousLocations, &last, &num, fp)) { 438 kprintf("circular stack frame: %p!\n", (void *)fp); 439 break; 440 } 441 if (fp == 0) 442 break; 443 } 444 445 return 0; 446 } 447 448 449 // #pragma mark - 450 451 452 void 453 arch_debug_save_registers(struct arch_debug_registers* registers) 454 { 455 } 456 457 458 bool 459 arch_debug_contains_call(Thread *thread, const char *symbol, 460 addr_t start, addr_t end) 461 { 462 return false; 463 } 464 465 466 void 467 arch_debug_stack_trace(void) 468 { 469 stack_trace(0, NULL); 470 } 471 472 473 void * 474 arch_debug_get_caller(void) 475 { 476 /* Return the thread id as the kernel (for example the lock code) actually 477 gets a somewhat valid indication of the caller back. */ 478 return (void*) thread_get_current_thread_id(); 479 } 480 481 482 int32 483 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, 484 int32 skipIframes, int32 skipFrames, uint32 flags) 485 { 486 // TODO: Implement! 487 return 0; 488 } 489 490 491 void* 492 arch_debug_get_interrupt_pc(bool* _isSyscall) 493 { 494 // TODO: Implement! 495 return NULL; 496 } 497 498 499 bool 500 arch_is_debug_variable_defined(const char* variableName) 501 { 502 // TODO: Implement! 503 return false; 504 } 505 506 507 status_t 508 arch_set_debug_variable(const char* variableName, uint64 value) 509 { 510 // TODO: Implement! 511 return B_ENTRY_NOT_FOUND; 512 } 513 514 515 status_t 516 arch_get_debug_variable(const char* variableName, uint64* value) 517 { 518 // TODO: Implement! 519 return B_ENTRY_NOT_FOUND; 520 } 521 522 523 status_t 524 arch_debug_init(kernel_args *args) 525 { 526 add_debugger_command("where", &stack_trace, "Same as \"sc\""); 527 add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)"); 528 add_debugger_command("sc", &stack_trace, "Stack crawl for current thread"); 529 530 return B_NO_ERROR; 531 } 532 533 534 /* arch_debug_call_with_fault_handler is in arch_asm.S */ 535 536 void 537 arch_debug_unset_current_thread(void) 538 { 539 // TODO: Implement! 540 } 541 542 543 ssize_t 544 arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) 545 { 546 // TODO: Implement! 547 return B_NOT_SUPPORTED; 548 } 549