1 /*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
4 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
5 * Distributed under the terms of the MIT License.
6 *
7 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
10
11
12 #include <arch/debug.h>
13
14 #include <stdio.h>
15 #include <stdlib.h>
16
17 #include <ByteOrder.h>
18 #include <TypeConstants.h>
19
20 #include <cpu.h>
21 #include <debug.h>
22 #include <debug_heap.h>
23 #include <elf.h>
24 #include <kernel.h>
25 #include <kimage.h>
26 #include <thread.h>
27 #include <vm/vm.h>
28 #include <vm/vm_types.h>
29 #include <vm/VMAddressSpace.h>
30 #include <vm/VMArea.h>
31
32
33 struct stack_frame {
34 stack_frame* previous;
35 addr_t return_address;
36 };
37
38 #define NUM_PREVIOUS_LOCATIONS 32
39
40
41 static bool is_kernel_stack_address(Thread* thread, addr_t address);
42
43
44 static bool
already_visited(addr_t * visited,int32 * _last,int32 * _num,addr_t bp)45 already_visited(addr_t* visited, int32* _last, int32* _num, addr_t bp)
46 {
47 int32 last = *_last;
48 int32 num = *_num;
49 int32 i;
50
51 for (i = 0; i < num; i++) {
52 if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == bp)
53 return true;
54 }
55
56 *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
57 visited[last] = bp;
58
59 if (num < NUM_PREVIOUS_LOCATIONS)
60 *_num = num + 1;
61
62 return false;
63 }
64
65
66 /*! Safe to be called only from outside the debugger.
67 */
68 static status_t
get_next_frame_no_debugger(addr_t bp,addr_t * _next,addr_t * _ip,bool onKernelStack,Thread * thread)69 get_next_frame_no_debugger(addr_t bp, addr_t* _next, addr_t* _ip,
70 bool onKernelStack, Thread* thread)
71 {
72 // TODO: Do this more efficiently in assembly.
73 stack_frame frame;
74 if (onKernelStack
75 && is_kernel_stack_address(thread, bp + sizeof(frame) - 1)) {
76 memcpy(&frame, (void*)bp, sizeof(frame));
77 } else if (!IS_USER_ADDRESS(bp)
78 || user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK) {
79 return B_BAD_ADDRESS;
80 }
81
82 *_ip = frame.return_address;
83 *_next = (addr_t)frame.previous;
84
85 return B_OK;
86 }
87
88
89 /*! Safe to be called only from inside the debugger.
90 */
91 static status_t
get_next_frame_debugger(addr_t bp,addr_t * _next,addr_t * _ip)92 get_next_frame_debugger(addr_t bp, addr_t* _next, addr_t* _ip)
93 {
94 stack_frame frame;
95 if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)bp, sizeof(frame)) != B_OK)
96 return B_BAD_ADDRESS;
97
98 *_ip = frame.return_address;
99 *_next = (addr_t)frame.previous;
100
101 return B_OK;
102 }
103
104
105 static status_t
lookup_symbol(Thread * thread,addr_t address,addr_t * _baseAddress,const char ** _symbolName,const char ** _imageName,bool * _exactMatch)106 lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
107 const char** _symbolName, const char** _imageName, bool* _exactMatch)
108 {
109 status_t status = B_ENTRY_NOT_FOUND;
110
111 if (IS_KERNEL_ADDRESS(address)) {
112 // a kernel symbol
113 status = elf_debug_lookup_symbol_address(address, _baseAddress,
114 _symbolName, _imageName, _exactMatch);
115 } else if (thread != NULL && thread->team != NULL) {
116 // try a lookup using the userland runtime loader structures
117 status = elf_debug_lookup_user_symbol_address(thread->team, address,
118 _baseAddress, _symbolName, _imageName, _exactMatch);
119
120 if (status != B_OK) {
121 // try to locate the image in the images loaded into user space
122 status = image_debug_lookup_user_symbol_address(thread->team,
123 address, _baseAddress, _symbolName, _imageName, _exactMatch);
124 }
125 }
126
127 return status;
128 }
129
130
131 #ifndef __x86_64__
132
133
134 static void
set_debug_argument_variable(int32 index,uint64 value)135 set_debug_argument_variable(int32 index, uint64 value)
136 {
137 char name[8];
138 snprintf(name, sizeof(name), "_arg%d", index);
139 set_debug_variable(name, value);
140 }
141
142
143 template<typename Type>
144 static Type
read_function_argument_value(void * argument,bool & _valueKnown)145 read_function_argument_value(void* argument, bool& _valueKnown)
146 {
147 Type value;
148 if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) {
149 _valueKnown = true;
150 return value;
151 }
152
153 _valueKnown = false;
154 return 0;
155 }
156
157
158 static status_t
print_demangled_call(const char * image,const char * symbol,addr_t args,bool noObjectMethod,bool addDebugVariables)159 print_demangled_call(const char* image, const char* symbol, addr_t args,
160 bool noObjectMethod, bool addDebugVariables)
161 {
162 static const size_t kBufferSize = 256;
163 char* buffer = (char*)debug_malloc(kBufferSize);
164 if (buffer == NULL)
165 return B_NO_MEMORY;
166
167 bool isObjectMethod;
168 const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
169 &isObjectMethod);
170 if (name == NULL) {
171 debug_free(buffer);
172 return B_ERROR;
173 }
174
175 uint32* arg = (uint32*)args;
176
177 if (noObjectMethod)
178 isObjectMethod = false;
179 if (isObjectMethod) {
180 const char* lastName = strrchr(name, ':') - 1;
181 int namespaceLength = lastName - name;
182
183 uint32 argValue = 0;
184 if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) {
185 kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image,
186 namespaceLength, name, argValue, lastName);
187 } else
188 kprintf("<%s> %.*s<\?\?\?>%s", image, namespaceLength, name, lastName);
189
190 if (addDebugVariables)
191 set_debug_variable("_this", argValue);
192 arg++;
193 } else
194 kprintf("<%s> %s", image, name);
195
196 kprintf("(");
197
198 size_t length;
199 int32 type, i = 0;
200 uint32 cookie = 0;
201 while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
202 kBufferSize, &type, &length) == B_OK) {
203 if (i++ > 0)
204 kprintf(", ");
205
206 // retrieve value and type identifier
207
208 uint64 value;
209 bool valueKnown = false;
210
211 switch (type) {
212 case B_INT64_TYPE:
213 value = read_function_argument_value<int64>(arg, valueKnown);
214 if (valueKnown)
215 kprintf("int64: \33[34m%lld\33[0m", value);
216 break;
217 case B_INT32_TYPE:
218 value = read_function_argument_value<int32>(arg, valueKnown);
219 if (valueKnown)
220 kprintf("int32: \33[34m%d\33[0m", (int32)value);
221 break;
222 case B_INT16_TYPE:
223 value = read_function_argument_value<int16>(arg, valueKnown);
224 if (valueKnown)
225 kprintf("int16: \33[34m%d\33[0m", (int16)value);
226 break;
227 case B_INT8_TYPE:
228 value = read_function_argument_value<int8>(arg, valueKnown);
229 if (valueKnown)
230 kprintf("int8: \33[34m%d\33[0m", (int8)value);
231 break;
232 case B_UINT64_TYPE:
233 value = read_function_argument_value<uint64>(arg, valueKnown);
234 if (valueKnown) {
235 kprintf("uint64: \33[34m%#Lx\33[0m", value);
236 if (value < 0x100000)
237 kprintf(" (\33[34m%Lu\33[0m)", value);
238 }
239 break;
240 case B_UINT32_TYPE:
241 value = read_function_argument_value<uint32>(arg, valueKnown);
242 if (valueKnown) {
243 kprintf("uint32: \33[34m%#x\33[0m", (uint32)value);
244 if (value < 0x100000)
245 kprintf(" (\33[34m%u\33[0m)", (uint32)value);
246 }
247 break;
248 case B_UINT16_TYPE:
249 value = read_function_argument_value<uint16>(arg, valueKnown);
250 if (valueKnown) {
251 kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
252 (uint16)value, (uint16)value);
253 }
254 break;
255 case B_UINT8_TYPE:
256 value = read_function_argument_value<uint8>(arg, valueKnown);
257 if (valueKnown) {
258 kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
259 (uint8)value, (uint8)value);
260 }
261 break;
262 case B_BOOL_TYPE:
263 value = read_function_argument_value<uint8>(arg, valueKnown);
264 if (valueKnown)
265 kprintf("\33[34m%s\33[0m", value ? "true" : "false");
266 break;
267 default:
268 if (buffer[0])
269 kprintf("%s: ", buffer);
270
271 if (length == 4) {
272 value = read_function_argument_value<uint32>(arg,
273 valueKnown);
274 if (valueKnown) {
275 if (value == 0
276 && (type == B_POINTER_TYPE || type == B_REF_TYPE))
277 kprintf("NULL");
278 else
279 kprintf("\33[34m%#x\33[0m", (uint32)value);
280 }
281 break;
282 }
283
284
285 if (length == 8) {
286 value = read_function_argument_value<uint64>(arg,
287 valueKnown);
288 } else
289 value = (uint64)arg;
290
291 if (valueKnown)
292 kprintf("\33[34m%#Lx\33[0m", value);
293 break;
294 }
295
296 if (!valueKnown)
297 kprintf("???");
298
299 if (valueKnown && type == B_STRING_TYPE) {
300 if (value == 0)
301 kprintf(" \33[31m\"<NULL>\"\33[0m");
302 else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)(addr_t)value,
303 kBufferSize) < B_OK) {
304 kprintf(" \33[31m\"<\?\?\?>\"\33[0m");
305 } else
306 kprintf(" \33[36m\"%s\"\33[0m", buffer);
307 }
308
309 if (addDebugVariables)
310 set_debug_argument_variable(i, value);
311 arg = (uint32*)((uint8*)arg + length);
312 }
313
314 debug_free(buffer);
315
316 kprintf(")");
317 return B_OK;
318 }
319
320
321 #else // __x86_64__
322
323
324 static status_t
print_demangled_call(const char * image,const char * symbol,addr_t args,bool noObjectMethod,bool addDebugVariables)325 print_demangled_call(const char* image, const char* symbol, addr_t args,
326 bool noObjectMethod, bool addDebugVariables)
327 {
328 // Since x86_64 uses registers rather than the stack for the first 6
329 // arguments we cannot use the same method as x86 to read the function
330 // arguments. Maybe we need DWARF support in the kernel debugger. For now
331 // just print out the function signature without the argument values.
332
333 static const size_t kBufferSize = 256;
334 char* buffer = (char*)debug_malloc(kBufferSize);
335 if (buffer == NULL)
336 return B_NO_MEMORY;
337
338 bool isObjectMethod;
339 const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
340 &isObjectMethod);
341 if (name == NULL) {
342 debug_free(buffer);
343 return B_ERROR;
344 }
345
346 kprintf("<%s> %s(", image, name);
347
348 size_t length;
349 int32 type, i = 0;
350 uint32 cookie = 0;
351 while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
352 kBufferSize, &type, &length) == B_OK) {
353 if (i++ > 0)
354 kprintf(", ");
355
356 if (buffer[0])
357 kprintf("%s", buffer);
358 else
359 kprintf("???");
360 }
361
362 debug_free(buffer);
363
364 kprintf(")");
365 return B_OK;
366 }
367
368
369 #endif // __x86_64__
370
371
372 static void
print_stack_frame(Thread * thread,addr_t ip,addr_t calleeBp,addr_t bp,int32 callIndex,bool demangle)373 print_stack_frame(Thread* thread, addr_t ip, addr_t calleeBp, addr_t bp,
374 int32 callIndex, bool demangle)
375 {
376 const char* symbol;
377 const char* image;
378 addr_t baseAddress;
379 bool exactMatch;
380 status_t status;
381 addr_t diff;
382
383 diff = bp - calleeBp;
384
385 // kernel space/user space switch
386 if (calleeBp > bp)
387 diff = 0;
388
389 status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image,
390 &exactMatch);
391
392 kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex,
393 B_PRINTF_POINTER_WIDTH, bp, diff, B_PRINTF_POINTER_WIDTH, ip);
394
395 if (status == B_OK) {
396 if (exactMatch && demangle) {
397 status = print_demangled_call(image, symbol,
398 bp + sizeof(stack_frame), false, false);
399 }
400
401 if (!exactMatch || !demangle || status != B_OK) {
402 if (symbol != NULL) {
403 kprintf("<%s> %s%s", image, symbol,
404 exactMatch ? "" : " (nearest)");
405 } else
406 kprintf("<%s@%p> <unknown>", image, (void*)baseAddress);
407 }
408
409 kprintf(" + %#04lx\n", ip - baseAddress);
410 } else {
411 VMArea *area = NULL;
412 if (thread != NULL && thread->team != NULL
413 && thread->team->address_space != NULL) {
414 area = thread->team->address_space->LookupArea(ip);
415 }
416 if (area != NULL) {
417 kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name,
418 (void*)area->Base(), ip - area->Base());
419 } else
420 kprintf("\n");
421 }
422 }
423
424
425 static void
print_iframe(iframe * frame)426 print_iframe(iframe* frame)
427 {
428 bool isUser = IFRAME_IS_USER(frame);
429
430 #ifdef __x86_64__
431 kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
432 frame + 1);
433
434 kprintf(" rax %#-18lx rbx %#-18lx rcx %#lx\n", frame->ax,
435 frame->bx, frame->cx);
436 kprintf(" rdx %#-18lx rsi %#-18lx rdi %#lx\n", frame->dx,
437 frame->si, frame->di);
438 kprintf(" rbp %#-18lx r8 %#-18lx r9 %#lx\n", frame->bp,
439 frame->r8, frame->r9);
440 kprintf(" r10 %#-18lx r11 %#-18lx r12 %#lx\n", frame->r10,
441 frame->r11, frame->r12);
442 kprintf(" r13 %#-18lx r14 %#-18lx r15 %#lx\n", frame->r13,
443 frame->r14, frame->r15);
444 kprintf(" rip %#-18lx rsp %#-18lx rflags %#lx\n", frame->ip,
445 frame->sp, frame->flags);
446 #else
447 kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
448 isUser ? (void*)(frame + 1) : (void*)&frame->user_sp);
449
450 kprintf(" eax %#-10x ebx %#-10x ecx %#-10x edx %#x\n",
451 frame->ax, frame->bx, frame->cx, frame->dx);
452 kprintf(" esi %#-10x edi %#-10x ebp %#-10x esp %#x\n",
453 frame->si, frame->di, frame->bp, frame->sp);
454 kprintf(" eip %#-10x eflags %#-10x", frame->ip, frame->flags);
455 if (isUser) {
456 // from user space
457 kprintf("user esp %#x", frame->user_sp);
458 }
459 kprintf("\n");
460 #endif
461
462 kprintf(" vector: %#lx, error code: %#lx\n",
463 (long unsigned int)frame->vector,
464 (long unsigned int)frame->error_code);
465 }
466
467
468 static bool
setup_for_thread(char * arg,Thread ** _thread,addr_t * _bp,phys_addr_t * _oldPageDirectory)469 setup_for_thread(char* arg, Thread** _thread, addr_t* _bp,
470 phys_addr_t* _oldPageDirectory)
471 {
472 Thread* thread = NULL;
473
474 if (arg != NULL) {
475 thread_id id = strtoul(arg, NULL, 0);
476 thread = Thread::GetDebug(id);
477 if (thread == NULL) {
478 kprintf("could not find thread %" B_PRId32 "\n", id);
479 return false;
480 }
481
482 if (id != thread_get_current_thread_id()) {
483 // switch to the page directory of the new thread to be
484 // able to follow the stack trace into userland
485 phys_addr_t newPageDirectory = x86_next_page_directory(
486 thread_get_current_thread(), thread);
487
488 if (newPageDirectory != 0) {
489 *_oldPageDirectory = x86_read_cr3();
490 x86_write_cr3(newPageDirectory);
491 }
492
493 if (thread->state == B_THREAD_RUNNING) {
494 // The thread is currently running on another CPU.
495 if (thread->cpu == NULL)
496 return false;
497 arch_debug_registers* registers = debug_get_debug_registers(
498 thread->cpu->cpu_num);
499 if (registers == NULL)
500 return false;
501 *_bp = registers->bp;
502 } else {
503 // Read frame pointer from the thread's stack.
504 *_bp = thread->arch_info.GetFramePointer();
505 }
506 } else
507 thread = NULL;
508 }
509
510 if (thread == NULL) {
511 // if we don't have a thread yet, we want the current one
512 // (ebp has been set by the caller for this case already)
513 thread = thread_get_current_thread();
514 }
515
516 *_thread = thread;
517 return true;
518 }
519
520
521 static bool
is_double_fault_stack_address(int32 cpu,addr_t address)522 is_double_fault_stack_address(int32 cpu, addr_t address)
523 {
524 size_t size;
525 addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size);
526 return address >= bottom && address < bottom + size;
527 }
528
529
530 static bool
is_kernel_stack_address(Thread * thread,addr_t address)531 is_kernel_stack_address(Thread* thread, addr_t address)
532 {
533 // We don't have a thread pointer in the early boot process, but then we are
534 // on the kernel stack for sure.
535 if (thread == NULL)
536 return IS_KERNEL_ADDRESS(address);
537
538 // Also in the early boot process we might have a thread structure, but it
539 // might not have its kernel stack attributes set yet.
540 if (thread->kernel_stack_top == 0)
541 return IS_KERNEL_ADDRESS(address);
542
543 return (address >= thread->kernel_stack_base
544 && address < thread->kernel_stack_top)
545 || (thread->cpu != NULL
546 && is_double_fault_stack_address(thread->cpu->cpu_num, address));
547 }
548
549
550 static bool
is_iframe(Thread * thread,addr_t frame)551 is_iframe(Thread* thread, addr_t frame)
552 {
553 if (!is_kernel_stack_address(thread, frame))
554 return false;
555
556 addr_t previousFrame = *(addr_t*)frame;
557 return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0
558 && previousFrame != 0);
559 }
560
561
562 static iframe*
find_previous_iframe(Thread * thread,addr_t frame)563 find_previous_iframe(Thread* thread, addr_t frame)
564 {
565 // iterate backwards through the stack frames, until we hit an iframe
566 while (is_kernel_stack_address(thread, frame)) {
567 if (is_iframe(thread, frame))
568 return (iframe*)frame;
569
570 frame = *(addr_t*)frame;
571 }
572
573 return NULL;
574 }
575
576
577 static iframe*
get_previous_iframe(Thread * thread,iframe * frame)578 get_previous_iframe(Thread* thread, iframe* frame)
579 {
580 if (frame == NULL)
581 return NULL;
582
583 return find_previous_iframe(thread, frame->bp);
584 }
585
586
587 static iframe*
get_current_iframe(Thread * thread)588 get_current_iframe(Thread* thread)
589 {
590 if (thread == thread_get_current_thread())
591 return x86_get_current_iframe();
592
593 // NOTE: This doesn't work, if the thread is running (on another CPU).
594 return find_previous_iframe(thread, thread->arch_info.GetFramePointer());
595 }
596
597
598 #define CHECK_DEBUG_VARIABLE(_name, _member, _settable) \
599 if (strcmp(variableName, _name) == 0) { \
600 settable = _settable; \
601 return (addr_t*)&_member; \
602 }
603
604
605 static addr_t*
find_debug_variable(const char * variableName,bool & settable)606 find_debug_variable(const char* variableName, bool& settable)
607 {
608 iframe* frame = get_current_iframe(debug_get_debugged_thread());
609 if (frame == NULL)
610 return NULL;
611
612 #ifdef __x86_64__
613 CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
614 CHECK_DEBUG_VARIABLE("ss", frame->ss, false);
615 CHECK_DEBUG_VARIABLE("r15", frame->r15, true);
616 CHECK_DEBUG_VARIABLE("r14", frame->r14, true);
617 CHECK_DEBUG_VARIABLE("r13", frame->r13, true);
618 CHECK_DEBUG_VARIABLE("r12", frame->r12, true);
619 CHECK_DEBUG_VARIABLE("r11", frame->r11, true);
620 CHECK_DEBUG_VARIABLE("r10", frame->r10, true);
621 CHECK_DEBUG_VARIABLE("r9", frame->r9, true);
622 CHECK_DEBUG_VARIABLE("r8", frame->r8, true);
623 CHECK_DEBUG_VARIABLE("rbp", frame->bp, true);
624 CHECK_DEBUG_VARIABLE("rsi", frame->si, true);
625 CHECK_DEBUG_VARIABLE("rdi", frame->di, true);
626 CHECK_DEBUG_VARIABLE("rdx", frame->dx, true);
627 CHECK_DEBUG_VARIABLE("rcx", frame->cx, true);
628 CHECK_DEBUG_VARIABLE("rbx", frame->bx, true);
629 CHECK_DEBUG_VARIABLE("rax", frame->ax, true);
630 CHECK_DEBUG_VARIABLE("rip", frame->ip, true);
631 CHECK_DEBUG_VARIABLE("rflags", frame->flags, true);
632 CHECK_DEBUG_VARIABLE("rsp", frame->sp, true);
633 #else
634 CHECK_DEBUG_VARIABLE("gs", frame->gs, false);
635 CHECK_DEBUG_VARIABLE("fs", frame->fs, false);
636 CHECK_DEBUG_VARIABLE("es", frame->es, false);
637 CHECK_DEBUG_VARIABLE("ds", frame->ds, false);
638 CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
639 CHECK_DEBUG_VARIABLE("edi", frame->di, true);
640 CHECK_DEBUG_VARIABLE("esi", frame->si, true);
641 CHECK_DEBUG_VARIABLE("ebp", frame->bp, true);
642 CHECK_DEBUG_VARIABLE("esp", frame->sp, true);
643 CHECK_DEBUG_VARIABLE("ebx", frame->bx, true);
644 CHECK_DEBUG_VARIABLE("edx", frame->dx, true);
645 CHECK_DEBUG_VARIABLE("ecx", frame->cx, true);
646 CHECK_DEBUG_VARIABLE("eax", frame->ax, true);
647 CHECK_DEBUG_VARIABLE("orig_eax", frame->orig_eax, true);
648 CHECK_DEBUG_VARIABLE("orig_edx", frame->orig_edx, true);
649 CHECK_DEBUG_VARIABLE("eip", frame->ip, true);
650 CHECK_DEBUG_VARIABLE("eflags", frame->flags, true);
651
652 if (IFRAME_IS_USER(frame)) {
653 CHECK_DEBUG_VARIABLE("user_esp", frame->user_sp, true);
654 CHECK_DEBUG_VARIABLE("user_ss", frame->user_ss, false);
655 }
656 #endif
657
658 return NULL;
659 }
660
661
662 static int
stack_trace(int argc,char ** argv)663 stack_trace(int argc, char** argv)
664 {
665 static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
666 "Prints a stack trace for the current, respectively the specified\n"
667 "thread.\n"
668 " -d - Disables the demangling of the symbols.\n"
669 " <thread id> - The ID of the thread for which to print the stack\n"
670 " trace.\n";
671 bool demangle = true;
672 int32 threadIndex = 1;
673 if (argc > 1 && !strcmp(argv[1], "-d")) {
674 demangle = false;
675 threadIndex++;
676 }
677
678 if (argc > threadIndex + 1
679 || (argc == 2 && strcmp(argv[1], "--help") == 0)) {
680 kprintf(usage, argv[0]);
681 return 0;
682 }
683
684 addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
685 Thread* thread = NULL;
686 phys_addr_t oldPageDirectory = 0;
687 addr_t bp = x86_get_stack_frame();
688 int32 num = 0, last = 0;
689
690 if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
691 &thread, &bp, &oldPageDirectory))
692 return 0;
693
694 DebuggedThreadSetter threadSetter(thread);
695
696 if (thread != NULL) {
697 kprintf("stack trace for thread %" B_PRId32 " \"%s\"\n", thread->id,
698 thread->name);
699
700 kprintf(" kernel stack: %p to %p\n",
701 (void*)thread->kernel_stack_base,
702 (void*)(thread->kernel_stack_top));
703 if (thread->user_stack_base != 0) {
704 kprintf(" user stack: %p to %p\n",
705 (void*)thread->user_stack_base,
706 (void*)(thread->user_stack_base + thread->user_stack_size));
707 }
708 }
709
710 kprintf("%-*s %-*s <image>:function + offset\n",
711 B_PRINTF_POINTER_WIDTH, "frame", B_PRINTF_POINTER_WIDTH, "caller");
712
713 bool onKernelStack = true;
714
715 for (int32 callIndex = 0; ; callIndex++) {
716 onKernelStack = onKernelStack
717 && is_kernel_stack_address(thread, bp);
718
719 if (onKernelStack && is_iframe(thread, bp)) {
720 iframe* frame = (iframe*)bp;
721
722 print_iframe(frame);
723 print_stack_frame(thread, frame->ip, bp, frame->bp, callIndex,
724 demangle);
725
726 bp = frame->bp;
727 } else {
728 addr_t ip, nextBp;
729
730 if (get_next_frame_debugger(bp, &nextBp, &ip) != B_OK) {
731 kprintf("%0*lx -- read fault\n", B_PRINTF_POINTER_WIDTH, bp);
732 break;
733 }
734
735 if (ip == 0 || bp == 0)
736 break;
737
738 print_stack_frame(thread, ip, bp, nextBp, callIndex, demangle);
739 bp = nextBp;
740 }
741
742 if (already_visited(previousLocations, &last, &num, bp)) {
743 kprintf("circular stack frame: %p!\n", (void*)bp);
744 break;
745 }
746 if (bp == 0)
747 break;
748 }
749
750 if (oldPageDirectory != 0) {
751 // switch back to the previous page directory to no cause any troubles
752 x86_write_cr3(oldPageDirectory);
753 }
754
755 return 0;
756 }
757
758
759 #ifndef __x86_64__
760 static void
print_call(Thread * thread,addr_t eip,addr_t ebp,addr_t nextEbp,int32 argCount)761 print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
762 int32 argCount)
763 {
764 const char *symbol, *image;
765 addr_t baseAddress;
766 bool exactMatch;
767 status_t status;
768 bool demangled = false;
769 int32 *arg = (int32 *)(nextEbp + 8);
770
771 status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
772 &exactMatch);
773
774 kprintf("%08lx %08lx ", ebp, eip);
775
776 if (status == B_OK) {
777 if (symbol != NULL) {
778 if (exactMatch && (argCount == 0 || argCount == -1)) {
779 status = print_demangled_call(image, symbol, (addr_t)arg,
780 argCount == -1, true);
781 if (status == B_OK)
782 demangled = true;
783 }
784 if (!demangled) {
785 kprintf("<%s>:%s%s", image, symbol,
786 exactMatch ? "" : " (nearest)");
787 }
788 } else {
789 kprintf("<%s@%p>:unknown + 0x%04lx", image,
790 (void *)baseAddress, eip - baseAddress);
791 }
792 } else {
793 VMArea *area = NULL;
794 if (thread->team->address_space != NULL)
795 area = thread->team->address_space->LookupArea(eip);
796 if (area != NULL) {
797 kprintf("%d:%s@%p + %#lx", area->id, area->name,
798 (void *)area->Base(), eip - area->Base());
799 }
800 }
801
802 if (!demangled) {
803 kprintf("(");
804
805 for (int32 i = 0; i < argCount; i++) {
806 if (i > 0)
807 kprintf(", ");
808 kprintf("%#x", *arg);
809 if (*arg > -0x10000 && *arg < 0x10000)
810 kprintf(" (%d)", *arg);
811
812 set_debug_argument_variable(i + 1, *(uint32 *)arg);
813 arg++;
814 }
815
816 kprintf(")\n");
817 } else
818 kprintf("\n");
819
820 set_debug_variable("_frame", nextEbp);
821 }
822
823
824 static int
show_call(int argc,char ** argv)825 show_call(int argc, char **argv)
826 {
827 static const char* usage
828 = "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n"
829 "Prints a function call with parameters of the current, respectively\n"
830 "the specified thread.\n"
831 " <thread id> - The ID of the thread for which to print the call.\n"
832 " <call index> - The index of the call in the stack trace.\n"
833 " <arg count> - The number of call arguments to print (use 'c' to\n"
834 " force the C++ demangler to use class methods,\n"
835 " use 'd' to disable demangling).\n";
836 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
837 kprintf(usage, argv[0]);
838 return 0;
839 }
840
841 Thread *thread = NULL;
842 phys_addr_t oldPageDirectory = 0;
843 addr_t ebp = x86_get_stack_frame();
844 int32 argCount = 0;
845
846 if (argc >= 2 && argv[argc - 1][0] == '-') {
847 if (argv[argc - 1][1] == 'c')
848 argCount = -1;
849 else if (argv[argc - 1][1] == 'd')
850 argCount = -2;
851 else
852 argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
853
854 if (argCount < -2 || argCount > 16) {
855 kprintf("Invalid argument count \"%d\".\n", argCount);
856 return 0;
857 }
858 argc--;
859 }
860
861 if (argc < 2 || argc > 3) {
862 kprintf(usage, argv[0]);
863 return 0;
864 }
865
866 if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp,
867 &oldPageDirectory))
868 return 0;
869
870 DebuggedThreadSetter threadSetter(thread);
871
872 int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0);
873
874 if (thread != NULL)
875 kprintf("thread %d, %s\n", thread->id, thread->name);
876
877 bool onKernelStack = true;
878
879 for (int32 index = 0; index <= callIndex; index++) {
880 onKernelStack = onKernelStack
881 && is_kernel_stack_address(thread, ebp);
882
883 if (onKernelStack && is_iframe(thread, ebp)) {
884 struct iframe *frame = (struct iframe *)ebp;
885
886 if (index == callIndex)
887 print_call(thread, frame->ip, ebp, frame->bp, argCount);
888
889 ebp = frame->bp;
890 } else {
891 addr_t eip, nextEbp;
892
893 if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
894 kprintf("%08lx -- read fault\n", ebp);
895 break;
896 }
897
898 if (eip == 0 || ebp == 0)
899 break;
900
901 if (index == callIndex)
902 print_call(thread, eip, ebp, nextEbp, argCount);
903
904 ebp = nextEbp;
905 }
906
907 if (ebp == 0)
908 break;
909 }
910
911 if (oldPageDirectory != 0) {
912 // switch back to the previous page directory to not cause any troubles
913 x86_write_cr3(oldPageDirectory);
914 }
915
916 return 0;
917 }
918 #endif
919
920
921 static int
dump_iframes(int argc,char ** argv)922 dump_iframes(int argc, char** argv)
923 {
924 static const char* usage = "usage: %s [ <thread id> ]\n"
925 "Prints the iframe stack for the current, respectively the specified\n"
926 "thread.\n"
927 " <thread id> - The ID of the thread for which to print the iframe\n"
928 " stack.\n";
929 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
930 kprintf(usage, argv[0]);
931 return 0;
932 }
933
934 Thread* thread = NULL;
935
936 if (argc < 2) {
937 thread = thread_get_current_thread();
938 } else if (argc == 2) {
939 thread_id id = strtoul(argv[1], NULL, 0);
940 thread = Thread::GetDebug(id);
941 if (thread == NULL) {
942 kprintf("could not find thread %" B_PRId32 "\n", id);
943 return 0;
944 }
945 } else if (argc > 2) {
946 kprintf(usage, argv[0]);
947 return 0;
948 }
949
950 if (thread != NULL) {
951 kprintf("iframes for thread %" B_PRId32 " \"%s\"\n", thread->id,
952 thread->name);
953 }
954
955 DebuggedThreadSetter threadSetter(thread);
956
957 iframe* frame = find_previous_iframe(thread, x86_get_stack_frame());
958 while (frame != NULL) {
959 print_iframe(frame);
960 frame = get_previous_iframe(thread, frame);
961 }
962
963 return 0;
964 }
965
966
967 static bool
is_calling(Thread * thread,addr_t ip,const char * pattern,addr_t start,addr_t end)968 is_calling(Thread* thread, addr_t ip, const char* pattern, addr_t start,
969 addr_t end)
970 {
971 if (pattern == NULL)
972 return ip >= start && ip < end;
973
974 if (!IS_KERNEL_ADDRESS(ip))
975 return false;
976
977 const char* symbol;
978 if (lookup_symbol(thread, ip, NULL, &symbol, NULL, NULL) != B_OK)
979 return false;
980
981 return strstr(symbol, pattern);
982 }
983
984
985 static int
cmd_in_context(int argc,char ** argv)986 cmd_in_context(int argc, char** argv)
987 {
988 if (argc != 2) {
989 print_debugger_command_usage(argv[0]);
990 return 0;
991 }
992
993 // get the thread ID
994 const char* commandLine = argv[1];
995 char threadIDString[16];
996 if (parse_next_debug_command_argument(&commandLine, threadIDString,
997 sizeof(threadIDString)) != B_OK) {
998 kprintf("Failed to parse thread ID.\n");
999 return 0;
1000 }
1001
1002 if (commandLine == NULL) {
1003 print_debugger_command_usage(argv[0]);
1004 return 0;
1005 }
1006
1007 uint64 threadID;
1008 if (!evaluate_debug_expression(threadIDString, &threadID, false))
1009 return 0;
1010
1011 // get the thread
1012 Thread* thread = Thread::GetDebug(threadID);
1013 if (thread == NULL) {
1014 kprintf("Could not find thread with ID \"%s\".\n", threadIDString);
1015 return 0;
1016 }
1017
1018 // switch the page directory, if necessary
1019 phys_addr_t oldPageDirectory = 0;
1020 if (thread != thread_get_current_thread()) {
1021 phys_addr_t newPageDirectory = x86_next_page_directory(
1022 thread_get_current_thread(), thread);
1023
1024 if (newPageDirectory != 0) {
1025 oldPageDirectory = x86_read_cr3();
1026 x86_write_cr3(newPageDirectory);
1027 }
1028 }
1029
1030 // execute the command
1031 {
1032 DebuggedThreadSetter threadSetter(thread);
1033 evaluate_debug_command(commandLine);
1034 }
1035
1036 // reset the page directory
1037 if (oldPageDirectory)
1038 x86_write_cr3(oldPageDirectory);
1039
1040 return 0;
1041 }
1042
1043
1044 // #pragma mark -
1045
1046
1047 void
arch_debug_save_registers(arch_debug_registers * registers)1048 arch_debug_save_registers(arch_debug_registers* registers)
1049 {
1050 // get the caller's frame pointer
1051 stack_frame* frame = (stack_frame*)x86_get_stack_frame();
1052 registers->bp = (addr_t)frame->previous;
1053 }
1054
1055
1056 void
arch_debug_stack_trace(void)1057 arch_debug_stack_trace(void)
1058 {
1059 stack_trace(0, NULL);
1060 }
1061
1062
1063 bool
arch_debug_contains_call(Thread * thread,const char * symbol,addr_t start,addr_t end)1064 arch_debug_contains_call(Thread* thread, const char* symbol, addr_t start,
1065 addr_t end)
1066 {
1067 DebuggedThreadSetter threadSetter(thread);
1068
1069 addr_t bp;
1070 if (thread == thread_get_current_thread())
1071 bp = x86_get_stack_frame();
1072 else {
1073 if (thread->state == B_THREAD_RUNNING) {
1074 // The thread is currently running on another CPU.
1075 if (thread->cpu == NULL)
1076 return false;
1077 arch_debug_registers* registers = debug_get_debug_registers(
1078 thread->cpu->cpu_num);
1079 if (registers == NULL)
1080 return false;
1081 bp = registers->bp;
1082 } else {
1083 // thread not running
1084 bp = thread->arch_info.GetFramePointer();
1085 }
1086 }
1087
1088 for (;;) {
1089 if (!is_kernel_stack_address(thread, bp))
1090 break;
1091
1092 if (is_iframe(thread, bp)) {
1093 iframe* frame = (iframe*)bp;
1094
1095 if (is_calling(thread, frame->ip, symbol, start, end))
1096 return true;
1097
1098 bp = frame->bp;
1099 } else {
1100 addr_t ip, nextBp;
1101
1102 if (get_next_frame_no_debugger(bp, &nextBp, &ip, true,
1103 thread) != B_OK
1104 || ip == 0 || bp == 0)
1105 break;
1106
1107 if (is_calling(thread, ip, symbol, start, end))
1108 return true;
1109
1110 bp = nextBp;
1111 }
1112
1113 if (bp == 0)
1114 break;
1115 }
1116
1117 return false;
1118 }
1119
1120
1121 /*! Captures a stack trace (the return addresses) of the current thread.
1122 \param returnAddresses The array the return address shall be written to.
1123 \param maxCount The maximum number of return addresses to be captured.
1124 \param skipIframes The number of interrupt frames that shall be skipped. If
1125 greater than 0, \a skipFrames is ignored.
1126 \param skipFrames The number of stack frames that shall be skipped.
1127 \param flags A combination of one or two of the following:
1128 - \c STACK_TRACE_KERNEL: Capture kernel return addresses.
1129 - \c STACK_TRACE_USER: Capture user return addresses.
1130 \return The number of return addresses written to the given array.
1131 */
1132 int32
arch_debug_get_stack_trace(addr_t * returnAddresses,int32 maxCount,int32 skipIframes,int32 skipFrames,uint32 flags)1133 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
1134 int32 skipIframes, int32 skipFrames, uint32 flags)
1135 {
1136 // Keep skipping normal stack frames until we've skipped the iframes we're
1137 // supposed to skip.
1138 if (skipIframes > 0)
1139 skipFrames = INT_MAX;
1140
1141 Thread* thread = thread_get_current_thread();
1142 int32 count = 0;
1143 addr_t bp = x86_get_stack_frame();
1144 bool onKernelStack = true;
1145
1146 if ((flags & (STACK_TRACE_KERNEL | STACK_TRACE_USER)) == STACK_TRACE_USER) {
1147 iframe* frame = x86_get_user_iframe();
1148 if (frame == NULL)
1149 return 0;
1150
1151 bp = (addr_t)frame;
1152 }
1153
1154 while (bp != 0 && count < maxCount) {
1155 onKernelStack = onKernelStack
1156 && is_kernel_stack_address(thread, bp);
1157 if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
1158 break;
1159
1160 addr_t ip;
1161 addr_t nextBp;
1162
1163 if (onKernelStack && is_iframe(thread, bp)) {
1164 iframe* frame = (iframe*)bp;
1165 ip = frame->ip;
1166 nextBp = frame->bp;
1167
1168 if (skipIframes > 0) {
1169 if (--skipIframes == 0)
1170 skipFrames = 0;
1171 }
1172 } else {
1173 if (get_next_frame_no_debugger(bp, &nextBp, &ip,
1174 onKernelStack, thread) != B_OK) {
1175 break;
1176 }
1177 }
1178
1179 if (ip == 0)
1180 break;
1181
1182 if (skipFrames > 0)
1183 skipFrames--;
1184 else
1185 returnAddresses[count++] = ip;
1186
1187 bp = nextBp;
1188 }
1189
1190 return count;
1191 }
1192
1193
1194 /*! Returns the program counter of the currently debugged (respectively this)
1195 thread where the innermost interrupts happened. \a _isSyscall, if specified,
1196 is set to whether this interrupt frame was created by a syscall. Returns
1197 \c NULL, if there's no such frame or a problem occurred retrieving it;
1198 \a _isSyscall won't be set in this case.
1199 */
1200 void*
arch_debug_get_interrupt_pc(bool * _isSyscall)1201 arch_debug_get_interrupt_pc(bool* _isSyscall)
1202 {
1203 iframe* frame = get_current_iframe(debug_get_debugged_thread());
1204 if (frame == NULL)
1205 return NULL;
1206
1207 if (_isSyscall != NULL)
1208 *_isSyscall = frame->type == IFRAME_TYPE_SYSCALL;
1209
1210 return (void*)(addr_t)frame->ip;
1211 }
1212
1213
1214 /*! Sets the current thread to \c NULL.
1215 Invoked in the kernel debugger only.
1216 */
1217 void
arch_debug_unset_current_thread(void)1218 arch_debug_unset_current_thread(void)
1219 {
1220 // Can't just write 0 to the GS base, that will cause the read from %gs:0
1221 // to fault. Instead point it at a NULL pointer, %gs:0 will get this value.
1222 static Thread* unsetThread = NULL;
1223 #ifdef __x86_64__
1224 x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&unsetThread);
1225 #else
1226 asm volatile("mov %0, %%gs:0" : : "r" (unsetThread) : "memory");
1227 #endif
1228 }
1229
1230
1231 bool
arch_is_debug_variable_defined(const char * variableName)1232 arch_is_debug_variable_defined(const char* variableName)
1233 {
1234 bool settable;
1235 return find_debug_variable(variableName, settable);
1236 }
1237
1238
1239 status_t
arch_set_debug_variable(const char * variableName,uint64 value)1240 arch_set_debug_variable(const char* variableName, uint64 value)
1241 {
1242 bool settable;
1243 size_t* variable = find_debug_variable(variableName, settable);
1244 if (variable == NULL)
1245 return B_ENTRY_NOT_FOUND;
1246
1247 if (!settable)
1248 return B_NOT_ALLOWED;
1249
1250 *variable = (size_t)value;
1251 return B_OK;
1252 }
1253
1254
1255 status_t
arch_get_debug_variable(const char * variableName,uint64 * value)1256 arch_get_debug_variable(const char* variableName, uint64* value)
1257 {
1258 bool settable;
1259 size_t* variable = find_debug_variable(variableName, settable);
1260 if (variable == NULL)
1261 return B_ENTRY_NOT_FOUND;
1262
1263 *value = *variable;
1264 return B_OK;
1265 }
1266
1267
1268 struct gdb_register {
1269 int32 type;
1270 uint64 value;
1271 };
1272
1273
1274 /*! Writes the contents of the CPU registers at some fixed outer stack frame or
1275 iframe into the given buffer in the format expected by gdb.
1276
1277 This function is called in response to gdb's 'g' command.
1278
1279 \param buffer The buffer to write the registers to.
1280 \param bufferSize The size of \a buffer in bytes.
1281 \return When successful, the number of bytes written to \a buffer, or a
1282 negative error code on error.
1283 */
1284 ssize_t
arch_debug_gdb_get_registers(char * buffer,size_t bufferSize)1285 arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
1286 {
1287 iframe* frame = get_current_iframe(debug_get_debugged_thread());
1288 if (frame == NULL)
1289 return B_NOT_SUPPORTED;
1290
1291 #ifdef __x86_64__
1292 // For x86_64 the register order is:
1293 //
1294 // rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
1295 // r8, r9, r10, r11, r12, r13, r14, r15,
1296 // rip, rflags, cs, ss, ds, es, fs, gs
1297 //
1298 // Annoyingly, GDB wants all the registers as 64-bit values, but then
1299 // RFLAGS and the segment registers as 32-bit values, hence the need for
1300 // the type information.
1301 static const int32 kRegisterCount = 24;
1302 gdb_register registers[kRegisterCount] = {
1303 { B_UINT64_TYPE, frame->ax }, { B_UINT64_TYPE, frame->bx },
1304 { B_UINT64_TYPE, frame->cx }, { B_UINT64_TYPE, frame->dx },
1305 { B_UINT64_TYPE, frame->si }, { B_UINT64_TYPE, frame->di },
1306 { B_UINT64_TYPE, frame->bp }, { B_UINT64_TYPE, frame->sp },
1307 { B_UINT64_TYPE, frame->r8 }, { B_UINT64_TYPE, frame->r9 },
1308 { B_UINT64_TYPE, frame->r10 }, { B_UINT64_TYPE, frame->r11 },
1309 { B_UINT64_TYPE, frame->r12 }, { B_UINT64_TYPE, frame->r13 },
1310 { B_UINT64_TYPE, frame->r14 }, { B_UINT64_TYPE, frame->r15 },
1311 { B_UINT64_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
1312 { B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ss },
1313 { B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1314 { B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1315 };
1316 #else
1317 // For x86 the register order is:
1318 //
1319 // eax, ecx, edx, ebx,
1320 // esp, ebp, esi, edi,
1321 // eip, eflags,
1322 // cs, ss, ds, es, fs, gs
1323 //
1324 // Note that even though the segment descriptors are actually 16 bits wide,
1325 // gdb requires them as 32 bit integers.
1326 static const int32 kRegisterCount = 16;
1327 gdb_register registers[kRegisterCount] = {
1328 { B_UINT32_TYPE, frame->ax }, { B_UINT32_TYPE, frame->cx },
1329 { B_UINT32_TYPE, frame->dx }, { B_UINT32_TYPE, frame->bx },
1330 { B_UINT32_TYPE, frame->sp }, { B_UINT32_TYPE, frame->bp },
1331 { B_UINT32_TYPE, frame->si }, { B_UINT32_TYPE, frame->di },
1332 { B_UINT32_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
1333 { B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ds },
1334 // assume ss == ds
1335 { B_UINT32_TYPE, frame->ds }, { B_UINT32_TYPE, frame->es },
1336 { B_UINT32_TYPE, frame->fs }, { B_UINT32_TYPE, frame->gs },
1337 };
1338 #endif
1339
1340 const char* const bufferStart = buffer;
1341
1342 for (int32 i = 0; i < kRegisterCount; i++) {
1343 // For some reason gdb wants the register dump in *big endian* format.
1344 int result = 0;
1345 switch (registers[i].type) {
1346 case B_UINT64_TYPE:
1347 result = snprintf(buffer, bufferSize, "%016" B_PRIx64,
1348 (uint64)B_HOST_TO_BENDIAN_INT64(registers[i].value));
1349 break;
1350 case B_UINT32_TYPE:
1351 result = snprintf(buffer, bufferSize, "%08" B_PRIx32,
1352 (uint32)B_HOST_TO_BENDIAN_INT32((uint32)registers[i].value));
1353 break;
1354 }
1355 if (result >= (int)bufferSize)
1356 return B_BUFFER_OVERFLOW;
1357
1358 buffer += result;
1359 bufferSize -= result;
1360 }
1361
1362 return buffer - bufferStart;
1363 }
1364
1365
1366 status_t
arch_debug_init(kernel_args * args)1367 arch_debug_init(kernel_args* args)
1368 {
1369 // at this stage, the debugger command system is alive
1370
1371 add_debugger_command("where", &stack_trace, "Same as \"sc\"");
1372 add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
1373 add_debugger_command("sc", &stack_trace,
1374 "Stack crawl for current thread (or any other)");
1375 add_debugger_command("iframe", &dump_iframes,
1376 "Dump iframes for the specified thread");
1377 #ifndef __x86_64__
1378 add_debugger_command("call", &show_call, "Show call with arguments");
1379 #endif
1380 add_debugger_command_etc("in_context", &cmd_in_context,
1381 "Executes a command in the context of a given thread",
1382 "<thread ID> <command> ...\n"
1383 "Executes a command in the context of a given thread.\n",
1384 B_KDEBUG_DONT_PARSE_ARGUMENTS);
1385
1386 return B_NO_ERROR;
1387 }
1388
1389