Remove check for ABIVERSION, so that I don't have to rebuild binutils when this is...
[nativeclient.git] / ncv / ncval.c
blobf56fcf2149aac78876255841480b29c34801ac63
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 "ncvalidate_internaltypes.h"
54 #include "ncdecode.h"
56 static const char *progname;
58 #define VERBOSE 1
59 #if VERBOSE
60 #define vprint(args) printf args
61 #else
62 #define vprint(args)
63 #endif
65 #if NACL_WINDOWS
66 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
67 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
68 #else
69 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
70 #endif
72 static int gettimeofday(struct timeval *tv, struct timezone *tz)
74 struct __timeb32 time_info;
76 if (NULL == tv) return -EFAULT;
77 if (!_ftime32_s(&time_info)) {
78 /* got the time */
79 tv->tv_sec = time_info.time;
80 /* translate from milli to micro seconds */
81 tv->tv_usec = time_info.millitm * 1000;
82 } else {
83 return -EINVAL;
85 return 0;
87 #else
88 #define INLINE inline
89 #endif
92 void fatal(const char *fmt, ...)
94 va_list ap;
95 fprintf(stderr, "%s: fatal error: ", progname);
96 va_start(ap, fmt);
97 vfprintf(stderr, fmt, ap);
98 va_end(ap);
99 fputc('\n', stderr);
100 exit(2);
103 int AnalyzeSections(ncfile *ncf, struct NCValidatorState *vstate) {
104 int badsections = 0;
105 int ii;
106 Elf32_Phdr *phdr = ncf->pheaders;
108 for (ii = 0; ii < ncf->phnum; ii++) {
109 vprint(("segment[%d] p_type %d p_offset %x vaddr %x paddr %x align %u\n",
110 ii, phdr[ii].p_type, (uint32_t)phdr[ii].p_offset,
111 (uint32_t)phdr[ii].p_vaddr, (uint32_t)phdr[ii].p_paddr,
112 (uint32_t)phdr[ii].p_align));
113 vprint((" filesz %x memsz %x flags %x\n",
114 phdr[ii].p_filesz, (uint32_t)phdr[ii].p_memsz,
115 (uint32_t)phdr[ii].p_flags));
116 if ((PT_LOAD != phdr[ii].p_type) ||
117 (0 == (phdr[ii].p_flags & PF_X)))
118 continue;
119 vprint(("parsing segment %d\n", ii));
120 /* note we use NCDecodeSegment instead of NCValidateSegment */
121 /* because we don't want the check for a hlt at the end of */
122 /* the text segment as required by NaCl. */
123 vstate->file_offset = phdr[ii].p_offset - phdr[ii].p_vaddr;
124 NCDecodeSegment(ncf->data + (phdr[ii].p_vaddr - ncf->vbase),
125 phdr[ii].p_vaddr, phdr[ii].p_memsz, vstate);
127 return -badsections;
131 static void AnalyzeCodeSegments(ncfile *ncf, const char *fname) {
132 uint32_t vbase, vlimit;
133 struct NCValidatorState *vstate;
135 GetVBaseAndLimit(ncf, &vbase, &vlimit);
136 vstate = NCValidateInit(vbase, vlimit, ncf->ncalign);
137 if (AnalyzeSections(ncf, vstate) < 0) {
138 fprintf(stderr, "%s: text validate failed\n", fname);
140 if (NCValidateFinish(vstate) != 0) {
141 vprint(("***MODULE %s IS UNSAFE***\n", fname));
142 } else {
143 vprint(("***module %s is safe***\n", fname));
145 Stats_Print(stdout, vstate);
146 NCValidateFreeState(&vstate);
147 vprint(("Validated %s\n", fname));
150 INLINE double timeval2double(const struct timeval *tv) {
151 return ((double)tv->tv_sec + ((double)tv->tv_usec)/1000000);
154 void PrintTimes(FILE *f, const char *fname,
155 struct timeval *t0,
156 struct timeval *t1,
157 struct timeval *t2) {
158 double dt0, dt1, dt2;
159 dt0 = timeval2double(t0);
160 dt1 = timeval2double(t1);
161 dt2 = timeval2double(t2);
163 fprintf(f, "%s: %0.6f %0.6f\n", fname, dt1 - dt0, dt2 - dt1);
166 int main(int argc, const char *argv[])
168 const char *loadname = argv[1];
169 struct timeval time0, timel, timev;
170 ncfile *ncf;
172 progname = argv[0];
173 if (loadname == NULL) {
174 extern void ncvalidate_unittests();
176 printf("no arguments given; running unit tests\n");
177 ncvalidate_unittests();
178 return 0;
181 gettimeofday(&time0, NULL);
182 ncf = nc_loadfile(loadname);
183 if (ncf == NULL)
184 fatal("nc_loadfile(%s): %s\n", loadname, strerror(errno));
186 gettimeofday(&timel, NULL);
187 AnalyzeCodeSegments(ncf, loadname);
188 gettimeofday(&timev, NULL);
190 PrintTimes(stderr, loadname, &time0, &timel, &timev);
192 nc_freefile(ncf);
194 return 0;