LCOV - code coverage report
Current view: directory - src/trusted/validator_x86 - ncval.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 185 147 79.5 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       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
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * ncval.c - command line validator for NaCl.
       9                 :  * Mostly for testing.
      10                 :  */
      11                 : 
      12                 : 
      13                 : #ifndef NACL_TRUSTED_BUT_NOT_TCB
      14                 : #error("This file is not meant for use in the TCB")
      15                 : #endif
      16                 : 
      17                 : #include "native_client/src/include/portability.h"
      18                 : 
      19                 : #include <stdio.h>
      20                 : #include <stdlib.h>
      21                 : #include <stdarg.h>
      22                 : #include <string.h>
      23                 : #include <errno.h>
      24                 : #include <sys/timeb.h>
      25                 : #include <time.h>
      26                 : #include "native_client/src/include/nacl_macros.h"
      27                 : #include "native_client/src/shared/gio/gio.h"
      28                 : #include "native_client/src/shared/platform/nacl_log.h"
      29                 : #include "native_client/src/shared/utils/flags.h"
      30                 : #include "native_client/src/trusted/validator/ncfileutil.h"
      31                 : #include "native_client/src/trusted/validator/x86/nacl_cpuid.h"
      32                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.h"
      33                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_internal.h"
      34                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_detailed.h"
      35                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h"
      36                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_opcode_histogram.h"
      37                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.h"
      38                 : #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode.h"
      39                 : #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode_verbose.h"
      40                 : #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.h"
      41                 : #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncvalidate_detailed.h"
      42                 : #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncvalidate_internaltypes.h"
      43                 : #include "native_client/src/trusted/validator_x86/nc_read_segment.h"
      44                 : #include "native_client/src/trusted/validator_x86/ncdis_segments.h"
      45                 : 
      46                 : #if NACL_TARGET_SUBARCH == 64
      47                 : #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables.h"
      48                 : #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncval_decode_tables.h"
      49                 : #include "native_client/src/trusted/validator_x86/ncdis_decode_tables.h"
      50                 : #endif
      51                 : 
      52                 : /* To turn on debugging of instruction decoding, change value of
      53                 :  * DEBUGGING to 1.
      54                 :  */
      55                 : #define DEBUGGING 0
      56                 : 
      57                 : #include "native_client/src/shared/utils/debugging.h"
      58                 : 
      59                 : /* When true, ncval will override the default reporter with the
      60                 :  * appropriate verbose reporter.
      61                 :  */
      62                 : static Bool override_reporter =
      63                 : #if DEBUGGING || !defined(NCVAL_TESTING)
      64                 :     TRUE
      65                 : #else
      66                 :     FALSE
      67                 : #endif
      68                 :     ;
      69                 : 
      70                 : /* Forward declarations. */
      71                 : static void usage(int exit_code);
      72                 : 
      73                 : #if NACL_TARGET_SUBARCH == 32
      74                 : /* Flag defining if statistics should be printed for callback validator
      75                 :  * model.
      76                 :  */
      77                 : static Bool NACL_FLAGS_stats_print = FALSE;
      78                 : #endif
      79                 : 
      80                 : /* Flag defining if detailed error messages should be generated. When
      81                 :  * false, runs performance model as used by sel_ldr.
      82                 :  */
      83                 : static Bool NACL_FLAGS_detailed_errors = TRUE;
      84                 : 
      85                 : /* Flag defining the name of a hex text to be used as the code segment.
      86                 :  */
      87                 : static char *NACL_FLAGS_hex_text = "";
      88                 : 
      89                 : /* Define if we should process segments (rather than sections) when applying SFI
      90                 :  * validator.
      91                 :  */
      92                 : static Bool NACL_FLAGS_analyze_segments = FALSE;
      93                 : 
      94                 : /* Define how many times we will analyze the code segment.
      95                 :  * Note: Values, other than 1, is only used for profiling.
      96                 :  */
      97                 : static int NACL_FLAGS_validate_attempts = 1;
      98                 : 
      99                 : /* Define the set of CPU features to use while validating. */
     100                 : static NaClCPUFeaturesX86 ncval_cpu_features;
     101                 : 
     102                 : /* Define whether timing should be applied when running the validator. */
     103                 : static Bool NACL_FLAGS_print_timing = FALSE;
     104                 : 
     105                 : /* Define the block alignment size to use. */
     106                 : static int NACL_FLAGS_block_alignment = 32;
     107                 : 
     108                 : /* Define what level of errors will be printed.
     109                 :  * Note: If multiple flags are true, the one with
     110                 :  * the highest severity will be selected.
     111                 :  */
     112                 : static Bool NACL_FLAGS_warnings = FALSE;
     113                 : static Bool NACL_FLAGS_errors = FALSE;
     114                 : static Bool NACL_FLAGS_fatal = FALSE;
     115                 : 
     116                 : /* Define if special stubout tests should be run. Such
     117                 :  * tests apply stubout, and then print out the modified
     118                 :  * disassembled code.
     119                 :  */
     120                 : static Bool NACL_FLAGS_stubout_memory = FALSE;
     121                 : 
     122                 : #if NACL_TARGET_SUBARCH == 64
     123                 : /* Flag that allows validator decoder to be used in place of full decoder.
     124                 :  */
     125                 : static Bool NACL_FLAGS_validator_decoder = FALSE;
     126                 : #endif
     127                 : 
     128                 : /* Generates NaClErrorMapping for error level suffix. */
     129                 : #define NaClError(s) { #s , LOG_## s}
     130                 : 
     131                 : /**************************************************
     132                 :  * Driver to apply the validator to a code segment
     133                 :  *************************************************/
     134                 : 
     135                 : /* Reports if named module is safe. */
     136              74 : static void NaClReportFileSafety(Bool success, const char *fname) {
     137              74 :   if (NACL_FLAGS_stubout_memory) {
     138                 :     /* The validator has been run to test stubbing out. Stubbing out,
     139                 :      * in this tool, means replacing instructions (modeled using hex
     140                 :      * text) that are unsafe and rejected by the validator, and are
     141                 :      * replaced with HALT instructions.
     142                 :      */
     143               0 :     NaClLog(LOG_INFO, "STUBBED OUT as follows:\n");
     144                 :   } else {
     145                 : #ifndef NCVAL_TESTING
     146              74 :     if (success) {
     147              32 :       NaClLog(LOG_INFO, "*** %s is safe ***\n", fname);
     148                 :     } else {
     149              42 :       NaClLog(LOG_INFO, "*** %s IS UNSAFE ***\n", fname);
     150                 :     }
     151                 : #endif
     152                 :   }
     153              74 : }
     154                 : 
     155                 : /* Reports if module is safe. */
     156                 : static void NaClReportSafety(Bool success,
     157              74 :                              const char* filename) {
     158              74 :   if (0 != strcmp(NACL_FLAGS_hex_text, "")) {
     159                 :     /* Special hex text processing, rather than filename. */
     160              62 :     if (0 == strcmp(NACL_FLAGS_hex_text, "-")) {
     161              62 :       NaClReportFileSafety(success, "<input>");
     162              62 :       return;
     163                 :     }
     164                 :   }
     165              12 :   NaClReportFileSafety(success, filename);
     166                 : }
     167                 : 
     168                 : /* The model of data to be passed to the load/analyze steps. */
     169                 : typedef void* NaClRunValidatorData;
     170                 : 
     171                 : /* The routine that loads the code segment(s) into memory (within
     172                 :  * the data arg). Returns true iff load was successful.
     173                 :  */
     174                 : typedef Bool (*NaClValidateLoad)(int argc, const char* argv[],
     175                 :                                  NaClRunValidatorData data);
     176                 : 
     177                 : /* The actual validation analysis, applied to the data returned by
     178                 :  * ValidateLoad. Assume that this function also deallocates any memory
     179                 :  * in loaded_data. Returns true iff analysis doesn't find any problems.
     180                 :  */
     181                 : typedef Bool (*NaClValidateAnalyze)(NaClRunValidatorData data);
     182                 : 
     183                 : /* Runs the validator using the given (command line) arguments.
     184                 :  *
     185                 :  * Parameters:
     186                 :  *    data - The model of data to be passed to the load/analyze steps.
     187                 :  *           Allows top-level call to pass control information
     188                 :  *           to the load and analyze functions, and between these
     189                 :  *           two functions.
     190                 :  *    load - The function to load in the data needed to validate.
     191                 :  *    analyze - The function to call to do validator analysis once
     192                 :  *           the data has been read in.
     193                 :  */
     194                 : static Bool NaClRunValidator(int argc, const char* argv[],
     195                 :                              NaClRunValidatorData data,
     196                 :                              NaClValidateLoad load,
     197              68 :                              NaClValidateAnalyze analyze) {
     198                 :   clock_t clock_0;
     199                 :   clock_t clock_l;
     200                 :   clock_t clock_v;
     201                 :   Bool return_value;
     202                 : 
     203              68 :   clock_0 = clock();
     204              68 :   return_value = load(argc, argv, data);
     205              68 :   if (!return_value) {
     206               0 :     NaClValidatorMessage(LOG_ERROR, NULL, "Unable to load code to validate\n");
     207               0 :     return FALSE;
     208                 :   }
     209              68 :   clock_l = clock();
     210              68 :   return_value = analyze(data);
     211              68 :   clock_v = clock();
     212                 : 
     213              68 :   if (NACL_FLAGS_print_timing) {
     214               3 :     NaClValidatorMessage(
     215                 :         LOG_INFO, NULL,
     216                 :         "load time: %0.6f  analysis time: %0.6f\n",
     217                 :         (double)(clock_l - clock_0) /  (double)CLOCKS_PER_SEC,
     218                 :         (double)(clock_v - clock_l) /  (double)CLOCKS_PER_SEC);
     219                 :   }
     220              68 :   return return_value;
     221                 : }
     222                 : 
     223                 : /* Default loader that does nothing. Typically this is because
     224                 :  * the data argument already contains the bytes to validate.
     225                 :  */
     226                 : Bool NaClValidateNoLoad(int argc, const char* argv[],
     227              62 :                         NaClRunValidatorData data) {
     228              62 :   return TRUE;
     229                 : }
     230                 : 
     231                 : /* Local file data for validator run. */
     232                 : typedef struct ValidateData {
     233                 :   /* The name of the elf file to validate. */
     234                 :   const char *fname;
     235                 :   /* The elf file to validate. */
     236                 :   ncfile *ncf;
     237                 : } ValidateData;
     238                 : 
     239                 : /* Load the elf file and return the loaded elf file. */
     240                 : static Bool ValidateElfLoad(int argc, const char *argv[],
     241               6 :                                 ValidateData *data) {
     242               6 :   if (argc != 2) {
     243               0 :     NaClLog(LOG_ERROR, "expected: %s file\n", argv[0]);
     244               0 :     usage(2);
     245                 :   }
     246               6 :   data->fname = argv[1];
     247                 : 
     248                 :   /* TODO(karl): Once we fix elf values put in by compiler, so that
     249                 :    * we no longer get load errors from ncfilutil.c, find a way to
     250                 :    * terminate early if errors occur during loading.
     251                 :    */
     252               6 :   data->ncf = nc_loadfile(data->fname);
     253               6 :   if (data->ncf == NULL) {
     254               0 :     NaClLog(LOG_ERROR, "nc_loadfile(%s): %s\n", data->fname, strerror(errno));
     255               0 :     usage(2);
     256                 :   }
     257               6 :   return NULL != data->ncf;
     258                 : }
     259                 : 
     260                 : /***************************************************
     261                 :  * Code to run SFI validator on hex text examples. *
     262                 :  ***************************************************/
     263                 : 
     264                 : /* Defines the maximum number of characters allowed on an input line
     265                 :  * of the input text defined by the commands command line option.
     266                 :  */
     267                 : #define NACL_MAX_INPUT_LINE 4096
     268                 : 
     269                 : typedef struct NaClValidatorByteArray {
     270                 :   uint8_t bytes[NACL_MAX_INPUT_LINE];
     271                 :   NaClPcAddress base;
     272                 :   NaClMemorySize num_bytes;
     273                 : } NaClValidatorByteArray;
     274                 : 
     275                 : static void HexFatal(const char *format, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
     276                 : 
     277                 : /* Print out given error message about the hex input file, and then exit. */
     278               0 : static void HexFatal(const char *format, ...) {
     279                 :   va_list ap;
     280               0 :   va_start(ap, format);
     281               0 :   NaClLogV(LOG_ERROR, format, ap);
     282               0 :   va_end(ap);
     283                 :   /* always succed, so that the testing framework works. */
     284               0 :   exit(0);
     285                 : }
     286                 : 
     287                 : /* Load the hex input file from the given command line arguments,
     288                 :  * and put it into the given data structure.
     289                 :  */
     290                 : static int ValidateHexLoad(int argc, const char *argv[],
     291              62 :                               NaClValidatorByteArray *data) {
     292              62 :   if (argc != 1) {
     293               0 :     HexFatal("expected: %s <options>\n", argv[0]);
     294                 :   }
     295              62 :   if (0 == strcmp(NACL_FLAGS_hex_text, "-")) {
     296              62 :     data->num_bytes = (NaClMemorySize)
     297                 :         NaClReadHexTextWithPc(stdin, &data->base, data->bytes,
     298                 :                               NACL_MAX_INPUT_LINE);
     299                 :   } else {
     300               0 :     FILE *input = fopen(NACL_FLAGS_hex_text, "r");
     301               0 :     if (NULL == input) {
     302               0 :       HexFatal("Can't open hex text file: %s\n", NACL_FLAGS_hex_text);
     303                 :     }
     304               0 :     data->num_bytes = (NaClMemorySize)
     305                 :         NaClReadHexTextWithPc(input, &data->base, data->bytes,
     306                 :                               NACL_MAX_INPUT_LINE);
     307               0 :     fclose(input);
     308               0 :     --argc;
     309                 :   }
     310              62 :   return argc;
     311                 : }
     312                 : 
     313                 : #if NACL_TARGET_SUBARCH == 32
     314                 : /***************************************
     315                 :  * Code to run segment based validator.*
     316                 :  ***************************************/
     317                 : 
     318               6 : int AnalyzeSegmentSections(ncfile *ncf, struct NCValidatorState *vstate) {
     319               6 :   int badsections = 0;
     320                 :   int ii;
     321               6 :   const Elf_Phdr *phdr = ncf->pheaders;
     322                 : 
     323              30 :   for (ii = 0; ii < ncf->phnum; ii++) {
     324              24 :     NaClLog(LOG_INFO,
     325                 :         "segment[%d] p_type %"NACL_PRIdElf_Word
     326                 :         " p_offset %"NACL_PRIxElf_Off" vaddr %"NACL_PRIxElf_Addr
     327                 :         " paddr %"NACL_PRIxElf_Addr" align %"NACL_PRIuElf_Xword"\n",
     328                 :         ii, phdr[ii].p_type, phdr[ii].p_offset,
     329                 :         phdr[ii].p_vaddr, phdr[ii].p_paddr,
     330                 :         phdr[ii].p_align);
     331                 : 
     332              24 :     NaClLog(LOG_INFO,
     333                 :             "    filesz %"NACL_PRIxElf_Xword" memsz %"NACL_PRIxElf_Xword
     334                 :             " flags %"NACL_PRIxElf_Word"\n",
     335                 :           phdr[ii].p_filesz, phdr[ii].p_memsz, phdr[ii].p_flags);
     336              24 :     if ((PT_LOAD != phdr[ii].p_type) ||
     337                 :         (0 == (phdr[ii].p_flags & PF_X)))
     338                 :       continue;
     339               6 :     NaClLog(LOG_INFO, "parsing segment %d\n", ii);
     340               6 :     NCValidateSegment(ncf->data + (phdr[ii].p_vaddr - ncf->vbase),
     341                 :                       phdr[ii].p_vaddr, phdr[ii].p_memsz, vstate);
     342                 :   }
     343               6 :   return -badsections;
     344                 : }
     345                 : 
     346                 : /* Initialize segment validator, using detailed (summary) error
     347                 :  * messages if selected.
     348                 :  */
     349                 : struct NCValidatorState* NCValInit(const NaClPcAddress vbase,
     350                 :                                    const NaClMemorySize codesize,
     351              68 :                                    const uint8_t alignment) {
     352              68 :   return NACL_FLAGS_detailed_errors
     353                 :       ? NCValidateInitDetailed(vbase, codesize, alignment, &ncval_cpu_features)
     354                 :       : NCValidateInit(vbase, codesize, alignment, &ncval_cpu_features);
     355                 : }
     356                 : 
     357                 : 
     358               6 : static Bool AnalyzeSegmentCodeSegments(ncfile *ncf, const char *fname) {
     359                 :   NaClPcAddress vbase, vlimit;
     360                 :   struct NCValidatorState *vstate;
     361                 :   Bool result;
     362                 : 
     363               6 :   GetVBaseAndLimit(ncf, &vbase, &vlimit);
     364               6 :   vstate = NCValInit(vbase, vlimit - vbase, ncf->ncalign);
     365               6 :   if (vstate == NULL) return FALSE;
     366               6 :   if (override_reporter) {
     367               6 :     NCValidateSetErrorReporter(vstate, &kNCVerboseErrorReporter);
     368                 :   }
     369               6 :   if (AnalyzeSegmentSections(ncf, vstate) < 0) {
     370               0 :     NaClLog(LOG_INFO, "%s: text validate failed\n", fname);
     371                 :   }
     372               6 :   result = (0 == NCValidateFinish(vstate)) ? TRUE : FALSE;
     373               6 :   NaClReportSafety(result, fname);
     374               6 :   if (NACL_FLAGS_stats_print) NCStatsPrint(vstate);
     375               6 :   NCValidateFreeState(&vstate);
     376               6 :   NaClLog(LOG_INFO, "Validated %s\n", fname);
     377               6 :   return result;
     378                 : }
     379                 : #endif
     380                 : 
     381                 : #if NACL_TARGET_SUBARCH == 64
     382                 : /******************************
     383                 :  * Code to run SFI validator. *
     384                 :  ******************************/
     385                 : 
     386                 : /* Define what should be used as the base register for
     387                 :  * memory accesses.
     388                 :  */
     389                 : static NaClOpKind nacl_base_register =
     390                 :     (64 == NACL_TARGET_SUBARCH ? RegR15 : RegUnknown);
     391                 : 
     392                 : /* Create validator state using detailed (summary) error messages
     393                 :  * if selected.
     394                 :  */
     395                 : struct NaClValidatorState* NaClValStateCreate(
     396                 :     const NaClPcAddress vbase,
     397                 :     const NaClMemorySize sz,
     398                 :     const uint8_t alignment,
     399                 :     const NaClOpKind base_register) {
     400                 :   return
     401                 :       NACL_FLAGS_detailed_errors
     402                 :       ? NaClValidatorStateCreateDetailed(vbase, sz, alignment, base_register,
     403                 :                                          &ncval_cpu_features)
     404                 :       : NaClValidatorStateCreate(vbase, sz, alignment, base_register,
     405                 :                                  &ncval_cpu_features);
     406                 : }
     407                 : 
     408                 : /* Returns the decoder tables to use. */
     409                 : static const NaClDecodeTables* NaClGetDecoderTables() {
     410                 :   return NACL_FLAGS_validator_decoder
     411                 :       ? kNaClValDecoderTables
     412                 :       : kNaClDecoderTables;
     413                 : }
     414                 : 
     415                 : /* Analyze each section in the given elf file, using the given validator
     416                 :  * state.
     417                 :  */
     418                 : static void AnalyzeSfiSections(ncfile *ncf, struct NaClValidatorState *vstate) {
     419                 :   int ii;
     420                 :   const Elf_Phdr *phdr = ncf->pheaders;
     421                 : 
     422                 :   for (ii = 0; ii < ncf->phnum; ii++) {
     423                 :     /* TODO(karl) fix types for this? */
     424                 :     NaClValidatorMessage(
     425                 :         LOG_INFO, vstate,
     426                 :         "segment[%d] p_type %d p_offset %"NACL_PRIxElf_Off
     427                 :         " vaddr %"NACL_PRIxElf_Addr
     428                 :         " paddr %"NACL_PRIxElf_Addr
     429                 :         " align %"NACL_PRIuElf_Xword"\n",
     430                 :         ii, phdr[ii].p_type, phdr[ii].p_offset,
     431                 :         phdr[ii].p_vaddr, phdr[ii].p_paddr,
     432                 :         phdr[ii].p_align);
     433                 :     NaClValidatorMessage(
     434                 :         LOG_INFO, vstate,
     435                 :         "    filesz %"NACL_PRIxElf_Xword
     436                 :         " memsz %"NACL_PRIxElf_Xword
     437                 :         " flags %"NACL_PRIxElf_Word"\n",
     438                 :         phdr[ii].p_filesz, phdr[ii].p_memsz,
     439                 :         phdr[ii].p_flags);
     440                 :     if ((PT_LOAD != phdr[ii].p_type) ||
     441                 :         (0 == (phdr[ii].p_flags & PF_X)))
     442                 :       continue;
     443                 :     NaClValidatorMessage(LOG_INFO, vstate, "parsing segment %d\n", ii);
     444                 :     NaClValidateSegmentUsingTables(ncf->data + (phdr[ii].p_vaddr - ncf->vbase),
     445                 :                                    phdr[ii].p_vaddr, phdr[ii].p_memsz, vstate,
     446                 :                                    NaClGetDecoderTables());
     447                 :   }
     448                 : }
     449                 : 
     450                 : static void AnalyzeSfiSegments(ncfile *ncf, NaClValidatorState *state) {
     451                 :   int ii;
     452                 :   const Elf_Shdr *shdr = ncf->sheaders;
     453                 : 
     454                 :   for (ii = 0; ii < ncf->shnum; ii++) {
     455                 :     NaClValidatorMessage(
     456                 :         LOG_INFO, state,
     457                 :         "section %d sh_addr %"NACL_PRIxElf_Addr" offset %"NACL_PRIxElf_Off
     458                 :         " flags %"NACL_PRIxElf_Xword"\n",
     459                 :          ii, shdr[ii].sh_addr, shdr[ii].sh_offset, shdr[ii].sh_flags);
     460                 :     if ((shdr[ii].sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR)
     461                 :       continue;
     462                 :     NaClValidatorMessage(LOG_INFO, state, "parsing section %d\n", ii);
     463                 :     NaClValidateSegmentUsingTables(ncf->data + (shdr[ii].sh_addr - ncf->vbase),
     464                 :                                    shdr[ii].sh_addr, shdr[ii].sh_size, state,
     465                 :                                    NaClGetDecoderTables());
     466                 :   }
     467                 : }
     468                 : 
     469                 : /* Analyze each code segment in the given elf file, stored in the
     470                 :  * file with the given path fname.
     471                 :  */
     472                 : static Bool AnalyzeSfiCodeSegments(ncfile *ncf, const char *fname) {
     473                 :   /* TODO(karl) convert these to be PcAddress and MemorySize */
     474                 :   NaClPcAddress vbase, vlimit;
     475                 :   NaClValidatorState *vstate;
     476                 :   Bool return_value = TRUE;
     477                 : 
     478                 :   GetVBaseAndLimit(ncf, &vbase, &vlimit);
     479                 :   vstate = NaClValStateCreate(vbase, vlimit - vbase,
     480                 :                               ncf->ncalign, nacl_base_register);
     481                 :   if (vstate == NULL) {
     482                 :     NaClValidatorMessage(LOG_ERROR, vstate, "Unable to create validator state");
     483                 :     return FALSE;
     484                 :   }
     485                 :   if (override_reporter) {
     486                 :     NaClValidatorStateSetErrorReporter(vstate, &kNaClVerboseErrorReporter);
     487                 :   }
     488                 :   if (NACL_FLAGS_analyze_segments) {
     489                 :     AnalyzeSfiSegments(ncf, vstate);
     490                 :   } else {
     491                 :     AnalyzeSfiSections(ncf, vstate);
     492                 :   }
     493                 :   return_value = NaClValidatesOk(vstate);
     494                 :   NaClReportSafety(return_value, fname);
     495                 :   NaClValidatorStateDestroy(vstate);
     496                 :   return return_value;
     497                 : }
     498                 : #endif
     499                 : 
     500                 : /***************************
     501                 :  * Top-level driver code. *
     502                 :  **************************/
     503                 : 
     504                 : /* Analyze the code segments of the elf file in the validator date. */
     505               6 : static Bool ValidateAnalyze(ValidateData *data) {
     506                 :   int i;
     507               6 :   Bool results = TRUE;
     508              12 :   for (i = 0; i < NACL_FLAGS_validate_attempts; ++i) {
     509                 :     Bool return_value =
     510                 : #if NACL_TARGET_SUBARCH == 64
     511                 :         AnalyzeSfiCodeSegments(data->ncf, data->fname);
     512                 : #else
     513               6 :         AnalyzeSegmentCodeSegments(data->ncf, data->fname);
     514                 : #endif
     515               6 :     if (!return_value) {
     516               2 :       results = FALSE;
     517                 :     }
     518                 :   }
     519               6 :   nc_freefile(data->ncf);
     520               6 :   return results;
     521                 : }
     522                 : 
     523                 : /* Define a sequence of bytes to validate whose virtual address begins at the
     524                 :  * given base.
     525                 :  */
     526                 : typedef struct NaClValidateBytes {
     527                 :   /* The sequence of bytes to validate. */
     528                 :   uint8_t* bytes;
     529                 :   /* The number of bytes in the sequence. */
     530                 :   NaClMemorySize num_bytes;
     531                 :   /* The virtual base adddress associated with the first byte in the
     532                 :    * sequence.
     533                 :    */
     534                 :   NaClPcAddress base;
     535                 : } NaClValidateBytes;
     536                 : 
     537                 : /* Apply the validator to the sequence of bytes in the given data. */
     538              62 : static Bool NaClValidateAnalyzeBytes(NaClValidateBytes* data) {
     539              62 :   Bool return_value = FALSE;
     540                 : #if NACL_TARGET_SUBARCH == 64
     541                 :   NaClValidatorState* state;
     542                 :   state = NaClValStateCreate(data->base,
     543                 :                              data->num_bytes,
     544                 :                              (uint8_t) NACL_FLAGS_block_alignment,
     545                 :                              nacl_base_register);
     546                 :   if (NULL == state) {
     547                 :     NaClValidatorMessage(LOG_ERROR, NULL, "Unable to create validator state");
     548                 :     return FALSE;
     549                 :   }
     550                 :   if (NACL_FLAGS_stubout_memory) {
     551                 :     NaClValidatorStateSetDoStubOut(state, TRUE);
     552                 :   }
     553                 :   if (override_reporter) {
     554                 :     NaClValidatorStateSetErrorReporter(state, &kNaClVerboseErrorReporter);
     555                 :   }
     556                 :   NaClValidateSegmentUsingTables(data->bytes, data->base, data->num_bytes,
     557                 :                                  state, NaClGetDecoderTables());
     558                 :   return_value = NaClValidatesOk(state);
     559                 :   if (state->did_stub_out) {
     560                 :     /* Used for golden file testing. */
     561                 :     printf("Some instructions were replaced with HLTs.\n");
     562                 :   }
     563                 :   NaClValidatorStateDestroy(state);
     564                 :   NaClReportSafety(return_value, "");
     565                 : #else
     566                 :   struct NCValidatorState *vstate;
     567              62 :   vstate = NCValInit(data->base, data->num_bytes,
     568                 :                      (uint8_t) NACL_FLAGS_block_alignment);
     569              62 :   if (vstate == NULL) {
     570               0 :     printf("Unable to create validator state, quitting!\n");
     571                 :   } else {
     572              62 :     if (NACL_FLAGS_stubout_memory) {
     573               0 :       NCValidateSetStubOutMode(vstate, 1);
     574                 :     }
     575              62 :     if (override_reporter) {
     576              62 :       NCValidateSetErrorReporter(vstate, &kNCVerboseErrorReporter);
     577                 :     }
     578              62 :     NCValidateSegment(&data->bytes[0], data->base, data->num_bytes, vstate);
     579              62 :     return_value = (0 == NCValidateFinish(vstate)) ? TRUE : FALSE;
     580              62 :     if (vstate->stats.didstubout) {
     581                 :       /* Used for golden file testing. */
     582               1 :       printf("Some instructions were replaced with HLTs.\n");
     583                 :     }
     584              62 :     NaClReportSafety(return_value, "");
     585              62 :     if (NACL_FLAGS_stats_print) NCStatsPrint(vstate);
     586              62 :     NCValidateFreeState(&vstate);
     587                 :   }
     588                 : #endif
     589              62 :   return return_value;
     590                 : }
     591                 : 
     592                 : /* Given the command line arguments in argc/argv, and the sequence of bytes
     593                 :  * in the given data, apply the validator to the given bytes.
     594                 :  */
     595                 : Bool NaClRunValidatorBytes(int argc,
     596                 :                            const char* argv[],
     597                 :                            uint8_t* bytes,
     598                 :                            NaClMemorySize num_bytes,
     599              62 :                            NaClPcAddress base) {
     600                 :   NaClValidateBytes data;
     601                 :   int i;
     602              62 :   Bool results = TRUE;
     603              62 :   data.bytes = bytes;
     604              62 :   data.num_bytes = num_bytes;
     605              62 :   data.base = base;
     606             124 :   for (i = 0; i < NACL_FLAGS_validate_attempts; ++i) {
     607              62 :     if (!NaClRunValidator(argc, argv, &data,
     608                 :                           (NaClValidateLoad) NaClValidateNoLoad,
     609                 :                           (NaClValidateAnalyze) NaClValidateAnalyzeBytes)) {
     610              38 :       results = FALSE;
     611                 :     }
     612                 :   }
     613              62 :   return results;
     614                 : }
     615                 : 
     616                 : 
     617                 : static const char usage_str[] =
     618                 :       "usage: ncval [options] file\n"
     619                 :       "\n"
     620                 :       "\tValidates an x86-%d nexe file.\n"
     621                 :       "\n"
     622                 :       "Options are:\n"
     623                 :       "\n"
     624                 :       "--alignment=N\n"
     625                 :       "\tSet block alignment to N bytes (only 16 or 32 allowed).\n"
     626                 :       "--annotate\n"
     627                 :       "\tRun validator using annotations that will be understood\n"
     628                 :       "\tby ncval_annotate.py.\n"
     629                 :       "--attempts=N\n"
     630                 :       "\tRun the validator on the nexe file (after loading) N times.\n"
     631                 :       "\tNote: this flag should only be used for profiling.\n"
     632                 :       "--CLFLUSH\n"
     633                 :       "\tModel a CPU that supports the clflush instruction.\n"
     634                 :       "--CMOV\n"
     635                 :       "\tModel a CPU that supports the cmov instructions.\n"
     636                 : #ifdef NCVAL_TESTING
     637                 :       "--conds\n"
     638                 :       "\tPrint out pre/post conditions associated with each instruction.\n"
     639                 : #endif
     640                 :       "--cpuid-all\n"
     641                 :       "\tModel a CPU that supports all available features.\n"
     642                 :       "--cpuid-none\n"
     643                 :       "\tModel a CPU that supports no avaliable features.\n"
     644                 :       "--CX8\n"
     645                 :       "\tModel a CPU that supports the cmpxchg8b instruction.\n"
     646                 :       "--detailed\n"
     647                 :       "\tPrint out detailed error messages, rather than use performant\n"
     648                 :       "\tcode used by sel_ldr\n"
     649                 :       "--errors\n"
     650                 :       "\tPrint out error and fatal error messages, but not\n"
     651                 :       "\tinformative and warning messages\n"
     652                 :       "--fatal\n"
     653                 :       "\tOnly print out fatal error messages.\n"
     654                 :       "--FXSR\n"
     655                 :       "\tModel a CPU that supports the sfence instructions.\n"
     656                 :       "--help\n"
     657                 :       "\tPrint this message, and then exit.\n"
     658                 :       "--hex_text=<file>\n"
     659                 :       "\tRead text file of hex bytes, and use that\n"
     660                 :       "\tas the definition of the code segment. Note: -hex_text=- will\n"
     661                 :       "\tread from stdin instead of a file.\n"
     662                 : #if NACL_TARGET_SUBARCH == 64
     663                 :       "--histogram\n"
     664                 :       "\tPrint out a histogram of found opcodes.\n"
     665                 :       "--identity_mask\n"
     666                 :       "\tMask jumps using 0xFF instead of one matching\n"
     667                 :       "\tthe block alignment.\n"
     668                 : #endif
     669                 :       "--local_cpuid\n"
     670                 :       "\tSet cpuid to values defined by local host this command is run on.\n"
     671                 :       "--LZCNT\n"
     672                 :       "\tModel a CPU that supports the lzcnt instruction.\n"
     673                 : #if NACL_TARGET_SUBARCH == 64
     674                 :       "--max_errors=N\n"
     675                 :       "\tPrint out at most N error messages. If N is zero,\n"
     676                 :       "\tno messages are printed. If N is < 0, all messages are printed.\n"
     677                 : #endif
     678                 :       "--MMX\n"
     679                 :       "\tModel a CPU that supports MMX instructions.\n"
     680                 :       "--MOVBE\n"
     681                 :       "\tModel a CPU that supports the movbe instruction.\n"
     682                 :       "--MSR\n"
     683                 :       "\tModel a CPU that supports the rdmsr and wrmsr instructions.\n"
     684                 :       "--POPCNT\n"
     685                 :       "\tModel a CPU that supports the popcnt instruction.\n"
     686                 : #if NACL_TARGET_SUBARCH == 64
     687                 :       "--readwrite_sfi\n"
     688                 :       "\tCheck for memory read and write software fault isolation.\n"
     689                 :       "--segments\n"
     690                 :       "\tAnalyze code in segments in elf file, instead of headers.\n"
     691                 : #endif
     692                 :       "--SSE\n"
     693                 :       "\tModel a CPU that supports SSE instructions.\n"
     694                 :       "--SSE2\n"
     695                 :       "\tModel a CPU that supports SSE 2 instructions.\n"
     696                 :       "--SSE3\n"
     697                 :       "\tModel a CPU that supports SSE 3 instructions.\n"
     698                 :       "--SSSE3\n"
     699                 :       "\tModel a CPU that supports SSSE 3 instructions.\n"
     700                 :       "--SSE41\n"
     701                 :       "\tModel a CPU that supports SSE 4.1 instructions.\n"
     702                 :       "--SSE42\n"
     703                 :       "\tModel a CPU that supports SSE 4.2 instructions.\n"
     704                 :       "--SSE4A\n"
     705                 :       "\tModel a CPU that supports SSE 4A instructions.\n"
     706                 : #if NACL_TARGET_SUBARCH == 32
     707                 :       "--stats\n"
     708                 :       "\tPrint statistics collected by the validator.\n"
     709                 : #endif
     710                 :       "--stubout\n"
     711                 :       "\tRun using stubout mode, replacing bad instructions with halts.\n"
     712                 :       "\tStubbed out disassembly will be printed after validator\n"
     713                 :       "\terror messages. Note: Only applied if --hex_text option is\n"
     714                 :       "\talso specified\n"
     715                 :       "-t\n"
     716                 :       "\tTime the validator and print out results.\n"
     717                 :       "--TSC\n"
     718                 :       "\tModel a CPU that supports the rdtsc instruction.\n"
     719                 :       "--x87\n"
     720                 :       "\tModel a CPU that supports x87 instructions.\n"
     721                 : #if NACL_TARGET_SUBARCH == 64
     722                 :       "--validator_decoder\n"
     723                 :       "\tUse validator (partial) decoder instead of full decoder.\n"
     724                 : #endif
     725                 :       "--VMX\n"
     726                 :       "\tModel a CPU that supports VMX instructions.\n"
     727                 :       "--3DNOW\n"
     728                 :       "\tModel a CPU that supports 3DNOW instructions.\n"
     729                 :       "--E3DNOW\n"
     730                 :       "\tModel a CPU that supports E3DNOW instructions.\n"
     731                 :       "\n"
     732                 :       "--SVM\n"
     733                 :       "\tModel a the CPU supports SVM instrutions.\n"
     734                 :       "--time\n"
     735                 :       "\tTime the validator and print out results. Same as option -t.\n"
     736                 : #if NACL_TARGET_SUBARCH == 64
     737                 :       "--trace_insts\n"
     738                 :       "\tTurn on validator trace of instructions, as processed..\n"
     739                 :       "--trace_verbose\n"
     740                 :       "\tTurn on all trace validator messages. Note: this\n"
     741                 :       "\tflag also implies --trace.\n"
     742                 : #endif
     743                 :       "--warnings\n"
     744                 :       "\tPrint out warnings, errors, and fatal errors, but not\n"
     745                 :       "\tinformative messages.\n"
     746                 : #if NACL_TARGET_SUBARCH == 64
     747                 :       "--write_sfi\n"
     748                 :       "\tOnly check for memory write software fault isolation.\n"
     749                 : #endif
     750                 :       "\n";
     751                 : 
     752               0 : static void usage(int exit_code) {
     753               0 :   printf(usage_str, NACL_TARGET_SUBARCH);
     754               0 :   exit(exit_code);
     755                 : }
     756                 : 
     757                 : /* Checks if arg is one of the expected "Bool" flags, and if so, sets
     758                 :  * the corresponding flag and returns true.
     759                 :  */
     760             359 : static Bool GrokABoolFlag(const char *arg) {
     761                 :   /* A set of boolean flags to be checked */
     762                 :   static struct {
     763                 :     const char *flag_name;
     764                 :     Bool *flag_ptr;
     765                 :   } flags[] = {
     766                 :     { "--segments" , &NACL_FLAGS_analyze_segments },
     767                 : #ifndef NCVAL_TESTING
     768                 :     { "--detailed", &NACL_FLAGS_detailed_errors },
     769                 : #endif
     770                 :     { "--stubout", &NACL_FLAGS_stubout_memory },
     771                 : #if NACL_TARGET_SUBARCH == 64
     772                 :     { "--trace_insts", &NACL_FLAGS_validator_trace_instructions },
     773                 : #endif
     774                 :     { "-t", &NACL_FLAGS_print_timing },
     775                 : #if NACL_TARGET_SUBARCH == 32
     776                 :     { "--stats", &NACL_FLAGS_stats_print },
     777                 : #endif
     778                 :     { "--annotate", &NACL_FLAGS_ncval_annotate },
     779                 : #if NACL_TARGET_SUBARCH == 64
     780                 :     { "--histogram", &NACL_FLAGS_opcode_histogram },
     781                 : #endif
     782                 :     { "--time"   , &NACL_FLAGS_print_timing },
     783                 : #if NACL_TARGET_SUBARCH == 64
     784                 :     { "--warnings", &NACL_FLAGS_warnings },
     785                 :     { "--errors" , &NACL_FLAGS_errors },
     786                 :     { "--fatal"  , &NACL_FLAGS_fatal },
     787                 :     { "--validator_decoder", &NACL_FLAGS_validator_decoder },
     788                 : #endif
     789                 :     { "--identity_mask", &NACL_FLAGS_identity_mask },
     790                 :   };
     791                 : 
     792                 :   /* A set of CPU features to check. */
     793                 :   static struct {
     794                 :     const char *feature_name;
     795                 :     NaClCPUFeatureID feature;
     796                 :   } features[] = {
     797                 :     { "--x87"    , NaClCPUFeature_x87 },
     798                 :     { "--MMX"    , NaClCPUFeature_MMX },
     799                 :     { "--SSE"    , NaClCPUFeature_SSE },
     800                 :     { "--SSE2"   , NaClCPUFeature_SSE2 },
     801                 :     { "--SSE3"   , NaClCPUFeature_SSE3 },
     802                 :     { "--SSSE3"  , NaClCPUFeature_SSSE3 },
     803                 :     { "--SSE41"  , NaClCPUFeature_SSE41 },
     804                 :     { "--SSE42"  , NaClCPUFeature_SSE42 },
     805                 :     { "--MOVBE"  , NaClCPUFeature_MOVBE },
     806                 :     { "--POPCNT" , NaClCPUFeature_POPCNT },
     807                 :     { "--CX8"    , NaClCPUFeature_CX8 },
     808                 :     { "--CX16"   , NaClCPUFeature_CX16 },
     809                 :     { "--CMOV"   , NaClCPUFeature_CMOV },
     810                 :     { "--MON"    , NaClCPUFeature_MON },
     811                 :     { "--FXSR"   , NaClCPUFeature_FXSR },
     812                 :     { "--CLFLUSH", NaClCPUFeature_CLFLUSH },
     813                 :     { "--TSC"    , NaClCPUFeature_TSC },
     814                 :     { "--MSR"    , NaClCPUFeature_MSR },
     815                 :     { "--VME"    , NaClCPUFeature_VME },
     816                 :     { "--PSN"    , NaClCPUFeature_PSN },
     817                 :     { "--VMX"    , NaClCPUFeature_VMX },
     818                 :     { "--3DNOW"  , NaClCPUFeature_3DNOW },
     819                 :     { "--EMMX"   , NaClCPUFeature_EMMX },
     820                 :     { "--E3DNOW" , NaClCPUFeature_E3DNOW },
     821                 :     { "--LZCNT"  , NaClCPUFeature_LZCNT },
     822                 :     { "--SSE4A"  , NaClCPUFeature_SSE4A },
     823                 :     { "--LM"     , NaClCPUFeature_LM },
     824                 :     { "--SVM"    , NaClCPUFeature_SVM },
     825                 :   };
     826                 : 
     827                 :   int i;
     828                 :   Bool flag_state;
     829            2635 :   for (i = 0; i < NACL_ARRAY_SIZE(flags); ++i) {
     830            2379 :     if (GrokBoolFlag(flags[i].flag_name, arg, flags[i].flag_ptr)) {
     831             103 :       return TRUE;
     832                 :     }
     833                 :   }
     834            7424 :   for (i = 0; i < NACL_ARRAY_SIZE(features); ++i) {
     835            7168 :     if (GrokBoolFlag(features[i].feature_name, arg, &flag_state)) {
     836               0 :       NaClSetCPUFeature(&ncval_cpu_features, features[i].feature, flag_state);
     837               0 :       return TRUE;
     838                 :     }
     839                 :   }
     840                 : 
     841             256 :   return FALSE;
     842                 : }
     843                 : 
     844                 : /* Checks if arg is one of the expected "int" flags, and if so, sets
     845                 :  * the corresponding flag and returns true.
     846                 :  */
     847             256 : static Bool GrokAnIntFlag(const char *arg) {
     848                 :   /* A set of boolean flags to be checked */
     849                 :   static struct {
     850                 :     const char *flag_name;
     851                 :     int *flag_ptr;
     852                 :   } flags[] = {
     853                 :     { "--alignment" , &NACL_FLAGS_block_alignment },
     854                 :     { "--max_errors", &NACL_FLAGS_max_reported_errors},
     855                 :     { "--attempts"  , &NACL_FLAGS_validate_attempts },
     856                 :   };
     857                 :   int i;
     858             713 :   for (i = 0; i < NACL_ARRAY_SIZE(flags); ++i) {
     859             582 :     if (GrokIntFlag(flags[i].flag_name, arg, flags[i].flag_ptr)) {
     860             125 :       return TRUE;
     861                 :     }
     862                 :   }
     863             131 :   return FALSE;
     864                 : }
     865                 : 
     866              68 : static int GrokFlags(int argc, const char *argv[]) {
     867                 :   int i;
     868                 :   int new_argc;
     869              68 :   Bool help = FALSE;
     870                 : #if NACL_TARGET_SUBARCH == 64
     871                 :   Bool write_sandbox = !NACL_FLAGS_read_sandbox;
     872                 : #endif
     873              68 :   if (argc == 0) return 0;
     874              68 :   new_argc = 1;
     875             427 :   for (i = 1; i < argc; ++i) {
     876                 :     Bool flag;
     877             359 :     const char *arg = argv[i];
     878             359 :     if (GrokABoolFlag(arg) ||
     879                 :         GrokAnIntFlag(arg) ||
     880                 :         GrokCstringFlag("--hex_text", arg, &NACL_FLAGS_hex_text)) {
     881                 :       /* Valid processed flag, continue to next flag. */
     882              69 :     } else if (GrokBoolFlag("--help", arg, &help)) {
     883               0 :         usage(0);
     884                 : #if NACL_TARGET_SUBARCH == 64
     885                 :     } else if (0 == strcmp("--trace_verbose", arg)) {
     886                 :       NaClValidatorFlagsSetTraceVerbose();
     887                 :     } else if (GrokBoolFlag("--write_sfi", arg, &write_sandbox)) {
     888                 :       NACL_FLAGS_read_sandbox = !write_sandbox;
     889                 :     } else if (GrokBoolFlag("--readwrite_sfi", arg, &NACL_FLAGS_read_sandbox)) {
     890                 :       write_sandbox = !NACL_FLAGS_read_sandbox;
     891                 :       continue;
     892                 : #endif
     893              69 :     } else if (0 == strcmp("--cpuid-all", arg)) {
     894              62 :       NaClSetAllCPUFeatures(&ncval_cpu_features);
     895               7 :     } else if (0 == strcmp("--cpuid-none", arg)) {
     896               1 :       NaClClearCPUFeatures(&ncval_cpu_features);
     897               6 :     } else if (GrokBoolFlag("--local_cpuid", arg, &flag)) {
     898               0 :       NaClGetCurrentCPUFeatures(&ncval_cpu_features);
     899                 :     } else {
     900               6 :       argv[new_argc++] = argv[i];
     901                 :     }
     902                 :   }
     903                 : 
     904                 :   /* Before returning, update internals to match command line
     905                 :    * values found.
     906                 :    */
     907              68 :   if (NACL_FLAGS_warnings) {
     908               0 :     NaClLogSetVerbosity(LOG_WARNING);
     909                 :   }
     910              68 :   if (NACL_FLAGS_errors) {
     911               0 :     NaClLogSetVerbosity(LOG_ERROR);
     912                 :   }
     913              68 :   if (NACL_FLAGS_fatal) {
     914               0 :     NaClLogSetVerbosity(LOG_FATAL);
     915                 :   }
     916              68 :   NCValidatorSetMaxDiagnostics(NACL_FLAGS_max_reported_errors);
     917              68 :   if (NACL_FLAGS_stubout_memory && (NACL_FLAGS_validate_attempts != 1)) {
     918               0 :     fprintf(stderr, "Can't specify --stubout when --attempts!=1\n");
     919                 :   }
     920                 : 
     921              68 :   return new_argc;
     922                 : }
     923                 : 
     924                 : /* Decode and print out code segment if stubout memory is specified
     925                 :  * command line.
     926                 :  */
     927                 : static void NaClMaybeDecodeDataSegment(
     928              62 :     uint8_t *mbase, NaClPcAddress vbase, NaClMemorySize size) {
     929              62 :   if (NACL_FLAGS_stubout_memory) {
     930                 :     /* Disassemble data segment to see how halts were inserted.
     931                 :      * Note: We use the full decoder (rather than the validator decoder)
     932                 :      * because the validator decoders are partial decodings, and can be
     933                 :      * confusing to the reader.
     934                 :      */
     935               0 :     NaClDisassembleSegment(mbase, vbase, size,
     936                 :                            NACL_DISASSEMBLE_FLAG(NaClDisassembleFull));
     937                 :   }
     938              62 : }
     939                 : 
     940              68 : int main(int argc, const char *argv[]) {
     941              68 :   int result = 0;
     942                 :   struct GioFile gio_out_stream;
     943              68 :   struct Gio *gout = (struct Gio*) &gio_out_stream;
     944                 : 
     945              68 :   if (argc < 2) {
     946               0 :     fprintf(stderr, "expected: %s file\n", argv[0]);
     947               0 :     usage(1);
     948                 :   }
     949                 : 
     950                 :   /* Set up logging. */
     951              68 :   if (!GioFileRefCtor(&gio_out_stream, stdout)) {
     952               0 :     fprintf(stderr, "Unable to create gio file for stdout!\n");
     953               0 :     return 1;
     954                 :   }
     955              68 :   NaClLogModuleInitExtended(LOG_INFO, gout);
     956              68 :   NaClLogDisableTimestamp();
     957                 : 
     958                 :   /* By default, assume no local cpu features are available. */
     959              68 :   NaClClearCPUFeatures(&ncval_cpu_features);
     960                 : 
     961                 :   /* Validate the specified input. */
     962              68 :   argc = GrokFlags(argc, argv);
     963              68 :   if (0 == strcmp(NACL_FLAGS_hex_text, "")) {
     964                 :     /* Run validator on elf file. */
     965                 :     ValidateData data;
     966                 :     Bool success = NaClRunValidator(
     967                 :         argc, argv, &data,
     968                 :         (NaClValidateLoad) ValidateElfLoad,
     969               6 :         (NaClValidateAnalyze) ValidateAnalyze);
     970               6 :     NaClReportSafety(success, argv[1]);
     971               6 :     result = (success ? 0 : 1);
     972                 :   } else {
     973                 :     /* Run validator on hex text file. */
     974                 :     NaClValidatorByteArray data;
     975              62 :     argc = ValidateHexLoad(argc, argv, &data);
     976              62 :     NaClRunValidatorBytes(
     977                 :         argc, argv, (uint8_t*) &data.bytes,
     978                 :         data.num_bytes, data.base);
     979              62 :     NaClMaybeDecodeDataSegment(&data.bytes[0], data.base, data.num_bytes);
     980                 :     /* always succeed, so that the testing framework works. */
     981              62 :     result = 0;
     982                 :   }
     983                 : 
     984              68 :   NaClLogModuleFini();
     985              68 :   GioFileDtor(gout);
     986              68 :   return result;
     987                 : }

Generated by: LCOV version 1.7