| Index: src/trusted/validator_mips/ncval.cc | 
| diff --git a/src/trusted/validator_mips/ncval.cc b/src/trusted/validator_mips/ncval.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..82eb92c99d19371b83c2d7f09faaafbbe132b2c1 | 
| --- /dev/null | 
| +++ b/src/trusted/validator_mips/ncval.cc | 
| @@ -0,0 +1,121 @@ | 
| +/* | 
| + * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 
| + * Use of this source code is governed by a BSD-style license that can be | 
| + * found in the LICENSE file. | 
| + */ | 
| + | 
| +#include <stdio.h> | 
| +#include <errno.h> | 
| +#include <string.h> | 
| + | 
| +#include <string> | 
| +#include <vector> | 
| +#include <algorithm> | 
| + | 
| +#include "native_client/src/include/nacl_string.h" | 
| +#include "native_client/src/trusted/validator/ncfileutil.h" | 
| +#include "native_client/src/trusted/validator_mips/model.h" | 
| +#include "native_client/src/trusted/validator_mips/validator.h" | 
| + | 
| +using nacl_mips_val::SfiValidator; | 
| +using nacl_mips_val::CodeSegment; | 
| + | 
| +using std::string; | 
| +using std::vector; | 
| + | 
| +/* | 
| + * Reports problems in an easily-parsed textual format, for consumption by a | 
| + * validation-reporting script. | 
| + * | 
| + * The format is as follows: | 
| + *   ncval: <hex vaddr> <decimal safety> <problem ID string> <hex ref vaddr> | 
| + * | 
| + * For possible safety levels, see inst_classes.h. | 
| + * | 
| + * For possible problem ID strings, see validator.h. | 
| + */ | 
| +class CommandLineProblemSink : public nacl_mips_val::ProblemSink { | 
| + public: | 
| +  virtual void ReportProblem(uint32_t vaddr, | 
| +                             nacl_mips_dec::SafetyLevel safety, | 
| +                             const nacl::string &problem_code, | 
| +                             uint32_t ref_vaddr) { | 
| +    fprintf(stderr, "ncval: %08X %d %s %08X\n", vaddr, safety, | 
| +        problem_code.c_str(), ref_vaddr); | 
| +  } | 
| +  virtual bool ShouldContinue() { | 
| +    // Collect *all* problems before returning! | 
| +    return true; | 
| +  } | 
| +}; | 
| + | 
| +const uint32_t kOneGig = 1U * 1024 * 1024 * 1024; | 
| +const uint32_t kQuarterGig = 256U * 1024 * 1024; | 
| + | 
| +int Validate(const ncfile *ncf, bool use_zero_masks) { | 
| +  SfiValidator validator( | 
| +      16,                                // Bytes per bundle. | 
| +      kQuarterGig,                       // Code region size. | 
| +      kOneGig,                           // Data region size. | 
| +      nacl_mips_dec::kRegListReserved,   // Read only registers. | 
| +      nacl_mips_dec::kRegisterStack);    // Data addressing register ($sp). | 
| + | 
| +  if (use_zero_masks) { | 
| +    validator.ChangeMasks(0, 0); | 
| +  } | 
| + | 
| +  CommandLineProblemSink sink; | 
| + | 
| +  Elf_Shdr *shdr = ncf->sheaders; | 
| + | 
| +  vector<CodeSegment> segments; | 
| +  for (int i = 0; i < ncf->shnum; i++) { | 
| +    if ((shdr[i].sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR) { | 
| +      continue; | 
| +    } | 
| + | 
| +    CodeSegment segment(ncf->data + (shdr[i].sh_addr - ncf->vbase), | 
| +        shdr[i].sh_addr, shdr[i].sh_size); | 
| +    segments.push_back(segment); | 
| +  } | 
| + | 
| +  std::sort(segments.begin(), segments.end()); | 
| + | 
| +  bool success = validator.Validate(segments, &sink); | 
| +  if (!success) return 1; | 
| +  return 0; | 
| +} | 
| + | 
| +int main(int argc, const char *argv[]) { | 
| +  bool use_zero_masks = false; | 
| +  const char *filename = NULL; | 
| + | 
| +  for (int i = 1; i < argc; ++i) { | 
| +    string o = argv[i]; | 
| +    if (o == "--zero-masks") { | 
| +      use_zero_masks = true; | 
| +    } else { | 
| +      if (filename != NULL) { | 
| +        // trigger error when filename is overwritten | 
| +        filename = NULL; | 
| +        break; | 
| +      } | 
| +      filename = argv[i]; | 
| +    } | 
| +  } | 
| + | 
| +  if (NULL == filename) { | 
| +    fprintf(stderr, "Usage: %s [--zero-masks] <filename>\n", argv[0]); | 
| +    return 2; | 
| +  } | 
| + | 
| +  ncfile *ncf = nc_loadfile(filename); | 
| +  if (!ncf) { | 
| +    fprintf(stderr, "Unable to load %s: %s\n", filename, strerror(errno)); | 
| +    return 1; | 
| +  } | 
| + | 
| +  int exit_code = Validate(ncf, use_zero_masks); | 
| +  nc_freefile(ncf); | 
| +  return exit_code; | 
| +} | 
|  |