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