]>
Commit | Line | Data |
---|---|---|
f4b28491 | 1 | // systemtap translator/driver |
213bee8f | 2 | // Copyright (C) 2005-2006 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" |
2b066ec1 FCE |
17 | |
18 | #include <iostream> | |
19 | #include <fstream> | |
20 | #include <sstream> | |
f4b28491 | 21 | #include <cerrno> |
24cb178f | 22 | #include <cstdlib> |
2b066ec1 FCE |
23 | |
24 | extern "C" { | |
25 | #include <glob.h> | |
26 | #include <unistd.h> | |
f4b28491 | 27 | #include <sys/utsname.h> |
5ee1c56b | 28 | #include <sys/times.h> |
1d738eed | 29 | #include <sys/time.h> |
f4b28491 | 30 | #include <time.h> |
f8949662 | 31 | #include <elfutils/libdwfl.h> |
2b066ec1 FCE |
32 | } |
33 | ||
34 | using namespace std; | |
35 | ||
36 | ||
f4b28491 | 37 | void |
c0de7a8d | 38 | version () |
2b066ec1 | 39 | { |
d54d4661 | 40 | clog |
d04cf5ff | 41 | << "SystemTap translator/driver " |
f4b28491 | 42 | << "(version " << VERSION << " built " << DATE << ")" << endl |
f8949662 | 43 | << "(Using " << dwfl_version (NULL) << " libraries.)" << endl |
b9b91512 | 44 | << "Copyright (C) 2005-2006 Red Hat, Inc. and others" << endl |
f8949662 | 45 | << "This is free software; see the source for copying conditions." << endl; |
c0de7a8d FCE |
46 | } |
47 | ||
48 | void | |
277c1957 | 49 | usage (systemtap_session& s, int exitcode) |
c0de7a8d FCE |
50 | { |
51 | version (); | |
52 | clog | |
f4b28491 | 53 | << endl |
b2d5d95c | 54 | << "Usage: stap [options] FILE Run script in file." |
f4b28491 | 55 | << endl |
b2d5d95c | 56 | << " or: stap [options] - Run script on stdin." |
f4b28491 | 57 | << endl |
d54d4661 | 58 | << " or: stap [options] -e SCRIPT Run given script." |
f4b28491 FCE |
59 | << endl |
60 | << endl | |
c0de7a8d | 61 | << "Options:" << endl |
f4b28491 | 62 | << " -- no more options after this" << endl |
b0ee93c4 | 63 | << " -v increase verbosity [" << s.verbose << "]" << endl |
c0de7a8d FCE |
64 | << " -h show help" << endl |
65 | << " -V show version" << endl | |
d5d7c2cc | 66 | << " -k keep temporary directory" << endl |
cbfbbf69 | 67 | << " -u unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl |
377b8831 | 68 | << " -g guru mode" << (s.guru_mode ? " [set]" : "") << endl |
f12b2552 | 69 | << " -b bulk (relayfs) mode" << (s.bulk_mode ? " [set]" : "") << endl |
f272aacc | 70 | << " -M Don't merge per-cpu files for bulk (relayfs) mode" << (s.merge ? "" : " [set]") << endl |
177a8ead FCE |
71 | << " -s NUM buffer size in megabytes, instead of " |
72 | << s.buffer_size << endl | |
f8949662 | 73 | << " -p NUM stop after pass NUM 1-5, instead of " |
177a8ead | 74 | << s.last_pass << endl |
f4b28491 FCE |
75 | << " (parse, elaborate, translate, compile, run)" << endl |
76 | << " -I DIR look in DIR for additional .stp script files"; | |
77 | if (s.include_path.size() == 0) | |
0d49d7bc | 78 | clog << endl; |
f4b28491 | 79 | else |
24cb178f | 80 | clog << ", in addition to" << endl; |
f4b28491 | 81 | for (unsigned i=0; i<s.include_path.size(); i++) |
0d49d7bc FCE |
82 | clog << " " << s.include_path[i] << endl; |
83 | clog | |
ed10c639 | 84 | << " -D NM=VAL emit macro definition into generated C code" << endl |
24cb178f FCE |
85 | << " -R DIR look in DIR for runtime, instead of" << endl |
86 | << " " << s.runtime_path << endl | |
177a8ead FCE |
87 | << " -r RELEASE use kernel RELEASE, instead of " |
88 | << s.kernel_release << endl | |
f12b2552 FCE |
89 | << " -m MODULE set probe module name, instead of " |
90 | << s.module_name << endl | |
177a8ead | 91 | << " -o FILE send output to file, instead of stdout" << endl |
f8949662 | 92 | << " -c CMD start the probes, run CMD, and exit when it finishes" |
f12b2552 | 93 | << endl |
4c5ff1bb | 94 | << " -x PID sets target() to PID" << endl |
4b17d6af | 95 | << " -t benchmarking timing information generated" << endl |
d5d7c2cc | 96 | ; |
d54d4661 | 97 | // -d: dump safety-related external references |
2b066ec1 | 98 | |
277c1957 | 99 | exit (exitcode); |
2b066ec1 FCE |
100 | } |
101 | ||
102 | ||
f4b28491 FCE |
103 | // little utility function |
104 | ||
105 | template <typename T> | |
106 | static string | |
107 | stringify(T t) | |
108 | { | |
109 | ostringstream s; | |
110 | s << t; | |
111 | return s.str (); | |
112 | } | |
113 | ||
114 | ||
2b066ec1 FCE |
115 | int |
116 | main (int argc, char * const argv []) | |
117 | { | |
2b066ec1 FCE |
118 | string cmdline_script; // -e PROGRAM |
119 | string script_file; // FILE | |
120 | bool have_script = false; | |
f4b28491 FCE |
121 | |
122 | // Initialize defaults | |
123 | systemtap_session s; | |
124 | struct utsname buf; | |
125 | (void) uname (& buf); | |
126 | s.kernel_release = string (buf.release); | |
44ce8ed5 | 127 | s.architecture = string (buf.machine); |
b0ee93c4 | 128 | s.verbose = 0; |
4b17d6af | 129 | s.timing = 0; |
377b8831 | 130 | s.guru_mode = false; |
16d8de1b | 131 | s.bulk_mode = false; |
cbfbbf69 | 132 | s.unoptimized = false; |
16d8de1b | 133 | s.buffer_size = 0; |
f4b28491 | 134 | s.last_pass = 5; |
ae24723e | 135 | s.module_name = "stap_" + stringify(getpid()); |
08c68653 | 136 | s.output_file = ""; // -o FILE |
f4b28491 | 137 | s.keep_tmpdir = false; |
4c5ff1bb MH |
138 | s.cmd = ""; |
139 | s.target_pid = 0; | |
f272aacc | 140 | s.merge=true; |
24cb178f FCE |
141 | |
142 | const char* s_p = getenv ("SYSTEMTAP_TAPSET"); | |
ec819dc3 LG |
143 | if (s_p != NULL) |
144 | { | |
24cb178f | 145 | s.include_path.push_back (s_p); |
ec819dc3 LG |
146 | s.include_path.push_back (string(s_p) + "/LKET"); |
147 | } | |
24cb178f | 148 | else |
ec819dc3 | 149 | { |
24cb178f | 150 | s.include_path.push_back (string(PKGDATADIR) + "/tapset"); |
ec819dc3 LG |
151 | s.include_path.push_back (string(PKGDATADIR) + "/tapset/LKET"); |
152 | } | |
24cb178f FCE |
153 | |
154 | const char* s_r = getenv ("SYSTEMTAP_RUNTIME"); | |
155 | if (s_r != NULL) | |
156 | s.runtime_path = s_r; | |
157 | else | |
158 | s.runtime_path = string(PKGDATADIR) + "/runtime"; | |
f4b28491 | 159 | |
2b066ec1 FCE |
160 | while (true) |
161 | { | |
f272aacc | 162 | int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgc:x:D:bs:u"); |
2b066ec1 FCE |
163 | if (grc < 0) |
164 | break; | |
165 | switch (grc) | |
166 | { | |
c0de7a8d FCE |
167 | case 'V': |
168 | version (); | |
169 | exit (0); | |
170 | ||
f272aacc LG |
171 | case 'M': |
172 | s.merge = false; | |
173 | break; | |
174 | ||
bd2b1e68 | 175 | case 'v': |
b0ee93c4 | 176 | s.verbose ++; |
bd2b1e68 GH |
177 | break; |
178 | ||
4b17d6af WC |
179 | case 't': |
180 | s.timing ++; | |
181 | break; | |
182 | ||
2b066ec1 | 183 | case 'p': |
f4b28491 FCE |
184 | s.last_pass = atoi (optarg); |
185 | if (s.last_pass < 1 || s.last_pass > 5) | |
2b066ec1 | 186 | { |
277c1957 DS |
187 | cerr << "Invalid pass number (should be 1-5)." << endl; |
188 | usage (s, 1); | |
2b066ec1 FCE |
189 | } |
190 | break; | |
191 | ||
192 | case 'I': | |
f4b28491 | 193 | s.include_path.push_back (string (optarg)); |
2b066ec1 FCE |
194 | break; |
195 | ||
196 | case 'e': | |
197 | if (have_script) | |
277c1957 DS |
198 | { |
199 | cerr << "Only one script can be given on the command line." | |
200 | << endl; | |
201 | usage (s, 1); | |
202 | } | |
2b066ec1 FCE |
203 | cmdline_script = string (optarg); |
204 | have_script = true; | |
205 | break; | |
206 | ||
207 | case 'o': | |
08c68653 | 208 | s.output_file = string (optarg); |
2b066ec1 FCE |
209 | break; |
210 | ||
f4b28491 FCE |
211 | case 'R': |
212 | s.runtime_path = string (optarg); | |
213 | break; | |
214 | ||
215 | case 'm': | |
216 | s.module_name = string (optarg); | |
217 | break; | |
218 | ||
219 | case 'r': | |
220 | s.kernel_release = string (optarg); | |
221 | break; | |
222 | ||
223 | case 'k': | |
224 | s.keep_tmpdir = true; | |
225 | break; | |
226 | ||
377b8831 FCE |
227 | case 'g': |
228 | s.guru_mode = true; | |
229 | break; | |
230 | ||
16d8de1b TZ |
231 | case 'b': |
232 | s.bulk_mode = true; | |
16d8de1b TZ |
233 | break; |
234 | ||
cbfbbf69 FCE |
235 | case 'u': |
236 | s.unoptimized = true; | |
237 | break; | |
238 | ||
16d8de1b TZ |
239 | case 's': |
240 | s.buffer_size = atoi (optarg); | |
241 | if (s.buffer_size < 1 || s.buffer_size > 64) | |
242 | { | |
277c1957 DS |
243 | cerr << "Invalid buffer size (should be 1-64)." << endl; |
244 | usage (s, 1); | |
16d8de1b TZ |
245 | } |
246 | break; | |
247 | ||
4c5ff1bb MH |
248 | case 'c': |
249 | s.cmd = string (optarg); | |
250 | break; | |
251 | ||
252 | case 'x': | |
253 | s.target_pid = atoi(optarg); | |
254 | break; | |
255 | ||
ed10c639 FCE |
256 | case 'D': |
257 | s.macros.push_back (string (optarg)); | |
258 | break; | |
259 | ||
2b066ec1 | 260 | case 'h': |
277c1957 DS |
261 | usage (s, 0); |
262 | break; | |
263 | ||
2b066ec1 | 264 | default: |
277c1957 DS |
265 | usage (s, 1); |
266 | break; | |
2b066ec1 FCE |
267 | } |
268 | } | |
269 | ||
f272aacc LG |
270 | if(!s.bulk_mode && !s.merge) |
271 | { | |
272 | cerr << "-M option is valid only for bulk (relayfs) mode." <<endl; | |
277c1957 | 273 | usage (s, 1); |
f272aacc LG |
274 | } |
275 | ||
276 | if(!s.output_file.empty() && s.bulk_mode && !s.merge) | |
277 | { | |
278 | cerr << "You can't specify -M, -b and -o options together." <<endl; | |
277c1957 | 279 | usage (s, 1); |
f272aacc LG |
280 | } |
281 | ||
2b066ec1 FCE |
282 | for (int i = optind; i < argc; i++) |
283 | { | |
284 | if (! have_script) | |
285 | { | |
286 | script_file = string (argv[i]); | |
287 | have_script = true; | |
288 | } | |
289 | else | |
f4b28491 | 290 | s.args.push_back (string (argv[i])); |
2b066ec1 FCE |
291 | } |
292 | ||
293 | // need a user file | |
294 | if (! have_script) | |
277c1957 DS |
295 | { |
296 | cerr << "A script must be specified." << endl; | |
297 | usage(s, 1); | |
298 | } | |
f4b28491 FCE |
299 | |
300 | int rc = 0; | |
2b066ec1 | 301 | |
ce3187ac | 302 | // override PATH and LC_ALL |
f8949662 | 303 | char* path = "PATH=/bin:/sbin:/usr/bin:/usr/sbin"; |
ce3187ac FCE |
304 | char* lc_all = "LC_ALL=C"; |
305 | rc = putenv (path) || putenv (lc_all); | |
306 | if (rc) | |
307 | { | |
308 | const char* e = strerror (errno); | |
309 | cerr << "setenv (\"" << path << "\" + \"" << lc_all << "\"): " | |
310 | << e << endl; | |
311 | } | |
f8949662 | 312 | |
ce3187ac | 313 | |
2b066ec1 FCE |
314 | // arguments parsed; get down to business |
315 | ||
f4b28491 FCE |
316 | // Create a temporary directory to build within. |
317 | // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end. | |
318 | { | |
ea8ea02c FCE |
319 | char* tmpdir_env = getenv("TMPDIR"); |
320 | if (! tmpdir_env) | |
321 | tmpdir_env = "/tmp"; | |
322 | ||
323 | string stapdir = "/stapXXXXXX"; | |
324 | string tmpdirt = tmpdir_env + stapdir; | |
325 | const char* tmpdir = mkdtemp((char *)tmpdirt.c_str()); | |
f4b28491 FCE |
326 | if (! tmpdir) |
327 | { | |
328 | const char* e = strerror (errno); | |
ea8ea02c FCE |
329 | cerr << "ERROR: cannot create temporary directory (\"" << tmpdirt << "\"): " << e << endl; |
330 | exit (1); // die | |
f4b28491 FCE |
331 | } |
332 | else | |
333 | s.tmpdir = tmpdir; | |
0d49d7bc | 334 | |
b0ee93c4 | 335 | if (s.verbose>1) |
0d49d7bc | 336 | clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl; |
f4b28491 | 337 | } |
2b066ec1 | 338 | |
5ee1c56b FCE |
339 | struct tms tms_before; |
340 | times (& tms_before); | |
1d738eed FCE |
341 | struct timeval tv_before; |
342 | gettimeofday (&tv_before, NULL); | |
2b066ec1 FCE |
343 | |
344 | // PASS 1a: PARSING USER SCRIPT | |
345 | // XXX: pass args vector, so parser (or lexer?) can substitute | |
346 | // $1..$NN with actual arguments | |
69c68955 | 347 | if (script_file == "-") |
177a8ead | 348 | s.user_file = parser::parse (s, cin, s.guru_mode); |
69c68955 | 349 | else if (script_file != "") |
177a8ead | 350 | s.user_file = parser::parse (s, script_file, s.guru_mode); |
2b066ec1 FCE |
351 | else |
352 | { | |
353 | istringstream ii (cmdline_script); | |
177a8ead | 354 | s.user_file = parser::parse (s, ii, s.guru_mode); |
2b066ec1 FCE |
355 | } |
356 | if (s.user_file == 0) | |
357 | // syntax errors already printed | |
358 | rc ++; | |
377b8831 | 359 | |
5519d363 | 360 | // Construct arch / kernel-versioning search path |
377b8831 | 361 | vector<string> version_suffixes; |
6f9f33e2 | 362 | string kvr = s.kernel_release; |
5519d363 KS |
363 | const string& arch = s.architecture; |
364 | // add full kernel-version-release (2.6.NN-FOOBAR) + arch | |
365 | version_suffixes.push_back ("/" + kvr + "/" + arch); | |
377b8831 | 366 | version_suffixes.push_back ("/" + kvr); |
5519d363 | 367 | // add kernel version (2.6.NN) + arch |
77a5c1f9 JS |
368 | string::size_type dash_index = kvr.find ('-'); |
369 | if (dash_index > 0 && dash_index != string::npos) { | |
6f9f33e2 JS |
370 | kvr.erase(dash_index); |
371 | version_suffixes.push_back ("/" + kvr + "/" + arch); | |
372 | version_suffixes.push_back ("/" + kvr); | |
5519d363 KS |
373 | } |
374 | // add kernel family (2.6) + arch | |
6f9f33e2 JS |
375 | string::size_type dot1_index = kvr.find ('.'); |
376 | string::size_type dot2_index = kvr.rfind ('.'); | |
377 | while (dot2_index > dot1_index && dot2_index != string::npos) { | |
378 | kvr.erase(dot2_index); | |
379 | version_suffixes.push_back ("/" + kvr + "/" + arch); | |
380 | version_suffixes.push_back ("/" + kvr); | |
381 | dot2_index = kvr.rfind ('.'); | |
5519d363 KS |
382 | } |
383 | // add architecture search path | |
384 | version_suffixes.push_back("/" + arch); | |
377b8831 FCE |
385 | // add empty string as last element |
386 | version_suffixes.push_back (""); | |
2b066ec1 FCE |
387 | |
388 | // PASS 1b: PARSING LIBRARY SCRIPTS | |
f4b28491 | 389 | for (unsigned i=0; i<s.include_path.size(); i++) |
2b066ec1 | 390 | { |
377b8831 FCE |
391 | // now iterate upon it |
392 | for (unsigned k=0; k<version_suffixes.size(); k++) | |
2b066ec1 | 393 | { |
377b8831 FCE |
394 | glob_t globbuf; |
395 | string dir = s.include_path[i] + version_suffixes[k] + "/*.stp"; | |
396 | int r = glob(dir.c_str (), 0, NULL, & globbuf); | |
397 | if (r == GLOB_NOSPACE || r == GLOB_ABORTED) | |
2b066ec1 | 398 | rc ++; |
377b8831 FCE |
399 | // GLOB_NOMATCH is acceptable |
400 | ||
b0ee93c4 | 401 | if (s.verbose>1) |
377b8831 FCE |
402 | clog << "Searched '" << dir << "', " |
403 | << "match count " << globbuf.gl_pathc << endl; | |
2b066ec1 | 404 | |
377b8831 FCE |
405 | for (unsigned j=0; j<globbuf.gl_pathc; j++) |
406 | { | |
24cb178f | 407 | // privilege only for /usr/share/systemtap? |
177a8ead | 408 | stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true); |
377b8831 FCE |
409 | if (f == 0) |
410 | rc ++; | |
411 | else | |
24cb178f | 412 | s.library_files.push_back (f); |
377b8831 | 413 | } |
d54d4661 | 414 | |
377b8831 FCE |
415 | globfree (& globbuf); |
416 | } | |
2b066ec1 FCE |
417 | } |
418 | ||
f4b28491 | 419 | if (rc == 0 && s.last_pass == 1) |
2b066ec1 | 420 | { |
f4b28491 FCE |
421 | cout << "# parse tree dump" << endl; |
422 | s.user_file->print (cout); | |
423 | cout << endl; | |
ae56fddd FCE |
424 | if (s.verbose) |
425 | for (unsigned i=0; i<s.library_files.size(); i++) | |
426 | { | |
427 | s.library_files[i]->print (cout); | |
428 | cout << endl; | |
429 | } | |
2b066ec1 FCE |
430 | } |
431 | ||
5ee1c56b FCE |
432 | struct tms tms_after; |
433 | times (& tms_after); | |
434 | unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK); | |
1d738eed FCE |
435 | struct timeval tv_after; |
436 | gettimeofday (&tv_after, NULL); | |
5ee1c56b FCE |
437 | |
438 | #define TIMESPRINT \ | |
439 | (tms_after.tms_cutime + tms_after.tms_utime \ | |
1d738eed | 440 | - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \ |
5ee1c56b | 441 | << (tms_after.tms_cstime + tms_after.tms_stime \ |
1d738eed FCE |
442 | - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \ |
443 | << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \ | |
444 | ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms." | |
5ee1c56b | 445 | |
eaf134e7 | 446 | // syntax errors, if any, are already printed |
5ee1c56b FCE |
447 | if (s.verbose) |
448 | { | |
449 | clog << "Pass 1: parsed user script and " | |
450 | << s.library_files.size() | |
451 | << " library script(s) in " | |
452 | << TIMESPRINT | |
453 | << endl; | |
454 | } | |
0d49d7bc | 455 | |
2cfb0e46 FCE |
456 | if (rc) |
457 | cerr << "Pass 1: parse failed. " | |
213bee8f | 458 | << "Try again with more '-v' (verbose) options." |
2cfb0e46 FCE |
459 | << endl; |
460 | ||
0d49d7bc | 461 | if (rc || s.last_pass == 1) goto cleanup; |
f4b28491 | 462 | |
5ee1c56b | 463 | times (& tms_before); |
1d738eed | 464 | gettimeofday (&tv_before, NULL); |
5ee1c56b | 465 | |
2b066ec1 | 466 | // PASS 2: ELABORATION |
0d49d7bc | 467 | rc = semantic_pass (s); |
f4b28491 FCE |
468 | |
469 | if (rc == 0 && s.last_pass == 2) | |
2b066ec1 | 470 | { |
553d27a5 | 471 | if (s.globals.size() > 0) |
f4b28491 | 472 | cout << "# globals" << endl; |
2b066ec1 FCE |
473 | for (unsigned i=0; i<s.globals.size(); i++) |
474 | { | |
475 | vardecl* v = s.globals[i]; | |
f4b28491 FCE |
476 | v->printsig (cout); |
477 | cout << endl; | |
2b066ec1 FCE |
478 | } |
479 | ||
553d27a5 | 480 | if (s.functions.size() > 0) |
f4b28491 | 481 | cout << "# functions" << endl; |
2b066ec1 FCE |
482 | for (unsigned i=0; i<s.functions.size(); i++) |
483 | { | |
484 | functiondecl* f = s.functions[i]; | |
f4b28491 FCE |
485 | f->printsig (cout); |
486 | cout << endl; | |
553d27a5 | 487 | if (f->locals.size() > 0) |
f4b28491 | 488 | cout << " # locals" << endl; |
553d27a5 FCE |
489 | for (unsigned j=0; j<f->locals.size(); j++) |
490 | { | |
491 | vardecl* v = f->locals[j]; | |
f4b28491 FCE |
492 | cout << " "; |
493 | v->printsig (cout); | |
494 | cout << endl; | |
553d27a5 | 495 | } |
cbfbbf69 FCE |
496 | if (s.verbose) |
497 | { | |
498 | f->body->print (cout); | |
499 | cout << endl; | |
500 | } | |
2b066ec1 FCE |
501 | } |
502 | ||
553d27a5 | 503 | if (s.probes.size() > 0) |
f4b28491 | 504 | cout << "# probes" << endl; |
2b066ec1 FCE |
505 | for (unsigned i=0; i<s.probes.size(); i++) |
506 | { | |
507 | derived_probe* p = s.probes[i]; | |
f4b28491 FCE |
508 | p->printsig (cout); |
509 | cout << endl; | |
553d27a5 | 510 | if (p->locals.size() > 0) |
f4b28491 | 511 | cout << " # locals" << endl; |
553d27a5 FCE |
512 | for (unsigned j=0; j<p->locals.size(); j++) |
513 | { | |
514 | vardecl* v = p->locals[j]; | |
f4b28491 FCE |
515 | cout << " "; |
516 | v->printsig (cout); | |
517 | cout << endl; | |
553d27a5 | 518 | } |
cbfbbf69 FCE |
519 | if (s.verbose) |
520 | { | |
521 | p->body->print (cout); | |
522 | cout << endl; | |
523 | } | |
2b066ec1 FCE |
524 | } |
525 | } | |
526 | ||
5ee1c56b | 527 | times (& tms_after); |
1d738eed FCE |
528 | gettimeofday (&tv_after, NULL); |
529 | ||
b0ee93c4 | 530 | if (s.verbose) clog << "Pass 2: analyzed script: " |
0d49d7bc FCE |
531 | << s.probes.size() << " probe(s), " |
532 | << s.functions.size() << " function(s), " | |
5ee1c56b FCE |
533 | << s.globals.size() << " global(s) in " |
534 | << TIMESPRINT | |
535 | << endl; | |
0d49d7bc | 536 | |
377b8831 FCE |
537 | if (rc) |
538 | cerr << "Pass 2: analysis failed. " | |
213bee8f | 539 | << "Try again with more '-v' (verbose) options." |
2cfb0e46 | 540 | << endl; |
377b8831 | 541 | |
0d49d7bc | 542 | if (rc || s.last_pass == 2) goto cleanup; |
f4b28491 | 543 | |
2b066ec1 | 544 | // PASS 3: TRANSLATION |
5ee1c56b FCE |
545 | |
546 | times (& tms_before); | |
1d738eed FCE |
547 | gettimeofday (&tv_before, NULL); |
548 | ||
0d49d7bc FCE |
549 | s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; |
550 | rc = translate_pass (s); | |
f4b28491 FCE |
551 | |
552 | if (rc == 0 && s.last_pass == 3) | |
553 | { | |
554 | ifstream i (s.translated_source.c_str()); | |
555 | cout << i.rdbuf(); | |
556 | } | |
0d49d7bc | 557 | |
5ee1c56b | 558 | times (& tms_after); |
1d738eed | 559 | gettimeofday (&tv_after, NULL); |
5ee1c56b | 560 | |
0d49d7bc FCE |
561 | if (s.verbose) clog << "Pass 3: translated to C into \"" |
562 | << s.translated_source | |
5ee1c56b FCE |
563 | << "\" in " |
564 | << TIMESPRINT | |
565 | << endl; | |
0d49d7bc | 566 | |
377b8831 | 567 | if (rc) |
2cfb0e46 | 568 | cerr << "Pass 3: translation failed. " |
213bee8f | 569 | << "Try again with more '-v' (verbose) options." |
2cfb0e46 | 570 | << endl; |
377b8831 | 571 | |
0d49d7bc | 572 | if (rc || s.last_pass == 3) goto cleanup; |
d54d4661 | 573 | |
f4b28491 | 574 | // PASS 4: COMPILATION |
5ee1c56b | 575 | times (& tms_before); |
1d738eed | 576 | gettimeofday (&tv_before, NULL); |
0d49d7bc | 577 | rc = compile_pass (s); |
5ee1c56b | 578 | times (& tms_after); |
1d738eed | 579 | gettimeofday (&tv_after, NULL); |
5ee1c56b FCE |
580 | |
581 | if (s.verbose) clog << "Pass 4: compiled C into \"" | |
582 | << s.module_name << ".ko" | |
583 | << "\" in " | |
584 | << TIMESPRINT | |
585 | << endl; | |
f4b28491 | 586 | |
eaf134e7 FCE |
587 | if (rc) |
588 | cerr << "Pass 4: compilation failed. " | |
213bee8f | 589 | << "Try again with more '-v' (verbose) options." |
2cfb0e46 | 590 | << endl; |
eaf134e7 | 591 | |
f8949662 | 592 | // XXX: what to do if rc==0 && last_pass == 4? dump .ko file to stdout? |
0d49d7bc | 593 | if (rc || s.last_pass == 4) goto cleanup; |
f4b28491 | 594 | |
0d49d7bc | 595 | // PASS 5: RUN |
5ee1c56b | 596 | times (& tms_before); |
1d738eed | 597 | gettimeofday (&tv_before, NULL); |
03d569d3 FCE |
598 | // NB: this message is a judgement call. The other passes don't emit |
599 | // a "hello, I'm starting" message, but then the others aren't interactive | |
600 | // and don't take an indefinite amount of time. | |
601 | if (s.verbose) clog << "Pass 5: starting run." << endl; | |
0d49d7bc | 602 | rc = run_pass (s); |
5ee1c56b | 603 | times (& tms_after); |
1d738eed | 604 | gettimeofday (&tv_after, NULL); |
5ee1c56b FCE |
605 | if (s.verbose) clog << "Pass 5: run completed in " |
606 | << TIMESPRINT | |
607 | << endl; | |
f4b28491 | 608 | |
eaf134e7 FCE |
609 | if (rc) |
610 | cerr << "Pass 5: run failed. " | |
213bee8f | 611 | << "Try again with more '-v' (verbose) options." |
2cfb0e46 | 612 | << endl; |
eaf134e7 | 613 | |
0d49d7bc | 614 | // if (rc) goto cleanup; |
2b066ec1 | 615 | |
0d49d7bc | 616 | cleanup: |
f4b28491 FCE |
617 | // Clean up temporary directory. Obviously, be careful with this. |
618 | if (s.tmpdir == "") | |
619 | ; // do nothing | |
620 | else | |
621 | { | |
622 | if (s.keep_tmpdir) | |
0d49d7bc | 623 | clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl; |
f4b28491 FCE |
624 | else |
625 | { | |
ce3187ac | 626 | string cleanupcmd = "rm -rf "; |
f4b28491 | 627 | cleanupcmd += s.tmpdir; |
b0ee93c4 | 628 | if (s.verbose>1) clog << "Running " << cleanupcmd << endl; |
d54d4661 | 629 | int status = system (cleanupcmd.c_str()); |
b0ee93c4 | 630 | if (status != 0 && s.verbose>1) |
d54d4661 | 631 | clog << "Cleanup command failed, status: " << status << endl; |
f4b28491 FCE |
632 | } |
633 | } | |
2b066ec1 | 634 | |
54dfabe9 | 635 | return rc ? EXIT_FAILURE : EXIT_SUCCESS; |
2b066ec1 | 636 | } |