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
|