OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <asm/unistd.h> | 5 #include <asm/unistd.h> |
6 | 6 |
7 | 7 |
8 .internal playground$segvSignalHandler | 8 .internal playground$segvSignalHandler |
9 .global playground$segvSignalHandler | 9 .global playground$segvSignalHandler |
10 playground$segvSignalHandler: | 10 playground$segvSignalHandler: |
11 // Inspect instruction at the point where the segmentation fault | 11 // Inspect instruction at the point where the segmentation fault |
12 // happened. If it is RDTSC, forward the request to the trusted | 12 // happened. If it is RDTSC, forward the request to the trusted |
13 // thread. | 13 // thread. |
14 mov $-3, %ebx // request for RDTSC | 14 mov $-3, %ebx // request for RDTSC |
15 mov 0xDC(%esp), %ebp // %eip at time of segmentation fault | 15 mov 0xDC(%esp), %ebp // %eip at time of segmentation fault |
16 cmpw $0x310F, (%ebp) // RDTSC | 16 cmpw $0x310F, (%ebp) // RDTSC |
17 jz 0f | 17 jz 1f |
18 cmpw $0x010F, (%ebp) // RDTSCP | 18 cmpw $0x010F, (%ebp) // RDTSCP |
19 jnz 10f | 19 jnz 12f |
20 cmpb $0xF9, 2(%ebp) | 20 cmpb $0xF9, 2(%ebp) |
21 jnz 10f | 21 jnz 12f |
22 mov $-4, %ebx // request for RDTSCP | 22 mov $-4, %ebx // request for RDTSCP |
23 0: | 23 1: |
24 #ifndef NDEBUG | 24 #ifndef NDEBUG |
25 lea 100f, %eax | 25 call 2f |
26 push %eax | 26 2:addl $(100f-.), 0(%esp) |
27 call playground$debugMessage | 27 call playground$debugMessage@PLT |
28 sub $4, %esp | 28 sub $4, %esp |
29 #else | 29 #else |
30 sub $8, %esp // allocate buffer for receiving timestamp | 30 sub $8, %esp // allocate buffer for receiving timestamp |
31 #endif | 31 #endif |
32 push %ebx | 32 push %ebx |
33 mov %fs:16, %ebx // fd = threadFdPub | 33 mov %fs:16, %ebx // fd = threadFdPub |
34 mov %esp, %ecx // buf = %esp | 34 mov %esp, %ecx // buf = %esp |
35 mov $4, %edx // len = sizeof(int) | 35 mov $4, %edx // len = sizeof(int) |
36 1:mov %edx, %eax // NR_write | 36 3:mov %edx, %eax // NR_write |
37 int $0x80 | 37 int $0x80 |
38 cmp %eax, %edx | 38 cmp %eax, %edx |
39 jz 8f | 39 jz 10f |
40 cmp $-4, %eax // EINTR | 40 cmp $-4, %eax // EINTR |
41 jz 1b | 41 jz 3b |
42 2:add $12, %esp // remove temporary buffer from stack | 42 4:add $12, %esp // remove temporary buffer from stack |
43 xor %eax, %eax | 43 xor %eax, %eax |
44 movl $0, 0xC8(%esp) // %edx at time of segmentation fault | 44 movl $0, 0xC8(%esp) // %edx at time of segmentation fault |
45 cmpw $0x310F, (%ebp) // RDTSC | 45 cmpw $0x310F, (%ebp) // RDTSC |
46 jz 3f | 46 jz 5f |
47 movl $0, 0xCC(%esp) // %ecx at time of segmentation fault | 47 movl $0, 0xCC(%esp) // %ecx at time of segmentation fault |
48 3:mov %eax, 0xD0(%esp) // %eax at time of segmentation fault | 48 5:mov %eax, 0xD0(%esp) // %eax at time of segmentation fault |
49 4:mov 0xDC(%esp), %ebp // %eip at time of segmentation fault | 49 6:mov 0xDC(%esp), %ebp // %eip at time of segmentation fault |
50 addl $2, 0xDC(%esp) // %eip at time of segmentation fault | 50 addl $2, 0xDC(%esp) // %eip at time of segmentation fault |
51 cmpw $0x010F, (%ebp) // RDTSCP | 51 cmpw $0x010F, (%ebp) // RDTSCP |
52 jnz 5f | 52 jnz 7f |
53 addl $1, 0xDC(%esp) // %eip at time of segmentation fault | 53 addl $1, 0xDC(%esp) // %eip at time of segmentation fault |
54 5:add $0x4, %esp | 54 7:add $0x4, %esp |
55 6:sub $0x1CC, %esp // a legacy signal stack is much larger | 55 8:sub $0x1CC, %esp // a legacy signal stack is much larger |
56 mov 0x1CC(%esp), %eax // push signal number | 56 mov 0x1CC(%esp), %eax // push signal number |
57 push %eax | 57 push %eax |
58 lea 0x270(%esp), %esi // copy siginfo register values | 58 lea 0x270(%esp), %esi // copy siginfo register values |
59 lea 0x4(%esp), %edi // into new location | 59 lea 0x4(%esp), %edi // into new location |
60 mov $22, %ecx | 60 mov $22, %ecx |
61 cld | 61 cld |
62 rep movsl | 62 rep movsl |
63 mov 0x2C8(%esp), %ebx // copy first half of signal mask | 63 mov 0x2C8(%esp), %ebx // copy first half of signal mask |
64 mov %ebx, 0x54(%esp) | 64 mov %ebx, 0x54(%esp) |
65 7:pop %eax // remove dummy argument (signo) | 65 9:pop %eax // remove dummy argument (signo) |
66 mov $119, %eax // NR_sigreturn | 66 mov $119, %eax // NR_sigreturn |
67 int $0x80 | 67 int $0x80 |
68 8:mov $12, %edx // len = 3*sizeof(int) | 68 10:mov $12, %edx // len = 3*sizeof(int) |
69 9:mov $3, %eax // NR_read | 69 11:mov $3, %eax // NR_read |
70 int $0x80 | 70 int $0x80 |
71 cmp $-4, %eax // EINTR | 71 cmp $-4, %eax // EINTR |
72 jz 9b | 72 jz 11b |
73 cmp %eax, %edx | 73 cmp %eax, %edx |
74 jnz 2b | 74 jnz 4b |
75 pop %eax | 75 pop %eax |
76 pop %edx | 76 pop %edx |
77 pop %ecx | 77 pop %ecx |
78 mov %edx, 0xC8(%esp) // %edx at time of segmentation fault | 78 mov %edx, 0xC8(%esp) // %edx at time of segmentation fault |
79 cmpw $0x310F, (%ebp) // RDTSC | 79 cmpw $0x310F, (%ebp) // RDTSC |
80 jz 3b | 80 jz 5b |
81 mov %ecx, 0xCC(%esp) // %ecx at time of segmentation fault | 81 mov %ecx, 0xCC(%esp) // %ecx at time of segmentation fault |
82 jmp 3b | 82 jmp 5b |
83 | 83 |
84 // If the instruction is INT 0, then this was probably the result | 84 // If the instruction is INT 0, then this was probably the result |
85 // of playground::Library being unable to find a way to safely | 85 // of playground::Library being unable to find a way to safely |
86 // rewrite the system call instruction. Retrieve the CPU register | 86 // rewrite the system call instruction. Retrieve the CPU register |
87 // at the time of the segmentation fault and invoke | 87 // at the time of the segmentation fault and invoke |
88 // syscallEntryPointWithFrame(). | 88 // syscallEntryPointWithFrame(). |
89 10:cmpw $0x00CD, (%ebp) // INT $0x0 | 89 12:cmpw $0x00CD, (%ebp) // INT $0x0 |
90 jnz 20f | 90 jnz 23f |
91 cmpl $__NR_clone + 0xF001, 0xD0(%esp) | 91 cmpl $__NR_clone + 0xF001, 0xD0(%esp) |
92 jz .L_handle_callback_request | 92 jz .L_handle_callback_request |
93 #ifndef NDEBUG | 93 #ifndef NDEBUG |
94 lea 200f, %eax | 94 call 1010f |
95 push %eax | 95 1010:addl $(200f-.), 0(%esp) |
96 call playground$debugMessage | 96 call playground$debugMessage@PLT |
97 add $0x4, %esp | 97 add $0x4, %esp |
98 #endif | 98 #endif |
99 mov 0xD0(%esp), %eax // %eax at time of segmentation fault | 99 mov 0xD0(%esp), %eax // %eax at time of segmentation fault |
100 mov 0xC4(%esp), %ebx // %ebx at time of segmentation fault | 100 mov 0xC4(%esp), %ebx // %ebx at time of segmentation fault |
101 mov 0xCC(%esp), %ecx // %ecx at time of segmentation fault | 101 mov 0xCC(%esp), %ecx // %ecx at time of segmentation fault |
102 mov 0xC8(%esp), %edx // %edx at time of segmentation fault | 102 mov 0xC8(%esp), %edx // %edx at time of segmentation fault |
103 mov 0xB8(%esp), %esi // %esi at time of segmentation fault | 103 mov 0xB8(%esp), %esi // %esi at time of segmentation fault |
104 mov 0xB4(%esp), %edi // %edi at time of segmentation fault | 104 mov 0xB4(%esp), %edi // %edi at time of segmentation fault |
105 mov 0xBC(%esp), %ebp // %ebp at time of segmentation fault | 105 mov 0xBC(%esp), %ebp // %ebp at time of segmentation fault |
106 | 106 |
107 // Handle sigprocmask() and rt_sigprocmask() | 107 // Handle sigprocmask() and rt_sigprocmask() |
108 cmp $175, %eax // NR_rt_sigprocmask | 108 cmp $175, %eax // NR_rt_sigprocmask |
109 jnz 11f | 109 jnz 13f |
110 mov $-22, %eax // -EINVAL | 110 mov $-22, %eax // -EINVAL |
111 cmp $8, %esi // %esi = sigsetsize (8 bytes = 64 signals) | 111 cmp $8, %esi // %esi = sigsetsize (8 bytes = 64 signals) |
112 jl 3b | 112 jl 5b |
113 jmp 12f | 113 jmp 14f |
114 11:cmp $126, %eax // NR_sigprocmask | 114 13:cmp $126, %eax // NR_sigprocmask |
115 jnz 16f | 115 jnz 18f |
116 mov $-22, %eax | 116 mov $-22, %eax |
117 12:mov 0xFC(%esp), %edi // signal mask at time of segmentation fault | 117 14:mov 0xFC(%esp), %edi // signal mask at time of segmentation fault |
118 mov 0x100(%esp), %ebp | 118 mov 0x100(%esp), %ebp |
119 test %ecx, %ecx // only set mask, if set is non-NULL | 119 test %ecx, %ecx // only set mask, if set is non-NULL |
120 jz 15f | 120 jz 17f |
121 mov 0(%ecx), %esi | 121 mov 0(%ecx), %esi |
122 mov 4(%ecx), %ecx | 122 mov 4(%ecx), %ecx |
123 cmp $0, %ebx // %ebx = how (SIG_BLOCK) | 123 cmp $0, %ebx // %ebx = how (SIG_BLOCK) |
124 jnz 13f | 124 jnz 15f |
125 or %esi, 0xFC(%esp) // signal mask at time of segmentation fault | 125 or %esi, 0xFC(%esp) // signal mask at time of segmentation fault |
126 or %ecx, 0x100(%esp) | 126 or %ecx, 0x100(%esp) |
127 jmp 15f | 127 jmp 17f |
128 13:cmp $1, %ebx // %ebx = how (SIG_UNBLOCK) | 128 15:cmp $1, %ebx // %ebx = how (SIG_UNBLOCK) |
129 jnz 14f | 129 jnz 16f |
130 xor $-1, %esi | 130 xor $-1, %esi |
131 xor $-1, %ecx | 131 xor $-1, %ecx |
132 and %esi, 0xFC(%esp) // signal mask at time of segmentation fault | 132 and %esi, 0xFC(%esp) // signal mask at time of segmentation fault |
133 and %ecx, 0x100(%esp) | 133 and %ecx, 0x100(%esp) |
134 jmp 15f | 134 jmp 17f |
135 14:cmp $2, %ebx // %ebx = how (SIG_SETMASK) | 135 16:cmp $2, %ebx // %ebx = how (SIG_SETMASK) |
136 jnz 3b | 136 jnz 5b |
137 mov %esi, 0xFC(%esp) // signal mask at time of segmentation fault | 137 mov %esi, 0xFC(%esp) // signal mask at time of segmentation fault |
138 mov %ecx, 0x100(%esp) | 138 mov %ecx, 0x100(%esp) |
139 15:xor %eax, %eax | 139 17:xor %eax, %eax |
140 test %edx, %edx // only return old mask, if set is non-NULL | 140 test %edx, %edx // only return old mask, if set is non-NULL |
141 jz 3b | 141 jz 5b |
142 mov %edi, 0(%edx) // old_set | 142 mov %edi, 0(%edx) // old_set |
143 mov %ebp, 4(%edx) | 143 mov %ebp, 4(%edx) |
144 jmp 3b | 144 jmp 5b |
145 | 145 |
146 // Handle sigreturn() and rt_sigreturn() | 146 // Handle sigreturn() and rt_sigreturn() |
147 // See syscall.cc for a discussion on how we can emulate rt_sigreturn() | 147 // See syscall.cc for a discussion on how we can emulate rt_sigreturn() |
148 // by calling sigreturn() with a suitably adjusted stack. | 148 // by calling sigreturn() with a suitably adjusted stack. |
149 16:cmp $119, %eax // NR_sigreturn | 149 18:cmp $119, %eax // NR_sigreturn |
150 jnz 17f | 150 jnz 19f |
151 mov 0xC0(%esp), %esp // %esp at time of segmentation fault | 151 mov 0xC0(%esp), %esp // %esp at time of segmentation fault |
152 int $0x80 // sigreturn() is unrestricted | 152 int $0x80 // sigreturn() is unrestricted |
153 17:cmp $173, %eax // NR_rt_sigreturn | 153 19:cmp $173, %eax // NR_rt_sigreturn |
154 jnz 18f | 154 jnz 20f |
155 mov 0xC0(%esp), %esp // %esp at time of segmentation fault | 155 mov 0xC0(%esp), %esp // %esp at time of segmentation fault |
156 sub $4, %esp // add fake return address | 156 sub $4, %esp // add fake return address |
157 jmp 4b | 157 jmp 6b |
158 | 158 |
159 // Copy signal frame onto new stack. In the process, we have to convert | 159 // Copy signal frame onto new stack. In the process, we have to convert |
160 // it from an RT signal frame to a legacy signal frame. | 160 // it from an RT signal frame to a legacy signal frame. |
161 // See clone.cc for details | 161 // See clone.cc for details |
162 18:cmp $120+0xF000, %eax // NR_clone + 0xF000 | 162 20:cmp $120+0xF000, %eax // NR_clone + 0xF000 |
163 jnz 19f | 163 jnz 21f |
164 lea -0x1C8(%esp), %eax // retain stack frame upon returning | 164 lea -0x1C8(%esp), %eax // retain stack frame upon returning |
165 mov %eax, 0xC0(%esp) // %esp at time of segmentation fault | 165 mov %eax, 0xC0(%esp) // %esp at time of segmentation fault |
166 jmp 3b | 166 jmp 5b |
167 | 167 |
168 // Forward system call to syscallEntryPointWithFrame() | 168 // Forward system call to syscallEntryPointWithFrame() |
169 19:push $3b | 169 21:call 22f |
| 170 22:subl $(.-5b), 0(%esp) |
170 push 0xE0(%esp) // %eip at time of segmentation fault | 171 push 0xE0(%esp) // %eip at time of segmentation fault |
171 jmp playground$syscallEntryPointWithFrame | 172 jmp playground$syscallEntryPointWithFrame@PLT |
172 | 173 |
173 // This was a genuine segmentation fault. Check Sandbox::sa_segv_ for | 174 // This was a genuine segmentation fault. Check Sandbox::sa_segv_ for |
174 // what we are supposed to do. | 175 // what we are supposed to do. |
175 // In order to implement SA_NODEFER, we have to keep track of recursive | 176 // In order to implement SA_NODEFER, we have to keep track of recursive |
176 // calls to SIGSEGV handlers. This means we have to increment a counter | 177 // calls to SIGSEGV handlers. This means we have to increment a counter |
177 // before calling the user's signal handler, and decrement it on | 178 // before calling the user's signal handler, and decrement it on |
178 // leaving the user's signal handler. | 179 // leaving the user's signal handler. |
179 // N.B. We currently do not correctly adjust the SEGV counter, if the | 180 // N.B. We currently do not correctly adjust the SEGV counter, if the |
180 // user's signal handler exits in way other than by returning (e.g. by | 181 // user's signal handler exits in way other than by returning (e.g. by |
181 // directly calling {,rt_}sigreturn(), or by calling siglongjmp()). | 182 // directly calling {,rt_}sigreturn(), or by calling siglongjmp()). |
182 // N.B. On i386, we don't have any guarantees that NX protection works. | 183 // N.B. On i386, we don't have any guarantees that NX protection works. |
183 // So, we don't even attempt to fake a correct restorer function. Some | 184 // So, we don't even attempt to fake a correct restorer function. Some |
184 // callers might be confused by this and will need fixing for running | 185 // callers might be confused by this and will need fixing for running |
185 // inside of the seccomp sandbox. | 186 // inside of the seccomp sandbox. |
186 20:lea playground$sa_segv, %eax | 187 23:call 24f |
| 188 24:pop %eax |
| 189 add $(_GLOBAL_OFFSET_TABLE_+(.-24b)), %eax |
| 190 lea playground$sa_segv@GOTOFF(%eax), %eax |
187 cmpl $0, 0(%eax) // SIG_DFL | 191 cmpl $0, 0(%eax) // SIG_DFL |
188 jz 21f | 192 jz 25f |
189 cmpl $1, 0(%eax) // SIG_IGN | 193 cmpl $1, 0(%eax) // SIG_IGN |
190 jnz 22f // can't really ignore synchronous signals | 194 jnz 26f // can't really ignore synchronous signals |
191 | 195 |
192 // Trigger the kernel's default signal disposition. The only way we can | 196 // Trigger the kernel's default signal disposition. The only way we can |
193 // do this from seccomp mode is by blocking the signal and retriggering | 197 // do this from seccomp mode is by blocking the signal and retriggering |
194 // it. | 198 // it. |
195 21:orb $4, 0xFD(%esp) // signal mask at time of segmentation fault | 199 25:orb $4, 0xFD(%esp) // signal mask at time of segmentation fault |
196 jmp 5b | 200 jmp 7b |
197 | 201 |
198 // Check sa_flags: | 202 // Check sa_flags: |
199 // - We can ignore SA_NOCLDSTOP, SA_NOCLDWAIT, and SA_RESTART as they | 203 // - We can ignore SA_NOCLDSTOP, SA_NOCLDWAIT, and SA_RESTART as they |
200 // do not have any effect for SIGSEGV. | 204 // do not have any effect for SIGSEGV. |
201 // - We have to always register our signal handler with SA_NODEFER so | 205 // - We have to always register our signal handler with SA_NODEFER so |
202 // that the user's signal handler can make system calls which might | 206 // that the user's signal handler can make system calls which might |
203 // require additional help from our SEGV handler. | 207 // require additional help from our SEGV handler. |
204 // - If the user's signal handler wasn't supposed to be SA_NODEFER, | 208 // - If the user's signal handler wasn't supposed to be SA_NODEFER, |
205 // then we emulate this behavior by keeping track of a recursion | 209 // then we emulate this behavior by keeping track of a recursion |
206 // counter. | 210 // counter. |
207 // | 211 // |
208 // TODO(markus): If/when we add support for sigaltstack(), we have to | 212 // TODO(markus): If/when we add support for sigaltstack(), we have to |
209 // handle SA_ONSTACK. | 213 // handle SA_ONSTACK. |
210 22:cmpl $0, %fs:0x1040-0x58 // check if we failed inside of SEGV handler | 214 26:cmpl $0, %fs:0x1040-0x58 // check if we failed inside of SEGV handler |
211 jnz 21b // if so, then terminate program | 215 jnz 25b // if so, then terminate program |
212 mov 0(%eax), %ebx // sa_segv_.sa_sigaction | 216 mov 0(%eax), %ebx // sa_segv_.sa_sigaction |
213 mov 4(%eax), %ecx // sa_segv_.sa_flags | 217 mov 4(%eax), %ecx // sa_segv_.sa_flags |
214 btl $31, %ecx // SA_RESETHAND | 218 btl $31, %ecx // SA_RESETHAND |
215 jnc 23f | 219 jnc 27f |
216 movl $0, 0(%eax) // set handler to SIG_DFL | 220 movl $0, 0(%eax) // set handler to SIG_DFL |
217 23:btl $30, %ecx // SA_NODEFER | 221 27:btl $30, %ecx // SA_NODEFER |
218 jc 26f | 222 jc 32f |
219 btl $2, %ecx // SA_SIGINFO | 223 btl $2, %ecx // SA_SIGINFO |
220 jnc 24f | 224 jnc 29f |
221 movl $27f, 0(%esp) // set appropriate restorer function | 225 add $4, %esp |
| 226 call 28f |
| 227 28:addl $(35f-.), 0(%esp) // set appropriate restorer function |
222 incl %fs:0x1040-0x58 // increment recursion counter | 228 incl %fs:0x1040-0x58 // increment recursion counter |
223 jmp *%ebx // call user's signal handler | 229 jmp *%ebx // call user's signal handler |
224 24:movl $28f, 0(%esp) | 230 29:add $4, %esp |
| 231 call 30f |
| 232 30:addl $(36f-.), 0(%esp) |
225 incl %fs:0x1040-0x58 // increment recursion counter | 233 incl %fs:0x1040-0x58 // increment recursion counter |
226 | 234 |
227 // We always register the signal handler to give us rt-style signal | 235 // We always register the signal handler to give us rt-style signal |
228 // frames. But if the user asked for legacy signal frames, we must | 236 // frames. But if the user asked for legacy signal frames, we must |
229 // convert the signal frame prior to calling the user's signal handler. | 237 // convert the signal frame prior to calling the user's signal handler. |
230 25:sub $0x1C8, %esp // a legacy signal stack is much larger | 238 31:sub $0x1C8, %esp // a legacy signal stack is much larger |
231 mov 0x1CC(%esp), %eax // push signal number | 239 mov 0x1CC(%esp), %eax // push signal number |
232 push %eax | 240 push %eax |
233 mov 0x1CC(%esp), %eax // push restorer function | 241 mov 0x1CC(%esp), %eax // push restorer function |
234 push %eax | 242 push %eax |
235 lea 0x274(%esp), %esi // copy siginfo register values | 243 lea 0x274(%esp), %esi // copy siginfo register values |
236 lea 0x8(%esp), %edi // into new location | 244 lea 0x8(%esp), %edi // into new location |
237 mov $22, %ecx | 245 mov $22, %ecx |
238 cld | 246 cld |
239 rep movsl | 247 rep movsl |
240 mov 0x2CC(%esp), %eax // copy first half of signal mask | 248 mov 0x2CC(%esp), %eax // copy first half of signal mask |
241 mov %eax, 0x58(%esp) | 249 mov %eax, 0x58(%esp) |
242 jmp *%ebx // call user's signal handler | 250 jmp *%ebx // call user's signal handler |
243 26:movl $7b, 0(%esp) // set appropriate restorer function | 251 32:add $4, %esp |
| 252 call 33f |
| 253 33:addl $(9b-.), 0(%esp) // set appropriate restorer function |
244 btl $2, %ecx // SA_SIGINFO | 254 btl $2, %ecx // SA_SIGINFO |
245 jnc 25b | 255 jnc 31b |
246 movl $6b, 0(%esp) // set appropriate restorer function | 256 add $4, %esp |
| 257 call 34f |
| 258 34:addl $(8b-.), 0(%esp) // set appropriate restorer function |
247 jmp *%ebx // call user's signal handler | 259 jmp *%ebx // call user's signal handler |
248 27:decl %fs:0x1040-0x58 | 260 35:decl %fs:0x1040-0x58 |
249 jmp 6b | 261 jmp 8b |
250 28:decl %fs:0x1040-0x58 | 262 36:decl %fs:0x1040-0x58 |
251 jmp 7b | 263 jmp 9b |
252 | 264 |
253 .L_handle_callback_request: | 265 .L_handle_callback_request: |
254 mov 0xC8(%esp), %eax // %edx at time of segmentation fault | 266 mov 0xC8(%esp), %eax // %edx at time of segmentation fault |
255 jmp *%eax | 267 jmp *%eax |
OLD | NEW |