xref: /aosp_15_r20/external/coreboot/payloads/libpayload/arch/x86/gdb.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but without any warranty; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14 
15 #include <exception.h>
16 #include <gdb.h>
17 #include <libpayload.h>
18 #include <stddef.h>
19 
20 static const u8 type_to_signal[] = {
21 	[EXC_DE]  = GDB_SIGFPE,
22 	[EXC_DB]  = GDB_SIGTRAP,
23 	[EXC_NMI] = GDB_SIGKILL,
24 	[EXC_BP]  = GDB_SIGTRAP,
25 	[EXC_OF]  = GDB_SIGFPE,
26 	[EXC_BR]  = GDB_SIGSEGV,
27 	[EXC_UD]  = GDB_SIGILL,
28 	[EXC_NM]  = GDB_SIGEMT,
29 	[EXC_DF]  = GDB_SIGKILL,
30 	[EXC_TS]  = GDB_SIGSEGV,
31 	[EXC_NP]  = GDB_SIGSEGV,
32 	[EXC_SS]  = GDB_SIGBUS,
33 	[EXC_GP]  = GDB_SIGSEGV,
34 	[EXC_PF]  = GDB_SIGSEGV,
35 	[EXC_MF]  = GDB_SIGEMT,
36 	[EXC_AC]  = GDB_SIGBUS,
37 	[EXC_MC]  = GDB_SIGKILL,
38 	[EXC_XF]  = GDB_SIGFPE,
39 	[EXC_SX]  = GDB_SIGFPE,
40 };
41 
gdb_exception_hook(u8 vector)42 static void gdb_exception_hook(u8 vector)
43 {
44 	gdb_command_loop(type_to_signal[vector]);
45 }
46 
gdb_arch_init(void)47 void gdb_arch_init(void)
48 {
49 	for (int vector = 0; vector < ARRAY_SIZE(type_to_signal); ++vector) {
50 		if (type_to_signal[vector])
51 			set_interrupt_handler(vector, &gdb_exception_hook);
52 	}
53 }
54 
gdb_arch_enter(void)55 void gdb_arch_enter(void)
56 {
57 	u8 *stack_pointer;
58 #if CONFIG(LP_ARCH_X86_64)
59 	asm volatile ("movq %%rsp, %0" : "=r"(stack_pointer));
60 #else
61 	asm volatile ("mov %%esp, %0" : "=r"(stack_pointer));
62 #endif
63 
64 	/* Avoid reentrant exceptions, just call the hook if in one already. */
65 	if (stack_pointer >= exception_stack && stack_pointer <= exception_stack_end)
66 		gdb_exception_hook(EXC_BP);
67 	else
68 		asm volatile ("int3");
69 }
70 
gdb_arch_set_single_step(int on)71 int gdb_arch_set_single_step(int on)
72 {
73 	const size_t tf_bit = 1 << 8;
74 
75 	if (on)
76 		exception_state->regs.reg_flags |= tf_bit;
77 	else
78 		exception_state->regs.reg_flags &= ~tf_bit;
79 
80 	return 0;
81 }
82 
gdb_arch_encode_regs(struct gdb_message * message)83 void gdb_arch_encode_regs(struct gdb_message *message)
84 {
85 	gdb_message_encode_bytes(message, &exception_state->regs,
86 				 sizeof(exception_state->regs));
87 }
88 
gdb_arch_decode_regs(int offset,struct gdb_message * message)89 void gdb_arch_decode_regs(int offset, struct gdb_message *message)
90 {
91 	gdb_message_decode_bytes(message, offset, &exception_state->regs,
92 				 sizeof(exception_state->regs));
93 }
94