sel_ldr: Remove support for rodata segment at start of executable
[nativeclient.git] / service_runtime / sel_universal.c
blobf376b56159198e0fd5aa422427da45bf0b50a452
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 * NaCl testing shell
36 #include "native_client/include/portability.h"
37 #include "native_client/intermodule_comm/nacl_imc_c.h"
38 #include "native_client/nonnacl_util/sel_ldr_launcher_c.h"
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <sys/types.h>
44 #include <signal.h>
46 #if NACL_WINDOWS
47 #include <process.h>
48 static int gettimeofday(struct timeval *tv, struct timezone *tz);
49 #else
50 #include <sys/time.h>
51 #include <sys/wait.h>
52 #include <unistd.h>
53 #endif
55 #include "native_client/service_runtime/nacl_check.h"
56 #include "native_client/tools/libsrpc/nacl_srpc.h"
58 #define MAX_ARRAY_SIZE 4096
59 #define MAX_COMMAND_LINE_ARGS 256
60 #define SEL_LDR_CMD_LINE_EXEC_POS 4
62 #if NACL_WINDOWS
63 static char* kSelLdrPathname = "/usr/local/nacl-sdk/nacl/bin/sel_ldr.exe";
64 #else
65 static char* kSelLdrPathname = "/usr/local/nacl-sdk/nacl/bin/sel_ldr";
66 #endif
68 static char* g_sel_ldr_pathname;
70 static int timed_rpc_count;
71 static uint32_t timed_rpc_method = 1;
72 static int timed_rpc_bytes = 4000;
74 void blackhole(char *s, ...) {}
75 /* #define DEBUG printf */
76 #define DEBUG blackhole
78 /* simple destructive tokenizer */
79 typedef struct {
80 const char* start;
81 int length;
82 } TOKEN;
84 /* expects *from to point to leading \" and returns pointer to trailing \" */
85 const char* ScanEscapeString(char* to, const char* from) {
86 CHECK(*from == '\"');
87 from++;
88 while (*from) {
89 if (*from == '\"') {
90 if (to) *to = '\0';
91 return from;
92 }else if (*from != '\\') {
93 if (to) *to++ = *from;
94 from++;
95 } else {
96 char next = *from++;
97 switch(next) {
98 case '\0':
99 return 0;
100 case '\\':
101 case '\"':
102 if (to) *to++ = next;
103 break;
104 case 'n':
105 if (to) *to++ = '\n';
106 break;
107 default:
108 return 0;
112 return 0;
115 int Tokenize(char* line, TOKEN *array, int n) {
116 int pos_start = 0;
117 int count = 0;
119 for( ; count < n; count++ ) {
120 int pos_end;
122 /* skip leading white space */
123 while (line[pos_start]) {
124 const char c = line[pos_start];
125 if (isspace(c)) {
126 pos_start++;
127 } else {
128 break;
132 if (!line[pos_start]) break;
134 /* find token end from current pos_start */
135 pos_end = pos_start;
137 while (line[pos_end]) {
138 const char c = line[pos_end];
140 if (isspace(c)) {
141 break;
142 } else if (c == '\"') {
143 const char* end = ScanEscapeString(0, &line[pos_end]);
144 if (!end) return -1;
145 pos_end = end - &line[0];
147 pos_end++;
150 /* save the token */
151 array[count].start = &line[pos_start];
152 array[count].length = pos_end - pos_start;
154 if (line[pos_end]) {
155 line[pos_end] = '\0'; /* DESTRUCTION!!! */
156 pos_end++;
158 pos_start = pos_end;
159 /* printf("TOKEN %s\n", array[count].start); */
162 return count;
165 /* NOTE: This is leaking memory left and right */
166 int ParseArg(NaClSrpcArg* arg, const char* token) {
167 long val;
168 int dim;
169 const char* comma;
170 int i;
172 DEBUG("TOKEN %s\n", token);
173 CHECK(token[1] == '(');
175 /* TODO: All the array versions leak memory. Fix them. */
176 switch (token[0]) {
177 case NACL_SRPC_ARG_TYPE_INVALID:
178 arg->tag = NACL_SRPC_ARG_TYPE_INVALID;
179 break;
180 case NACL_SRPC_ARG_TYPE_BOOL:
181 val = strtol(&token[2], 0, 0);
182 arg->tag = NACL_SRPC_ARG_TYPE_BOOL;
183 arg->u.bval = val;
184 break;
185 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
186 dim = strtol(&token[2], 0, 0);
187 arg->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
188 arg->u.caval.carr = (char*) calloc(dim, sizeof(char));
189 arg->u.caval.count = dim;
190 comma = strstr(token, ",");
191 if (comma) {
192 const char* p;
193 for (p = comma+1, i = 0; *p != ')' && i < dim; ++p, ++i)
194 arg->u.caval.carr[i] = *p;
196 break;
197 case NACL_SRPC_ARG_TYPE_DOUBLE:
198 arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE;
199 arg->u.dval = strtod(&token[2], 0);
200 break;
201 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
202 dim = strtol(&token[2], 0, 0);
203 arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY;
204 arg->u.daval.darr = (double*) calloc(dim, sizeof(double));
205 CHECK(arg->u.daval.darr);
206 arg->u.daval.count = dim;
207 comma = token;
208 for (i = 0; i < dim; ++i) {
209 comma = strstr(comma, ",");
210 if (!comma) break;
211 ++comma;
212 arg->u.daval.darr[i] = strtod(comma, 0);
214 break;
215 case NACL_SRPC_ARG_TYPE_HANDLE:
216 val = strtol(&token[2], 0, 0);
217 arg->tag = NACL_SRPC_ARG_TYPE_HANDLE;
218 arg->u.hval = (void *)val;
219 break;
220 case NACL_SRPC_ARG_TYPE_INT:
221 val = strtol(&token[2], 0, 0);
222 arg->tag = NACL_SRPC_ARG_TYPE_INT;
223 arg->u.ival = val;
224 break;
225 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
226 dim = strtol(&token[2], 0, 0);
227 arg->tag = NACL_SRPC_ARG_TYPE_INT_ARRAY;
228 /* LEAK */
229 arg->u.iaval.iarr = (int*) calloc(dim, sizeof(int));
230 CHECK(arg->u.iaval.iarr);
231 arg->u.iaval.count = dim;
232 comma = token;
233 for (i = 0; i < dim; ++i) {
234 comma = strstr(comma, ",");
235 if (!comma) break;
236 ++comma;
237 arg->u.iaval.iarr[i] = strtol(comma, 0, 0);
239 break;
240 case NACL_SRPC_ARG_TYPE_STRING:
241 arg->tag = NACL_SRPC_ARG_TYPE_STRING;
242 /* this is a conservative estimate */
243 arg->u.sval = malloc(strlen(token));
244 ScanEscapeString(arg->u.sval, token + 2);
245 break;
247 * The two cases below are added to avoid warnings, they are only used
248 * in the plugin code
250 case NACL_SRPC_ARG_TYPE_OBJECT:
251 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
252 default:
253 return -1;
256 return 1;
259 int ParseArgs(NaClSrpcArg* arg, const TOKEN* token, int n) {
260 int i;
261 for (i = 0; i < n; ++i) {
262 if (ParseArg(&arg[i], token[i].start) < 0)
263 return -1;
265 return n;
268 void DumpArg(const NaClSrpcArg* arg) {
269 unsigned int count;
270 unsigned int i;
272 switch(arg->tag) {
273 case NACL_SRPC_ARG_TYPE_INVALID:
274 printf("X()");
275 break;
276 case NACL_SRPC_ARG_TYPE_BOOL:
277 printf("b(%d)", arg->u.bval);
278 break;
279 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
280 for (i = 0; i < arg->u.caval.count; ++i)
281 putchar(arg->u.caval.carr[i]);
282 break;
283 case NACL_SRPC_ARG_TYPE_DOUBLE:
284 printf("d(%f)", arg->u.dval);
285 break;
286 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
287 count = arg->u.daval.count;
288 printf("D(%d", count);
289 for (i=0; i < count; ++i)
290 printf(",%f", arg->u.daval.darr[i]);
291 printf(")");
292 break;
293 case NACL_SRPC_ARG_TYPE_HANDLE:
294 printf("h(%x)", (unsigned int) arg->u.hval);
295 break;
296 case NACL_SRPC_ARG_TYPE_INT:
297 printf("i(%d)", arg->u.ival);
298 break;
299 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
300 count = arg->u.iaval.count;
301 printf("I(%d", count);
302 for (i=0; i < count; ++i)
303 printf(",%d", arg->u.iaval.iarr[i]);
304 printf(")");
305 break;
306 case NACL_SRPC_ARG_TYPE_STRING:
307 /* TODO: do proper escaping */
308 printf("s(\"%s\")", arg->u.sval);
309 break;
310 case NACL_SRPC_ARG_TYPE_OBJECT:
311 /* this is a pointer that NaCl module can do nothing with */
312 printf("o(%p)", arg->u.oval);
313 break;
314 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
315 count = arg->u.vaval.count;
316 printf("A(%d", count);
317 for (i=0; i < count; ++i) {
318 printf(",");
319 DumpArg(&arg->u.vaval.varr[i]);
321 printf(")");
322 break;
323 default:
324 break;
328 void DumpArgs(const NaClSrpcArg* arg, int n) {
329 int i;
330 for (i=0; i<n; ++i) {
331 printf(" ");
332 DumpArg(&arg[i]);
334 printf("\n");
337 void BuildArgVec(NaClSrpcArg* argv[], NaClSrpcArg arg[], int count) {
338 int i;
339 CHECK(count < NACL_SRPC_MAX_ARGS);
340 for (i = 0; i < count; ++i) {
341 argv[i] = &arg[i];
343 argv[count] = NULL;
346 void FreeArrayArgs(NaClSrpcArg arg[], int count) {
347 int i;
348 for (i = 0; i < count; ++i) {
349 switch(arg[i].tag) {
350 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
351 free(arg[i].u.caval.carr);
352 break;
353 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
354 free(arg[i].u.daval.darr);
355 break;
356 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
357 free(arg[i].u.iaval.iarr);
358 break;
359 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
360 FreeArrayArgs(arg[i].u.vaval.varr, arg[i].u.vaval.count);
361 break;
362 case NACL_SRPC_ARG_TYPE_INVALID:
363 case NACL_SRPC_ARG_TYPE_BOOL:
364 case NACL_SRPC_ARG_TYPE_DOUBLE:
365 case NACL_SRPC_ARG_TYPE_HANDLE:
366 case NACL_SRPC_ARG_TYPE_INT:
367 case NACL_SRPC_ARG_TYPE_STRING:
368 case NACL_SRPC_ARG_TYPE_OBJECT:
369 default:
370 break;
375 static void CommandLoop(NaClHandle imc_handle) {
376 NaClSrpcError errcode;
377 NaClSrpcChannel rpc_channel;
378 int command_count = 0;
380 NaClSrpcClientCtor(&rpc_channel, NaClSrpcImcDescTypeFromHandle(imc_handle));
383 * Process rpcs.
385 for (;;) {
386 char buffer[4096];
387 TOKEN tokens[NACL_SRPC_MAX_ARGS];
388 int n;
389 const char *command;
391 fprintf(stderr, "%d> ", command_count);
392 ++command_count;
394 if (!fgets(buffer, sizeof(buffer), stdin))
395 break;
397 n = Tokenize(buffer, tokens, NACL_SRPC_MAX_ARGS);
399 if (n < 1) {
400 if (n < 0)
401 fprintf(stderr, "bad line\n");
402 continue;
405 command = tokens[0].start;
406 if (0 == strcmp("#", command)) {
407 continue;
408 } else if (0 == strcmp("service", command)) {
409 NaClSrpcDumpInterfaceDesc(&rpc_channel);
410 } else if (0 == strcmp("quit", command)) {
411 break;
412 } else if (0 == strcmp("rpc", command)) {
413 int int_out_sep;
414 int n_in;
415 NaClSrpcArg in[NACL_SRPC_MAX_ARGS];
416 NaClSrpcArg* inv[NACL_SRPC_MAX_ARGS + 1];
417 int n_out;
418 NaClSrpcArg out[NACL_SRPC_MAX_ARGS];
419 NaClSrpcArg* outv[NACL_SRPC_MAX_ARGS + 1];
420 int rpc_num;
422 if (n < 2) {
423 fprintf(stderr, "bad rpc command\n");
424 continue;
427 for (int_out_sep = 2; int_out_sep < n; ++int_out_sep) {
428 if (0 == strcmp(tokens[int_out_sep].start, "*"))
429 break;
432 if (int_out_sep == n) {
433 fprintf(stderr, "no in out arg separator for rpc command\n");
434 continue;
438 * Build the input parameter values.
441 n_in = int_out_sep - 2;
442 DEBUG("parsing in args %d\n", n_in);
443 BuildArgVec(inv, in, n_in);
445 if (ParseArgs(in, &tokens[2], n_in) < 0) {
446 fprintf(stderr, "bad input args for rpc\n");
447 continue;
451 * Build the output (rpc return) values.
454 n_out = n - int_out_sep - 1;
455 DEBUG("parsing out args %d\n", n_out);
456 BuildArgVec(outv, out, n_out);
458 if (ParseArgs(out, &tokens[int_out_sep + 1], n_out) < 0) {
459 fprintf(stderr, "bad output args for rpc\n");
460 continue;
463 rpc_num = NaClSrpcGetRpcNum(&rpc_channel, tokens[1].start);
464 if (rpc_num < 0) {
465 fprintf(stderr, "unknown rpc\n");
466 continue;
469 fprintf(stderr,"using rpc %s no %d\n", tokens[1].start, rpc_num);
470 errcode = NaClSrpcInvokeV(&rpc_channel, rpc_num, inv, outv);
471 if (NACL_SRPC_RESULT_OK != errcode) {
472 fprintf(stderr, "rpc call failed %s\n", NaClSrpcErrorString(errcode));
473 continue;
477 * dump result vector
479 printf("%s RESULTS: ", tokens[1].start);
480 DumpArgs(outv[0], n_out);
483 * Free the storage allocated for array valued parameters and returns.
485 FreeArrayArgs(in, n_in);
486 FreeArrayArgs(out, n_out);
487 } else {
488 fprintf(stderr, "unknown command\n");
489 continue;
494 * Shut down the rpc streams.
496 NaClSrpcDtor(&rpc_channel);
501 * This function works with the rpc services in tests/srpc to test the
502 * interfaces.
504 static void TestRandomRpcs(NaClHandle imc_handle) {
505 NaClSrpcArg in;
506 NaClSrpcArg* inv[2];
507 NaClSrpcArg out;
508 NaClSrpcArg* outv[2];
509 NaClSrpcError errcode;
510 NaClSrpcChannel rpc_channel;
511 int argument_count;
512 int return_count;
513 int i;
515 inv[0] = &in;
516 inv[1] = NULL;
518 outv[0] = &out;
519 outv[1] = NULL;
522 * Set up the connection to the child process.
524 NaClSrpcClientCtor(&rpc_channel, NaClSrpcImcDescTypeFromHandle(imc_handle));
526 * TODO: set up timing on both ends of the IMC channel.
529 do {
530 if (timed_rpc_method < 1 || timed_rpc_method >= rpc_channel.rpc_count) {
531 fprintf(stderr, "method number must be between 1 and %d (inclusive)\n",
532 rpc_channel.rpc_count - 1);
533 break;
536 argument_count = strlen(rpc_channel.rpc_descr[timed_rpc_method].in_args);
537 return_count = strlen(rpc_channel.rpc_descr[timed_rpc_method].out_args);
539 if (argument_count != return_count) {
540 fprintf(stderr, "method argument and return count must match\n");
541 break;
544 if (1 < argument_count) {
545 fprintf(stderr, "method must take zero or one argument\n");
546 break;
549 if (argument_count == 0) {
550 inv[0] = NULL;
551 outv[0] = NULL;
552 } else {
553 enum NaClSrpcArgType type;
554 static char c_in[MAX_ARRAY_SIZE];
555 static char c_out[MAX_ARRAY_SIZE];
556 static double d_in[MAX_ARRAY_SIZE / sizeof(double)];
557 static double d_out[MAX_ARRAY_SIZE / sizeof(double)];
558 static int i_in[MAX_ARRAY_SIZE / sizeof(int)];
559 static int i_out[MAX_ARRAY_SIZE / sizeof(int)];
560 char* macbeth =
561 "She should have died hereafter;"
562 "There would have been a time for such a word."
563 "To-morrow, and to-morrow, and to-morrow,"
564 "Creeps in this petty pace from day to day"
565 "To the last syllable of recorded time,"
566 "And all our yesterdays have lighted fools"
567 "The way to dusty death. Out, out, brief candle!"
568 "Life's but a walking shadow, a poor player"
569 "That struts and frets his hour upon the stage"
570 "And then is heard no more: it is a tale"
571 "Told by an idiot, full of sound and fury,"
572 "Signifying nothing";
574 in.tag = rpc_channel.rpc_descr[timed_rpc_method].in_args[0];
575 out.tag = rpc_channel.rpc_descr[timed_rpc_method].out_args[0];
577 type = rpc_channel.rpc_descr[timed_rpc_method].in_args[0];
578 switch (type) {
579 case NACL_SRPC_ARG_TYPE_BOOL:
580 in.u.bval = 1;
581 break;
582 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
583 in.u.caval.count = timed_rpc_bytes;
584 in.u.caval.carr = c_in;
585 out.u.caval.count = in.u.iaval.count;
586 out.u.caval.carr = c_out;
587 break;
588 case NACL_SRPC_ARG_TYPE_DOUBLE:
589 in.u.dval = 3.1415926;
590 break;
591 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
592 in.u.daval.count = timed_rpc_bytes / sizeof(double);
593 in.u.daval.darr = d_in;
594 out.u.daval.count = in.u.iaval.count;
595 out.u.daval.darr = d_out;
596 break;
597 case NACL_SRPC_ARG_TYPE_INT:
598 in.u.ival = -1;
599 break;
600 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
601 in.u.iaval.count = timed_rpc_bytes / sizeof(int);
602 in.u.iaval.iarr = i_in;
603 out.u.iaval.count = in.u.iaval.count;
604 out.u.iaval.iarr = i_out;
605 break;
606 case NACL_SRPC_ARG_TYPE_STRING:
607 /* TODO: needs length variation */
608 in.u.sval = macbeth;
609 break;
610 case NACL_SRPC_ARG_TYPE_INVALID:
611 case NACL_SRPC_ARG_TYPE_HANDLE:
612 case NACL_SRPC_ARG_TYPE_OBJECT:
613 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
614 continue;
619 * Do the rpcs.
621 for (i = 0; i < timed_rpc_count; ++i) {
622 errcode = NaClSrpcInvokeV(&rpc_channel, timed_rpc_method, inv, outv);
623 if (NACL_SRPC_RESULT_OK != errcode) {
624 fprintf(stderr, "rpc call failed %s\n", NaClSrpcErrorString(errcode));
625 break;
629 if (i == timed_rpc_count) {
630 NaClSrpcArg* timer_inv[] = { NULL };
631 NaClSrpcArg tm[4];
632 NaClSrpcArg* timer_outv[5];
633 double total_server_usec;
634 double dummy_receive;
635 double dummy_imc_read;
636 double dummy_imc_write;
638 timer_outv[0] = &tm[0];
639 timer_outv[1] = &tm[1];
640 timer_outv[2] = &tm[2];
641 timer_outv[3] = &tm[3];
642 timer_outv[4] = NULL;
644 NaClSrpcGetTimes(&rpc_channel,
645 &total_server_usec,
646 &dummy_receive,
647 &dummy_imc_read,
648 &dummy_imc_write);
649 printf("server time observed by client: %.6f sec\n",
650 total_server_usec / 1000000.0);
651 tm[0].tag = NACL_SRPC_ARG_TYPE_DOUBLE;
652 tm[1].tag = NACL_SRPC_ARG_TYPE_DOUBLE;
653 tm[2].tag = NACL_SRPC_ARG_TYPE_DOUBLE;
654 tm[3].tag = NACL_SRPC_ARG_TYPE_DOUBLE;
655 errcode = NaClSrpcInvokeV(&rpc_channel,
656 NACL_SRPC_GET_TIMES_METHOD,
657 timer_inv,
658 timer_outv);
659 printf("server send time: %.6f sec\n", tm[0].u.dval / 1000000.0);
660 printf("server receive time: %.6f sec\n", tm[1].u.dval / 1000000.0);
661 printf("imc read time: %.6f sec\n", tm[2].u.dval / 1000000.0);
662 printf("imc write time: %.6f sec\n", tm[3].u.dval / 1000000.0);
663 printf("PASS\n");
665 } while (0);
668 * Shut down the rpc streams.
670 NaClSrpcDtor(&rpc_channel);
674 #if defined(HAVE_SDL)
675 #include <SDL.h>
676 #endif
678 int main(int argc, char *argv[]) {
679 NaClHandle imc_handle;
680 struct NaClSelLdrLauncher* launcher;
681 int opt;
682 static char* application_name;
683 char* nextp;
684 int i;
685 int sel_ldr_argc;
686 char** tmp_ldr_argv;
687 char** sel_ldr_argv;
688 int module_argc;
689 char** module_argv;
691 /* Descriptor transfer requires the following. */
692 NaClNrdAllModulesInit();
694 /* The -p option can change the sel_ldr binary used. */
695 g_sel_ldr_pathname = kSelLdrPathname;
697 /* We are only testing if this count is not zero. */
698 timed_rpc_count = 0;
700 /* command line parsing */
701 while ((opt = getopt(argc, argv, "f:p:r:v")) != -1) {
702 switch (opt) {
703 case 'f':
704 application_name = optarg;
705 break;
706 case 'p':
707 g_sel_ldr_pathname = optarg;
708 break;
709 case 'r':
710 timed_rpc_count = strtol(optarg, &nextp, 0);
711 if (':' == *nextp) {
712 timed_rpc_method = strtol(nextp + 1, &nextp, 0);
713 if (':' == *nextp) {
714 timed_rpc_bytes = strtol(nextp + 1, 0, 0);
717 printf("Testing: %d iterations, method %d, %d bytes\n",
718 timed_rpc_count,
719 timed_rpc_method,
720 timed_rpc_bytes);
721 break;
722 case 'v':
723 NaClLogIncrVerbosity();
724 break;
725 default:
726 fprintf(stderr,
727 "Usage: sel_universal [-f nacl_file]\n"
728 " [-p sel_ldr]\n"
729 " [-r count:method:bytes]\n");
730 return -1;
735 * Pass any extra arguments on to sel_ldr or the application.
737 tmp_ldr_argv = NULL;
738 sel_ldr_argc = 0;
739 module_argv = NULL;
740 module_argc = 0;
741 for (i = 0; i < argc; ++i) {
742 if (tmp_ldr_argv == NULL) {
743 /* sel_universal arguments come first. */
744 if (!strcmp("--", argv[i])) {
745 tmp_ldr_argv = &argv[i + 1];
747 } else if (module_argv == NULL) {
748 /* sel_ldr arguments come next. */
749 if (!strcmp("--", argv[i])) {
750 module_argv = &argv[i + 1];
751 } else {
752 ++sel_ldr_argc;
754 } else {
755 /* application arguments come last. */
756 ++module_argc;
761 * Append the -P 5 option to the command line to pass the channel to the
762 * SRPC interface.
764 sel_ldr_argv = (char**) malloc(module_argc * sizeof(*module_argv));
765 sel_ldr_argv[0] = "-P";
766 sel_ldr_argv[1] = "5";
767 for (i = 0; i < sel_ldr_argc; ++i) {
768 sel_ldr_argv[i + 2] = tmp_ldr_argv[i];
772 * Start sel_ldr with the given application and arguments.
774 launcher = NaClSelLdrStart(application_name,
776 sel_ldr_argc + 2,
777 (const char**) sel_ldr_argv,
778 module_argc,
779 (const char**) module_argv);
780 imc_handle = NaClSelLdrGetChannel(launcher);
782 if (timed_rpc_count == 0) {
783 CommandLoop(imc_handle);
784 } else {
785 TestRandomRpcs(imc_handle);
788 NaClSelLdrShutdown(launcher);
790 NaClNrdAllModulesFini();
791 return 0;
794 #if NACL_WINDOWS
795 /* TODO: create one utility function to get usec times. */
796 static int gettimeofday(struct timeval *tv, struct timezone *tz) {
797 unsigned __int64 timer = 0;
798 FILETIME filetime;
799 GetSystemTimeAsFileTime(&filetime);
800 timer |= filetime.dwHighDateTime;
801 timer <<= 32;
802 timer |= filetime.dwLowDateTime;
803 /* FILETIME has 100ns precision. Convert to usec. */
804 timer /= 10;
805 tv->tv_sec = (long) (timer / 1000000UL);
806 tv->tv_usec = (long) (timer % 1000000UL);
807 return 0;
809 #endif