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