Allocate sandbox address space at 0x10000000
[nativeclient.git] / ncv / ncval.c
blobe7954754bfd37206c9b96954e3783bef44f7154a
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * ncval.c - command line validator for NaCl.
34 * Mostly for testing.
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #if !NACL_WINDOWS
41 #include <unistd.h>
42 #endif
43 #include <errno.h>
44 #include <fcntl.h>
45 #include "native_client/include/nacl_elf.h"
46 #if !NACL_WINDOWS
47 #include <sys/time.h>
48 #endif
49 #include <sys/timeb.h>
50 #include <time.h>
51 #include "ncfileutil.h"
52 #include "ncvalidate.h"
53 #include "ncdecode.h"
55 static const char *progname;
57 #define VERBOSE 1
58 #if VERBOSE
59 #define vprint(args) printf args
60 #else
61 #define vprint(args)
62 #endif
64 #if NACL_WINDOWS
65 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
66 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
67 #else
68 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
69 #endif
71 static int gettimeofday(struct timeval *tv, struct timezone *tz)
73 struct __timeb32 time_info;
75 if (NULL == tv) return -EFAULT;
76 if (!_ftime32_s(&time_info)) {
77 /* got the time */
78 tv->tv_sec = time_info.time;
79 /* translate from milli to micro seconds */
80 tv->tv_usec = time_info.millitm * 1000;
81 } else {
82 return -EINVAL;
84 return 0;
86 #else
87 #define INLINE inline
88 #endif
91 void fatal(const char *fmt, ...)
93 va_list ap;
94 fprintf(stderr, "%s: fatal error: ", progname);
95 va_start(ap, fmt);
96 vfprintf(stderr, fmt, ap);
97 va_end(ap);
98 fputc('\n', stderr);
99 exit(2);
102 int AnalyzeSections(ncfile *ncf, struct NCValidatorState *vstate) {
103 int badsections = 0;
104 int ii;
105 Elf32_Shdr *shdr = ncf->sheaders;
107 for (ii = 0; ii < ncf->shnum; ii++) {
108 vprint(("section %d sh_addr %x offset %x flags %x\n",
109 ii, (uint32_t)shdr[ii].sh_addr,
110 (uint32_t)shdr[ii].sh_offset, (uint32_t)shdr[ii].sh_flags));
111 if ((shdr[ii].sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR)
112 continue;
113 vprint(("parsing section %d\n", ii));
114 /* note we use NCDecodeSegment instead of NCValidateSegment */
115 /* because we don't want the check for a hlt at the end of */
116 /* the text segment as required by NaCl. */
117 NCDecodeSegment(ncf->data + (shdr[ii].sh_addr - ncf->vbase),
118 shdr[ii].sh_addr, shdr[ii].sh_size, vstate);
120 return -badsections;
124 static void AnalyzeCodeSegments(ncfile *ncf, const char *fname) {
125 uint32_t vbase, vlimit;
126 struct NCValidatorState *vstate;
128 GetVBaseAndLimit(ncf, &vbase, &vlimit);
129 vstate = NCValidateInit(vbase, vlimit, ncf->ncalign);
130 if (AnalyzeSections(ncf, vstate) < 0) {
131 fprintf(stderr, "%s: text validate failed\n", fname);
133 if (NCValidateFinish(vstate) != 0) {
134 vprint(("***MODULE %s IS UNSAFE***\n", fname));
135 } else {
136 vprint(("***module %s is safe***\n", fname));
138 Stats_Print(stdout, vstate);
139 NCValidateFreeState(&vstate);
140 vprint(("Validated %s\n", fname));
143 INLINE double timeval2double(const struct timeval *tv) {
144 return ((double)tv->tv_sec + ((double)tv->tv_usec)/1000000);
147 void PrintTimes(FILE *f, const char *fname,
148 struct timeval *t0,
149 struct timeval *t1,
150 struct timeval *t2) {
151 double dt0, dt1, dt2;
152 dt0 = timeval2double(t0);
153 dt1 = timeval2double(t1);
154 dt2 = timeval2double(t2);
156 fprintf(f, "%s: %0.6f %0.6f\n", fname, dt1 - dt0, dt2 - dt1);
159 int main(int argc, const char *argv[])
161 const char *loadname = argv[1];
162 struct timeval time0, timel, timev;
163 ncfile *ncf;
165 progname = argv[0];
166 if (loadname == NULL) {
167 extern void ncvalidate_unittests();
169 printf("no arguments given; running unit tests\n");
170 ncvalidate_unittests();
171 return 0;
174 gettimeofday(&time0, NULL);
175 ncf = nc_loadfile(loadname);
176 if (ncf == NULL)
177 fatal("nc_loadfile(%s): %s\n", loadname, strerror(errno));
179 gettimeofday(&timel, NULL);
180 AnalyzeCodeSegments(ncf, loadname);
181 gettimeofday(&timev, NULL);
183 PrintTimes(stderr, loadname, &time0, &timel, &timev);
185 nc_freefile(ncf);
187 return 0;