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