Merge branch 'upstream'
[nativeclient.git] / ncv / ncval.c
blobbe6970006f0e51d62cf4b47e6ca2e8efeeb0b007
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 "native_client/include/portability.h"
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include "native_client/include/nacl_elf.h"
45 #include <sys/timeb.h>
46 #include <time.h>
47 #include "ncfileutil.h"
48 #include "ncvalidate.h"
49 #include "ncvalidate_internaltypes.h"
50 #include "ncdecode.h"
52 static const char *progname;
54 #define VERBOSE 1
55 #if VERBOSE
56 #define vprint(args) printf args
57 #else
58 #define vprint(args)
59 #endif
61 #if NACL_WINDOWS
62 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
63 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
64 #else
65 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
66 #endif
68 static int gettimeofday(struct timeval *tv, struct timezone *tz)
70 struct __timeb32 time_info;
72 if (NULL == tv) return -EFAULT;
73 if (!_ftime32_s(&time_info)) {
74 /* got the time */
75 tv->tv_sec = time_info.time;
76 /* translate from milli to micro seconds */
77 tv->tv_usec = time_info.millitm * 1000;
78 } else {
79 return -EINVAL;
81 return 0;
83 #endif
86 void fatal(const char *fmt, ...)
88 va_list ap;
89 fprintf(stderr, "%s: fatal error: ", progname);
90 va_start(ap, fmt);
91 vfprintf(stderr, fmt, ap);
92 va_end(ap);
93 fputc('\n', stderr);
94 exit(2);
97 int AnalyzeSections(ncfile *ncf, struct NCValidatorState *vstate) {
98 int badsections = 0;
99 int ii;
100 Elf32_Phdr *phdr = ncf->pheaders;
102 for (ii = 0; ii < ncf->phnum; ii++) {
103 vprint(("segment[%d] p_type %d p_offset %x vaddr %x paddr %x align %u\n",
104 ii, phdr[ii].p_type, (uint32_t)phdr[ii].p_offset,
105 (uint32_t)phdr[ii].p_vaddr, (uint32_t)phdr[ii].p_paddr,
106 (uint32_t)phdr[ii].p_align));
107 vprint((" filesz %x memsz %x flags %x\n",
108 phdr[ii].p_filesz, (uint32_t)phdr[ii].p_memsz,
109 (uint32_t)phdr[ii].p_flags));
110 if ((PT_LOAD != phdr[ii].p_type) ||
111 (0 == (phdr[ii].p_flags & PF_X)))
112 continue;
113 vprint(("parsing segment %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 vstate->file_offset = phdr[ii].p_offset - phdr[ii].p_vaddr;
118 NCDecodeSegment(ncf->data + (phdr[ii].p_vaddr - ncf->vbase),
119 phdr[ii].p_vaddr, phdr[ii].p_memsz, vstate);
121 return -badsections;
125 static void AnalyzeCodeSegments(ncfile *ncf, const char *fname) {
126 uint32_t vbase, vlimit;
127 struct NCValidatorState *vstate;
129 GetVBaseAndLimit(ncf, &vbase, &vlimit);
130 vstate = NCValidateInit(vbase, vlimit, ncf->ncalign);
131 if (AnalyzeSections(ncf, vstate) < 0) {
132 fprintf(stderr, "%s: text validate failed\n", fname);
134 if (NCValidateFinish(vstate) != 0) {
135 vprint(("***MODULE %s IS UNSAFE***\n", fname));
136 } else {
137 vprint(("***module %s is safe***\n", fname));
139 Stats_Print(stdout, vstate);
140 NCValidateFreeState(&vstate);
141 vprint(("Validated %s\n", fname));
144 double timeval2double(const struct timeval *tv) {
145 return ((double)tv->tv_sec + ((double)tv->tv_usec)/1000000);
148 void PrintTimes(FILE *f, const char *fname,
149 struct timeval *t0,
150 struct timeval *t1,
151 struct timeval *t2) {
152 double dt0, dt1, dt2;
153 dt0 = timeval2double(t0);
154 dt1 = timeval2double(t1);
155 dt2 = timeval2double(t2);
157 fprintf(f, "%s: %0.6f %0.6f\n", fname, dt1 - dt0, dt2 - dt1);
160 int main(int argc, const char *argv[])
162 const char *loadname = argv[1];
163 struct timeval time0, timel, timev;
164 ncfile *ncf;
166 progname = argv[0];
167 if (loadname == NULL) {
168 extern void ncvalidate_unittests();
170 printf("no arguments given; running unit tests\n");
171 ncvalidate_unittests();
172 return 0;
175 gettimeofday(&time0, NULL);
176 ncf = nc_loadfile(loadname);
177 if (ncf == NULL)
178 fatal("nc_loadfile(%s): %s\n", loadname, strerror(errno));
180 gettimeofday(&timel, NULL);
181 AnalyzeCodeSegments(ncf, loadname);
182 gettimeofday(&timev, NULL);
184 PrintTimes(stderr, loadname, &time0, &timel, &timev);
186 nc_freefile(ncf);
188 return 0;