2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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.
45 #include "native_client/include/nacl_elf.h"
49 #include <sys/timeb.h>
51 #include "ncfileutil.h"
52 #include "ncvalidate.h"
53 #include "ncvalidate_internaltypes.h"
56 static const char *progname
;
60 #define vprint(args) printf args
66 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
67 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
69 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
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
)) {
79 tv
->tv_sec
= time_info
.time
;
80 /* translate from milli to micro seconds */
81 tv
->tv_usec
= time_info
.millitm
* 1000;
92 void fatal(const char *fmt
, ...)
95 fprintf(stderr
, "%s: fatal error: ", progname
);
97 vfprintf(stderr
, fmt
, ap
);
103 int AnalyzeSections(ncfile
*ncf
, struct NCValidatorState
*vstate
) {
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
)))
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
);
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
));
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
,
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
;
173 if (loadname
== NULL
) {
174 extern void ncvalidate_unittests();
176 printf("no arguments given; running unit tests\n");
177 ncvalidate_unittests();
181 gettimeofday(&time0
, NULL
);
182 ncf
= nc_loadfile(loadname
);
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
);