Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: src/trusted/validator_ragel/unreviewed/decoder_test.c

Issue 11000033: Move validator_x86_XX.rl out of unreviewed. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698