OLD | NEW |
---|---|
1 /* | 1 /* |
Dmitry Polukhin
2012/11/02 17:31:06
I think this test need to be converted to C++ and
| |
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 #include <assert.h> | 7 #include <assert.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <stdarg.h> | 9 #include <stdarg.h> |
10 #include <stdlib.h> | 10 #include <stdlib.h> |
11 #include <string.h> | 11 #include <string.h> |
12 | 12 |
13 #include "native_client/src/include/elf32.h" | 13 #include "native_client/src/include/elf32.h" |
14 #include "native_client/src/include/elf64.h" | 14 #include "native_client/src/include/elf64.h" |
15 #include "native_client/src/shared/platform/nacl_check.h" | 15 #include "native_client/src/shared/platform/nacl_check.h" |
16 #include "native_client/src/shared/utils/types.h" | 16 #include "native_client/src/shared/utils/types.h" |
17 #include "native_client/src/trusted/validator_ragel/unreviewed/decoder.h" | 17 #include "native_client/src/trusted/validator_ragel/decoder.h" |
18 | 18 |
19 /* This is a copy of NaClLog from shared/platform/nacl_log.c to avoid | 19 /* This is a copy of NaClLog from shared/platform/nacl_log.c to avoid |
20 * linking in code in NaCl shared code in the unreviewed/Makefile and be able to | 20 * linking in code in NaCl shared code in the unreviewed/Makefile and be able to |
21 * use CHECK(). | 21 * use CHECK(). |
22 | 22 |
23 * TODO(khim): remove the copy of NaClLog implementation as soon as | 23 * TODO(khim): remove the copy of NaClLog implementation as soon as |
24 * unreviewed/Makefile is eliminated. | 24 * unreviewed/Makefile is eliminated. |
25 */ | 25 */ |
26 void NaClLog(int detail_level, char const *fmt, ...) { | 26 void NaClLog(int detail_level, char const *fmt, ...) { |
27 va_list ap; | 27 va_list ap; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
124 NULL, "cr15", "db15", "tr15" } | 124 NULL, "cr15", "db15", "tr15" } |
125 }; | 125 }; |
126 assert(kRegisterNames[name][type]); | 126 assert(kRegisterNames[name][type]); |
127 return kRegisterNames[name][type]; | 127 return kRegisterNames[name][type]; |
128 } else { | 128 } else { |
129 assert(FALSE); | 129 assert(FALSE); |
130 return NULL; | 130 return NULL; |
131 } | 131 } |
132 } | 132 } |
133 | 133 |
134 Bool IsNameInList(const char *name, ...) { | 134 Bool IsNameInList(const char *name, ...) { |
Brad Chen
2012/10/22 21:29:05
Could you use an array rather than varargs here? I
Dmitry Polukhin
2012/11/02 17:31:06
This function can be converted to function with tw
| |
135 va_list value_list; | 135 va_list value_list; |
136 | 136 |
137 va_start(value_list, name); | 137 va_start(value_list, name); |
138 | 138 |
139 for (;;) { | 139 for (;;) { |
140 const char *element = va_arg(value_list, const char*); | 140 const char *element = va_arg(value_list, const char*); |
141 if (element) { | 141 if (element) { |
142 if (strcmp(name, element) == 0) { | 142 if (strcmp(name, element) == 0) { |
143 va_end(value_list); | 143 va_end(value_list); |
144 return TRUE; | 144 return TRUE; |
145 } | 145 } |
146 } else { | 146 } else { |
147 va_end(value_list); | 147 va_end(value_list); |
148 return FALSE; | 148 return FALSE; |
149 } | 149 } |
150 } | 150 } |
151 } | 151 } |
152 | 152 |
153 /* | |
154 * "fwait" is nasty: few of them will be included in other X87 instructions | |
155 * ("fclex", "finit", "fstcw", "fstsw", "fsave" have two names, other | |
156 * instructions are unchanged) - but if after them we see regular instruction | |
157 * then we must print them all. This convoluted logic is not needed when we | |
158 * don't print anything so decoder does not include it. | |
159 */ | |
160 static Bool ProcessFWait(const uint8_t **begin, const uint8_t *end, | |
Dmitry Polukhin
2012/11/02 17:31:06
Too many arguments, class with state should solve
| |
161 struct Instruction *instruction, | |
162 struct DecodeState *userdata, | |
163 unsigned char *rex_prefix, Bool *spurious_rex_prefix, | |
164 enum OperandName *rm_base, | |
165 enum OperandName *rm_index) { | |
166 /* Instruction is "fwait" if it's 0x9b or if it's REX prefix plus 0x9b. */ | |
167 if (((end == *begin + 1) && ((*begin)[0] == 0x9b)) || | |
168 ((end == *begin + 2) && | |
169 (((*begin)[0] & 0xf0) == 0x40) && ((*begin)[1] == 0x9b))) { | |
170 if (!(userdata->fwait)) { | |
171 userdata->fwait = *begin; | |
172 } | |
173 return TRUE; | |
174 } else if (userdata->fwait) { | |
175 /* | |
176 * If it's x87 instruction then we can fold some fwait's in the instruction | |
177 * itself. | |
178 * | |
179 * Instruction is x87 instruction if it has opcode from 0xd8 to 0xdf, but it | |
180 * can include either 0x66 prefix or REX prefix, or both. | |
181 */ | |
182 if ((((*begin)[0] & 0xf8) == 0xd8) || | |
183 (((((*begin)[0] & 0xf0) == 0x40) || ((*begin)[0] == 0x66)) && | |
184 (((*begin)[1] & 0xf8) == 0xd8)) || | |
185 (((*begin)[0] == 0x66) && (((*begin)[1] & 0xf0) == 0x40) && | |
186 (((*begin)[2] & 0xf8) == 0xd8))) { | |
187 /* | |
188 * fwait "prefix" can only include two 0x9b bytes or one rex byte - and | |
189 * then only if the instruction itself have no rex prefix. | |
190 */ | |
191 int fwait_count = !!(instruction->prefix.data16); | |
192 int rex_count = (!!*rex_prefix) | (!!(instruction->prefix.data16)); | |
193 for (;;) { | |
194 if (*begin == userdata->fwait) | |
195 break; | |
196 if (((*begin)[-1]) == 0x9b) { | |
197 if (fwait_count < 2) { | |
198 --*begin; | |
199 ++fwait_count; | |
200 if (((*begin)[1] & 0xf0) == 0x40) | |
201 break; | |
202 } else { | |
203 break; | |
204 } | |
205 } else if (((*begin)[-1] & 0xf0) == 0x40) { | |
206 if (rex_count >= 1) | |
207 break; | |
208 --*begin; | |
209 ++rex_count; | |
210 if (!*rex_prefix) { | |
211 *rex_prefix = **begin; | |
212 /* | |
213 * Bug-to-bug compatibility: objdump will erroneously use bits from | |
214 * first REX prefix (attached to "fwait") and not from the | |
215 * second REX prefix (attached to the instruction itself). | |
216 * | |
217 * Duplicate this error here till it'll be fixed in objdump. | |
218 */ | |
219 if ((*rex_prefix & 0x01) && (*rm_base <= REG_RDI)) { | |
220 if (instruction->operands_count == 1 && | |
221 instruction->operands[0].name == REG_RM) | |
222 *rm_base |= REG_R8; | |
223 else | |
224 *spurious_rex_prefix = TRUE; | |
225 } | |
226 if (*rex_prefix & 0x02) { | |
227 if (instruction->operands_count == 1 && | |
228 instruction->operands[0].name == REG_RM) { | |
229 if (*rm_index <= REG_RDI) | |
230 *rm_index |= REG_R8; | |
231 else if (*rm_index == REG_RIZ) | |
232 *rm_index = REG_R12; | |
233 else if (*rm_index == NO_REG) | |
234 *spurious_rex_prefix = TRUE; | |
235 } else { | |
236 *spurious_rex_prefix = TRUE; | |
237 } | |
238 } | |
239 if (*rex_prefix & 0x0c) | |
240 *spurious_rex_prefix = TRUE; | |
241 } | |
242 } | |
243 } | |
244 if (*begin != userdata->fwait) { | |
245 while (userdata->fwait < *begin) { | |
246 printf("%*lx:\t%02x \tfwait\n", | |
247 userdata->width, (long)(userdata->fwait - userdata->offset), | |
248 *userdata->fwait); | |
249 ++(userdata->fwait); | |
250 } | |
251 } | |
252 } else { | |
253 while ((userdata->fwait) < *begin) { | |
254 printf("%*lx:\t%02x \tfwait\n", | |
255 userdata->width, (long)(userdata->fwait - userdata->offset), | |
256 *userdata->fwait); | |
257 ++(userdata->fwait); | |
258 } | |
259 } | |
260 userdata->fwait = FALSE; | |
261 } | |
262 return FALSE; | |
263 } | |
264 | |
153 void ProcessInstruction(const uint8_t *begin, const uint8_t *end, | 265 void ProcessInstruction(const uint8_t *begin, const uint8_t *end, |
Dmitry Polukhin
2012/11/02 17:31:06
I think it should be converted to so class Instruc
| |
154 struct Instruction *instruction, void *userdata) { | 266 struct Instruction *instruction, void *callback_data) { |
267 struct DecodeState *userdata = callback_data; | |
155 const char *instruction_name = instruction->name; | 268 const char *instruction_name = instruction->name; |
156 unsigned char operands_count = instruction->operands_count; | 269 unsigned char operands_count = instruction->operands_count; |
157 unsigned char rex_prefix = instruction->prefix.rex; | 270 unsigned char rex_prefix = instruction->prefix.rex; |
158 enum OperandName rm_index = instruction->rm.index; | 271 enum OperandName rm_index = instruction->rm.index; |
159 enum OperandName rm_base = instruction->rm.base; | 272 enum OperandName rm_base = instruction->rm.base; |
160 Bool data16_prefix = instruction->prefix.data16; | 273 Bool data16_prefix = instruction->prefix.data16; |
161 const uint8_t *p; | 274 const uint8_t *p; |
162 char delimeter = ' '; | 275 char delimeter = ' '; |
163 Bool print_rip = FALSE; | 276 Bool print_rip = FALSE; |
164 Bool empty_rex_prefix_ok = FALSE; | 277 Bool empty_rex_prefix_ok = FALSE; |
165 Bool spurious_rex_prefix = FALSE; | 278 Bool spurious_rex_prefix = FALSE; |
166 #define print_name(x) (printf((x)), shown_name += strlen((x))) | 279 #define print_name(x) (printf((x)), shown_name += strlen((x))) |
Brad Chen
2012/10/22 21:29:05
What is your goal in making this a macro rather th
| |
167 size_t shown_name = 0; | 280 size_t shown_name = 0; |
168 int i, operand_type; | 281 int i, operand_type; |
169 | 282 |
283 if (ProcessFWait(&begin, end, instruction, callback_data, | |
284 &rex_prefix, &spurious_rex_prefix, &rm_base, &rm_index)) | |
285 return; | |
286 | |
170 /* | 287 /* |
171 * "fwait" is nasty: few of them will be included in other X87 instructions | 288 * Objdump will print data16 (0x66) prefix on a separate line for "fbld", |
172 * ("fclex", "finit", "fstcw", "fstsw", "fsave" have two names, other | 289 * "fbstp", "fild", "fistp", "fld", and "fstp" instructions. |
173 * instructions are unchanged) - but if after them we see regular instruction | |
174 * then we must print them all. This convoluted logic is not needed when we | |
175 * don't print anything so decoder does not include it. | |
176 */ | 290 */ |
177 if (((end == begin + 1) && (begin[0] == 0x9b)) || | |
178 ((end == begin + 2) && | |
179 ((begin[0] & 0xf0) == 0x40) && (begin[1] == 0x9b))) { | |
180 if (!(((struct DecodeState *)userdata)->fwait)) { | |
181 ((struct DecodeState *)userdata)->fwait = begin; | |
182 } | |
183 return; | |
184 } else if (((struct DecodeState *)userdata)->fwait) { | |
185 /* If it's x87 instruction then we can fold some fwait's in the instruction | |
186 itself. */ | |
187 if (((begin[0] >= 0xd8) && (begin[0] <= 0xdf)) || | |
188 ((((begin[0] & 0xf0) == 0x40) || (begin[0] == 0x66)) && | |
189 (begin[1] >= 0xd8) && (begin[1] <= 0xdf)) || | |
190 ((begin[0] == 0x66) || ((begin[1] & 0xf0) == 0x40) || | |
191 (begin[2] >= 0xd8) || (begin[2] <= 0xdf))) { | |
192 /* fwait "prefix" can only include two 0x9b bytes or one rex byte - and | |
193 * then only if the instruction itself have no rex prefix. */ | |
194 int fwait_count = !!data16_prefix; | |
195 int rex_count = (!!rex_prefix) | (!!data16_prefix); | |
196 for (;;) { | |
197 if (begin == ((struct DecodeState *)userdata)->fwait) | |
198 break; | |
199 if ((begin[-1]) == 0x9b) { | |
200 if (fwait_count < 2) { | |
201 --begin; | |
202 ++fwait_count; | |
203 if ((begin[1] & 0xf0) == 0x40) | |
204 break; | |
205 } else { | |
206 break; | |
207 } | |
208 } else if ((begin[-1] & 0xf0) == 0x40) { | |
209 if (rex_count >= 1) | |
210 break; | |
211 --begin; | |
212 ++rex_count; | |
213 if (!rex_prefix) { | |
214 rex_prefix = *begin; | |
215 /* Bug-to-bug compatibility, fun... */ | |
216 if ((rex_prefix & 0x01) && (rm_base <= REG_RDI)) { | |
217 if (operands_count == 1 && | |
218 instruction->operands[0].name == REG_RM) | |
219 rm_base |= REG_R8; | |
220 else | |
221 spurious_rex_prefix = TRUE; | |
222 } | |
223 if (rex_prefix & 0x02) { | |
224 if (operands_count == 1 && | |
225 instruction->operands[0].name == REG_RM) { | |
226 if (rm_index <= REG_RDI) | |
227 rm_index |= REG_R8; | |
228 else if (rm_index == REG_RIZ) | |
229 rm_index = REG_R12; | |
230 else if (rm_index == NO_REG) | |
231 spurious_rex_prefix = TRUE; | |
232 } else { | |
233 spurious_rex_prefix = TRUE; | |
234 } | |
235 } | |
236 if (rex_prefix & 0x0c) | |
237 spurious_rex_prefix = TRUE; | |
238 } | |
239 } | |
240 } | |
241 if (begin != ((struct DecodeState *)userdata)->fwait) { | |
242 while ((((struct DecodeState *)userdata)->fwait) < begin) { | |
243 printf("%*lx:\t%02x \tfwait\n", | |
244 ((struct DecodeState *)userdata)->width, | |
245 (long)((((struct DecodeState *)userdata)->fwait) - | |
246 (((struct DecodeState *)userdata)->offset)), | |
247 *((struct DecodeState *)userdata)->fwait); | |
248 ++(((struct DecodeState *)userdata)->fwait); | |
249 } | |
250 } | |
251 } else { | |
252 while ((((struct DecodeState *)userdata)->fwait) < begin) { | |
253 printf("%*lx:\t%02x \tfwait\n", | |
254 ((struct DecodeState *)userdata)->width, | |
255 (long)((((struct DecodeState *)userdata)->fwait) - | |
256 (((struct DecodeState *)userdata)->offset)), | |
257 *((struct DecodeState *)userdata)->fwait); | |
258 ++(((struct DecodeState *)userdata)->fwait); | |
259 } | |
260 } | |
261 ((struct DecodeState *)userdata)->fwait = FALSE; | |
262 } | |
263 | |
264 if ((data16_prefix) && (begin[0] == 0x66) && (!(rex_prefix & 0x08)) && | 291 if ((data16_prefix) && (begin[0] == 0x66) && (!(rex_prefix & 0x08)) && |
265 (IsNameInList(instruction_name, | 292 (IsNameInList(instruction_name, |
266 "fbld", "fbstp", "fild", "fistp", "fld", "fstp", NULL))) { | 293 "fbld", "fbstp", "fild", "fistp", "fld", "fstp", NULL))) { |
267 printf("%*lx:\t66 \tdata16\n", | 294 printf("%*lx:\t66 \tdata16\n", |
268 ((struct DecodeState *)userdata)->width, | 295 userdata->width, (long)(begin - userdata->offset)); |
269 (long)(begin - (((struct DecodeState *)userdata)->offset))); | |
270 data16_prefix = FALSE; | 296 data16_prefix = FALSE; |
271 ++begin; | 297 ++begin; |
272 } | 298 } |
273 printf("%*lx:\t", ((struct DecodeState *)userdata)->width, | 299 |
274 (long)(begin - (((struct DecodeState *)userdata)->offset))); | 300 /* Start the main processing part: print offset here. */ |
301 printf("%*lx:\t", userdata->width, (long)(begin - userdata->offset)); | |
275 for (p = begin; p < begin + 7; ++p) { | 302 for (p = begin; p < begin + 7; ++p) { |
276 if (p >= end) | 303 if (p >= end) |
277 printf(" "); | 304 printf(" "); |
278 else | 305 else |
279 printf("%02x ", *p); | 306 printf("%02x ", *p); |
280 } | 307 } |
281 printf("\t"); | 308 printf("\t"); |
309 | |
282 /* | 310 /* |
283 * "pclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, | 311 * "pclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, |
284 * 0x10, and 0x11. Objdump incorrectly mixes them up with 0x2 and 0x03. | 312 * 0x10, and 0x11. Objdump incorrectly mixes them up with 0x2 and 0x03. |
285 */ | 313 */ |
286 if (!strcmp(instruction_name, "pclmulqdq")) { | 314 if (!strcmp(instruction_name, "pclmulqdq")) { |
287 if (instruction->imm[0] < 0x04) { | 315 if (instruction->imm[0] < 0x04) { |
288 switch (instruction->imm[0]) { | 316 switch (instruction->imm[0]) { |
289 case 0x02: instruction_name = "pclmullqhqdq"; break; | 317 case 0x02: instruction_name = "pclmullqhqdq"; break; |
290 case 0x03: instruction_name = "pclmulhqhqdq"; break; | 318 case 0x03: instruction_name = "pclmulhqhqdq"; break; |
291 } | 319 } |
292 --operands_count; | 320 --operands_count; |
293 } | 321 } |
294 } | 322 } |
323 | |
295 /* | 324 /* |
296 * "vpclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, | 325 * "vpclmulqdq" has two-operand mnemonic names for "imm8" equal to 0x01, 0x01, |
297 * 0x10, and 0x11. Objdump mixes them with 0x2 and 0x03. | 326 * 0x10, and 0x11. Objdump mixes them with 0x2 and 0x03. |
298 */ | 327 */ |
299 if (!strcmp(instruction_name, "vpclmulqdq")) { | 328 if (!strcmp(instruction_name, "vpclmulqdq")) { |
300 if (instruction->imm[0] < 0x04) { | 329 if (instruction->imm[0] < 0x04) { |
301 switch (instruction->imm[0]) { | 330 switch (instruction->imm[0]) { |
302 case 0x02: instruction_name = "vpclmullqhqdq"; break; | 331 case 0x02: instruction_name = "vpclmullqhqdq"; break; |
303 case 0x03: instruction_name = "vpclmulhqhqdq"; break; | 332 case 0x03: instruction_name = "vpclmulhqhqdq"; break; |
304 } | 333 } |
305 --operands_count; | 334 --operands_count; |
306 } | 335 } |
307 } | 336 } |
337 | |
308 spurious_rex_prefix |= | 338 spurious_rex_prefix |= |
309 rex_prefix && | 339 rex_prefix && |
310 (instruction->prefix.rex_b_spurious || | 340 (instruction->prefix.rex_b_spurious || |
311 instruction->prefix.rex_x_spurious || | 341 instruction->prefix.rex_x_spurious || |
312 instruction->prefix.rex_r_spurious || | 342 instruction->prefix.rex_r_spurious || |
313 instruction->prefix.rex_w_spurious); | 343 instruction->prefix.rex_w_spurious); |
344 | |
345 /* | |
346 * Objdump sometimes does not show spurious rex prefixes. Adjust the | |
347 * spurious_rex_prefix variable here for these cases. | |
348 */ | |
314 if (operands_count > 0) { | 349 if (operands_count > 0) { |
315 if (!((struct DecodeState *)userdata)->ia32_mode) | 350 if (!userdata->ia32_mode) |
316 for (i=0; i<operands_count; ++i) | 351 for (i=0; i<operands_count; ++i) |
317 /* | 352 /* |
318 * Objdump mistakenly allows "lock" with "mov %crX,%rXX" only in ia32 | 353 * Objdump mistakenly allows "lock" with "mov %crX,%rXX" only in ia32 |
319 * mode. It's perfectly valid in amd64, too, so instead of changing | 354 * mode. It's perfectly valid in amd64, too, so instead of changing |
320 * the decoder we fix it here. | 355 * the decoder we fix it here. |
321 */ | 356 */ |
322 if (instruction->operands[i].type == OPERAND_TYPE_CONTROL_REGISTER && | 357 if (instruction->operands[i].type == OPERAND_TYPE_CONTROL_REGISTER && |
323 *begin == 0xf0 && !instruction->prefix.lock) { | 358 *begin == 0xf0 && !instruction->prefix.lock) { |
324 print_name("lock "); | 359 print_name("lock "); |
325 if (rex_prefix & 0x04) { | 360 if (rex_prefix & 0x04) { |
326 if (!instruction->prefix.rex_b_spurious && | 361 if (!instruction->prefix.rex_b_spurious && |
327 instruction->prefix.rex_r_spurious && | 362 instruction->prefix.rex_r_spurious && |
328 !instruction->prefix.rex_x_spurious && | 363 !instruction->prefix.rex_x_spurious && |
329 !instruction->prefix.rex_w_spurious) | 364 !instruction->prefix.rex_w_spurious) |
330 spurious_rex_prefix = FALSE; | 365 spurious_rex_prefix = FALSE; |
331 } else { | 366 } else { |
332 instruction->operands[i].name -= 8; | 367 instruction->operands[i].name -= 8; |
333 } | 368 } |
334 } | 369 } |
335 } | 370 } |
336 /* Only few rare instructions show spurious REX.B in objdump. */ | 371 |
337 if (!spurious_rex_prefix && instruction->prefix.rex_b_spurious) | |
338 if (IsNameInList(instruction_name, | |
339 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", | |
340 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", | |
341 "jecxz", "jrcxz", "loop", "loope", "loopne", NULL)) | |
342 spurious_rex_prefix = TRUE; | |
343 /* Some instructions don't show spurious REX.B in objdump. */ | 372 /* Some instructions don't show spurious REX.B in objdump. */ |
344 if (spurious_rex_prefix && | 373 if (spurious_rex_prefix && |
345 instruction->prefix.rex_b_spurious && | 374 instruction->prefix.rex_b_spurious && |
346 !instruction->prefix.rex_r_spurious && | 375 !instruction->prefix.rex_r_spurious && |
347 !instruction->prefix.rex_x_spurious && | 376 !instruction->prefix.rex_x_spurious && |
348 !instruction->prefix.rex_w_spurious) { | 377 !instruction->prefix.rex_w_spurious) { |
349 if (operands_count > 0) | 378 if (operands_count > 0) |
350 for (i=0; i<operands_count; ++i) | 379 for (i=0; i<operands_count; ++i) |
351 if (instruction->operands[i].name == REG_RM && | 380 if (instruction->operands[i].name == REG_RM && |
352 instruction->rm.disp_type != DISP64) { | 381 instruction->rm.disp_type != DISP64) { |
353 spurious_rex_prefix = FALSE; | 382 spurious_rex_prefix = FALSE; |
354 break; | 383 break; |
355 } | 384 } |
356 } | 385 } |
386 | |
357 /* Some instructions don't show spurious REX.W in objdump. */ | 387 /* Some instructions don't show spurious REX.W in objdump. */ |
358 if (spurious_rex_prefix && | 388 if (spurious_rex_prefix && |
359 !instruction->prefix.rex_b_spurious && | 389 !instruction->prefix.rex_b_spurious && |
360 !instruction->prefix.rex_r_spurious && | 390 !instruction->prefix.rex_r_spurious && |
361 !instruction->prefix.rex_x_spurious && | 391 !instruction->prefix.rex_x_spurious && |
362 instruction->prefix.rex_w_spurious) { | 392 instruction->prefix.rex_w_spurious) { |
363 if (IsNameInList(instruction_name, | 393 if (IsNameInList(instruction_name, |
364 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", | 394 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", |
365 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", | 395 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", |
366 "jecxz", "jrcxz", "loop", "loope", "loopne", | 396 "jecxz", "jrcxz", "loop", "loope", "loopne", |
(...skipping 20 matching lines...) Expand all Loading... | |
387 if (!spurious_rex_prefix && (rex_prefix & 0x08) && | 417 if (!spurious_rex_prefix && (rex_prefix & 0x08) && |
388 ((IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && | 418 ((IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && |
389 instruction->operands[0].name != JMP_TO) || | 419 instruction->operands[0].name != JMP_TO) || |
390 IsNameInList(instruction_name, | 420 IsNameInList(instruction_name, |
391 "fldenvs", "fnstenvs", "fnsaves", | 421 "fldenvs", "fnstenvs", "fnsaves", |
392 "frstors", "fsaves", "fstenvs", | 422 "frstors", "fsaves", "fstenvs", |
393 "in", "ins", "out", "outs", | 423 "in", "ins", "out", "outs", |
394 "popf", "push", "pushf", NULL))) | 424 "popf", "push", "pushf", NULL))) |
395 spurious_rex_prefix = TRUE; | 425 spurious_rex_prefix = TRUE; |
396 | 426 |
427 /* | |
428 * Print prefixes. For the case where two prefixes are present we must print | |
429 * them in a corrent order. First print prefixes from begin[0], then handle | |
430 * prefixes from begin[1] (at this point we don't support more then two | |
431 * prefixes). | |
432 */ | |
397 if (instruction->prefix.lock && (begin[0] == 0xf0)) | 433 if (instruction->prefix.lock && (begin[0] == 0xf0)) |
398 print_name("lock "); | 434 print_name("lock "); |
399 if (instruction->prefix.repnz && (begin[0] == 0xf2)) | 435 if (instruction->prefix.repnz && (begin[0] == 0xf2)) |
400 print_name("repnz "); | 436 print_name("repnz "); |
401 if (instruction->prefix.repz && (begin[0] == 0xf3)) { | 437 if (instruction->prefix.repz && (begin[0] == 0xf3)) { |
402 /* | 438 /* |
403 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other | 439 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other |
404 * instructions print "repz". | 440 * instructions print "repz". |
405 */ | 441 */ |
406 if (IsNameInList(instruction_name, | 442 if (IsNameInList(instruction_name, |
407 "ins", "lods", "movs", "outs", "stos", NULL)) | 443 "ins", "lods", "movs", "outs", "stos", NULL)) |
408 print_name("rep "); | 444 print_name("rep "); |
409 else | 445 else |
410 print_name("repz "); | 446 print_name("repz "); |
411 } | 447 } |
412 | |
413 if (((data16_prefix) && (rex_prefix & 0x08)) && | 448 if (((data16_prefix) && (rex_prefix & 0x08)) && |
414 !IsNameInList(instruction_name, | 449 !IsNameInList(instruction_name, |
415 "bsf", "bsr", "fldenvs", "fnstenvs", "fnsaves", "frstors", | 450 "bsf", "bsr", "fldenvs", "fnstenvs", "fnsaves", "frstors", |
416 "fsaves", "fstenvs", "movbe", NULL)) { | 451 "fsaves", "fstenvs", "movbe", NULL)) { |
417 if ((end - begin) != 3 || | 452 if ((end - begin) != 3 || |
418 (begin[0] != 0x66) || ((begin[1] & 0x48) != 0x48) || (begin[2] != 0x90)) | 453 (begin[0] != 0x66) || ((begin[1] & 0x48) != 0x48) || (begin[2] != 0x90)) |
419 print_name("data32 "); | 454 print_name("data32 "); |
420 } | 455 } |
421 | |
422 if (instruction->prefix.lock && (begin[0] != 0xf0)) { | 456 if (instruction->prefix.lock && (begin[0] != 0xf0)) { |
423 print_name("lock "); | 457 print_name("lock "); |
424 } | 458 } |
425 if (instruction->prefix.repnz && (begin[0] != 0xf2)) { | 459 if (instruction->prefix.repnz && (begin[0] != 0xf2)) { |
426 print_name("repnz "); | 460 print_name("repnz "); |
427 } | 461 } |
428 if (instruction->prefix.repz && (begin[0] != 0xf3)) { | 462 if (instruction->prefix.repz && (begin[0] != 0xf3)) { |
429 /* | 463 /* |
430 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other | 464 * This prefix is "rep" for "ins", "lods", "movs", "outs", "stos". For other |
431 * instructions print "repz". | 465 * instructions print "repz". |
432 */ | 466 */ |
433 if (IsNameInList(instruction_name, | 467 if (IsNameInList(instruction_name, |
434 "ins", "lods", "movs", "outs", "stos", NULL)) | 468 "ins", "lods", "movs", "outs", "stos", NULL)) |
435 print_name("rep "); | 469 print_name("rep "); |
436 else | 470 else |
437 print_name("repz "); | 471 print_name("repz "); |
438 } | 472 } |
439 | 473 |
474 /* | |
475 * REX prefix. Empty REX prefix (without REX.B, REX.X, REX.R, or REX.W bits) | |
476 * is not always spurious: it can be used to select between 8-bit registers | |
477 * (%ah vs %spl, %ch vs %bpl, %dh vs %dil, and %bh vs %sil). | |
478 */ | |
440 if (rex_prefix == 0x40) { | 479 if (rex_prefix == 0x40) { |
441 if (operands_count > 0) | 480 if (operands_count > 0) |
442 for (i=0; i<operands_count; ++i) | 481 for (i=0; i<operands_count; ++i) |
443 /* | 482 /* |
444 * "Empty" rex prefix (0x40) is used to select "sil"/"dil"/"spl"/"bpl". | 483 * "Empty" rex prefix (0x40) is used to select "sil"/"dil"/"spl"/"bpl". |
445 */ | 484 */ |
446 if (instruction->operands[i].type == OPERAND_TYPE_8_BIT && | 485 if (instruction->operands[i].type == OPERAND_TYPE_8_BIT && |
447 instruction->operands[i].name <= REG_RDI) { | 486 instruction->operands[i].name <= REG_RDI) { |
448 empty_rex_prefix_ok = TRUE; | 487 empty_rex_prefix_ok = TRUE; |
449 } | 488 } |
450 if (!empty_rex_prefix_ok) | 489 if (!empty_rex_prefix_ok) |
451 print_name("rex "); | 490 print_name("rex "); |
491 /* | |
492 * Non-empty REX prefix is shown if and only if if it's spurious. | |
Brad Chen
2012/10/22 21:29:05
if if
| |
493 */ | |
452 } else if (spurious_rex_prefix) { | 494 } else if (spurious_rex_prefix) { |
453 print_name("rex."); | 495 print_name("rex."); |
454 if (rex_prefix & 0x08) { | 496 if (rex_prefix & 0x08) { |
455 print_name("W"); | 497 print_name("W"); |
456 } | 498 } |
457 if (rex_prefix & 0x04) { | 499 if (rex_prefix & 0x04) { |
458 print_name("R"); | 500 print_name("R"); |
459 } | 501 } |
460 if (rex_prefix & 0x02) { | 502 if (rex_prefix & 0x02) { |
461 print_name("X"); | 503 print_name("X"); |
462 } | 504 } |
463 if (rex_prefix & 0x01) { | 505 if (rex_prefix & 0x01) { |
464 print_name("B"); | 506 print_name("B"); |
465 } | 507 } |
466 print_name(" "); | 508 print_name(" "); |
467 } | 509 } |
468 | 510 |
511 /* Prefixes are printed. Print the instruction name. */ | |
469 printf("%s", instruction_name); | 512 printf("%s", instruction_name); |
470 shown_name += strlen(instruction_name); | 513 shown_name += strlen(instruction_name); |
471 | 514 |
515 /* In some cases AT&T instruction uses suffix to show the size of operand. */ | |
Brad Chen
2012/10/22 21:29:05
It looks to me like it may be the case that the st
| |
472 if (instruction->att_instruction_suffix) { | 516 if (instruction->att_instruction_suffix) { |
517 /* But special versions of "nop" never use these suffixes. */ | |
473 if (!IsNameInList(instruction_name, | 518 if (!IsNameInList(instruction_name, |
474 "nopw 0x0(%eax,%eax,1)", | 519 "nopw 0x0(%eax,%eax,1)", |
475 "nopw 0x0(%rax,%rax,1)", | 520 "nopw 0x0(%rax,%rax,1)", |
476 NULL)) { | 521 NULL)) { |
477 printf("%s", instruction->att_instruction_suffix); | 522 printf("%s", instruction->att_instruction_suffix); |
478 shown_name += strlen(instruction->att_instruction_suffix); | 523 shown_name += strlen(instruction->att_instruction_suffix); |
479 } | 524 } |
480 } else { | 525 } else { |
481 /* | 526 /* |
482 * Objdump prints size suffixes for "crc32" instruction even when it's | 527 * Objdump prints size suffixes for "crc32" instruction even when it's |
483 * not really needed. | 528 * not really needed. |
484 */ | 529 */ |
485 if (strcmp(instruction_name, "crc32") == 0) { | 530 if (strcmp(instruction_name, "crc32") == 0) { |
486 if (instruction->operands[1].type == OPERAND_TYPE_8_BIT) | 531 if (instruction->operands[1].type == OPERAND_TYPE_8_BIT) |
487 print_name("b"); | 532 print_name("b"); |
488 else if (instruction->operands[1].type == OPERAND_TYPE_16_BIT) | 533 else if (instruction->operands[1].type == OPERAND_TYPE_16_BIT) |
489 print_name("w"); | 534 print_name("w"); |
490 else if (instruction->operands[1].type == OPERAND_TYPE_32_BIT) | 535 else if (instruction->operands[1].type == OPERAND_TYPE_32_BIT) |
491 print_name("l"); | 536 print_name("l"); |
492 else if (instruction->operands[1].type == OPERAND_TYPE_64_BIT) | 537 else if (instruction->operands[1].type == OPERAND_TYPE_64_BIT) |
493 print_name("q"); | 538 print_name("q"); |
494 } | 539 } |
495 } | 540 } |
541 | |
542 /* Regular "mov" with 64-bit immediate is printed as "movabs" by objdump. */ | |
496 if (strcmp(instruction_name, "mov") == 0 && | 543 if (strcmp(instruction_name, "mov") == 0 && |
497 instruction->operands[1].name == REG_IMM && | 544 instruction->operands[1].name == REG_IMM && |
498 instruction->operands[1].type == OPERAND_TYPE_64_BIT) | 545 instruction->operands[1].type == OPERAND_TYPE_64_BIT) |
499 print_name("abs"); | 546 print_name("abs"); |
500 | 547 |
548 /* | |
549 * Jump instructions can use branch-prediction prefixes. They are shown as | |
550 * suffixes by objdump. | |
551 */ | |
501 if (IsNameInList(instruction_name, | 552 if (IsNameInList(instruction_name, |
502 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", | 553 "ja", "jae", "jbe", "jb", "je", "jg", "jge", "jle", |
503 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", | 554 "jl", "jne", "jno", "jnp", "jns", "jo", "jp", "js", |
504 "jecxz", "jrcxz", "loop", "loope", "loopne", NULL)) { | 555 "jecxz", "jrcxz", "loop", "loope", "loopne", NULL)) { |
505 if (instruction->prefix.branch_not_taken) | 556 if (instruction->prefix.branch_not_taken) |
506 print_name(",pn"); | 557 print_name(",pn"); |
507 else if (instruction->prefix.branch_taken) | 558 else if (instruction->prefix.branch_taken) |
508 print_name(",pt"); | 559 print_name(",pt"); |
509 } | 560 } |
561 #undef print_name | |
510 | 562 |
511 #undef print_name | 563 /* Objdump does not print spaces after some "special" instructions. */ |
512 if ((strcmp(instruction_name, "nop") != 0 || operands_count != 0) && | 564 if ((strcmp(instruction_name, "nop") != 0 || operands_count != 0) && |
513 !IsNameInList( | 565 !IsNameInList( |
514 instruction_name, | 566 instruction_name, |
515 "fwait", | 567 "fwait", |
516 "nopw 0x0(%eax,%eax,1)", | 568 "nopw 0x0(%eax,%eax,1)", |
517 "nopw 0x0(%rax,%rax,1)", | 569 "nopw 0x0(%rax,%rax,1)", |
518 "nopw %cs:0x0(%eax,%eax,1)", | 570 "nopw %cs:0x0(%eax,%eax,1)", |
519 "nopw %cs:0x0(%rax,%rax,1)", | 571 "nopw %cs:0x0(%rax,%rax,1)", |
520 "nopw %cs:0x0(%eax,%eax,1)", | 572 "nopw %cs:0x0(%eax,%eax,1)", |
521 "nopw %cs:0x0(%rax,%rax,1)", | 573 "nopw %cs:0x0(%rax,%rax,1)", |
522 "data32 nopw %cs:0x0(%eax,%eax,1)", | 574 "data32 nopw %cs:0x0(%eax,%eax,1)", |
523 "data32 nopw %cs:0x0(%rax,%rax,1)", | 575 "data32 nopw %cs:0x0(%rax,%rax,1)", |
524 "data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 576 "data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
525 "data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 577 "data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
526 "data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 578 "data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
527 "data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 579 "data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
528 "data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 580 "data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
529 "data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 581 "data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
530 "data32 data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", | 582 "data32 data32 data32 data32 data32 nopw %cs:0x0(%eax,%eax,1)", |
531 "data32 data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", | 583 "data32 data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)", |
532 NULL)) { | 584 NULL)) { |
585 /* | |
586 * In this is "regular" instruction with a short name then it's operands are | |
587 * aligned. | |
588 */ | |
533 while (shown_name < 6) { | 589 while (shown_name < 6) { |
534 printf(" "); | 590 printf(" "); |
535 ++shown_name; | 591 ++shown_name; |
536 } | 592 } |
537 if (operands_count == 0) | 593 if (operands_count == 0) |
538 printf(" "); | 594 printf(" "); |
539 } | 595 } |
596 | |
597 /* Print instruction operands. */ | |
540 for (i=operands_count-1; i>=0; --i) { | 598 for (i=operands_count-1; i>=0; --i) { |
541 printf("%c", delimeter); | 599 printf("%c", delimeter); |
600 /* If the instruction is "call" or "jmp" then we need to print asterics. */ | |
542 if (IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && | 601 if (IsNameInList(instruction_name, "call", "jmp", "lcall", "ljmp", NULL) && |
543 instruction->operands[i].name != JMP_TO) | 602 instruction->operands[i].name != JMP_TO) |
544 printf("*"); | 603 printf("*"); |
545 /* | 604 /* |
546 * Both AMD manual and Intel manual agree that mov from general purpose | 605 * Both AMD manual and Intel manual agree that mov from general purpose |
547 * register to segment register has signature "mov Ew Sw", but objdump | 606 * register to segment register has signature "mov Ew Sw", but objdump |
548 * insists on 32bit/64 bit. This is clearly an error in objdump so we fix | 607 * insists on 32bit/64 bit. This is clearly an error in objdump so we fix |
549 * it here and not in decoder. | 608 * it here and not in decoder. |
550 */ | 609 */ |
551 if ((begin[0] >= 0x48) && (begin[0] <= 0x4f) && (begin[1] == 0x8e) && | 610 if ((begin[0] >= 0x48) && (begin[0] <= 0x4f) && (begin[1] == 0x8e) && |
552 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { | 611 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { |
553 operand_type = OPERAND_TYPE_64_BIT; | 612 operand_type = OPERAND_TYPE_64_BIT; |
554 } else if (((begin[0] == 0x8e) || | 613 } else if (((begin[0] == 0x8e) || |
555 ((begin[0] >= 0x40) && (begin[0] <= 0x4f) && (begin[1] == 0x8e))) && | 614 ((begin[0] >= 0x40) && (begin[0] <= 0x4f) && (begin[1] == 0x8e))) && |
556 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { | 615 (instruction->operands[i].type == OPERAND_TYPE_16_BIT)) { |
557 operand_type = OPERAND_TYPE_32_BIT; | 616 operand_type = OPERAND_TYPE_32_BIT; |
558 } else { | 617 } else { |
559 operand_type = instruction->operands[i].type; | 618 operand_type = instruction->operands[i].type; |
560 } | 619 } |
620 | |
621 /* All the special cases are handled, let's print the normal operands! */ | |
561 switch (instruction->operands[i].name) { | 622 switch (instruction->operands[i].name) { |
562 case REG_RAX: | 623 case REG_RAX: |
563 case REG_RCX: | 624 case REG_RCX: |
564 case REG_RDX: | 625 case REG_RDX: |
565 case REG_RBX: | 626 case REG_RBX: |
566 case REG_RSP: | 627 case REG_RSP: |
567 case REG_RBP: | 628 case REG_RBP: |
568 case REG_RSI: | 629 case REG_RSI: |
569 case REG_RDI: | 630 case REG_RDI: |
570 case REG_R8: | 631 case REG_R8: |
(...skipping 12 matching lines...) Expand all Loading... | |
583 printf("%%st"); | 644 printf("%%st"); |
584 break; | 645 break; |
585 case REG_RM: | 646 case REG_RM: |
586 if (instruction->rm.disp_type != DISPNONE) { | 647 if (instruction->rm.disp_type != DISPNONE) { |
587 if ((instruction->rm.disp_type == DISP64) || | 648 if ((instruction->rm.disp_type == DISP64) || |
588 (instruction->rm.offset >= 0)) | 649 (instruction->rm.offset >= 0)) |
589 printf("0x%"NACL_PRIx64, instruction->rm.offset); | 650 printf("0x%"NACL_PRIx64, instruction->rm.offset); |
590 else | 651 else |
591 printf("-0x%"NACL_PRIx64, -instruction->rm.offset); | 652 printf("-0x%"NACL_PRIx64, -instruction->rm.offset); |
592 } | 653 } |
593 if (((struct DecodeState *)userdata)->ia32_mode) { | 654 if (userdata->ia32_mode) { |
594 if ((rm_base != NO_REG) || | 655 if ((rm_base != NO_REG) || |
595 (rm_index != NO_REG) || | 656 (rm_index != NO_REG) || |
596 (instruction->rm.scale != 0)) | 657 (instruction->rm.scale != 0)) |
597 printf("("); | 658 printf("("); |
598 if (rm_base != NO_REG) | 659 if (rm_base != NO_REG) |
599 printf("%%%s", | 660 printf("%%%s", |
600 RegisterNameAsString(rm_base, OPERAND_TYPE_32_BIT, FALSE)); | 661 RegisterNameAsString(rm_base, OPERAND_TYPE_32_BIT, FALSE)); |
601 if (rm_index == REG_RIZ) { | 662 if (rm_index == REG_RIZ) { |
602 if ((rm_base != REG_RSP) || (instruction->rm.scale != 0)) | 663 if ((rm_base != REG_RSP) || (instruction->rm.scale != 0)) |
603 printf(",%%eiz,%d", 1 << instruction->rm.scale); | 664 printf(",%%eiz,%d", 1 << instruction->rm.scale); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 case REG_IMM: | 703 case REG_IMM: |
643 printf("$0x%"NACL_PRIx64,instruction->imm[0]); | 704 printf("$0x%"NACL_PRIx64,instruction->imm[0]); |
644 break; | 705 break; |
645 case REG_IMM2: | 706 case REG_IMM2: |
646 printf("$0x%"NACL_PRIx64,instruction->imm[1]); | 707 printf("$0x%"NACL_PRIx64,instruction->imm[1]); |
647 break; | 708 break; |
648 case REG_PORT_DX: | 709 case REG_PORT_DX: |
649 printf("(%%dx)"); | 710 printf("(%%dx)"); |
650 break; | 711 break; |
651 case REG_DS_RBX: | 712 case REG_DS_RBX: |
652 if (((struct DecodeState *)userdata)->ia32_mode) | 713 if (userdata->ia32_mode) |
653 printf("%%ds:(%%ebx)"); | 714 printf("%%ds:(%%ebx)"); |
654 else | 715 else |
655 printf("%%ds:(%%rbx)"); | 716 printf("%%ds:(%%rbx)"); |
656 break; | 717 break; |
657 case REG_ES_RDI: | 718 case REG_ES_RDI: |
658 if (((struct DecodeState *)userdata)->ia32_mode) | 719 if (userdata->ia32_mode) |
659 printf("%%es:(%%edi)"); | 720 printf("%%es:(%%edi)"); |
660 else | 721 else |
661 printf("%%es:(%%rdi)"); | 722 printf("%%es:(%%rdi)"); |
662 break; | 723 break; |
663 case REG_DS_RSI: | 724 case REG_DS_RSI: |
664 if (((struct DecodeState *)userdata)->ia32_mode) | 725 if (userdata->ia32_mode) |
665 printf("%%ds:(%%esi)"); | 726 printf("%%ds:(%%esi)"); |
666 else | 727 else |
667 printf("%%ds:(%%rsi)"); | 728 printf("%%ds:(%%rsi)"); |
668 break; | 729 break; |
669 case JMP_TO: | 730 case JMP_TO: |
670 if (instruction->operands[0].type == OPERAND_TYPE_16_BIT) | 731 if (instruction->operands[0].type == OPERAND_TYPE_16_BIT) |
671 printf("0x%lx", (long)((end + instruction->rm.offset - | 732 printf("0x%lx", (long)((end + instruction->rm.offset - |
672 (((struct DecodeState *)userdata)->offset)) & 0xffff)); | 733 (userdata->offset)) & 0xffff)); |
673 else | 734 else |
674 printf("0x%lx", (long)(end + instruction->rm.offset - | 735 printf("0x%lx", (long)(end + instruction->rm.offset - |
675 (((struct DecodeState *)userdata)->offset))); | 736 (userdata->offset))); |
676 break; | 737 break; |
677 case REG_RIP: | 738 case REG_RIP: |
678 case REG_RIZ: | 739 case REG_RIZ: |
679 case NO_REG: | 740 case NO_REG: |
680 assert(FALSE); | 741 assert(FALSE); |
681 } | 742 } |
682 delimeter = ','; | 743 delimeter = ','; |
683 } | 744 } |
745 | |
746 /* | |
747 * If %rip was used then objdump will show the actual address as the comment. | |
748 */ | |
684 if (print_rip) { | 749 if (print_rip) { |
685 printf(" # 0x%8"NACL_PRIx64, | 750 printf(" # 0x%8"NACL_PRIx64, |
686 (uint64_t) (end + instruction->rm.offset - | 751 (uint64_t) (end + instruction->rm.offset - |
687 (((struct DecodeState *)userdata)->offset))); | 752 (userdata->offset))); |
688 } | 753 } |
754 | |
755 /* First line of instruction decoding is printed. Finish the line. */ | |
689 printf("\n"); | 756 printf("\n"); |
690 begin += 7; | 757 begin += 7; |
758 /* if there are more then seven bytes we need to print the rest. */ | |
691 while (begin < end) { | 759 while (begin < end) { |
692 printf("%*"NACL_PRIx64":\t", ((struct DecodeState *)userdata)->width, | 760 printf("%*"NACL_PRIx64":\t", userdata->width, |
693 (uint64_t) (begin - (((struct DecodeState *)userdata)->offset))); | 761 (uint64_t) (begin - (userdata->offset))); |
694 for (p = begin; p < begin + 7; ++p) { | 762 for (p = begin; p < begin + 7; ++p) { |
695 if (p >= end) { | 763 if (p >= end) { |
696 printf("\n"); | 764 printf("\n"); |
697 return; | 765 return; |
698 } else { | 766 } else { |
699 printf("%02x ", *p); | 767 printf("%02x ", *p); |
700 } | 768 } |
701 } | 769 } |
702 printf("\n"); | 770 printf("\n"); |
703 if (p >= end) | 771 if (p >= end) |
704 return; | 772 return; |
705 begin += 7; | 773 begin += 7; |
706 } | 774 } |
707 } | 775 } |
708 | 776 |
709 void ProcessError (const uint8_t *ptr, void *userdata) { | 777 void ProcessError (const uint8_t *ptr, void *userdata) { |
710 printf("rejected at %"NACL_PRIx64" (byte 0x%02"NACL_PRIx32")\n", | 778 printf("rejected at %"NACL_PRIx64" (byte 0x%02"NACL_PRIx32")\n", |
711 (uint64_t) (ptr - (((struct DecodeState *)userdata)->offset)), | 779 (uint64_t) (ptr - (((struct DecodeState *)userdata)->offset)), |
712 *ptr); | 780 *ptr); |
713 } | 781 } |
714 | 782 |
715 int DecodeFile(const char *filename, int repeat_count) { | 783 int DecodeFile(const char *filename, int repeat_count) { |
Brad Chen
2012/10/22 21:29:05
The two if statements that follow the calls to Che
| |
716 size_t data_size; | 784 size_t data_size; |
717 uint8_t *data; | 785 uint8_t *data; |
718 int count; | 786 int count; |
719 | 787 |
720 ReadImage(filename, &data, &data_size); | 788 ReadImage(filename, &data, &data_size); |
721 if (data[4] == 1) { | 789 if (data[4] == 1) { |
722 for (count = 0; count < repeat_count; ++count) { | 790 for (count = 0; count < repeat_count; ++count) { |
723 Elf32_Ehdr *header; | 791 Elf32_Ehdr *header; |
724 int index; | 792 int index; |
725 | 793 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
816 return 0; | 884 return 0; |
817 } | 885 } |
818 | 886 |
819 int main(int argc, char **argv) { | 887 int main(int argc, char **argv) { |
820 int index, initial_index = 1, repeat_count = 1; | 888 int index, initial_index = 1, repeat_count = 1; |
821 if (argc == 1) { | 889 if (argc == 1) { |
822 printf("%s: no input files\n", argv[0]); | 890 printf("%s: no input files\n", argv[0]); |
823 exit(1); | 891 exit(1); |
824 } | 892 } |
825 if (!strcmp(argv[1], "--repeat")) | 893 if (!strcmp(argv[1], "--repeat")) |
826 repeat_count = atoi(argv[2]), | 894 repeat_count = atoi(argv[2]), |
Dmitry Polukhin
2012/11/02 17:31:06
Please don't use comma to separate statements. Thi
| |
827 initial_index += 2; | 895 initial_index += 2; |
828 for (index = initial_index; index < argc; ++index) { | 896 for (index = initial_index; index < argc; ++index) { |
829 const char *filename = argv[index]; | 897 const char *filename = argv[index]; |
830 int rc = DecodeFile(filename, repeat_count); | 898 int rc = DecodeFile(filename, repeat_count); |
831 if (!rc) { | 899 if (!rc) { |
832 printf("file '%s' can not be fully decoded\n", filename); | 900 printf("file '%s' can not be fully decoded\n", filename); |
833 return 1; | 901 return 1; |
834 } | 902 } |
835 } | 903 } |
836 return 0; | 904 return 0; |
837 } | 905 } |
OLD | NEW |