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