xref: /haiku/src/system/kernel/arch/x86/arch_debug.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
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 			// read %ebp from the thread's stack stored by a pushad
361 			*_ebp = thread->arch_info.current_stack.esp[2];
362 		} else
363 			thread = NULL;
364 	}
365 
366 	if (thread == NULL) {
367 		// if we don't have a thread yet, we want the current one
368 		// (ebp has been set by the caller for this case already)
369 		thread = thread_get_current_thread();
370 	}
371 
372 	*_thread = thread;
373 	return true;
374 }
375 
376 
377 static bool
378 is_double_fault_stack_address(int32 cpu, addr_t address)
379 {
380 	size_t size;
381 	addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size);
382 	return address >= bottom && address < bottom + size;
383 }
384 
385 
386 static bool
387 is_kernel_stack_address(struct thread* thread, addr_t address)
388 {
389 	// We don't have a thread pointer in the early boot process, but then we are
390 	// on the kernel stack for sure.
391 	if (thread == NULL)
392 		return IS_KERNEL_ADDRESS(address);
393 
394 	// Also in the early boot process we might have a thread structure, but it
395 	// might not have its kernel stack attributes set yet.
396 	if (thread->kernel_stack_top == 0)
397 		return IS_KERNEL_ADDRESS(address);
398 
399 	return (address >= thread->kernel_stack_base
400 			&& address < thread->kernel_stack_top)
401 		|| (thread->cpu != NULL
402 			&& is_double_fault_stack_address(thread->cpu->cpu_num, address));
403 }
404 
405 
406 static bool
407 is_iframe(struct thread* thread, addr_t frame)
408 {
409 	if (!is_kernel_stack_address(thread, frame))
410 		return false;
411 
412 	addr_t previousFrame = *(addr_t*)frame;
413 	return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0);
414 }
415 
416 
417 static struct iframe *
418 find_previous_iframe(struct thread *thread, addr_t frame)
419 {
420 	// iterate backwards through the stack frames, until we hit an iframe
421 	while (is_kernel_stack_address(thread, frame)) {
422 		if (is_iframe(thread, frame))
423 			return (struct iframe*)frame;
424 
425 		frame = *(addr_t*)frame;
426 	}
427 
428 	return NULL;
429 }
430 
431 
432 static struct iframe*
433 get_previous_iframe(struct thread* thread, struct iframe* frame)
434 {
435 	if (frame == NULL)
436 		return NULL;
437 
438 	return find_previous_iframe(thread, frame->ebp);
439 }
440 
441 
442 static struct iframe*
443 get_current_iframe(struct thread* thread)
444 {
445 	if (thread == thread_get_current_thread())
446 		return i386_get_current_iframe();
447 
448 	addr_t ebp = thread->arch_info.current_stack.esp[2];
449 		// NOTE: This doesn't work, if the thread is running (on another CPU).
450 	return find_previous_iframe(thread, ebp);
451 }
452 
453 
454 uint32*
455 find_debug_variable(const char* variableName, bool& settable)
456 {
457 	struct iframe* frame = get_current_iframe(debug_get_debugged_thread());
458 	if (frame == NULL)
459 		return NULL;
460 
461 	settable = false;
462 
463 	if (strcmp(variableName, "gs") == 0) {
464 		return &frame->gs;
465 	} else if (strcmp(variableName, "fs") == 0) {
466 		return &frame->fs;
467 	} else if (strcmp(variableName, "es") == 0) {
468 		return &frame->es;
469 	} else if (strcmp(variableName, "ds") == 0) {
470 		return &frame->ds;
471 	} else if (strcmp(variableName, "cs") == 0) {
472 		return &frame->cs;
473 	} else if (strcmp(variableName, "edi") == 0) {
474 		settable = true;
475 		return &frame->edi;
476 	} else if (strcmp(variableName, "esi") == 0) {
477 		settable = true;
478 		return &frame->esi;
479 	} else if (strcmp(variableName, "ebp") == 0) {
480 		settable = true;
481 		return &frame->ebp;
482 	} else if (strcmp(variableName, "esp") == 0) {
483 		settable = true;
484 		return &frame->esp;
485 	} else if (strcmp(variableName, "ebx") == 0) {
486 		settable = true;
487 		return &frame->ebx;
488 	} else if (strcmp(variableName, "edx") == 0) {
489 		settable = true;
490 		return &frame->edx;
491 	} else if (strcmp(variableName, "ecx") == 0) {
492 		settable = true;
493 		return &frame->ecx;
494 	} else if (strcmp(variableName, "eax") == 0) {
495 		settable = true;
496 		return &frame->eax;
497 	} else if (strcmp(variableName, "orig_eax") == 0) {
498 		settable = true;
499 		return &frame->orig_eax;
500 	} else if (strcmp(variableName, "orig_edx") == 0) {
501 		settable = true;
502 		return &frame->orig_edx;
503 	} else if (strcmp(variableName, "eip") == 0) {
504 		settable = true;
505 		return &frame->eip;
506 	} else if (strcmp(variableName, "eflags") == 0) {
507 		settable = true;
508 		return &frame->flags;
509 	}
510 
511 	if (IFRAME_IS_USER(frame)) {
512 		if (strcmp(variableName, "user_esp") == 0) {
513 			settable = true;
514 			return &frame->user_esp;
515 		} else if (strcmp(variableName, "user_ss") == 0) {
516 			return &frame->user_ss;
517 		}
518 	}
519 
520 	return NULL;
521 }
522 
523 
524 static int
525 stack_trace(int argc, char **argv)
526 {
527 	static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
528 		"Prints a stack trace for the current, respectively the specified\n"
529 		"thread.\n"
530 		"  -d           -  Disables the demangling of the symbols.\n"
531 		"  <thread id>  -  The ID of the thread for which to print the stack\n"
532 		"                  trace.\n";
533 	bool demangle = true;
534 	int32 threadIndex = 1;
535 	if (argc > 1 && !strcmp(argv[1], "-d")) {
536 		demangle = false;
537 		threadIndex++;
538 	}
539 
540 	if (argc > threadIndex + 1
541 		|| (argc == 2 && strcmp(argv[1], "--help") == 0)) {
542 		kprintf(usage, argv[0]);
543 		return 0;
544 	}
545 
546 	uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
547 	struct thread *thread = NULL;
548 	addr_t oldPageDirectory = 0;
549 	uint32 ebp = x86_read_ebp();
550 	int32 num = 0, last = 0;
551 
552 	if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
553 			&thread, &ebp, &oldPageDirectory))
554 		return 0;
555 
556 	if (thread != NULL) {
557 		kprintf("stack trace for thread %ld \"%s\"\n", thread->id,
558 			thread->name);
559 
560 		kprintf("    kernel stack: %p to %p\n",
561 			(void *)thread->kernel_stack_base,
562 			(void *)(thread->kernel_stack_top));
563 		if (thread->user_stack_base != 0) {
564 			kprintf("      user stack: %p to %p\n",
565 				(void *)thread->user_stack_base,
566 				(void *)(thread->user_stack_base + thread->user_stack_size));
567 		}
568 	}
569 
570 	kprintf("frame               caller     <image>:function + offset\n");
571 
572 	bool onKernelStack = true;
573 
574 	for (int32 callIndex = 0;; callIndex++) {
575 		onKernelStack = onKernelStack
576 			&& is_kernel_stack_address(thread, ebp);
577 
578 		if (onKernelStack && is_iframe(thread, ebp)) {
579 			struct iframe *frame = (struct iframe *)ebp;
580 
581 			print_iframe(frame);
582 			print_stack_frame(thread, frame->eip, ebp, frame->ebp, callIndex,
583 				demangle);
584 
585  			ebp = frame->ebp;
586 		} else {
587 			addr_t eip, nextEbp;
588 
589 			if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
590 				kprintf("%08lx -- read fault\n", ebp);
591 				break;
592 			}
593 
594 			if (eip == 0 || ebp == 0)
595 				break;
596 
597 			print_stack_frame(thread, eip, ebp, nextEbp, callIndex, demangle);
598 			ebp = nextEbp;
599 		}
600 
601 		if (already_visited(previousLocations, &last, &num, ebp)) {
602 			kprintf("circular stack frame: %p!\n", (void *)ebp);
603 			break;
604 		}
605 		if (ebp == 0)
606 			break;
607 	}
608 
609 	if (oldPageDirectory != 0) {
610 		// switch back to the previous page directory to no cause any troubles
611 		write_cr3(oldPageDirectory);
612 	}
613 
614 	return 0;
615 }
616 
617 
618 static void
619 print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
620 	int32 argCount)
621 {
622 	const char *symbol, *image;
623 	addr_t baseAddress;
624 	bool exactMatch;
625 	status_t status;
626 	bool demangled = false;
627 	int32 *arg = (int32 *)(nextEbp + 8);
628 
629 	status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
630 		&exactMatch);
631 
632 	kprintf("%08lx %08lx   ", ebp, eip);
633 
634 	if (status == B_OK) {
635 		if (symbol != NULL) {
636 			if (exactMatch && (argCount == 0 || argCount == -1)) {
637 				status = print_demangled_call(image, symbol, (addr_t)arg,
638 					argCount == -1, true);
639 				if (status == B_OK)
640 					demangled = true;
641 			}
642 			if (!demangled) {
643 				kprintf("<%s>:%s%s", image, symbol,
644 					exactMatch ? "" : " (nearest)");
645 			}
646 		} else {
647 			kprintf("<%s@%p>:unknown + 0x%04lx", image,
648 				(void *)baseAddress, eip - baseAddress);
649 		}
650 	} else {
651 		VMArea *area = NULL;
652 		if (thread->team->address_space != NULL)
653 			area = thread->team->address_space->LookupArea(eip);
654 		if (area != NULL) {
655 			kprintf("%ld:%s@%p + %#lx", area->id, area->name,
656 				(void *)area->Base(), eip - area->Base());
657 		}
658 	}
659 
660 	if (!demangled) {
661 		kprintf("(");
662 
663 		for (int32 i = 0; i < argCount; i++) {
664 			if (i > 0)
665 				kprintf(", ");
666 			kprintf("%#lx", *arg);
667 			if (*arg > -0x10000 && *arg < 0x10000)
668 				kprintf(" (%ld)", *arg);
669 
670 			set_debug_argument_variable(i + 1, *(uint32 *)arg);
671 			arg++;
672 		}
673 
674 		kprintf(")\n");
675 	} else
676 		kprintf("\n");
677 
678 	set_debug_variable("_frame", nextEbp);
679 }
680 
681 
682 static int
683 show_call(int argc, char **argv)
684 {
685 	static const char* usage
686 		= "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n"
687 		"Prints a function call with parameters of the current, respectively\n"
688 		"the specified thread.\n"
689 		"  <thread id>   -  The ID of the thread for which to print the call.\n"
690 		"  <call index>  -  The index of the call in the stack trace.\n"
691 		"  <arg count>   -  The number of call arguments to print (use 'c' to\n"
692 		"                   force the C++ demangler to use class methods,\n"
693 		"                   use 'd' to disable demangling).\n";
694 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
695 		kprintf(usage, argv[0]);
696 		return 0;
697 	}
698 
699 	struct thread *thread = NULL;
700 	addr_t oldPageDirectory = 0;
701 	addr_t ebp = x86_read_ebp();
702 	int32 argCount = 0;
703 
704 	if (argc >= 2 && argv[argc - 1][0] == '-') {
705 		if (argv[argc - 1][1] == 'c')
706 			argCount = -1;
707 		else if (argv[argc - 1][1] == 'd')
708 			argCount = -2;
709 		else
710 			argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
711 
712 		if (argCount < -2 || argCount > 16) {
713 			kprintf("Invalid argument count \"%ld\".\n", argCount);
714 			return 0;
715 		}
716 		argc--;
717 	}
718 
719 	if (argc < 2 || argc > 3) {
720 		kprintf(usage, argv[0]);
721 		return 0;
722 	}
723 
724 	if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp,
725 			&oldPageDirectory))
726 		return 0;
727 
728 	int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0);
729 
730 	if (thread != NULL)
731 		kprintf("thread %ld, %s\n", thread->id, thread->name);
732 
733 	bool onKernelStack = true;
734 
735 	for (int32 index = 0; index <= callIndex; index++) {
736 		onKernelStack = onKernelStack
737 			&& is_kernel_stack_address(thread, ebp);
738 
739 		if (onKernelStack && is_iframe(thread, ebp)) {
740 			struct iframe *frame = (struct iframe *)ebp;
741 
742 			if (index == callIndex)
743 				print_call(thread, frame->eip, ebp, frame->ebp, argCount);
744 
745  			ebp = frame->ebp;
746 		} else {
747 			addr_t eip, nextEbp;
748 
749 			if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
750 				kprintf("%08lx -- read fault\n", ebp);
751 				break;
752 			}
753 
754 			if (eip == 0 || ebp == 0)
755 				break;
756 
757 			if (index == callIndex)
758 				print_call(thread, eip, ebp, nextEbp, argCount);
759 
760 			ebp = nextEbp;
761 		}
762 
763 		if (ebp == 0)
764 			break;
765 	}
766 
767 	if (oldPageDirectory != 0) {
768 		// switch back to the previous page directory to not cause any troubles
769 		write_cr3(oldPageDirectory);
770 	}
771 
772 	return 0;
773 }
774 
775 
776 static int
777 dump_iframes(int argc, char **argv)
778 {
779 	static const char* usage = "usage: %s [ <thread id> ]\n"
780 		"Prints the iframe stack for the current, respectively the specified\n"
781 		"thread.\n"
782 		"  <thread id>  -  The ID of the thread for which to print the iframe\n"
783 		"                  stack.\n";
784 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
785 		kprintf(usage, argv[0]);
786 		return 0;
787 	}
788 
789 	struct thread *thread = NULL;
790 
791 	if (argc < 2) {
792 		thread = thread_get_current_thread();
793 	} else if (argc == 2) {
794 		thread_id id = strtoul(argv[1], NULL, 0);
795 		thread = thread_get_thread_struct_locked(id);
796 		if (thread == NULL) {
797 			kprintf("could not find thread %ld\n", id);
798 			return 0;
799 		}
800 	} else if (argc > 2) {
801 		kprintf(usage, argv[0]);
802 		return 0;
803 	}
804 
805 	if (thread != NULL)
806 		kprintf("iframes for thread %ld \"%s\"\n", thread->id, thread->name);
807 
808 	struct iframe* frame = find_previous_iframe(thread, x86_read_ebp());
809 	while (frame != NULL) {
810 		print_iframe(frame);
811 		frame = get_previous_iframe(thread, frame);
812 	}
813 
814 	return 0;
815 }
816 
817 
818 static bool
819 is_calling(struct thread *thread, addr_t eip, const char *pattern,
820 	addr_t start, addr_t end)
821 {
822 	if (pattern == NULL)
823 		return eip >= start && eip < end;
824 
825 	const char *symbol;
826 	if (lookup_symbol(thread, eip, NULL, &symbol, NULL, NULL) != B_OK)
827 		return false;
828 
829 	return strstr(symbol, pattern);
830 }
831 
832 
833 static int
834 cmd_in_context(int argc, char** argv)
835 {
836 	if (argc != 2) {
837 		print_debugger_command_usage(argv[0]);
838 		return 0;
839 	}
840 
841 	// get the thread ID
842 	const char* commandLine = argv[1];
843 	char threadIDString[16];
844 	if (parse_next_debug_command_argument(&commandLine, threadIDString,
845 			sizeof(threadIDString)) != B_OK) {
846 		kprintf("Failed to parse thread ID.\n");
847 		return 0;
848 	}
849 
850 	if (commandLine == NULL) {
851 		print_debugger_command_usage(argv[0]);
852 		return 0;
853 	}
854 
855 	uint64 threadID;
856 	if (!evaluate_debug_expression(threadIDString, &threadID, false))
857 		return 0;
858 
859 	// get the thread
860 	struct thread* thread = thread_get_thread_struct_locked(threadID);
861 	if (thread == NULL) {
862 		kprintf("Could not find thread with ID \"%s\".\n", threadIDString);
863 		return 0;
864 	}
865 
866 	// switch the page directory, if necessary
867 	addr_t oldPageDirectory = 0;
868 	if (thread != thread_get_current_thread()) {
869 		addr_t newPageDirectory = (addr_t)x86_next_page_directory(
870 			thread_get_current_thread(), thread);
871 
872 		if (newPageDirectory != 0) {
873 			read_cr3(oldPageDirectory);
874 			write_cr3(newPageDirectory);
875 		}
876 	}
877 
878 	struct thread* previousThread = debug_set_debugged_thread(thread);
879 
880 	// execute the command
881 	evaluate_debug_command(commandLine);
882 
883 	debug_set_debugged_thread(previousThread);
884 
885 	// reset the page directory
886 	if (oldPageDirectory)
887 		write_cr3(oldPageDirectory);
888 
889 	return 0;
890 }
891 
892 
893 //	#pragma mark -
894 
895 
896 void
897 arch_debug_stack_trace(void)
898 {
899 	stack_trace(0, NULL);
900 }
901 
902 
903 bool
904 arch_debug_contains_call(struct thread *thread, const char *symbol,
905 	addr_t start, addr_t end)
906 {
907 	addr_t ebp;
908 	if (thread == thread_get_current_thread())
909 		ebp = x86_read_ebp();
910 	else
911 		ebp = thread->arch_info.current_stack.esp[2];
912 
913 	for (;;) {
914 		if (!is_kernel_stack_address(thread, ebp))
915 			break;
916 
917 		if (is_iframe(thread, ebp)) {
918 			struct iframe *frame = (struct iframe *)ebp;
919 
920 			if (is_calling(thread, frame->eip, symbol, start, end))
921 				return true;
922 
923  			ebp = frame->ebp;
924 		} else {
925 			addr_t eip, nextEbp;
926 
927 			if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK
928 				|| eip == 0 || ebp == 0)
929 				break;
930 
931 			if (is_calling(thread, eip, symbol, start, end))
932 				return true;
933 
934 			ebp = nextEbp;
935 		}
936 
937 		if (ebp == 0)
938 			break;
939 	}
940 
941 	return false;
942 }
943 
944 
945 void *
946 arch_debug_get_caller(void)
947 {
948 	struct stack_frame *frame = (struct stack_frame *)x86_read_ebp();
949 	return (void *)frame->previous->return_address;
950 }
951 
952 
953 /*!	Captures a stack trace (the return addresses) of the current thread.
954 	\param returnAddresses The array the return address shall be written to.
955 	\param maxCount The maximum number of return addresses to be captured.
956 	\param skipIframes The number of interrupt frames that shall be skipped. If
957 		greater than 0, \a skipFrames is ignored.
958 	\param skipFrames The number of stack frames that shall be skipped.
959 	\param flags A combination of one or two of the following:
960 		- \c STACK_TRACE_KERNEL: Capture kernel return addresses.
961 		- \c STACK_TRACE_USER: Capture user return addresses.
962 	\return The number of return addresses written to the given array.
963 */
964 int32
965 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
966 	int32 skipIframes, int32 skipFrames, uint32 flags)
967 {
968 	// Keep skipping normal stack frames until we've skipped the iframes we're
969 	// supposed to skip.
970 	if (skipIframes > 0)
971 		skipFrames = INT_MAX;
972 
973 	struct thread* thread = thread_get_current_thread();
974 	int32 count = 0;
975 	addr_t ebp = x86_read_ebp();
976 	bool onKernelStack = true;
977 
978 	while (ebp != 0 && count < maxCount) {
979 		onKernelStack = onKernelStack
980 			&& is_kernel_stack_address(thread, ebp);
981 		if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
982 			break;
983 
984 		addr_t eip;
985 		addr_t nextEbp;
986 
987 		if (onKernelStack && is_iframe(thread, ebp)) {
988 			struct iframe *frame = (struct iframe*)ebp;
989 			eip = frame->eip;
990  			nextEbp = frame->ebp;
991 
992 			if (skipIframes > 0) {
993 				if (--skipIframes == 0)
994 					skipFrames = 0;
995 			}
996 		} else {
997 			if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK)
998 				break;
999 		}
1000 
1001 		if (skipFrames <= 0
1002 			&& ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) {
1003 			returnAddresses[count++] = eip;
1004 		} else
1005 			skipFrames--;
1006 
1007 		ebp = nextEbp;
1008 	}
1009 
1010 	return count;
1011 }
1012 
1013 
1014 /*!	Returns the program counter of the currently debugged (respectively this)
1015 	thread where the innermost interrupts happened. \a _isSyscall, if specified,
1016 	is set to whether this interrupt frame was created by a syscall. Returns
1017 	\c NULL, if there's no such frame or a problem occurred retrieving it;
1018 	\a _isSyscall won't be set in this case.
1019 */
1020 void*
1021 arch_debug_get_interrupt_pc(bool* _isSyscall)
1022 {
1023 	struct iframe* frame = get_current_iframe(debug_get_debugged_thread());
1024 	if (frame == NULL)
1025 		return NULL;
1026 
1027 	if (_isSyscall != NULL)
1028 		*_isSyscall = frame->vector == 99;
1029 
1030 	return (void*)(addr_t)frame->eip;
1031 }
1032 
1033 
1034 /*!	Sets the current thread to \c NULL.
1035 	Invoked in the kernel debugger only.
1036 */
1037 void
1038 arch_debug_unset_current_thread(void)
1039 {
1040 	write_dr3(NULL);
1041 }
1042 
1043 
1044 bool
1045 arch_is_debug_variable_defined(const char* variableName)
1046 {
1047 	bool settable;
1048 	return find_debug_variable(variableName, settable);
1049 }
1050 
1051 
1052 status_t
1053 arch_set_debug_variable(const char* variableName, uint64 value)
1054 {
1055 	bool settable;
1056 	uint32* variable = find_debug_variable(variableName, settable);
1057 	if (variable == NULL)
1058 		return B_ENTRY_NOT_FOUND;
1059 
1060 	if (!settable)
1061 		return B_NOT_ALLOWED;
1062 
1063 	*variable = (uint32)value;
1064 	return B_OK;
1065 }
1066 
1067 
1068 status_t
1069 arch_get_debug_variable(const char* variableName, uint64* value)
1070 {
1071 	bool settable;
1072 	uint32* variable = find_debug_variable(variableName, settable);
1073 	if (variable == NULL)
1074 		return B_ENTRY_NOT_FOUND;
1075 
1076 	*value = *variable;
1077 	return B_OK;
1078 }
1079 
1080 
1081 status_t
1082 arch_debug_init(kernel_args *args)
1083 {
1084 	// at this stage, the debugger command system is alive
1085 
1086 	add_debugger_command("where", &stack_trace, "Same as \"sc\"");
1087 	add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
1088 	add_debugger_command("sc", &stack_trace,
1089 		"Stack crawl for current thread (or any other)");
1090 	add_debugger_command("iframe", &dump_iframes,
1091 		"Dump iframes for the specified thread");
1092 	add_debugger_command("call", &show_call, "Show call with arguments");
1093 	add_debugger_command_etc("in_context", &cmd_in_context,
1094 		"Executes a command in the context of a given thread",
1095 		"<thread ID> <command> ...\n"
1096 		"Executes a command in the context of a given thread.\n",
1097 		B_KDEBUG_DONT_PARSE_ARGUMENTS);
1098 
1099 	return B_NO_ERROR;
1100 }
1101 
1102