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