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
|
/*
* Interrupt handlers for GDB stub
*/
#define SIZEOF_I386_REGS 32
#define SIZEOF_I386_FLAGS 4
/****************************************************************************
* Interrupt handlers
****************************************************************************
*/
.section ".text", "ax", @progbits
.code32
/* POSIX signal numbers for reporting traps to GDB */
#define SIGILL 4
#define SIGTRAP 5
#define SIGBUS 7
#define SIGFPE 8
#define SIGSEGV 11
#define SIGSTKFLT 16
.globl gdbmach_nocode_sigfpe
gdbmach_nocode_sigfpe:
pushl $SIGFPE
jmp gdbmach_interrupt
.globl gdbmach_nocode_sigtrap
gdbmach_nocode_sigtrap:
pushl $SIGTRAP
jmp gdbmach_interrupt
.globl gdbmach_nocode_sigstkflt
gdbmach_nocode_sigstkflt:
pushl $SIGSTKFLT
jmp gdbmach_interrupt
.globl gdbmach_nocode_sigill
gdbmach_nocode_sigill:
pushl $SIGILL
jmp gdbmach_interrupt
.globl gdbmach_withcode_sigbus
gdbmach_withcode_sigbus:
movl $SIGBUS, (%esp)
jmp gdbmach_interrupt
.globl gdbmach_withcode_sigsegv
gdbmach_withcode_sigsegv:
movl $SIGSEGV, (%esp)
jmp gdbmach_interrupt
/* When invoked, the stack contains: eflags, cs, eip, signo. */
#define IH_OFFSET_GDB_REGS ( 0 )
#define IH_OFFSET_GDB_EIP ( IH_OFFSET_GDB_REGS + SIZEOF_I386_REGS )
#define IH_OFFSET_GDB_EFLAGS ( IH_OFFSET_GDB_EIP + 4 )
#define IH_OFFSET_GDB_SEG_REGS ( IH_OFFSET_GDB_EFLAGS + SIZEOF_I386_FLAGS )
#define IH_OFFSET_GDB_END ( IH_OFFSET_GDB_SEG_REGS + 6 * 4 )
#define IH_OFFSET_SIGNO ( IH_OFFSET_GDB_END )
#define IH_OFFSET_OLD_EIP ( IH_OFFSET_SIGNO + 4 )
#define IH_OFFSET_OLD_CS ( IH_OFFSET_OLD_EIP + 4 )
#define IH_OFFSET_OLD_EFLAGS ( IH_OFFSET_OLD_CS + 4 )
#define IH_OFFSET_END ( IH_OFFSET_OLD_EFLAGS + 4 )
/* We also access the stack whilst still storing or restoring
* the register snapshot. Since ESP is in flux, we need
* special offsets.
*/
#define IH_OFFSET_FLUX_OLD_CS ( IH_OFFSET_OLD_CS - 44 )
#define IH_OFFSET_FLUX_OLD_EFLAGS ( IH_OFFSET_OLD_EFLAGS - 40 )
#define IH_OFFSET_FLUX_OLD_EIP ( IH_OFFSET_OLD_EIP - 36 )
#define IH_OFFSET_FLUX_END ( IH_OFFSET_END - 20 )
gdbmach_interrupt:
/* Store CPU state in GDB register snapshot */
pushw $0
pushw %gs
pushw $0
pushw %fs
pushw $0
pushw %es
pushw $0
pushw %ds
pushw $0
pushw %ss
pushw $0
pushw IH_OFFSET_FLUX_OLD_CS + 2(%esp)
pushl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
pushl IH_OFFSET_FLUX_OLD_EIP(%esp)
pushl %edi
pushl %esi
pushl %ebp
leal IH_OFFSET_FLUX_END(%esp), %edi
pushl %edi /* old ESP */
pushl %ebx
pushl %edx
pushl %ecx
pushl %eax
/* Switch to virtual addressing */
call _intr_to_virt
/* Call GDB stub exception handler */
pushl %esp
pushl (IH_OFFSET_SIGNO + 4)(%esp)
call gdbmach_handler
addl $8, %esp
/* Copy register snapshot to new stack and switch to new stack */
movl %esp, %esi
movl (IH_OFFSET_GDB_SEG_REGS + 4)(%esp), %eax
movl %eax, %es
movl (IH_OFFSET_GDB_REGS + 16)(%esp), %edi
subl $IH_OFFSET_END, %edi
movl $(IH_OFFSET_END / 4), %ecx
pushl %edi
ss rep movsl
popl %edi
movl %eax, %ss
movl %edi, %esp
/* Restore CPU state from GDB register snapshot */
popl %eax
popl %ecx
popl %edx
popl %ebx
popl %ebp /* Skip %esp: already loaded */
popl %ebp
popl %esi
popl %edi
popl IH_OFFSET_FLUX_OLD_EIP(%esp)
popl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
popl IH_OFFSET_FLUX_OLD_CS(%esp)
popl %ds /* Skip %ss: already loaded */
popl %ds
popl %es
popl %fs
popl %gs
addl $4, %esp /* drop signo */
iret
|