summaryrefslogtreecommitdiffstats
path: root/src/arch/x86_64/core/gdbidt.S
blob: 89280bf8982c4be733e7de77aa00b1ed308cc39e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * You can also choose to distribute this program under the terms of
 * the Unmodified Binary Distribution Licence (as given in the file
 * COPYING.UBDL), provided that you have satisfied its requirements.
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

/** @file
 *
 * GDB exception handlers
 *
 */

/* Size of a register */
#define SIZEOF_REG 8

/* POSIX signal numbers for reporting traps to GDB */
#define SIGILL 4
#define SIGTRAP 5
#define SIGFPE 8
#define SIGSTKFLT 16

	.section ".text.gdbmach_interrupt", "ax", @progbits
	.code64

	.struct 0
/* Register dump created for GDB stub */
regs:
regs_rax:	.space	SIZEOF_REG
regs_rbx:	.space	SIZEOF_REG
regs_rcx:	.space	SIZEOF_REG
regs_rdx:	.space	SIZEOF_REG
regs_rsi:	.space	SIZEOF_REG
regs_rdi:	.space	SIZEOF_REG
regs_rbp:	.space	SIZEOF_REG
regs_rsp:	.space	SIZEOF_REG
regs_r8:	.space	SIZEOF_REG
regs_r9:	.space	SIZEOF_REG
regs_r10:	.space	SIZEOF_REG
regs_r11:	.space	SIZEOF_REG
regs_r12:	.space	SIZEOF_REG
regs_r13:	.space	SIZEOF_REG
regs_r14:	.space	SIZEOF_REG
regs_r15:	.space	SIZEOF_REG
regs_rip:	.space	SIZEOF_REG
regs_rflags:	.space	SIZEOF_REG
regs_cs:	.space	SIZEOF_REG
regs_ss:	.space	SIZEOF_REG
regs_ds:	.space	SIZEOF_REG
regs_es:	.space	SIZEOF_REG
regs_fs:	.space	SIZEOF_REG
regs_gs:	.space	SIZEOF_REG
regs_end:
/* GDB signal code */
gdb:
gdb_code:	.space	SIZEOF_REG
gdb_end:
/* Long-mode exception frame */
frame:
frame_rip:	.space	SIZEOF_REG
frame_cs:	.space	SIZEOF_REG
frame_rflags:	.space	SIZEOF_REG
frame_rsp:	.space	SIZEOF_REG
frame_ss:	.space	SIZEOF_REG
frame_end:
	.previous

	.globl	gdbmach_sigfpe
gdbmach_sigfpe:
	push	$SIGFPE
	jmp	gdbmach_interrupt

	.globl	gdbmach_sigtrap
gdbmach_sigtrap:
	push	$SIGTRAP
	jmp	gdbmach_interrupt

	.globl	gdbmach_sigstkflt
gdbmach_sigstkflt:
	push	$SIGSTKFLT
	jmp	gdbmach_interrupt

	.globl	gdbmach_sigill
gdbmach_sigill:
	push	$SIGILL
	jmp	gdbmach_interrupt

gdbmach_interrupt:

	/* Create register dump */
	pushq	%gs
	pushq	%fs
	pushq	$0		/* %es unused in long mode */
	pushq	$0		/* %ds unused in long mode */
	pushq	( frame_ss	- regs_ss	- SIZEOF_REG )(%rsp)
	pushq	( frame_cs	- regs_cs	- SIZEOF_REG )(%rsp)
	pushq	( frame_rflags	- regs_rflags	- SIZEOF_REG )(%rsp)
	pushq	( frame_rip	- regs_rip	- SIZEOF_REG )(%rsp)
	pushq	%r15
	pushq	%r14
	pushq	%r13
	pushq	%r12
	pushq	%r11
	pushq	%r10
	pushq	%r9
	pushq	%r8
	pushq	( frame_rsp	- regs_rsp	- SIZEOF_REG )(%rsp)
	pushq	%rbp
	pushq	%rdi
	pushq	%rsi
	pushq	%rdx
	pushq	%rcx
	pushq	%rbx
	pushq	%rax

	/* Call GDB stub exception handler */
	movq	gdb_code(%rsp), %rdi
	movq	%rsp, %rsi
	call	gdbmach_handler

	/* Restore from register dump */
	popq	%rax
	popq	%rbx
	popq	%rcx
	popq	%rdx
	popq	%rsi
	popq	%rdi
	popq	%rbp
	popq	( frame_rsp	- regs_rsp	- SIZEOF_REG )(%rsp)
	popq	%r8
	popq	%r9
	popq	%r10
	popq	%r11
	popq	%r12
	popq	%r13
	popq	%r14
	popq	%r15
	popq	( frame_rip	- regs_rip	- SIZEOF_REG )(%rsp)
	popq	( frame_rflags	- regs_rflags	- SIZEOF_REG )(%rsp)
	popq	( frame_cs	- regs_cs	- SIZEOF_REG )(%rsp)
	popq	( frame_ss	- regs_ss	- SIZEOF_REG )(%rsp)
	addq	$( regs_fs - regs_ds ), %rsp	/* skip %ds, %es */
	popq	%fs
	popq	%gs

	/* Skip code */
	addq	$( gdb_end - gdb_code ), %rsp	/* skip code */

	/* Return */
	iretq