OLD | NEW |
(Empty) | |
| 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 #include <stdio.h> |
| 8 #include <errno.h> |
| 9 #include <string.h> |
| 10 |
| 11 #include <string> |
| 12 #include <vector> |
| 13 #include <algorithm> |
| 14 |
| 15 #include "native_client/src/include/nacl_string.h" |
| 16 #include "native_client/src/trusted/validator/ncfileutil.h" |
| 17 #include "native_client/src/trusted/validator_mips/model.h" |
| 18 #include "native_client/src/trusted/validator_mips/validator.h" |
| 19 |
| 20 using nacl_mips_val::SfiValidator; |
| 21 using nacl_mips_val::CodeSegment; |
| 22 |
| 23 using std::string; |
| 24 using std::vector; |
| 25 |
| 26 /* |
| 27 * Reports problems in an easily-parsed textual format, for consumption by a |
| 28 * validation-reporting script. |
| 29 * |
| 30 * The format is as follows: |
| 31 * ncval: <hex vaddr> <decimal safety> <problem ID string> <hex ref vaddr> |
| 32 * |
| 33 * For possible safety levels, see inst_classes.h. |
| 34 * |
| 35 * For possible problem ID strings, see validator.h. |
| 36 */ |
| 37 class CommandLineProblemSink : public nacl_mips_val::ProblemSink { |
| 38 public: |
| 39 virtual void ReportProblem(uint32_t vaddr, |
| 40 nacl_mips_dec::SafetyLevel safety, |
| 41 const nacl::string &problem_code, |
| 42 uint32_t ref_vaddr) { |
| 43 fprintf(stderr, "ncval: %08X %d %s %08X\n", vaddr, safety, |
| 44 problem_code.c_str(), ref_vaddr); |
| 45 } |
| 46 virtual bool ShouldContinue() { |
| 47 // Collect *all* problems before returning! |
| 48 return true; |
| 49 } |
| 50 }; |
| 51 |
| 52 const uint32_t kOneGig = 1U * 1024 * 1024 * 1024; |
| 53 const uint32_t kQuarterGig = 256U * 1024 * 1024; |
| 54 |
| 55 int Validate(const ncfile *ncf, bool use_zero_masks) { |
| 56 SfiValidator validator( |
| 57 16, // Bytes per bundle. |
| 58 kQuarterGig, // Code region size. |
| 59 kOneGig, // Data region size. |
| 60 nacl_mips_dec::kRegListReserved, // Read only registers. |
| 61 nacl_mips_dec::kRegisterStack); // Data addressing register ($sp). |
| 62 |
| 63 if (use_zero_masks) { |
| 64 validator.ChangeMasks(0, 0); |
| 65 } |
| 66 |
| 67 CommandLineProblemSink sink; |
| 68 |
| 69 Elf_Shdr *shdr = ncf->sheaders; |
| 70 |
| 71 vector<CodeSegment> segments; |
| 72 for (int i = 0; i < ncf->shnum; i++) { |
| 73 if ((shdr[i].sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR) { |
| 74 continue; |
| 75 } |
| 76 |
| 77 CodeSegment segment(ncf->data + (shdr[i].sh_addr - ncf->vbase), |
| 78 shdr[i].sh_addr, shdr[i].sh_size); |
| 79 segments.push_back(segment); |
| 80 } |
| 81 |
| 82 std::sort(segments.begin(), segments.end()); |
| 83 |
| 84 bool success = validator.Validate(segments, &sink); |
| 85 if (!success) return 1; |
| 86 return 0; |
| 87 } |
| 88 |
| 89 int main(int argc, const char *argv[]) { |
| 90 bool use_zero_masks = false; |
| 91 const char *filename = NULL; |
| 92 |
| 93 for (int i = 1; i < argc; ++i) { |
| 94 string o = argv[i]; |
| 95 if (o == "--zero-masks") { |
| 96 use_zero_masks = true; |
| 97 } else { |
| 98 if (filename != NULL) { |
| 99 // trigger error when filename is overwritten |
| 100 filename = NULL; |
| 101 break; |
| 102 } |
| 103 filename = argv[i]; |
| 104 } |
| 105 } |
| 106 |
| 107 if (NULL == filename) { |
| 108 fprintf(stderr, "Usage: %s [--zero-masks] <filename>\n", argv[0]); |
| 109 return 2; |
| 110 } |
| 111 |
| 112 ncfile *ncf = nc_loadfile(filename); |
| 113 if (!ncf) { |
| 114 fprintf(stderr, "Unable to load %s: %s\n", filename, strerror(errno)); |
| 115 return 1; |
| 116 } |
| 117 |
| 118 int exit_code = Validate(ncf, use_zero_masks); |
| 119 nc_freefile(ncf); |
| 120 return exit_code; |
| 121 } |
OLD | NEW |