| 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;
 | 
| +}
 | 
| 
 |