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.
36 #include "native_client/include/portability.h"
44 #include "native_client/include/nacl_elf.h"
45 #include <sys/timeb.h>
47 #include "ncfileutil.h"
48 #include "ncvalidate.h"
49 #include "ncvalidate_internaltypes.h"
52 static const char *progname
;
56 #define vprint(args) printf args
62 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
63 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
65 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
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
)) {
75 tv
->tv_sec
= time_info
.time
;
76 /* translate from milli to micro seconds */
77 tv
->tv_usec
= time_info
.millitm
* 1000;
86 void fatal(const char *fmt
, ...)
89 fprintf(stderr
, "%s: fatal error: ", progname
);
91 vfprintf(stderr
, fmt
, ap
);
97 int AnalyzeSections(ncfile
*ncf
, struct NCValidatorState
*vstate
) {
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
)))
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
);
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
));
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
,
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
;
167 if (loadname
== NULL
) {
168 extern void ncvalidate_unittests();
170 printf("no arguments given; running unit tests\n");
171 ncvalidate_unittests();
175 gettimeofday(&time0
, NULL
);
176 ncf
= nc_loadfile(loadname
);
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
);