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