xref: /haiku/src/system/kernel/arch/x86/arch_debug.cpp (revision 62f5ba006a08b0df30631375878effaf67ae5dbc)
1 /*
2  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 
11 #include <arch/debug.h>
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 #include <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.h>
24 #include <vm/vm_types.h>
25 #include <vm/VMAddressSpace.h>
26 #include <vm/VMArea.h>
27 
28 #include <arch_cpu.h>
29 
30 
31 struct stack_frame {
32 	struct stack_frame	*previous;
33 	addr_t				return_address;
34 };
35 
36 #define NUM_PREVIOUS_LOCATIONS 32
37 
38 
39 static bool
40 already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp)
41 {
42 	int32 last = *_last;
43 	int32 num = *_num;
44 	int32 i;
45 
46 	for (i = 0; i < num; i++) {
47 		if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == ebp)
48 			return true;
49 	}
50 
51 	*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
52 	visited[last] = ebp;
53 
54 	if (num < NUM_PREVIOUS_LOCATIONS)
55 		*_num = num + 1;
56 
57 	return false;
58 }
59 
60 
61 /*!	Safe to be called only from outside the debugger.
62 */
63 static status_t
64 get_next_frame_no_debugger(addr_t ebp, addr_t *_next, addr_t *_eip)
65 {
66 	// TODO: Do this more efficiently in assembly.
67 	stack_frame frame;
68 	if (user_memcpy(&frame, (void*)ebp, sizeof(frame)) != B_OK)
69 		return B_BAD_ADDRESS;
70 
71 	*_eip = frame.return_address;
72 	*_next = (addr_t)frame.previous;
73 
74 	return B_OK;
75 }
76 
77 
78 /*!	Safe to be called only from inside the debugger.
79 */
80 static status_t
81 get_next_frame_debugger(addr_t ebp, addr_t *_next, addr_t *_eip)
82 {
83 	stack_frame frame;
84 	if (debug_memcpy(&frame, (void*)ebp, sizeof(frame)) != B_OK)
85 		return B_BAD_ADDRESS;
86 
87 	*_eip = frame.return_address;
88 	*_next = (addr_t)frame.previous;
89 
90 	return B_OK;
91 }
92 
93 
94 static status_t
95 lookup_symbol(struct thread* thread, addr_t address, addr_t *_baseAddress,
96 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
97 {
98 	status_t status = B_ENTRY_NOT_FOUND;
99 
100 	if (IS_KERNEL_ADDRESS(address)) {
101 		// a kernel symbol
102 		status = elf_debug_lookup_symbol_address(address, _baseAddress,
103 			_symbolName, _imageName, _exactMatch);
104 	} else if (thread != NULL && thread->team != NULL) {
105 		// try a lookup using the userland runtime loader structures
106 		status = elf_debug_lookup_user_symbol_address(thread->team, address,
107 			_baseAddress, _symbolName, _imageName, _exactMatch);
108 
109 		if (status != B_OK) {
110 			// try to locate the image in the images loaded into user space
111 			status = image_debug_lookup_user_symbol_address(thread->team,
112 				address, _baseAddress, _symbolName, _imageName, _exactMatch);
113 		}
114 	}
115 
116 	return status;
117 }
118 
119 
120 static void
121 set_debug_argument_variable(int32 index, uint64 value)
122 {
123 	char name[8];
124 	snprintf(name, sizeof(name), "_arg%ld", index);
125 	set_debug_variable(name, value);
126 }
127 
128 
129 static status_t
130 print_demangled_call(const char* image, const char* symbol, addr_t args,
131 	bool noObjectMethod, bool addDebugVariables)
132 {
133 	static const size_t kBufferSize = 256;
134 	char* buffer = (char*)debug_malloc(kBufferSize);
135 	if (buffer == NULL)
136 		return B_NO_MEMORY;
137 
138 	bool isObjectMethod;
139 	const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
140 		&isObjectMethod);
141 	if (name == NULL) {
142 		debug_free(buffer);
143 		return B_ERROR;
144 	}
145 
146 	uint32* arg = (uint32*)args;
147 
148 	if (noObjectMethod)
149 		isObjectMethod = false;
150 	if (isObjectMethod) {
151 		const char* lastName = strrchr(name, ':') - 1;
152 		int namespaceLength = lastName - name;
153 
154 		kprintf("<%s> %.*s<\33[32m%p\33[0m>%s", image, namespaceLength, name,
155 			*(uint32 **)arg, lastName);
156 		if (addDebugVariables)
157 			set_debug_variable("_this", *(uint32 *)arg);
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 
176 		switch (type) {
177 			case B_INT64_TYPE:
178 				value = *(int64*)arg;
179 				kprintf("int64: \33[34m%Ld\33[0m", value);
180 				break;
181 			case B_INT32_TYPE:
182 				value = *(int32*)arg;
183 				kprintf("int32: \33[34m%ld\33[0m", (int32)value);
184 				break;
185 			case B_INT16_TYPE:
186 				value = *(int16*)arg;
187 				kprintf("int16: \33[34m%d\33[0m", (int16)value);
188 				break;
189 			case B_INT8_TYPE:
190 				value = *(int8*)arg;
191 				kprintf("int8: \33[34m%d\33[0m", (int8)value);
192 				break;
193 			case B_UINT64_TYPE:
194 				value = *(uint64*)arg;
195 				kprintf("uint64: \33[34m%#Lx\33[0m", value);
196 				if (value < 0x100000)
197 					kprintf(" (\33[34m%Lu\33[0m)", value);
198 				break;
199 			case B_UINT32_TYPE:
200 				value = *(uint32*)arg;
201 				kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value);
202 				if (value < 0x100000)
203 					kprintf(" (\33[34m%lu\33[0m)", (uint32)value);
204 				break;
205 			case B_UINT16_TYPE:
206 				value = *(uint16*)arg;
207 				kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
208 					(uint16)value, (uint16)value);
209 				break;
210 			case B_UINT8_TYPE:
211 				value = *(uint8*)arg;
212 				kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
213 					(uint8)value, (uint8)value);
214 				break;
215 			case B_BOOL_TYPE:
216 				value = *(uint8*)arg;
217 				kprintf("\33[34m%s\33[0m", value ? "true" : "false");
218 				break;
219 			default:
220 				if (buffer[0])
221 					kprintf("%s: ", buffer);
222 
223 				if (length == 4) {
224 					value = *(uint32*)arg;
225 					if (value == 0
226 						&& (type == B_POINTER_TYPE || type == B_REF_TYPE))
227 						kprintf("NULL");
228 					else
229 						kprintf("\33[34m%#lx\33[0m", (uint32)value);
230 					break;
231 				}
232 
233 				if (length == 8)
234 					value = *(uint64*)arg;
235 				else
236 					value = (uint64)arg;
237 				kprintf("\33[34m%#Lx\33[0m", value);
238 				break;
239 		}
240 
241 		if (type == B_STRING_TYPE) {
242 			if (value == 0)
243 				kprintf(" \33[31m\"<NULL>\"\33[0m");
244 			else if (debug_strlcpy(buffer, (char*)value, kBufferSize) < B_OK)
245 				kprintf(" \33[31m\"<???>\"\33[0m");
246 			else
247 				kprintf(" \33[36m\"%s\"\33[0m", buffer);
248 		}
249 
250 		if (addDebugVariables)
251 			set_debug_argument_variable(i, value);
252 		arg = (uint32*)((uint8*)arg + length);
253 	}
254 
255 	debug_free(buffer);
256 
257 	kprintf(")");
258 	return B_OK;
259 }
260 
261 
262 static void
263 print_stack_frame(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
264 	int32 callIndex, bool demangle)
265 {
266 	const char *symbol, *image;
267 	addr_t baseAddress;
268 	bool exactMatch;
269 	status_t status;
270 	addr_t diff;
271 
272 	diff = nextEbp - ebp;
273 
274 	// kernel space/user space switch
275 	if (diff & 0x80000000)
276 		diff = 0;
277 
278 	status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
279 		&exactMatch);
280 
281 	kprintf("%2ld %08lx (+%4ld) %08lx   ", callIndex, ebp, diff, eip);
282 
283 	if (status == B_OK) {
284 		if (exactMatch && demangle) {
285 			status = print_demangled_call(image, symbol, nextEbp + 8, false,
286 				false);
287 		}
288 
289 		if (!exactMatch || !demangle || status != B_OK) {
290 			if (symbol != NULL) {
291 				kprintf("<%s>:%s%s", image, symbol,
292 					exactMatch ? "" : " (nearest)");
293 			} else
294 				kprintf("<%s@%p>:unknown", image, (void *)baseAddress);
295 		}
296 
297 		kprintf(" + 0x%04lx\n", eip - baseAddress);
298 	} else {
299 		VMArea *area = NULL;
300 		if (thread != NULL && thread->team != NULL
301 			&& thread->team->address_space != NULL) {
302 			area = thread->team->address_space->LookupArea(eip);
303 		}
304 		if (area != NULL) {
305 			kprintf("%ld:%s@%p + %#lx\n", area->id, area->name,
306 				(void*)area->Base(), eip - area->Base());
307 		} else
308 			kprintf("\n");
309 	}
310 }
311 
312 
313 static void
314 print_iframe(struct iframe *frame)
315 {
316 	bool isUser = IFRAME_IS_USER(frame);
317 	kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
318 		isUser ? (uint32*)(frame + 1) : &frame->user_esp);
319 
320 	kprintf(" eax 0x%-9lx    ebx 0x%-9lx     ecx 0x%-9lx  edx 0x%lx\n",
321 		frame->eax, frame->ebx, frame->ecx, frame->edx);
322 	kprintf(" esi 0x%-9lx    edi 0x%-9lx     ebp 0x%-9lx  esp 0x%lx\n",
323 		frame->esi, frame->edi, frame->ebp, frame->esp);
324 	kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->eip, frame->flags);
325 	if (isUser) {
326 		// from user space
327 		kprintf("user esp 0x%lx", frame->user_esp);
328 	}
329 	kprintf("\n");
330 	kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector,
331 		frame->error_code);
332 }
333 
334 
335 static bool
336 setup_for_thread(char *arg, struct thread **_thread, uint32 *_ebp,
337 	uint32 *_oldPageDirectory)
338 {
339 	struct thread *thread = NULL;
340 
341 	if (arg != NULL) {
342 		thread_id id = strtoul(arg, NULL, 0);
343 		thread = thread_get_thread_struct_locked(id);
344 		if (thread == NULL) {
345 			kprintf("could not find thread %ld\n", id);
346 			return false;
347 		}
348 
349 		if (id != thread_get_current_thread_id()) {
350 			// switch to the page directory of the new thread to be
351 			// able to follow the stack trace into userland
352 			addr_t newPageDirectory = (addr_t)x86_next_page_directory(
353 				thread_get_current_thread(), thread);
354 
355 			if (newPageDirectory != 0) {
356 				read_cr3(*_oldPageDirectory);
357 				write_cr3(newPageDirectory);
358 			}
359 
360 			if (thread->state == B_THREAD_RUNNING) {
361 				// The thread is currently running on another CPU.
362 				if (thread->cpu == NULL)
363 					return false;
364 				arch_debug_registers* registers = debug_get_debug_registers(
365 					thread->cpu->cpu_num);
366 				if (registers == NULL)
367 					return false;
368 				*_ebp = registers->ebp;
369 			} else {
370 				// read %ebp from the thread's stack stored by a pushad
371 				*_ebp = thread->arch_info.current_stack.esp[2];
372 			}
373 		} else
374 			thread = NULL;
375 	}
376 
377 	if (thread == NULL) {
378 		// if we don't have a thread yet, we want the current one
379 		// (ebp has been set by the caller for this case already)
380 		thread = thread_get_current_thread();
381 	}
382 
383 	*_thread = thread;
384 	return true;
385 }
386 
387 
388 static bool
389 is_double_fault_stack_address(int32 cpu, addr_t address)
390 {
391 	size_t size;
392 	addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size);
393 	return address >= bottom && address < bottom + size;
394 }
395 
396 
397 static bool
398 is_kernel_stack_address(struct thread* thread, addr_t address)
399 {
400 	// We don't have a thread pointer in the early boot process, but then we are
401 	// on the kernel stack for sure.
402 	if (thread == NULL)
403 		return IS_KERNEL_ADDRESS(address);
404 
405 	// Also in the early boot process we might have a thread structure, but it
406 	// might not have its kernel stack attributes set yet.
407 	if (thread->kernel_stack_top == 0)
408 		return IS_KERNEL_ADDRESS(address);
409 
410 	return (address >= thread->kernel_stack_base
411 			&& address < thread->kernel_stack_top)
412 		|| (thread->cpu != NULL
413 			&& is_double_fault_stack_address(thread->cpu->cpu_num, address));
414 }
415 
416 
417 static bool
418 is_iframe(struct thread* thread, addr_t frame)
419 {
420 	if (!is_kernel_stack_address(thread, frame))
421 		return false;
422 
423 	addr_t previousFrame = *(addr_t*)frame;
424 	return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0);
425 }
426 
427 
428 static struct iframe *
429 find_previous_iframe(struct thread *thread, addr_t frame)
430 {
431 	// iterate backwards through the stack frames, until we hit an iframe
432 	while (is_kernel_stack_address(thread, frame)) {
433 		if (is_iframe(thread, frame))
434 			return (struct iframe*)frame;
435 
436 		frame = *(addr_t*)frame;
437 	}
438 
439 	return NULL;
440 }
441 
442 
443 static struct iframe*
444 get_previous_iframe(struct thread* thread, struct iframe* frame)
445 {
446 	if (frame == NULL)
447 		return NULL;
448 
449 	return find_previous_iframe(thread, frame->ebp);
450 }
451 
452 
453 static struct iframe*
454 get_current_iframe(struct thread* thread)
455 {
456 	if (thread == thread_get_current_thread())
457 		return i386_get_current_iframe();
458 
459 	addr_t ebp = thread->arch_info.current_stack.esp[2];
460 		// NOTE: This doesn't work, if the thread is running (on another CPU).
461 	return find_previous_iframe(thread, ebp);
462 }
463 
464 
465 uint32*
466 find_debug_variable(const char* variableName, bool& settable)
467 {
468 	struct iframe* frame = get_current_iframe(debug_get_debugged_thread());
469 	if (frame == NULL)
470 		return NULL;
471 
472 	settable = false;
473 
474 	if (strcmp(variableName, "gs") == 0) {
475 		return &frame->gs;
476 	} else if (strcmp(variableName, "fs") == 0) {
477 		return &frame->fs;
478 	} else if (strcmp(variableName, "es") == 0) {
479 		return &frame->es;
480 	} else if (strcmp(variableName, "ds") == 0) {
481 		return &frame->ds;
482 	} else if (strcmp(variableName, "cs") == 0) {
483 		return &frame->cs;
484 	} else if (strcmp(variableName, "edi") == 0) {
485 		settable = true;
486 		return &frame->edi;
487 	} else if (strcmp(variableName, "esi") == 0) {
488 		settable = true;
489 		return &frame->esi;
490 	} else if (strcmp(variableName, "ebp") == 0) {
491 		settable = true;
492 		return &frame->ebp;
493 	} else if (strcmp(variableName, "esp") == 0) {
494 		settable = true;
495 		return &frame->esp;
496 	} else if (strcmp(variableName, "ebx") == 0) {
497 		settable = true;
498 		return &frame->ebx;
499 	} else if (strcmp(variableName, "edx") == 0) {
500 		settable = true;
501 		return &frame->edx;
502 	} else if (strcmp(variableName, "ecx") == 0) {
503 		settable = true;
504 		return &frame->ecx;
505 	} else if (strcmp(variableName, "eax") == 0) {
506 		settable = true;
507 		return &frame->eax;
508 	} else if (strcmp(variableName, "orig_eax") == 0) {
509 		settable = true;
510 		return &frame->orig_eax;
511 	} else if (strcmp(variableName, "orig_edx") == 0) {
512 		settable = true;
513 		return &frame->orig_edx;
514 	} else if (strcmp(variableName, "eip") == 0) {
515 		settable = true;
516 		return &frame->eip;
517 	} else if (strcmp(variableName, "eflags") == 0) {
518 		settable = true;
519 		return &frame->flags;
520 	}
521 
522 	if (IFRAME_IS_USER(frame)) {
523 		if (strcmp(variableName, "user_esp") == 0) {
524 			settable = true;
525 			return &frame->user_esp;
526 		} else if (strcmp(variableName, "user_ss") == 0) {
527 			return &frame->user_ss;
528 		}
529 	}
530 
531 	return NULL;
532 }
533 
534 
535 static int
536 stack_trace(int argc, char **argv)
537 {
538 	static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
539 		"Prints a stack trace for the current, respectively the specified\n"
540 		"thread.\n"
541 		"  -d           -  Disables the demangling of the symbols.\n"
542 		"  <thread id>  -  The ID of the thread for which to print the stack\n"
543 		"                  trace.\n";
544 	bool demangle = true;
545 	int32 threadIndex = 1;
546 	if (argc > 1 && !strcmp(argv[1], "-d")) {
547 		demangle = false;
548 		threadIndex++;
549 	}
550 
551 	if (argc > threadIndex + 1
552 		|| (argc == 2 && strcmp(argv[1], "--help") == 0)) {
553 		kprintf(usage, argv[0]);
554 		return 0;
555 	}
556 
557 	uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
558 	struct thread *thread = NULL;
559 	addr_t oldPageDirectory = 0;
560 	uint32 ebp = x86_read_ebp();
561 	int32 num = 0, last = 0;
562 
563 	if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
564 			&thread, &ebp, &oldPageDirectory))
565 		return 0;
566 
567 	if (thread != NULL) {
568 		kprintf("stack trace for thread %ld \"%s\"\n", thread->id,
569 			thread->name);
570 
571 		kprintf("    kernel stack: %p to %p\n",
572 			(void *)thread->kernel_stack_base,
573 			(void *)(thread->kernel_stack_top));
574 		if (thread->user_stack_base != 0) {
575 			kprintf("      user stack: %p to %p\n",
576 				(void *)thread->user_stack_base,
577 				(void *)(thread->user_stack_base + thread->user_stack_size));
578 		}
579 	}
580 
581 	kprintf("frame               caller     <image>:function + offset\n");
582 
583 	bool onKernelStack = true;
584 
585 	for (int32 callIndex = 0;; callIndex++) {
586 		onKernelStack = onKernelStack
587 			&& is_kernel_stack_address(thread, ebp);
588 
589 		if (onKernelStack && is_iframe(thread, ebp)) {
590 			struct iframe *frame = (struct iframe *)ebp;
591 
592 			print_iframe(frame);
593 			print_stack_frame(thread, frame->eip, ebp, frame->ebp, callIndex,
594 				demangle);
595 
596  			ebp = frame->ebp;
597 		} else {
598 			addr_t eip, nextEbp;
599 
600 			if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
601 				kprintf("%08lx -- read fault\n", ebp);
602 				break;
603 			}
604 
605 			if (eip == 0 || ebp == 0)
606 				break;
607 
608 			print_stack_frame(thread, eip, ebp, nextEbp, callIndex, demangle);
609 			ebp = nextEbp;
610 		}
611 
612 		if (already_visited(previousLocations, &last, &num, ebp)) {
613 			kprintf("circular stack frame: %p!\n", (void *)ebp);
614 			break;
615 		}
616 		if (ebp == 0)
617 			break;
618 	}
619 
620 	if (oldPageDirectory != 0) {
621 		// switch back to the previous page directory to no cause any troubles
622 		write_cr3(oldPageDirectory);
623 	}
624 
625 	return 0;
626 }
627 
628 
629 static void
630 print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
631 	int32 argCount)
632 {
633 	const char *symbol, *image;
634 	addr_t baseAddress;
635 	bool exactMatch;
636 	status_t status;
637 	bool demangled = false;
638 	int32 *arg = (int32 *)(nextEbp + 8);
639 
640 	status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
641 		&exactMatch);
642 
643 	kprintf("%08lx %08lx   ", ebp, eip);
644 
645 	if (status == B_OK) {
646 		if (symbol != NULL) {
647 			if (exactMatch && (argCount == 0 || argCount == -1)) {
648 				status = print_demangled_call(image, symbol, (addr_t)arg,
649 					argCount == -1, true);
650 				if (status == B_OK)
651 					demangled = true;
652 			}
653 			if (!demangled) {
654 				kprintf("<%s>:%s%s", image, symbol,
655 					exactMatch ? "" : " (nearest)");
656 			}
657 		} else {
658 			kprintf("<%s@%p>:unknown + 0x%04lx", image,
659 				(void *)baseAddress, eip - baseAddress);
660 		}
661 	} else {
662 		VMArea *area = NULL;
663 		if (thread->team->address_space != NULL)
664 			area = thread->team->address_space->LookupArea(eip);
665 		if (area != NULL) {
666 			kprintf("%ld:%s@%p + %#lx", area->id, area->name,
667 				(void *)area->Base(), eip - area->Base());
668 		}
669 	}
670 
671 	if (!demangled) {
672 		kprintf("(");
673 
674 		for (int32 i = 0; i < argCount; i++) {
675 			if (i > 0)
676 				kprintf(", ");
677 			kprintf("%#lx", *arg);
678 			if (*arg > -0x10000 && *arg < 0x10000)
679 				kprintf(" (%ld)", *arg);
680 
681 			set_debug_argument_variable(i + 1, *(uint32 *)arg);
682 			arg++;
683 		}
684 
685 		kprintf(")\n");
686 	} else
687 		kprintf("\n");
688 
689 	set_debug_variable("_frame", nextEbp);
690 }
691 
692 
693 static int
694 show_call(int argc, char **argv)
695 {
696 	static const char* usage
697 		= "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n"
698 		"Prints a function call with parameters of the current, respectively\n"
699 		"the specified thread.\n"
700 		"  <thread id>   -  The ID of the thread for which to print the call.\n"
701 		"  <call index>  -  The index of the call in the stack trace.\n"
702 		"  <arg count>   -  The number of call arguments to print (use 'c' to\n"
703 		"                   force the C++ demangler to use class methods,\n"
704 		"                   use 'd' to disable demangling).\n";
705 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
706 		kprintf(usage, argv[0]);
707 		return 0;
708 	}
709 
710 	struct thread *thread = NULL;
711 	addr_t oldPageDirectory = 0;
712 	addr_t ebp = x86_read_ebp();
713 	int32 argCount = 0;
714 
715 	if (argc >= 2 && argv[argc - 1][0] == '-') {
716 		if (argv[argc - 1][1] == 'c')
717 			argCount = -1;
718 		else if (argv[argc - 1][1] == 'd')
719 			argCount = -2;
720 		else
721 			argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
722 
723 		if (argCount < -2 || argCount > 16) {
724 			kprintf("Invalid argument count \"%ld\".\n", argCount);
725 			return 0;
726 		}
727 		argc--;
728 	}
729 
730 	if (argc < 2 || argc > 3) {
731 		kprintf(usage, argv[0]);
732 		return 0;
733 	}
734 
735 	if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp,
736 			&oldPageDirectory))
737 		return 0;
738 
739 	int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0);
740 
741 	if (thread != NULL)
742 		kprintf("thread %ld, %s\n", thread->id, thread->name);
743 
744 	bool onKernelStack = true;
745 
746 	for (int32 index = 0; index <= callIndex; index++) {
747 		onKernelStack = onKernelStack
748 			&& is_kernel_stack_address(thread, ebp);
749 
750 		if (onKernelStack && is_iframe(thread, ebp)) {
751 			struct iframe *frame = (struct iframe *)ebp;
752 
753 			if (index == callIndex)
754 				print_call(thread, frame->eip, ebp, frame->ebp, argCount);
755 
756  			ebp = frame->ebp;
757 		} else {
758 			addr_t eip, nextEbp;
759 
760 			if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
761 				kprintf("%08lx -- read fault\n", ebp);
762 				break;
763 			}
764 
765 			if (eip == 0 || ebp == 0)
766 				break;
767 
768 			if (index == callIndex)
769 				print_call(thread, eip, ebp, nextEbp, argCount);
770 
771 			ebp = nextEbp;
772 		}
773 
774 		if (ebp == 0)
775 			break;
776 	}
777 
778 	if (oldPageDirectory != 0) {
779 		// switch back to the previous page directory to not cause any troubles
780 		write_cr3(oldPageDirectory);
781 	}
782 
783 	return 0;
784 }
785 
786 
787 static int
788 dump_iframes(int argc, char **argv)
789 {
790 	static const char* usage = "usage: %s [ <thread id> ]\n"
791 		"Prints the iframe stack for the current, respectively the specified\n"
792 		"thread.\n"
793 		"  <thread id>  -  The ID of the thread for which to print the iframe\n"
794 		"                  stack.\n";
795 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
796 		kprintf(usage, argv[0]);
797 		return 0;
798 	}
799 
800 	struct thread *thread = NULL;
801 
802 	if (argc < 2) {
803 		thread = thread_get_current_thread();
804 	} else if (argc == 2) {
805 		thread_id id = strtoul(argv[1], NULL, 0);
806 		thread = thread_get_thread_struct_locked(id);
807 		if (thread == NULL) {
808 			kprintf("could not find thread %ld\n", id);
809 			return 0;
810 		}
811 	} else if (argc > 2) {
812 		kprintf(usage, argv[0]);
813 		return 0;
814 	}
815 
816 	if (thread != NULL)
817 		kprintf("iframes for thread %ld \"%s\"\n", thread->id, thread->name);
818 
819 	struct iframe* frame = find_previous_iframe(thread, x86_read_ebp());
820 	while (frame != NULL) {
821 		print_iframe(frame);
822 		frame = get_previous_iframe(thread, frame);
823 	}
824 
825 	return 0;
826 }
827 
828 
829 static bool
830 is_calling(struct thread *thread, addr_t eip, const char *pattern,
831 	addr_t start, addr_t end)
832 {
833 	if (pattern == NULL)
834 		return eip >= start && eip < end;
835 
836 	if (!IS_KERNEL_ADDRESS(eip))
837 		return false;
838 
839 	const char *symbol;
840 	if (lookup_symbol(thread, eip, NULL, &symbol, NULL, NULL) != B_OK)
841 		return false;
842 
843 	return strstr(symbol, pattern);
844 }
845 
846 
847 static int
848 cmd_in_context(int argc, char** argv)
849 {
850 	if (argc != 2) {
851 		print_debugger_command_usage(argv[0]);
852 		return 0;
853 	}
854 
855 	// get the thread ID
856 	const char* commandLine = argv[1];
857 	char threadIDString[16];
858 	if (parse_next_debug_command_argument(&commandLine, threadIDString,
859 			sizeof(threadIDString)) != B_OK) {
860 		kprintf("Failed to parse thread ID.\n");
861 		return 0;
862 	}
863 
864 	if (commandLine == NULL) {
865 		print_debugger_command_usage(argv[0]);
866 		return 0;
867 	}
868 
869 	uint64 threadID;
870 	if (!evaluate_debug_expression(threadIDString, &threadID, false))
871 		return 0;
872 
873 	// get the thread
874 	struct thread* thread = thread_get_thread_struct_locked(threadID);
875 	if (thread == NULL) {
876 		kprintf("Could not find thread with ID \"%s\".\n", threadIDString);
877 		return 0;
878 	}
879 
880 	// switch the page directory, if necessary
881 	addr_t oldPageDirectory = 0;
882 	if (thread != thread_get_current_thread()) {
883 		addr_t newPageDirectory = (addr_t)x86_next_page_directory(
884 			thread_get_current_thread(), thread);
885 
886 		if (newPageDirectory != 0) {
887 			read_cr3(oldPageDirectory);
888 			write_cr3(newPageDirectory);
889 		}
890 	}
891 
892 	struct thread* previousThread = debug_set_debugged_thread(thread);
893 
894 	// execute the command
895 	evaluate_debug_command(commandLine);
896 
897 	debug_set_debugged_thread(previousThread);
898 
899 	// reset the page directory
900 	if (oldPageDirectory)
901 		write_cr3(oldPageDirectory);
902 
903 	return 0;
904 }
905 
906 
907 //	#pragma mark -
908 
909 
910 void
911 arch_debug_save_registers(struct arch_debug_registers* registers)
912 {
913 	// get the caller's frame pointer
914 	stack_frame* frame = (stack_frame*)x86_read_ebp();
915 	registers->ebp = (addr_t)frame->previous;
916 }
917 
918 
919 void
920 arch_debug_stack_trace(void)
921 {
922 	stack_trace(0, NULL);
923 }
924 
925 
926 bool
927 arch_debug_contains_call(struct thread *thread, const char *symbol,
928 	addr_t start, addr_t end)
929 {
930 	addr_t ebp;
931 	if (thread == thread_get_current_thread())
932 		ebp = x86_read_ebp();
933 	else {
934 		if (thread->state == B_THREAD_RUNNING) {
935 			// The thread is currently running on another CPU.
936 			if (thread->cpu == NULL)
937 				return false;
938 			arch_debug_registers* registers = debug_get_debug_registers(
939 				thread->cpu->cpu_num);
940 			if (registers == NULL)
941 				return false;
942 			ebp = registers->ebp;
943 		} else {
944 			// thread not running
945 			ebp = thread->arch_info.current_stack.esp[2];
946 		}
947 	}
948 
949 	for (;;) {
950 		if (!is_kernel_stack_address(thread, ebp))
951 			break;
952 
953 		if (is_iframe(thread, ebp)) {
954 			struct iframe *frame = (struct iframe *)ebp;
955 
956 			if (is_calling(thread, frame->eip, symbol, start, end))
957 				return true;
958 
959  			ebp = frame->ebp;
960 		} else {
961 			addr_t eip, nextEbp;
962 
963 			if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK
964 				|| eip == 0 || ebp == 0)
965 				break;
966 
967 			if (is_calling(thread, eip, symbol, start, end))
968 				return true;
969 
970 			ebp = nextEbp;
971 		}
972 
973 		if (ebp == 0)
974 			break;
975 	}
976 
977 	return false;
978 }
979 
980 
981 void *
982 arch_debug_get_caller(void)
983 {
984 	struct stack_frame *frame = (struct stack_frame *)x86_read_ebp();
985 	return (void *)frame->previous->return_address;
986 }
987 
988 
989 /*!	Captures a stack trace (the return addresses) of the current thread.
990 	\param returnAddresses The array the return address shall be written to.
991 	\param maxCount The maximum number of return addresses to be captured.
992 	\param skipIframes The number of interrupt frames that shall be skipped. If
993 		greater than 0, \a skipFrames is ignored.
994 	\param skipFrames The number of stack frames that shall be skipped.
995 	\param flags A combination of one or two of the following:
996 		- \c STACK_TRACE_KERNEL: Capture kernel return addresses.
997 		- \c STACK_TRACE_USER: Capture user return addresses.
998 	\return The number of return addresses written to the given array.
999 */
1000 int32
1001 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
1002 	int32 skipIframes, int32 skipFrames, uint32 flags)
1003 {
1004 	// Keep skipping normal stack frames until we've skipped the iframes we're
1005 	// supposed to skip.
1006 	if (skipIframes > 0)
1007 		skipFrames = INT_MAX;
1008 
1009 	struct thread* thread = thread_get_current_thread();
1010 	int32 count = 0;
1011 	addr_t ebp = x86_read_ebp();
1012 	bool onKernelStack = true;
1013 
1014 	while (ebp != 0 && count < maxCount) {
1015 		onKernelStack = onKernelStack
1016 			&& is_kernel_stack_address(thread, ebp);
1017 		if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
1018 			break;
1019 
1020 		addr_t eip;
1021 		addr_t nextEbp;
1022 
1023 		if (onKernelStack && is_iframe(thread, ebp)) {
1024 			struct iframe *frame = (struct iframe*)ebp;
1025 			eip = frame->eip;
1026  			nextEbp = frame->ebp;
1027 
1028 			if (skipIframes > 0) {
1029 				if (--skipIframes == 0)
1030 					skipFrames = 0;
1031 			}
1032 		} else {
1033 			if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK)
1034 				break;
1035 		}
1036 
1037 		if (skipFrames <= 0
1038 			&& ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) {
1039 			returnAddresses[count++] = eip;
1040 		} else
1041 			skipFrames--;
1042 
1043 		ebp = nextEbp;
1044 	}
1045 
1046 	return count;
1047 }
1048 
1049 
1050 /*!	Returns the program counter of the currently debugged (respectively this)
1051 	thread where the innermost interrupts happened. \a _isSyscall, if specified,
1052 	is set to whether this interrupt frame was created by a syscall. Returns
1053 	\c NULL, if there's no such frame or a problem occurred retrieving it;
1054 	\a _isSyscall won't be set in this case.
1055 */
1056 void*
1057 arch_debug_get_interrupt_pc(bool* _isSyscall)
1058 {
1059 	struct iframe* frame = get_current_iframe(debug_get_debugged_thread());
1060 	if (frame == NULL)
1061 		return NULL;
1062 
1063 	if (_isSyscall != NULL)
1064 		*_isSyscall = frame->vector == 99;
1065 
1066 	return (void*)(addr_t)frame->eip;
1067 }
1068 
1069 
1070 /*!	Sets the current thread to \c NULL.
1071 	Invoked in the kernel debugger only.
1072 */
1073 void
1074 arch_debug_unset_current_thread(void)
1075 {
1076 	write_dr3(NULL);
1077 }
1078 
1079 
1080 bool
1081 arch_is_debug_variable_defined(const char* variableName)
1082 {
1083 	bool settable;
1084 	return find_debug_variable(variableName, settable);
1085 }
1086 
1087 
1088 status_t
1089 arch_set_debug_variable(const char* variableName, uint64 value)
1090 {
1091 	bool settable;
1092 	uint32* variable = find_debug_variable(variableName, settable);
1093 	if (variable == NULL)
1094 		return B_ENTRY_NOT_FOUND;
1095 
1096 	if (!settable)
1097 		return B_NOT_ALLOWED;
1098 
1099 	*variable = (uint32)value;
1100 	return B_OK;
1101 }
1102 
1103 
1104 status_t
1105 arch_get_debug_variable(const char* variableName, uint64* value)
1106 {
1107 	bool settable;
1108 	uint32* variable = find_debug_variable(variableName, settable);
1109 	if (variable == NULL)
1110 		return B_ENTRY_NOT_FOUND;
1111 
1112 	*value = *variable;
1113 	return B_OK;
1114 }
1115 
1116 
1117 status_t
1118 arch_debug_init(kernel_args *args)
1119 {
1120 	// at this stage, the debugger command system is alive
1121 
1122 	add_debugger_command("where", &stack_trace, "Same as \"sc\"");
1123 	add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
1124 	add_debugger_command("sc", &stack_trace,
1125 		"Stack crawl for current thread (or any other)");
1126 	add_debugger_command("iframe", &dump_iframes,
1127 		"Dump iframes for the specified thread");
1128 	add_debugger_command("call", &show_call, "Show call with arguments");
1129 	add_debugger_command_etc("in_context", &cmd_in_context,
1130 		"Executes a command in the context of a given thread",
1131 		"<thread ID> <command> ...\n"
1132 		"Executes a command in the context of a given thread.\n",
1133 		B_KDEBUG_DONT_PARSE_ARGUMENTS);
1134 
1135 	return B_NO_ERROR;
1136 }
1137 
1138