OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | |
8 * This is the core of amd64-mode validator. Please note that this file | |
9 * combines ragel machine description and C language actions. Please read | |
10 * validator_internals.html first to understand how the whole thing is built: | |
11 * it explains how the byte sequences are constructed, what constructs like | |
12 * “@{}” or “REX_WRX?” mean, etc. | |
Brad Chen
2012/10/05 16:47:21
Thanks, this is helpful.
| |
13 */ | |
14 | |
7 #include <assert.h> | 15 #include <assert.h> |
8 #include <errno.h> | 16 #include <errno.h> |
9 #include <stddef.h> | 17 #include <stddef.h> |
10 #include <stdio.h> | 18 #include <stdio.h> |
11 #include <stdlib.h> | 19 #include <stdlib.h> |
12 #include <string.h> | 20 #include <string.h> |
13 | 21 |
14 #include "native_client/src/trusted/validator_ragel/unreviewed/validator_interna l.h" | 22 #include "native_client/src/trusted/validator_ragel/validator_internal.h" |
15 | 23 |
16 %%{ | 24 %%{ |
17 machine x86_64_validator; | 25 machine x86_64_validator; |
18 alphtype unsigned char; | 26 alphtype unsigned char; |
19 variable p current_position; | 27 variable p current_position; |
20 variable pe end_of_bundle; | 28 variable pe end_of_bundle; |
21 variable eof end_of_bundle; | 29 variable eof end_of_bundle; |
22 variable cs current_state; | 30 variable cs current_state; |
23 | 31 |
24 include byte_machine "byte_machines.rl"; | 32 include byte_machine "byte_machines.rl"; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 process_2_operands_zero_extends(&restricted_register, | 106 process_2_operands_zero_extends(&restricted_register, |
99 &instruction_info_collected, rex_prefix, | 107 &instruction_info_collected, rex_prefix, |
100 operand_states); | 108 operand_states); |
101 } | 109 } |
102 | 110 |
103 include decode_x86_64 "validator_x86_64_instruction.rl"; | 111 include decode_x86_64 "validator_x86_64_instruction.rl"; |
104 | 112 |
105 data16condrep = (data16 | condrep data16 | data16 condrep); | 113 data16condrep = (data16 | condrep data16 | data16 condrep); |
106 data16rep = (data16 | rep data16 | data16 rep); | 114 data16rep = (data16 | rep data16 | data16 rep); |
107 | 115 |
108 # Special %rbp modifications without required sandboxing | 116 # Special %rbp modifications—the ones which don't need a sandboxing. |
117 # | |
118 # Note that there are two different opcodes for “mov”: “mov” with opcode | |
119 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from | |
120 # “B” to “A”. | |
109 rbp_modifications = | 121 rbp_modifications = |
110 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp | 122 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp |
111 (b_0100_10x0 0x8b 0xec) # | mov %rsp,%rbp | 123 (b_0100_10x0 0x8b 0xec) # mov %rsp,%rbp |
Brad Chen
2012/10/05 16:47:21
This is much improved with the comments and '|' li
khim
2012/10/15 16:38:57
This was the only case where they were not lined u
Brad Chen
2012/10/16 00:16:55
The way a code review works is I am a proxy for fu
| |
112 #(b_0100_1xx0 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rbp | |
113 #(b_0100_1xx0 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rbp | |
114 @process_0_operands; | 124 @process_0_operands; |
115 | 125 |
116 # Special instructions used for %rbp sandboxing | 126 # Special instructions used for %rbp sandboxing. |
127 # | |
128 # This is the “second half” of the %rbp sandboxing. Any zero-extending | |
129 # instruction which stores the data in %ebp can be first part, but unlike | |
130 # the situation with other “normal” registers you can not just write to | |
131 # %ebp and continue: such activity MUST restore the status quo immediately | |
132 # via one of these instructions. | |
117 rbp_sandboxing = | 133 rbp_sandboxing = |
118 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp | 134 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp |
119 b_0100_10x1 0x03 0xef | # add %r15,%rbp | 135 b_0100_10x1 0x03 0xef | # add %r15,%rbp |
120 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp | 136 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp |
121 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp | 137 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp |
138 # “Normal” instructions detect an error when confronted with restricted | |
139 # register %rbp. These instructions require this state instead. | |
140 # | |
141 # Check this precondition and mark the beginning of the instruction as | |
142 # invalid jump for target. | |
122 @{ if (restricted_register == REG_RBP) | 143 @{ if (restricted_register == REG_RBP) |
123 instruction_info_collected |= RESTRICTED_REGISTER_USED; | 144 instruction_info_collected |= RESTRICTED_REGISTER_USED; |
124 else | 145 else |
125 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; | 146 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; |
126 restricted_register = NO_REG; | 147 restricted_register = NO_REG; |
127 BitmapClearBit(valid_targets, (instruction_start - data)); | 148 MakeInvalidJumpTarget((instruction_start - data), valid_targets); |
128 }; | 149 }; |
129 | 150 |
130 # Special %rbp modifications without required sandboxing | 151 # Special %rsp modifications—the ones which don't need a sandboxing. |
152 # | |
153 # Note that there are two different opcodes for “mov”: “mov” with opcode | |
154 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from | |
155 # “B” to “A”. | |
131 rsp_modifications = | 156 rsp_modifications = |
132 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp | 157 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp |
133 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp | 158 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp |
134 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp | 159 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp |
135 #Superfluous bits are not supported: | 160 #Superfluous bits are not supported: |
136 # http://code.google.com/p/nativeclient/issues/detail?id=3012 | 161 # http://code.google.com/p/nativeclient/issues/detail?id=3012 |
137 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp | 162 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp |
138 @process_0_operands; | 163 @process_0_operands; |
139 | 164 |
140 # Special instructions used for %rbp sandboxing | 165 # Special instructions used for %rsp sandboxing. |
166 # | |
167 # This is the “second half” of the %rsp sandboxing. Any zero-extending | |
168 # instruction which stores the data in %esp can be first part, but unlike | |
169 # the situation with other “normal” registers you can not just write to | |
170 # %esp and continue: such activity MUST restore the status quo immediately | |
171 # via one of these instructions. | |
141 rsp_sandboxing = | 172 rsp_sandboxing = |
142 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp | 173 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp |
143 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp | 174 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp |
144 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp | 175 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp |
176 # “Normal” instructions detect an error when confronted with restricted | |
Brad Chen
2012/10/05 16:47:21
I don't think you mean "detect an error when confr
khim
2012/10/15 16:38:57
I mean normal_instruction ragel machine here, of c
Brad Chen
2012/10/16 00:16:55
As written the comment is unclear. Please clarify.
khim
2013/03/08 17:59:53
Done.
| |
177 # register %rsp. These instructions require this state instead. | |
178 # | |
179 # Check this precondition and mark the beginning of the instruction as | |
180 # invalid jump for target. | |
145 @{ if (restricted_register == REG_RSP) | 181 @{ if (restricted_register == REG_RSP) |
146 instruction_info_collected |= RESTRICTED_REGISTER_USED; | 182 instruction_info_collected |= RESTRICTED_REGISTER_USED; |
147 else | 183 else |
148 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; | 184 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; |
149 restricted_register = NO_REG; | 185 restricted_register = NO_REG; |
150 BitmapClearBit(valid_targets, (instruction_start - data)); | 186 MakeInvalidJumpTarget((instruction_start - data), valid_targets); |
151 }; | 187 }; |
152 | 188 |
153 # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction | 189 # naclcall or nacljmp. These are three-instruction indirection-jump sequences. |
154 # and as such will detect case where %rbp/%rsp is illegally modified. | 190 # and $~0x1f, %eXX |
191 # and RBASE, %rXX | |
192 # jmpq *%rXX (or: callq *%rXX) | |
193 # Note: first "and $~0x1f, %eXX" is a normal instruction and as such will | |
194 # detect case where %rbp/%rsp is illegally modified when this machine will be | |
Brad Chen
2012/10/05 16:47:21
Instead of "detect" do you mean "match"?
khim
2012/10/15 16:38:57
No, detect. I mean the following: "0x83 b_11_100_x
Brad Chen
2012/10/16 00:16:55
Let me try to reword my comment to make it clearer
khim
2013/03/08 17:59:53
Tried to reword the meaning to avoid ambiguous wor
| |
195 # combined with normal_instruction machine. | |
196 # | |
197 # There are number of variants present which differ by the REX prefix usage: | |
198 # we need to make sure “%eXX” in “and”, “%rXX” in “add”, and “%eXX” in “jmpq” | |
199 # or “callq” is the same register and it's much simpler to do if one single | |
200 # action handles only fixed number of bytes. | |
201 # | |
202 # Additional complication arises because x86-64 contains two different “add” | |
203 # instruction: with “0x01” and “0x03” opcode. They differ in the direction | |
204 # used: both can add “A” and “B” but one of them stores the result in “A” and | |
205 # other stores the result in “B” (see AMD/Intel manual for clarification). | |
206 # Both should be allowed. | |
207 # | |
208 # REGISTER USAGE ABBREVIATIONS: | |
209 # E86: legacy ia32 registers (all eight: %eax to %edi) | |
210 # R86: 64-bit counterparts for legacy 386 registers (%rax to %rdi) | |
211 # R64: new amd64 registers (only seven: %r8 to %r14) | |
212 # E86: 32-bit counterparts for new amd64 registers (%r8d to %r14d) | |
Brad Chen
2012/10/05 16:47:21
Please list these in this order: E86, R86, E64, R6
khim
2012/10/15 16:38:57
Done.
| |
213 # RBASE: %r15 (used as “base of untrusted world” in NaCl for amd64) | |
155 naclcall_or_nacljmp = | 214 naclcall_or_nacljmp = |
156 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 215 # This block encodes call and jump superinstructions of the form: |
157 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 216 # 0: 83 e_ e0 and $~0x1f,E86 |
158 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 217 # 3: 4_ 01 f_ add RBASE,R86 |
159 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) | 218 # 6: ff e_ jmpq *R86 |
160 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 219 #### INSTRUCTION ONE (three bytes) |
161 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 220 # and $~0x1f, E86 |
162 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 221 (0x83 b_11_100_xxx 0xe0 |
163 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 222 #### INSTRUCTION TWO (three bytes) |
164 @{ | 223 # add RBASE, R86 (0x01 opcode) |
165 instruction_start -= 6; | 224 b_0100_11x0 0x01 b_11_111_xxx |
166 if (RMFromModRM(instruction_start[1]) != | 225 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix) |
167 RMFromModRM(instruction_start[5]) || | 226 # callq R86 |
168 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) | 227 ((REX_WRX? 0xff b_11_010_xxx) | |
169 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 228 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix) |
170 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 229 # jmpq R86 |
171 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 230 (REX_WRX? 0xff b_11_100_xxx))) |
172 restricted_register = NO_REG; | 231 @{ |
173 } | | 232 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start, |
233 current_position, data, valid_targets, | |
234 FALSE, FALSE); | |
235 } | | |
174 | 236 |
175 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 237 # This block encodes call and jump superinstructions of the form: |
176 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 238 # 0: 83 e_ e0 and $~0x1f,E86 |
177 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 239 # 3: 4_ 03 f_ add RBASE,R86 |
178 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) | 240 # 6: ff e_ jmpq *R86 |
179 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 241 #### INSTRUCTION ONE (three bytes) |
180 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 242 # and $~0x1f, E86 |
181 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 243 (0x83 b_11_100_xxx 0xe0 |
182 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 244 #### INSTRUCTION TWO (three bytes) |
183 @{ | 245 # add RBASE, R86 (0x03 opcode) |
184 instruction_start -= 6; | 246 b_0100_10x1 0x03 b_11_xxx_111 |
185 if (RMFromModRM(instruction_start[1]) != | 247 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix) |
186 RegFromModRM(instruction_start[5]) || | 248 # callq R86 |
187 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) | 249 ((REX_WRX? 0xff b_11_010_xxx) | |
188 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 250 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix) |
189 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 251 # jmpq R86 |
190 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 252 (REX_WRX? 0xff b_11_100_xxx))) |
191 restricted_register = NO_REG; | 253 @{ |
192 } | | 254 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start, |
Brad Chen
2012/10/05 16:47:21
As I mentioned in the file where this procedure is
khim
2012/10/15 16:38:57
Done.
| |
255 current_position, data, valid_targets, | |
256 FALSE, TRUE); | |
257 } | | |
193 | 258 |
194 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 259 # This block encodes call and jump superinstructions of the form: |
195 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 260 # 0: 4_ 83 e_ e0 and $~0x1f,E86 |
196 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 261 # 4: 4_ 01 f_ add RBASE,R86 |
197 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) | 262 # 7: ff e_ jmpq *R86 |
198 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 263 #### INSTRUCTION ONE (four bytes) |
199 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 264 # and $~0x1f, E86 |
200 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 265 ((REX_RX 0x83 b_11_100_xxx 0xe0 |
201 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | | 266 #### INSTRUCTION TWO (three bytes) |
267 # add RBASE, R86 (0x01 opcode) | |
268 b_0100_11x0 0x01 b_11_111_xxx | |
269 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix) | |
270 # callq R86 | |
271 ((REX_WRX? 0xff b_11_010_xxx) | | |
272 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix) | |
273 # jmpq R86 | |
274 (REX_WRX? 0xff b_11_100_xxx))) | | |
202 | 275 |
203 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 276 # This block encodes call and jump superinstructions of the form: |
204 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 | 277 # 0: 4_ 83 e_ e0 and $~0x1f,E64 |
205 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 278 # 4: 4_ 01 f_ add RBASE,R64 |
206 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe) | 279 # 7: 4_ ff e_ jmpq *R64 |
207 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 280 #### INSTRUCTION ONE (four bytes) |
208 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | | 281 # and $~0x1f, E64 |
209 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 282 (b_0100_0xx1 0x83 (b_11_100_xxx - b_11_100_111) 0xe0 |
210 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) | 283 #### INSTRUCTION TWO (three bytes) |
211 @{ | 284 # add RBASE, R64 (0x01 opcode) |
212 instruction_start -= 7; | 285 b_0100_11x1 0x01 (b_11_111_xxx - b_11_111_111) |
213 if (RMFromModRM(instruction_start[2]) != | 286 #### INSTRUCTION THREE: call (three bytes) |
214 RMFromModRM(instruction_start[6]) || | 287 # callq R64 |
215 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) | 288 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) | |
216 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 289 #### INSTRUCTION THREE: jmp (three bytes) |
217 BitmapClearBit(valid_targets, (instruction_start - data) + 4); | 290 # jmpq R64 |
218 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 291 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111))))) |
219 restricted_register = NO_REG; | 292 @{ |
220 } | | 293 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start, |
294 current_position, data, valid_targets, | |
295 TRUE, FALSE); | |
296 } | | |
221 | 297 |
222 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 298 # This block encodes call and jump superinstructions of the form: |
223 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 299 # 0: 4_ 83 e_ e0 and $~0x1f,E86 |
224 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 300 # 4: 4_ 03 f_ add RBASE,R86 |
225 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) | 301 # 7: ff e_ jmpq *R86 |
226 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 302 #### INSTRUCTION ONE (four bytes) |
227 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 303 # and $~0x1f, E86 |
228 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 304 ((REX_RX 0x83 b_11_100_xxx 0xe0 |
229 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | | 305 #### INSTRUCTION TWO (three bytes) |
306 # add RBASE, R86 (0x03 opcode) | |
307 b_0100_10x1 0x03 b_11_xxx_111 | |
308 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix) | |
309 # callq R86 | |
310 ((REX_WRX? 0xff b_11_010_xxx) | | |
311 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix) | |
312 # jmpq R86 | |
313 (REX_WRX? 0xff b_11_100_xxx))) | | |
230 | 314 |
231 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 315 # This block encodes call and jump superinstructions of the form: |
232 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 | 316 # 0: 4_ 83 e_ e0 and $~0x1f,E64 |
233 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 317 # 4: 4_ 03 f_ add RBASE,R64 |
234 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7) | 318 # 7: 4_ ff e_ jmpq *R64 |
235 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 319 #### INSTRUCTION ONE (four bytes) |
236 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | | 320 # and $~0x1f, E64 |
237 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 321 (b_0100_0xx1 0x83 (b_11_100_xxx - b_11_100_111) 0xe0 |
238 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) | 322 #### INSTRUCTION TWO (three bytes) |
239 @{ | 323 # add RBASE, R64 (0x03 opcode) |
240 instruction_start -= 7; | 324 b_0100_11x1 0x03 (b_11_xxx_111 - b_11_111_111) |
241 if (RMFromModRM(instruction_start[2]) != | 325 #### INSTRUCTION THREE: call (three bytes) |
242 RegFromModRM(instruction_start[6]) || | 326 # callq R64 |
243 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) | 327 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) | |
244 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 328 #### INSTRUCTION THREE: jmp (three bytes) |
245 BitmapClearBit(valid_targets, (instruction_start - data) + 4); | 329 # jmpq R64 |
246 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 330 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111))))) |
247 restricted_register = NO_REG; | 331 @{ |
248 }; | 332 ProcessNaclCallOrNaclJmp(&instruction_info_collected, &instruction_start, |
333 current_position, data, valid_targets, | |
334 TRUE, TRUE); | |
335 }; | |
249 | 336 |
250 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand | 337 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand |
251 # maskmovq %mmX,%mmY | 338 # maskmovq %mmX,%mmY |
252 maskmovq = | 339 maskmovq = |
253 REX_WRXB? (0x0f 0xf7) | 340 REX_WRXB? (0x0f 0xf7) |
254 @CPUFeature_EMMX modrm_registers; | 341 @CPUFeature_EMMX modrm_registers; |
255 # maskmovdqu %xmmX, %xmmY | 342 # maskmovdqu %xmmX, %xmmY |
256 maskmovdqu = | 343 maskmovdqu = |
257 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix | 344 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix |
258 @CPUFeature_SSE2 modrm_registers; | 345 @CPUFeature_SSE2 modrm_registers; |
(...skipping 23 matching lines...) Expand all Loading... | |
282 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) | 369 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) |
283 string_instruction_rsi_rdi = | 370 string_instruction_rsi_rdi = |
284 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) | 371 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) |
285 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) | 372 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) |
286 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) | 373 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) |
287 | 374 |
288 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) | 375 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) |
289 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) | 376 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) |
290 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) | 377 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) |
291 | 378 |
379 # Superinstruction which handle instructions which require sandboxed %rsi. | |
380 # | |
381 # There are two variants which handle spurious REX prefixes. | |
382 # | |
383 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi”: | |
384 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode | |
385 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the | |
386 # same register there are no functional difference between these opcodes. | |
292 sandbox_instruction_rsi_no_rdi = | 387 sandbox_instruction_rsi_no_rdi = |
293 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 388 (0x89 | 0x8b) 0xf6 # mov %esi,%esi |
294 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 389 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi |
295 string_instruction_rsi_no_rdi | 390 string_instruction_rsi_no_rdi |
296 @{ | 391 @{ |
297 instruction_start -= 6; | 392 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
298 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 393 valid_targets, FALSE); |
299 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | |
300 restricted_register = NO_REG; | |
301 } | | 394 } | |
302 | 395 |
303 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 396 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi |
304 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 397 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi |
305 string_instruction_rsi_no_rdi | 398 string_instruction_rsi_no_rdi |
306 @{ | 399 @{ |
307 instruction_start -= 7; | 400 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
308 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 401 valid_targets, TRUE); |
309 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | |
310 restricted_register = NO_REG; | |
311 }; | 402 }; |
312 | 403 |
404 # Superinstruction which handle instructions which require sandboxed %rdi. | |
405 # | |
406 # There are two variants which handle spurious REX prefixes. | |
407 # | |
408 # Note that both “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”: | |
409 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode | |
410 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the | |
411 # same register there are no functional difference between these opcodes. | |
313 sandbox_instruction_rdi_no_rsi = | 412 sandbox_instruction_rdi_no_rsi = |
314 (0x89 | 0x8b) 0xff . # mov %edi,%edi | 413 (0x89 | 0x8b) 0xff # mov %edi,%edi |
315 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 414 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi |
316 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) | 415 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) |
317 @{ | 416 @{ |
318 instruction_start -= 6; | 417 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
319 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 418 valid_targets, FALSE); |
320 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | |
321 restricted_register = NO_REG; | |
322 } | | 419 } | |
323 | 420 |
324 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi | 421 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi |
325 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 422 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi |
326 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) | 423 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) |
327 @{ | 424 @{ |
328 instruction_start -= 7; | 425 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
329 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 426 valid_targets, TRUE); |
330 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | |
331 restricted_register = NO_REG; | |
332 }; | 427 }; |
333 | 428 |
334 | 429 |
335 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) | 430 # Superinstruction which handle instructions which require both sandboxed %rsi |
431 # and sandboxed %rdi. | |
432 # | |
433 # There are four variants which handle spurious REX prefixes. | |
434 # | |
435 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi” while both | |
436 # “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”: “mov” with opcode “0x89” | |
437 # moves from “A” to “B” while “mov” with opcode “0x8b” moves from “B” to “A” | |
438 # but when “A” and “B” happen to denote the same register there are no | |
439 # functional difference between these opcodes. | |
440 # | |
441 # Note: we call SandboxRsiOrRdiMakeInteriorInvalidJumpTargets in actions here | |
442 # twice because we have two sandboxings here - one for %rsi and one for %rdi. | |
336 sandbox_instruction_rsi_rdi = | 443 sandbox_instruction_rsi_rdi = |
337 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 444 (0x89 | 0x8b) 0xf6 # mov %esi,%esi |
338 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 445 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi |
339 (0x89 | 0x8b) 0xff . # mov %edi,%edi | 446 (0x89 | 0x8b) 0xff # mov %edi,%edi |
340 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 447 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi |
341 string_instruction_rsi_rdi | 448 string_instruction_rsi_rdi |
342 @{ | 449 @{ |
343 instruction_start -= 12; | 450 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
344 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 451 valid_targets, FALSE); |
345 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 452 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
346 BitmapClearBit(valid_targets, (instruction_start - data) + 8); | 453 valid_targets, FALSE); |
347 BitmapClearBit(valid_targets, (instruction_start - data) + 12); | |
348 restricted_register = NO_REG; | |
349 } | | 454 } | |
350 | 455 |
351 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 456 (0x89 | 0x8b) 0xf6 # mov %esi,%esi |
352 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 457 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi |
353 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi | 458 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi |
354 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 459 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi |
355 string_instruction_rsi_rdi | 460 string_instruction_rsi_rdi |
356 @{ | 461 @{ |
357 instruction_start -= 13; | 462 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
358 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 463 valid_targets, TRUE); |
359 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 464 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
360 BitmapClearBit(valid_targets, (instruction_start - data) + 9); | 465 valid_targets, FALSE); |
361 BitmapClearBit(valid_targets, (instruction_start - data) + 13); | |
362 restricted_register = NO_REG; | |
363 } | | 466 } | |
364 | 467 |
365 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 468 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi |
366 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 469 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi |
367 (0x89 | 0x8b) 0xff . # mov %edi,%edi | 470 (0x89 | 0x8b) 0xff # mov %edi,%edi |
368 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 471 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi |
369 string_instruction_rsi_rdi | 472 string_instruction_rsi_rdi |
370 @{ | 473 @{ |
371 instruction_start -= 13; | 474 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
372 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 475 valid_targets, FALSE); |
373 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 476 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
374 BitmapClearBit(valid_targets, (instruction_start - data) + 9); | 477 valid_targets, TRUE); |
375 BitmapClearBit(valid_targets, (instruction_start - data) + 13); | |
376 restricted_register = NO_REG; | |
377 } | | 478 } | |
378 | 479 |
379 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 480 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi |
380 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 481 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi |
381 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi | 482 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi |
382 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 483 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi |
383 string_instruction_rsi_rdi | 484 string_instruction_rsi_rdi |
384 @{ | 485 @{ |
385 instruction_start -= 14; | 486 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
386 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 487 valid_targets, TRUE); |
387 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 488 SandboxRsiOrRdiMakeInteriorInvalidJumpTargets(&instruction_start, data, |
388 BitmapClearBit(valid_targets, (instruction_start - data) + 10); | 489 valid_targets, TRUE); |
389 BitmapClearBit(valid_targets, (instruction_start - data) + 14); | |
390 restricted_register = NO_REG; | |
391 }; | 490 }; |
392 | 491 |
393 special_instruction = | 492 special_instruction = |
394 (rbp_modifications | | 493 (rbp_modifications | |
395 rsp_modifications | | 494 rsp_modifications | |
396 rbp_sandboxing | | 495 rbp_sandboxing | |
397 rsp_sandboxing | | 496 rsp_sandboxing | |
398 naclcall_or_nacljmp | | 497 naclcall_or_nacljmp | |
399 sandbox_instruction_rsi_no_rdi | | 498 sandbox_instruction_rsi_no_rdi | |
400 sandbox_instruction_rdi_no_rsi | | 499 sandbox_instruction_rdi_no_rsi | |
401 sandbox_instruction_rsi_rdi) | 500 sandbox_instruction_rsi_rdi) |
501 # Mark the instruction as special—currently this information is used only in | |
502 # tests, but in the future we may use it for dynamic code modification | |
503 # support. | |
402 @{ | 504 @{ |
403 instruction_info_collected |= SPECIAL_INSTRUCTION; | 505 instruction_info_collected |= SPECIAL_INSTRUCTION; |
404 }; | 506 }; |
405 | 507 |
406 # Remove special instructions which are only allowed in special cases. | 508 # Remove special instructions which are only allowed in special cases. |
407 normal_instruction = one_instruction - special_instruction; | 509 normal_instruction = one_instruction - special_instruction; |
408 | 510 |
409 # Check if call is properly aligned | 511 # Check if call is properly aligned. |
512 # | |
513 # For direct call we explicitly encode all variations. For indirect call | |
514 # we accept all the special instructions which ends with indirect call. | |
410 call_alignment = | 515 call_alignment = |
411 ((normal_instruction & | 516 ((normal_instruction & |
412 # Direct call | 517 # Direct call |
413 ((data16 REX_RXB? 0xe8 rel16) | | 518 ((data16 REX_RXB? 0xe8 rel16) | |
414 (REX_WRXB? 0xe8 rel32) | | 519 (REX_WRXB? 0xe8 rel32) | |
415 (data16 REXW_RXB 0xe8 rel32))) | | 520 (data16 REXW_RXB 0xe8 rel32))) | |
416 (special_instruction & | 521 (special_instruction & |
417 # Indirect call | 522 # Indirect call |
418 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & | 523 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & |
419 (modrm_memory | modrm_registers))))) | 524 (modrm_memory | modrm_registers))))) |
525 # Call instruction must aligned to the end of bundle. Previously this was | |
526 # strict requirement, today it's just warning to aid with debugging. | |
420 @{ | 527 @{ |
421 if (((current_position - data) & kBundleMask) != kBundleMask) | 528 if (((current_position - data) & kBundleMask) != kBundleMask) |
422 instruction_info_collected |= BAD_CALL_ALIGNMENT; | 529 instruction_info_collected |= BAD_CALL_ALIGNMENT; |
423 }; | 530 }; |
424 | 531 |
425 | 532 |
426 main := ((call_alignment | normal_instruction | special_instruction) | 533 main := ((call_alignment | normal_instruction | special_instruction) |
534 # Beginning of the instruction is always valid target for jump. If this | |
535 # instruction is, in fact, part of the superinstruction then we'll clear | |
536 # that bit later. | |
427 >{ | 537 >{ |
428 BitmapSetBit(valid_targets, current_position - data); | 538 MakeJumpTargetValid(current_position - data, valid_targets); |
429 } | 539 } |
540 # Here we call the user callback if there are validation errors or if the | |
541 # CALL_USER_CALLBACK_ON_EACH_INSTRUCTION option is used. | |
542 # | |
543 # After that we move instruction_start and clean all the variables which | |
544 # only used in the processing of a single instruction (prefixes, operand | |
545 # states and instruction_info_collected). | |
430 @{ | 546 @{ |
431 if ((instruction_info_collected & | 547 if ((instruction_info_collected & |
432 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) || | 548 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) || |
433 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { | 549 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { |
434 result &= user_callback( | 550 result &= user_callback( |
435 instruction_start, current_position, | 551 instruction_start, current_position, |
436 instruction_info_collected | | 552 instruction_info_collected | |
437 ((restricted_register << RESTRICTED_REGISTER_SHIFT) & | 553 ((restricted_register << RESTRICTED_REGISTER_SHIFT) & |
438 RESTRICTED_REGISTER_MASK), callback_data); | 554 RESTRICTED_REGISTER_MASK), callback_data); |
439 } | 555 } |
440 /* On successful match the instruction start must point to the next byte | 556 /* On successful match the instruction start must point to the next byte |
441 * to be able to report the new offset as the start of instruction | 557 * to be able to report the new offset as the start of instruction |
442 * causing error. */ | 558 * causing error. */ |
443 instruction_start = current_position + 1; | 559 instruction_start = current_position + 1; |
444 instruction_info_collected = 0; | 560 instruction_info_collected = 0; |
445 SET_REX_PREFIX(FALSE); | 561 SET_REX_PREFIX(FALSE); |
562 /* Top three bis of VEX2 are inverted: see AMD/Intel manual. */ | |
446 SET_VEX_PREFIX2(0xe0); | 563 SET_VEX_PREFIX2(0xe0); |
447 SET_VEX_PREFIX3(0x00); | 564 SET_VEX_PREFIX3(0x00); |
448 operand_states = 0; | 565 operand_states = 0; |
449 })* | 566 })* |
450 $err{ | 567 $err{ |
451 result &= user_callback(instruction_start, current_position, | 568 result &= user_callback(instruction_start, current_position, |
452 UNRECOGNIZED_INSTRUCTION, callback_data); | 569 UNRECOGNIZED_INSTRUCTION, callback_data); |
453 continue; | 570 continue; |
454 }; | 571 }; |
455 | 572 |
456 }%% | 573 }%% |
457 | 574 |
458 %% write data; | 575 %% write data; |
459 | 576 |
460 Bool ValidateChunkAMD64(const uint8_t *data, size_t size, | 577 Bool ValidateChunkAMD64(const uint8_t *data, size_t size, |
461 enum validation_options options, | 578 enum validation_options options, |
462 const NaClCPUFeaturesX86 *cpu_features, | 579 const NaClCPUFeaturesX86 *cpu_features, |
463 validation_callback_func user_callback, | 580 ValidationCallbackFunc user_callback, |
464 void *callback_data) { | 581 void *callback_data) { |
465 bitmap_word valid_targets_small; | 582 bitmap_word valid_targets_small; |
466 bitmap_word jump_dests_small; | 583 bitmap_word jump_dests_small; |
467 bitmap_word *valid_targets; | 584 bitmap_word *valid_targets; |
468 bitmap_word *jump_dests; | 585 bitmap_word *jump_dests; |
469 const uint8_t *current_position; | 586 const uint8_t *current_position; |
470 const uint8_t *end_of_bundle; | 587 const uint8_t *end_of_bundle; |
471 int result = TRUE; | 588 int result = TRUE; |
472 | 589 |
473 CHECK(sizeof valid_targets_small == sizeof jump_dests_small); | 590 CHECK(sizeof valid_targets_small == sizeof jump_dests_small); |
(...skipping 26 matching lines...) Expand all Loading... | |
500 current_position = end_of_bundle, | 617 current_position = end_of_bundle, |
501 end_of_bundle = current_position + kBundleSize) { | 618 end_of_bundle = current_position + kBundleSize) { |
502 /* Start of the instruction being processed. */ | 619 /* Start of the instruction being processed. */ |
503 const uint8_t *instruction_start = current_position; | 620 const uint8_t *instruction_start = current_position; |
504 int current_state; | 621 int current_state; |
505 uint32_t instruction_info_collected = 0; | 622 uint32_t instruction_info_collected = 0; |
506 /* Keeps one byte of information per operand in the current instruction: | 623 /* Keeps one byte of information per operand in the current instruction: |
507 * 2 bits for register kinds, | 624 * 2 bits for register kinds, |
508 * 5 bits for register numbers (16 regs plus RIZ). */ | 625 * 5 bits for register numbers (16 regs plus RIZ). */ |
509 uint32_t operand_states = 0; | 626 uint32_t operand_states = 0; |
510 enum register_name base = NO_REG; | 627 enum OperandName base = NO_REG; |
511 enum register_name index = NO_REG; | 628 enum OperandName index = NO_REG; |
512 enum register_name restricted_register = NO_REG; | 629 enum OperandName restricted_register = NO_REG; |
513 uint8_t rex_prefix = FALSE; | 630 uint8_t rex_prefix = FALSE; |
514 uint8_t vex_prefix2 = 0xe0; | 631 uint8_t vex_prefix2 = 0xe0; |
515 uint8_t vex_prefix3 = 0x00; | 632 uint8_t vex_prefix3 = 0x00; |
516 | 633 |
517 %% write init; | 634 %% write init; |
518 %% write exec; | 635 %% write exec; |
519 | 636 |
520 if (restricted_register == REG_RBP) | 637 if (restricted_register == REG_RBP) |
521 result &= user_callback(end_of_bundle, end_of_bundle, | 638 result &= user_callback(end_of_bundle, end_of_bundle, |
522 RESTRICTED_RBP_UNPROCESSED | | 639 RESTRICTED_RBP_UNPROCESSED | |
(...skipping 10 matching lines...) Expand all Loading... | |
533 user_callback, callback_data); | 650 user_callback, callback_data); |
534 | 651 |
535 /* We only use malloc for a large code sequences */ | 652 /* We only use malloc for a large code sequences */ |
536 if (size > sizeof valid_targets_small) { | 653 if (size > sizeof valid_targets_small) { |
537 free(jump_dests); | 654 free(jump_dests); |
538 free(valid_targets); | 655 free(valid_targets); |
539 } | 656 } |
540 if (!result) errno = EINVAL; | 657 if (!result) errno = EINVAL; |
541 return result; | 658 return result; |
542 } | 659 } |
OLD | NEW |