]> sourceware.org Git - systemtap.git/blame - main.cxx
2007-06-25 Martin Hunt <hunt@redhat.com>
[systemtap.git] / main.cxx
CommitLineData
f4b28491 1// systemtap translator/driver
9abec538 2// Copyright (C) 2005-2007 Red Hat Inc.
f12b2552 3// Copyright (C) 2005 IBM Corp.
77a5c1f9 4// Copyright (C) 2006 Intel Corporation.
69c68955
FCE
5//
6// This file is part of systemtap, and is free software. You can
7// redistribute it and/or modify it under the terms of the GNU General
8// Public License (GPL); either version 2, or (at your option) any
9// later version.
2b066ec1
FCE
10
11#include "config.h"
12#include "staptree.h"
13#include "parse.h"
14#include "elaborate.h"
15#include "translate.h"
f4b28491 16#include "buildrun.h"
dc38c0ae 17#include "session.h"
1b78aef5
DS
18#include "hash.h"
19#include "cache.h"
20#include "util.h"
2b066ec1
FCE
21
22#include <iostream>
23#include <fstream>
24#include <sstream>
f4b28491 25#include <cerrno>
24cb178f 26#include <cstdlib>
2b066ec1
FCE
27
28extern "C" {
29#include <glob.h>
30#include <unistd.h>
f4b28491 31#include <sys/utsname.h>
5ee1c56b 32#include <sys/times.h>
1d738eed 33#include <sys/time.h>
f59e98c4 34#include <sys/stat.h>
f4b28491 35#include <time.h>
f8949662 36#include <elfutils/libdwfl.h>
2b066ec1
FCE
37}
38
39using namespace std;
40
41
f4b28491 42void
c0de7a8d 43version ()
2b066ec1 44{
d54d4661 45 clog
d04cf5ff 46 << "SystemTap translator/driver "
c4a94c1a
FCE
47 << "(version " << VERSION << "/" << dwfl_version (NULL)
48 << " built " << DATE << ")" << endl
5212330d 49 << "Copyright (C) 2005-2007 Red Hat, Inc. and others" << endl
f8949662 50 << "This is free software; see the source for copying conditions." << endl;
c0de7a8d
FCE
51}
52
53void
277c1957 54usage (systemtap_session& s, int exitcode)
c0de7a8d
FCE
55{
56 version ();
57 clog
f4b28491 58 << endl
b2d5d95c 59 << "Usage: stap [options] FILE Run script in file."
f4b28491 60 << endl
b2d5d95c 61 << " or: stap [options] - Run script on stdin."
f4b28491 62 << endl
d54d4661 63 << " or: stap [options] -e SCRIPT Run given script."
f4b28491
FCE
64 << endl
65 << endl
c0de7a8d 66 << "Options:" << endl
f4b28491 67 << " -- no more options after this" << endl
b0ee93c4 68 << " -v increase verbosity [" << s.verbose << "]" << endl
c0de7a8d
FCE
69 << " -h show help" << endl
70 << " -V show version" << endl
d5d7c2cc 71 << " -k keep temporary directory" << endl
cbfbbf69 72 << " -u unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl
377b8831 73 << " -g guru mode" << (s.guru_mode ? " [set]" : "") << endl
44f75386
FCE
74 << " -P prologue-searching for function probes"
75 << (s.prologue_searching ? " [set]" : "") << endl
6dfd08d7 76 << " -b bulk (percpu file) mode" << (s.bulk_mode ? " [set]" : "") << endl
177a8ead
FCE
77 << " -s NUM buffer size in megabytes, instead of "
78 << s.buffer_size << endl
f8949662 79 << " -p NUM stop after pass NUM 1-5, instead of "
177a8ead 80 << s.last_pass << endl
f4b28491
FCE
81 << " (parse, elaborate, translate, compile, run)" << endl
82 << " -I DIR look in DIR for additional .stp script files";
83 if (s.include_path.size() == 0)
0d49d7bc 84 clog << endl;
f4b28491 85 else
24cb178f 86 clog << ", in addition to" << endl;
f4b28491 87 for (unsigned i=0; i<s.include_path.size(); i++)
0d49d7bc
FCE
88 clog << " " << s.include_path[i] << endl;
89 clog
ed10c639 90 << " -D NM=VAL emit macro definition into generated C code" << endl
24cb178f
FCE
91 << " -R DIR look in DIR for runtime, instead of" << endl
92 << " " << s.runtime_path << endl
b8da0ad1 93 << " -r RELEASE cross-compile to kernel RELEASE, instead of "
177a8ead 94 << s.kernel_release << endl
f12b2552
FCE
95 << " -m MODULE set probe module name, instead of "
96 << s.module_name << endl
177a8ead 97 << " -o FILE send output to file, instead of stdout" << endl
f8949662 98 << " -c CMD start the probes, run CMD, and exit when it finishes"
f12b2552 99 << endl
4c5ff1bb 100 << " -x PID sets target() to PID" << endl
cbd6fc7b 101 << " -t collect probe timing information" << endl
d5d7c2cc 102 ;
d54d4661 103 // -d: dump safety-related external references
2b066ec1 104
277c1957 105 exit (exitcode);
2b066ec1
FCE
106}
107
108
1b78aef5
DS
109static void
110printscript(systemtap_session& s, ostream& o)
111{
83d7fcdc
DS
112 if (s.embeds.size() > 0)
113 o << "# global embedded code" << endl;
114 for (unsigned i=0; i<s.embeds.size(); i++)
115 {
116 embeddedcode* ec = s.embeds[i];
117 ec->print (o);
118 o << endl;
119 }
120
1b78aef5
DS
121 if (s.globals.size() > 0)
122 o << "# globals" << endl;
123 for (unsigned i=0; i<s.globals.size(); i++)
124 {
125 vardecl* v = s.globals[i];
126 v->printsig (o);
9ba8c134
JS
127 if (s.verbose && v->init)
128 {
129 o << " = ";
130 v->init->print(o);
131 }
1b78aef5
DS
132 o << endl;
133 }
134
135 if (s.functions.size() > 0)
136 o << "# functions" << endl;
137 for (unsigned i=0; i<s.functions.size(); i++)
138 {
139 functiondecl* f = s.functions[i];
140 f->printsig (o);
141 o << endl;
142 if (f->locals.size() > 0)
143 o << " # locals" << endl;
144 for (unsigned j=0; j<f->locals.size(); j++)
145 {
146 vardecl* v = f->locals[j];
147 o << " ";
148 v->printsig (o);
149 o << endl;
150 }
151 if (s.verbose)
152 {
153 f->body->print (o);
154 o << endl;
155 }
156 }
157
158 if (s.probes.size() > 0)
159 o << "# probes" << endl;
160 for (unsigned i=0; i<s.probes.size(); i++)
161 {
162 derived_probe* p = s.probes[i];
163 p->printsig (o);
164 o << endl;
165 if (p->locals.size() > 0)
166 o << " # locals" << endl;
167 for (unsigned j=0; j<p->locals.size(); j++)
168 {
169 vardecl* v = p->locals[j];
170 o << " ";
171 v->printsig (o);
172 o << endl;
173 }
174 if (s.verbose)
175 {
176 p->body->print (o);
177 o << endl;
178 }
179 }
180}
181
2b066ec1
FCE
182int
183main (int argc, char * const argv [])
184{
2b066ec1
FCE
185 string cmdline_script; // -e PROGRAM
186 string script_file; // FILE
187 bool have_script = false;
ea3f75ae 188 bool release_changed = false;
f4b28491
FCE
189
190 // Initialize defaults
191 systemtap_session s;
192 struct utsname buf;
193 (void) uname (& buf);
194 s.kernel_release = string (buf.release);
44ce8ed5 195 s.architecture = string (buf.machine);
b0ee93c4 196 s.verbose = 0;
4b17d6af 197 s.timing = 0;
377b8831 198 s.guru_mode = false;
16d8de1b 199 s.bulk_mode = false;
cbfbbf69 200 s.unoptimized = false;
44f75386
FCE
201
202#ifdef ENABLE_PROLOGUES
203 s.prologue_searching = true;
204#else
205 s.prologue_searching = false;
206#endif
207
16d8de1b 208 s.buffer_size = 0;
f4b28491 209 s.last_pass = 5;
ae24723e 210 s.module_name = "stap_" + stringify(getpid());
08c68653 211 s.output_file = ""; // -o FILE
f4b28491 212 s.keep_tmpdir = false;
4c5ff1bb
MH
213 s.cmd = "";
214 s.target_pid = 0;
f272aacc 215 s.merge=true;
47dd066d 216 s.perfmon=0;
f1bad60c 217 s.symtab = false;
1b78aef5 218 s.use_cache = true;
24cb178f
FCE
219
220 const char* s_p = getenv ("SYSTEMTAP_TAPSET");
ec819dc3
LG
221 if (s_p != NULL)
222 {
24cb178f 223 s.include_path.push_back (s_p);
ec819dc3
LG
224 s.include_path.push_back (string(s_p) + "/LKET");
225 }
24cb178f 226 else
ec819dc3 227 {
24cb178f 228 s.include_path.push_back (string(PKGDATADIR) + "/tapset");
ec819dc3
LG
229 s.include_path.push_back (string(PKGDATADIR) + "/tapset/LKET");
230 }
24cb178f
FCE
231
232 const char* s_r = getenv ("SYSTEMTAP_RUNTIME");
233 if (s_r != NULL)
234 s.runtime_path = s_r;
235 else
236 s.runtime_path = string(PKGDATADIR) + "/runtime";
f4b28491 237
1b78aef5
DS
238 const char* s_d = getenv ("SYSTEMTAP_DIR");
239 if (s_d != NULL)
240 s.data_path = s_d;
241 else
242 s.data_path = get_home_directory() + string("/.systemtap");
243 if (create_dir(s.data_path.c_str()) == 1)
244 {
245 const char* e = strerror (errno);
246 cerr << "Warning: failed to create systemtap data directory (\""
247 << s.data_path << "\"): " << e << endl;
248 cerr << "Disabling cache support." << endl;
249 s.use_cache = false;
250 }
251
252 if (s.use_cache)
253 {
254 s.cache_path = s.data_path + "/cache";
255 if (create_dir(s.cache_path.c_str()) == 1)
256 {
257 const char* e = strerror (errno);
258 cerr << "Warning: failed to create cache directory (\""
259 << s.cache_path << "\"): " << e << endl;
260 cerr << "Disabling cache support." << endl;
261 s.use_cache = false;
262 }
263 }
264
2b066ec1
FCE
265 while (true)
266 {
44f75386
FCE
267 // NB: also see find_hash(), help(), switch stmt below, stap.1 man page
268 int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:u");
2b066ec1
FCE
269 if (grc < 0)
270 break;
271 switch (grc)
272 {
c0de7a8d
FCE
273 case 'V':
274 version ();
275 exit (0);
276
f272aacc
LG
277 case 'M':
278 s.merge = false;
279 break;
280
bd2b1e68 281 case 'v':
b0ee93c4 282 s.verbose ++;
bd2b1e68
GH
283 break;
284
4b17d6af
WC
285 case 't':
286 s.timing ++;
287 break;
288
2b066ec1 289 case 'p':
f4b28491
FCE
290 s.last_pass = atoi (optarg);
291 if (s.last_pass < 1 || s.last_pass > 5)
2b066ec1 292 {
277c1957
DS
293 cerr << "Invalid pass number (should be 1-5)." << endl;
294 usage (s, 1);
2b066ec1
FCE
295 }
296 break;
297
298 case 'I':
f4b28491 299 s.include_path.push_back (string (optarg));
2b066ec1
FCE
300 break;
301
302 case 'e':
303 if (have_script)
277c1957
DS
304 {
305 cerr << "Only one script can be given on the command line."
306 << endl;
307 usage (s, 1);
308 }
2b066ec1
FCE
309 cmdline_script = string (optarg);
310 have_script = true;
311 break;
312
313 case 'o':
08c68653 314 s.output_file = string (optarg);
2b066ec1
FCE
315 break;
316
f4b28491
FCE
317 case 'R':
318 s.runtime_path = string (optarg);
319 break;
320
321 case 'm':
322 s.module_name = string (optarg);
3b942fed
DS
323 {
324 string::size_type len = s.module_name.length();
325
326 // If the module name ends with '.ko', chop it off since
327 // modutils doesn't like modules named 'foo.ko.ko'.
328 if (len > 3 && s.module_name.substr(len - 3, 3) == ".ko")
329 {
330 s.module_name.erase(len - 3);
331 len -= 3;
332 cerr << "Truncating module name to '" << s.module_name
333 << "'" << endl;
334 }
335
336 // Make sure an empty module name wasn't specified (-m "")
337 if (len == 0)
338 {
339 cerr << "Module name cannot be empty." << endl;
340 usage (s, 1);
341 }
342
343 // Make sure the module name is only composed of the
344 // following chars: [_a-zA-Z0-9]
345 const string identchars("_" "abcdefghijklmnopqrstuvwxyz"
346 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789");
347 if (s.module_name.find_first_not_of(identchars) != string::npos)
348 {
349 cerr << "Invalid module name (must only be composed of"
350 " characters [_a-zA-Z0-9])." << endl;
351 usage (s, 1);
352 }
353 }
354
1b78aef5
DS
355 cerr << "Warning: using '-m' disables cache support." << endl;
356 s.use_cache = false;
f4b28491
FCE
357 break;
358
359 case 'r':
360 s.kernel_release = string (optarg);
ea3f75ae 361 release_changed = true;
f4b28491
FCE
362 break;
363
364 case 'k':
365 s.keep_tmpdir = true;
366 break;
367
377b8831
FCE
368 case 'g':
369 s.guru_mode = true;
370 break;
371
44f75386
FCE
372 case 'P':
373 s.prologue_searching = true;
374 break;
375
16d8de1b
TZ
376 case 'b':
377 s.bulk_mode = true;
16d8de1b
TZ
378 break;
379
cbfbbf69
FCE
380 case 'u':
381 s.unoptimized = true;
382 break;
383
16d8de1b
TZ
384 case 's':
385 s.buffer_size = atoi (optarg);
386 if (s.buffer_size < 1 || s.buffer_size > 64)
387 {
277c1957
DS
388 cerr << "Invalid buffer size (should be 1-64)." << endl;
389 usage (s, 1);
16d8de1b
TZ
390 }
391 break;
392
4c5ff1bb
MH
393 case 'c':
394 s.cmd = string (optarg);
395 break;
396
397 case 'x':
398 s.target_pid = atoi(optarg);
399 break;
400
ed10c639
FCE
401 case 'D':
402 s.macros.push_back (string (optarg));
403 break;
404
2b066ec1 405 case 'h':
277c1957
DS
406 usage (s, 0);
407 break;
408
2b066ec1 409 default:
277c1957
DS
410 usage (s, 1);
411 break;
2b066ec1
FCE
412 }
413 }
414
f272aacc
LG
415 if(!s.bulk_mode && !s.merge)
416 {
417 cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
277c1957 418 usage (s, 1);
f272aacc
LG
419 }
420
421 if(!s.output_file.empty() && s.bulk_mode && !s.merge)
422 {
423 cerr << "You can't specify -M, -b and -o options together." <<endl;
277c1957 424 usage (s, 1);
f272aacc
LG
425 }
426
ea3f75ae
DS
427 if (s.last_pass > 4 && release_changed)
428 {
b8da0ad1
FCE
429 if (s.verbose)
430 cerr << "Warning: changing last pass to 4 since cross-compiling" << endl;
ea3f75ae
DS
431 s.last_pass = 4;
432 }
433
2b066ec1
FCE
434 for (int i = optind; i < argc; i++)
435 {
436 if (! have_script)
437 {
438 script_file = string (argv[i]);
439 have_script = true;
440 }
441 else
f4b28491 442 s.args.push_back (string (argv[i]));
2b066ec1
FCE
443 }
444
445 // need a user file
446 if (! have_script)
277c1957
DS
447 {
448 cerr << "A script must be specified." << endl;
449 usage(s, 1);
450 }
f4b28491
FCE
451
452 int rc = 0;
2b066ec1 453
ce3187ac 454 // override PATH and LC_ALL
c72dc86c
JS
455 const char *path = "/bin:/sbin:/usr/bin:/usr/sbin";
456 rc = setenv("PATH", path, 1) || setenv("LC_ALL", "C", 1);
ce3187ac
FCE
457 if (rc)
458 {
459 const char* e = strerror (errno);
c72dc86c 460 cerr << "setenv (\"PATH=" << path << "\" + \"LC_ALL=C\"): "
ce3187ac
FCE
461 << e << endl;
462 }
f8949662 463
861c2f28
DS
464 // Get rid of a few standard environment variables (which might
465 // cause us to do unintended things).
466 rc = unsetenv("IFS") || unsetenv("CDPATH") || unsetenv("ENV")
467 || unsetenv("BASH_ENV");
468 if (rc)
469 {
470 const char* e = strerror (errno);
471 cerr << "unsetenv failed: " << e << endl;
472 }
473
197a4d62
JS
474 s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
475
2b066ec1 476 // arguments parsed; get down to business
72d18b98
FCE
477 if (s.verbose > 1)
478 version ();
2b066ec1 479
f4b28491
FCE
480 // Create a temporary directory to build within.
481 // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
482 {
c72dc86c 483 const char* tmpdir_env = getenv("TMPDIR");
ea8ea02c
FCE
484 if (! tmpdir_env)
485 tmpdir_env = "/tmp";
486
487 string stapdir = "/stapXXXXXX";
488 string tmpdirt = tmpdir_env + stapdir;
489 const char* tmpdir = mkdtemp((char *)tmpdirt.c_str());
f4b28491
FCE
490 if (! tmpdir)
491 {
492 const char* e = strerror (errno);
ea8ea02c
FCE
493 cerr << "ERROR: cannot create temporary directory (\"" << tmpdirt << "\"): " << e << endl;
494 exit (1); // die
f4b28491
FCE
495 }
496 else
497 s.tmpdir = tmpdir;
0d49d7bc 498
b0ee93c4 499 if (s.verbose>1)
0d49d7bc 500 clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491 501 }
2b066ec1 502
1b78aef5
DS
503 // Create the name of the C source file within the temporary
504 // directory.
505 s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
506
5ee1c56b
FCE
507 struct tms tms_before;
508 times (& tms_before);
1d738eed
FCE
509 struct timeval tv_before;
510 gettimeofday (&tv_before, NULL);
2b066ec1
FCE
511
512 // PASS 1a: PARSING USER SCRIPT
f59e98c4
FCE
513
514 struct stat user_file_stat;
515 int user_file_stat_rc = -1;
516
69c68955 517 if (script_file == "-")
129be0ac
FCE
518 {
519 s.user_file = parser::parse (s, cin, s.guru_mode);
520 user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
521 }
69c68955 522 else if (script_file != "")
f59e98c4
FCE
523 {
524 s.user_file = parser::parse (s, script_file, s.guru_mode);
525 user_file_stat_rc = stat (script_file.c_str(), & user_file_stat);
526 }
2b066ec1
FCE
527 else
528 {
529 istringstream ii (cmdline_script);
177a8ead 530 s.user_file = parser::parse (s, ii, s.guru_mode);
2b066ec1
FCE
531 }
532 if (s.user_file == 0)
533 // syntax errors already printed
534 rc ++;
377b8831 535
5519d363 536 // Construct arch / kernel-versioning search path
377b8831 537 vector<string> version_suffixes;
6f9f33e2 538 string kvr = s.kernel_release;
5519d363
KS
539 const string& arch = s.architecture;
540 // add full kernel-version-release (2.6.NN-FOOBAR) + arch
541 version_suffixes.push_back ("/" + kvr + "/" + arch);
377b8831 542 version_suffixes.push_back ("/" + kvr);
5519d363 543 // add kernel version (2.6.NN) + arch
197a4d62
JS
544 if (kvr != s.kernel_base_release) {
545 kvr = s.kernel_base_release;
6f9f33e2
JS
546 version_suffixes.push_back ("/" + kvr + "/" + arch);
547 version_suffixes.push_back ("/" + kvr);
5519d363
KS
548 }
549 // add kernel family (2.6) + arch
6f9f33e2
JS
550 string::size_type dot1_index = kvr.find ('.');
551 string::size_type dot2_index = kvr.rfind ('.');
552 while (dot2_index > dot1_index && dot2_index != string::npos) {
553 kvr.erase(dot2_index);
554 version_suffixes.push_back ("/" + kvr + "/" + arch);
555 version_suffixes.push_back ("/" + kvr);
556 dot2_index = kvr.rfind ('.');
5519d363
KS
557 }
558 // add architecture search path
559 version_suffixes.push_back("/" + arch);
377b8831
FCE
560 // add empty string as last element
561 version_suffixes.push_back ("");
2b066ec1
FCE
562
563 // PASS 1b: PARSING LIBRARY SCRIPTS
f4b28491 564 for (unsigned i=0; i<s.include_path.size(); i++)
2b066ec1 565 {
377b8831
FCE
566 // now iterate upon it
567 for (unsigned k=0; k<version_suffixes.size(); k++)
2b066ec1 568 {
377b8831
FCE
569 glob_t globbuf;
570 string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
571 int r = glob(dir.c_str (), 0, NULL, & globbuf);
572 if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
2b066ec1 573 rc ++;
377b8831
FCE
574 // GLOB_NOMATCH is acceptable
575
c4a94c1a 576 if (s.verbose>1 && globbuf.gl_pathc > 0)
377b8831 577 clog << "Searched '" << dir << "', "
c4a94c1a 578 << "found " << globbuf.gl_pathc << endl;
2b066ec1 579
377b8831
FCE
580 for (unsigned j=0; j<globbuf.gl_pathc; j++)
581 {
24cb178f 582 // privilege only for /usr/share/systemtap?
f59e98c4 583
177a8ead 584 stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true);
377b8831
FCE
585 if (f == 0)
586 rc ++;
587 else
24cb178f 588 s.library_files.push_back (f);
f59e98c4
FCE
589
590 struct stat tapset_file_stat;
591 int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
592 if (stat_rc == 0 && user_file_stat_rc == 0 &&
593 user_file_stat.st_dev == tapset_file_stat.st_dev &&
594 user_file_stat.st_ino == tapset_file_stat.st_ino)
595 {
129be0ac
FCE
596 clog << "usage error: tapset file '" << globbuf.gl_pathv[j]
597 << "' cannot be run directly as a session script." << endl;
f59e98c4
FCE
598 rc ++;
599 }
600
377b8831 601 }
d54d4661 602
377b8831
FCE
603 globfree (& globbuf);
604 }
2b066ec1
FCE
605 }
606
f4b28491 607 if (rc == 0 && s.last_pass == 1)
2b066ec1 608 {
f4b28491
FCE
609 cout << "# parse tree dump" << endl;
610 s.user_file->print (cout);
611 cout << endl;
ae56fddd
FCE
612 if (s.verbose)
613 for (unsigned i=0; i<s.library_files.size(); i++)
614 {
615 s.library_files[i]->print (cout);
616 cout << endl;
617 }
2b066ec1
FCE
618 }
619
5ee1c56b
FCE
620 struct tms tms_after;
621 times (& tms_after);
622 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
1d738eed
FCE
623 struct timeval tv_after;
624 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
625
626#define TIMESPRINT \
627 (tms_after.tms_cutime + tms_after.tms_utime \
1d738eed 628 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
5ee1c56b 629 << (tms_after.tms_cstime + tms_after.tms_stime \
1d738eed
FCE
630 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
631 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
632 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
5ee1c56b 633
eaf134e7 634 // syntax errors, if any, are already printed
5ee1c56b
FCE
635 if (s.verbose)
636 {
637 clog << "Pass 1: parsed user script and "
638 << s.library_files.size()
639 << " library script(s) in "
640 << TIMESPRINT
641 << endl;
642 }
0d49d7bc 643
2cfb0e46
FCE
644 if (rc)
645 cerr << "Pass 1: parse failed. "
213bee8f 646 << "Try again with more '-v' (verbose) options."
2cfb0e46
FCE
647 << endl;
648
0d49d7bc 649 if (rc || s.last_pass == 1) goto cleanup;
f4b28491 650
5ee1c56b 651 times (& tms_before);
1d738eed 652 gettimeofday (&tv_before, NULL);
5ee1c56b 653
2b066ec1 654 // PASS 2: ELABORATION
0d49d7bc 655 rc = semantic_pass (s);
f4b28491
FCE
656
657 if (rc == 0 && s.last_pass == 2)
1b78aef5 658 printscript(s, cout);
2b066ec1 659
5ee1c56b 660 times (& tms_after);
1d738eed
FCE
661 gettimeofday (&tv_after, NULL);
662
b0ee93c4 663 if (s.verbose) clog << "Pass 2: analyzed script: "
0d49d7bc
FCE
664 << s.probes.size() << " probe(s), "
665 << s.functions.size() << " function(s), "
b20febf3 666 << s.embeds.size() << " embed(s), "
5ee1c56b
FCE
667 << s.globals.size() << " global(s) in "
668 << TIMESPRINT
669 << endl;
0d49d7bc 670
377b8831
FCE
671 if (rc)
672 cerr << "Pass 2: analysis failed. "
213bee8f 673 << "Try again with more '-v' (verbose) options."
2cfb0e46 674 << endl;
1b78aef5
DS
675 // Generate hash. There isn't any point in generating the hash
676 // if last_pass is 2, since we'll quit before using it.
677 else if (s.last_pass != 2 && s.use_cache)
678 {
679 ostringstream o;
680 unsigned saved_verbose;
1b78aef5 681
9abec538
FCE
682 {
683 // Make sure we're in verbose mode, so that printscript()
684 // will output function/probe bodies.
685 saved_verbose = s.verbose;
686 s.verbose = 3;
687 printscript(s, o); // Print script to 'o'
688 s.verbose = saved_verbose;
689 }
1b78aef5
DS
690
691 // Generate hash
692 find_hash (s, o.str());
693
694 // See if we can use cached source/module.
695 if (get_from_cache(s))
696 {
697 // If our last pass isn't 5, we're done (since passes 3 and
698 // 4 just generate what we just pulled out of the cache).
699 if (s.last_pass < 5) goto cleanup;
700
701 // Short-circuit to pass 5.
702 goto pass_5;
703 }
704 }
377b8831 705
0d49d7bc 706 if (rc || s.last_pass == 2) goto cleanup;
f4b28491 707
2b066ec1 708 // PASS 3: TRANSLATION
5ee1c56b
FCE
709
710 times (& tms_before);
1d738eed
FCE
711 gettimeofday (&tv_before, NULL);
712
0d49d7bc 713 rc = translate_pass (s);
f4b28491
FCE
714
715 if (rc == 0 && s.last_pass == 3)
716 {
717 ifstream i (s.translated_source.c_str());
718 cout << i.rdbuf();
719 }
0d49d7bc 720
5ee1c56b 721 times (& tms_after);
1d738eed 722 gettimeofday (&tv_after, NULL);
5ee1c56b 723
0d49d7bc
FCE
724 if (s.verbose) clog << "Pass 3: translated to C into \""
725 << s.translated_source
5ee1c56b
FCE
726 << "\" in "
727 << TIMESPRINT
728 << endl;
0d49d7bc 729
377b8831 730 if (rc)
2cfb0e46 731 cerr << "Pass 3: translation failed. "
213bee8f 732 << "Try again with more '-v' (verbose) options."
2cfb0e46 733 << endl;
377b8831 734
0d49d7bc 735 if (rc || s.last_pass == 3) goto cleanup;
d54d4661 736
f4b28491 737 // PASS 4: COMPILATION
5ee1c56b 738 times (& tms_before);
1d738eed 739 gettimeofday (&tv_before, NULL);
0d49d7bc 740 rc = compile_pass (s);
9abec538
FCE
741
742 if (rc == 0 && s.last_pass == 4)
743 cout << s.hash_path << endl;
744
5ee1c56b 745 times (& tms_after);
1d738eed 746 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
747
748 if (s.verbose) clog << "Pass 4: compiled C into \""
749 << s.module_name << ".ko"
750 << "\" in "
751 << TIMESPRINT
752 << endl;
f4b28491 753
eaf134e7
FCE
754 if (rc)
755 cerr << "Pass 4: compilation failed. "
213bee8f 756 << "Try again with more '-v' (verbose) options."
2cfb0e46 757 << endl;
1b78aef5
DS
758 else if (s.use_cache)
759 {
760 // Update cache.
761 add_to_cache(s);
762 }
eaf134e7 763
0d49d7bc 764 if (rc || s.last_pass == 4) goto cleanup;
f4b28491 765
9abec538 766
0d49d7bc 767 // PASS 5: RUN
1b78aef5 768pass_5:
5ee1c56b 769 times (& tms_before);
1d738eed 770 gettimeofday (&tv_before, NULL);
03d569d3
FCE
771 // NB: this message is a judgement call. The other passes don't emit
772 // a "hello, I'm starting" message, but then the others aren't interactive
773 // and don't take an indefinite amount of time.
774 if (s.verbose) clog << "Pass 5: starting run." << endl;
0d49d7bc 775 rc = run_pass (s);
5ee1c56b 776 times (& tms_after);
1d738eed 777 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
778 if (s.verbose) clog << "Pass 5: run completed in "
779 << TIMESPRINT
780 << endl;
f4b28491 781
eaf134e7
FCE
782 if (rc)
783 cerr << "Pass 5: run failed. "
213bee8f 784 << "Try again with more '-v' (verbose) options."
2cfb0e46 785 << endl;
eaf134e7 786
0d49d7bc 787 // if (rc) goto cleanup;
2b066ec1 788
0d49d7bc 789 cleanup:
f4b28491
FCE
790 // Clean up temporary directory. Obviously, be careful with this.
791 if (s.tmpdir == "")
792 ; // do nothing
793 else
794 {
795 if (s.keep_tmpdir)
0d49d7bc 796 clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491
FCE
797 else
798 {
ce3187ac 799 string cleanupcmd = "rm -rf ";
f4b28491 800 cleanupcmd += s.tmpdir;
b0ee93c4 801 if (s.verbose>1) clog << "Running " << cleanupcmd << endl;
d54d4661 802 int status = system (cleanupcmd.c_str());
b0ee93c4 803 if (status != 0 && s.verbose>1)
d54d4661 804 clog << "Cleanup command failed, status: " << status << endl;
f4b28491
FCE
805 }
806 }
2b066ec1 807
54dfabe9 808 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
2b066ec1 809}
This page took 0.144361 seconds and 5 git commands to generate.