]> sourceware.org Git - systemtap.git/blame - main.cxx
YAAU (Yet Another AUTHORS Update)
[systemtap.git] / main.cxx
CommitLineData
f4b28491 1// systemtap translator/driver
e7a0bd52 2// Copyright (C) 2005-2009 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"
c0f9d4b0 22#include "git_version.h"
2b066ec1
FCE
23
24#include <iostream>
25#include <fstream>
26#include <sstream>
f4b28491 27#include <cerrno>
24cb178f 28#include <cstdlib>
e00f99a7 29#include <limits.h>
2b066ec1
FCE
30
31extern "C" {
32#include <glob.h>
33#include <unistd.h>
49abf162 34#include <signal.h>
f4b28491 35#include <sys/utsname.h>
5ee1c56b 36#include <sys/times.h>
1d738eed 37#include <sys/time.h>
f59e98c4 38#include <sys/stat.h>
f4b28491 39#include <time.h>
f8949662 40#include <elfutils/libdwfl.h>
5f0a03a6 41#include <getopt.h>
2b066ec1
FCE
42}
43
44using namespace std;
45
46
f4b28491 47void
c0de7a8d 48version ()
2b066ec1 49{
d54d4661 50 clog
d04cf5ff 51 << "SystemTap translator/driver "
c4a94c1a 52 << "(version " << VERSION << "/" << dwfl_version (NULL)
2881ab63 53 << " " << GIT_MESSAGE << ")" << endl
e7a0bd52 54 << "Copyright (C) 2005-2009 Red Hat, Inc. and others" << endl
f8949662 55 << "This is free software; see the source for copying conditions." << endl;
c0de7a8d
FCE
56}
57
58void
277c1957 59usage (systemtap_session& s, int exitcode)
c0de7a8d
FCE
60{
61 version ();
62 clog
f4b28491 63 << endl
b2d5d95c 64 << "Usage: stap [options] FILE Run script in file."
f4b28491 65 << endl
b2d5d95c 66 << " or: stap [options] - Run script on stdin."
f4b28491 67 << endl
d54d4661 68 << " or: stap [options] -e SCRIPT Run given script."
f4b28491 69 << endl
16442b90
FCE
70 << " or: stap [options] -l PROBE List matching probes."
71 << endl
d4e35ac8
WH
72 << " or: stap [options] -L PROBE List matching probes and local variables."
73 << endl
f4b28491 74 << endl
c0de7a8d 75 << "Options:" << endl
16442b90 76 << " -- end of translator options, script options follow" << endl
c0de7a8d
FCE
77 << " -h show help" << endl
78 << " -V show version" << endl
e0b4e89d
FCE
79 << " -p NUM stop after pass NUM 1-5, instead of " << s.last_pass << endl
80 << " (parse, elaborate, translate, compile, run)" << endl
81 << " -v add verbosity to all passes" << endl
82 << " --vp {N}+ add per-pass verbosity [";
83 for (unsigned i=0; i<5; i++)
84 clog << (s.perpass_verbose[i] <= 9 ? s.perpass_verbose[i] : 9);
85 clog
86 << "]" << endl
d5d7c2cc 87 << " -k keep temporary directory" << endl
cbfbbf69 88 << " -u unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl
a9e8f7e0 89 << " -w suppress warnings" << (s.suppress_warnings ? " [set]" : "") << endl
377b8831 90 << " -g guru mode" << (s.guru_mode ? " [set]" : "") << endl
dff50e09 91 << " -P prologue-searching for function probes"
44f75386 92 << (s.prologue_searching ? " [set]" : "") << endl
6dfd08d7 93 << " -b bulk (percpu file) mode" << (s.bulk_mode ? " [set]" : "") << endl
e0b4e89d 94 << " -s NUM buffer size in megabytes, instead of " << s.buffer_size << endl
f4b28491
FCE
95 << " -I DIR look in DIR for additional .stp script files";
96 if (s.include_path.size() == 0)
0d49d7bc 97 clog << endl;
f4b28491 98 else
24cb178f 99 clog << ", in addition to" << endl;
f4b28491 100 for (unsigned i=0; i<s.include_path.size(); i++)
0d49d7bc
FCE
101 clog << " " << s.include_path[i] << endl;
102 clog
ed10c639 103 << " -D NM=VAL emit macro definition into generated C code" << endl
24cb178f 104 << " -R DIR look in DIR for runtime, instead of" << endl
b5e66ada
FCE
105 << " " << s.runtime_path << endl
106 << " -r DIR cross-compile to kernel with given build tree; or else" << endl
107 << " -r RELEASE cross-compile to kernel /lib/modules/RELEASE/build, instead of" << endl
108 << " " << s.kernel_build_tree << endl
109 << " -m MODULE set probe module name, instead of " << endl
110 << " " << s.module_name << endl
04ae1b09 111 << " -o FILE send script output to file, instead of stdout. This supports" << endl
54f1da8f 112 << " strftime(3) formats for FILE" << endl
b5e66ada 113 << " -c CMD start the probes, run CMD, and exit when it finishes" << endl
4c5ff1bb 114 << " -x PID sets target() to PID" << endl
701c41be
MH
115 << " -F run as on-file flight recorder with -o." << endl
116 << " run as on-memory flight recorder without -o." << endl
117 << " -S size[,n] set maximum of the size and the number of files." << endl
a8368458
FCE
118 << " -d OBJECT add unwind/symbol data for OBJECT file";
119 if (s.unwindsym_modules.size() == 0)
120 clog << endl;
121 else
122 clog << ", in addition to" << endl;
1a0dbc5a
FCE
123 {
124 vector<string> syms (s.unwindsym_modules.begin(), s.unwindsym_modules.end());
125 for (unsigned i=0; i<syms.size(); i++)
126 clog << " " << syms[i] << endl;
127 }
a8368458 128 clog
cbd6fc7b 129 << " -t collect probe timing information" << endl
1c0b94ef 130#ifdef HAVE_LIBSQLITE3
5f0a03a6 131 << " -q generate information on tapset coverage" << endl
1c0b94ef 132#endif /* HAVE_LIBSQLITE3 */
05ec91b4 133#if 0 /* PR6864: disable temporarily; should merge with -d somehow */
5f0a03a6
JK
134 << " --kelf make do with symbol table from vmlinux" << endl
135 << " --kmap[=FILE]" << endl
136 << " make do with symbol table from nm listing" << endl
05ec91b4
FCE
137#endif
138 // Formerly present --ignore-{vmlinux,dwarf} options are for testsuite use
139 // only, and don't belong in the eyesight of a plain user.
3bd0d4df
RA
140 << " --skip-badvars" << endl
141 << " overlook context of bad $ variables" << endl
c3a3c0c9 142 << endl
d5d7c2cc 143 ;
2b066ec1 144
277c1957 145 exit (exitcode);
2b066ec1
FCE
146}
147
148
1b78aef5
DS
149static void
150printscript(systemtap_session& s, ostream& o)
151{
16442b90 152 if (s.listing_mode)
83d7fcdc 153 {
16442b90
FCE
154 // We go through some heroic measures to produce clean output.
155 set<string> seen;
83d7fcdc 156
16442b90 157 for (unsigned i=0; i<s.probes.size(); i++)
9ba8c134 158 {
f76427a2
FCE
159 if (pending_interrupts) return;
160
16442b90
FCE
161 derived_probe* p = s.probes[i];
162 // NB: p->basest() is not so interesting;
163 // p->almost_basest() doesn't quite work, so ...
164 vector<probe*> chain;
165 p->collect_derivation_chain (chain);
166 probe* second = (chain.size()>1) ? chain[chain.size()-2] : chain[0];
167
168 #if 0
169 cerr << "\tchain[" << chain.size() << "]:" << endl;
170 for (unsigned i=0; i<chain.size(); i++)
171 { cerr << "\t"; chain[i]->printsig(cerr); cerr << endl; }
172 #endif
173
174 stringstream tmps;
7fb2f650
FCE
175 const probe_alias *a = second->get_alias();
176 if (a)
177 {
178 assert (a->alias_names.size() >= 1);
179 a->alias_names[0]->print(tmps); // XXX: [0] is arbitrary; perhaps print all
dff50e09 180 }
7fb2f650
FCE
181 else
182 {
183 assert (second->locations.size() >= 1);
184 second->locations[0]->print(tmps); // XXX: [0] is less arbitrary here, but still ...
185 }
186 string pp = tmps.str();
16442b90
FCE
187
188 // Now duplicate-eliminate. An alias may have expanded to
189 // several actual derived probe points, but we only want to
190 // print the alias head name once.
191 if (seen.find (pp) == seen.end())
192 {
d4e35ac8 193 o << pp;
223f5b6b 194 // Print the locals for -L mode only
e2086848 195 if (s.unoptimized) {
223f5b6b
JS
196 for (unsigned j=0; j<p->locals.size(); j++)
197 {
198 o << " ";
199 vardecl* v = p->locals[j];
200 v->printsig (o);
201 }
e2086848
WH
202 // Print arguments of probe if there
203 p->printargs(o);
204 }
223f5b6b 205 o << endl;
16442b90
FCE
206 seen.insert (pp);
207 }
9ba8c134 208 }
1b78aef5 209 }
16442b90 210 else
1b78aef5 211 {
16442b90
FCE
212 if (s.embeds.size() > 0)
213 o << "# global embedded code" << endl;
214 for (unsigned i=0; i<s.embeds.size(); i++)
1b78aef5 215 {
f76427a2 216 if (pending_interrupts) return;
16442b90
FCE
217 embeddedcode* ec = s.embeds[i];
218 ec->print (o);
219 o << endl;
220 }
dff50e09 221
16442b90
FCE
222 if (s.globals.size() > 0)
223 o << "# globals" << endl;
224 for (unsigned i=0; i<s.globals.size(); i++)
1b78aef5 225 {
f76427a2 226 if (pending_interrupts) return;
16442b90
FCE
227 vardecl* v = s.globals[i];
228 v->printsig (o);
229 if (s.verbose && v->init)
230 {
231 o << " = ";
232 v->init->print(o);
233 }
234 o << endl;
235 }
dff50e09 236
16442b90
FCE
237 if (s.functions.size() > 0)
238 o << "# functions" << endl;
f76427a2 239 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
1b78aef5 240 {
f76427a2
FCE
241 if (pending_interrupts) return;
242 functiondecl* f = it->second;
16442b90
FCE
243 f->printsig (o);
244 o << endl;
245 if (f->locals.size() > 0)
246 o << " # locals" << endl;
247 for (unsigned j=0; j<f->locals.size(); j++)
248 {
249 vardecl* v = f->locals[j];
250 o << " ";
251 v->printsig (o);
252 o << endl;
253 }
254 if (s.verbose)
255 {
256 f->body->print (o);
257 o << endl;
258 }
259 }
dff50e09 260
16442b90
FCE
261 if (s.probes.size() > 0)
262 o << "# probes" << endl;
263 for (unsigned i=0; i<s.probes.size(); i++)
1b78aef5 264 {
f76427a2 265 if (pending_interrupts) return;
16442b90
FCE
266 derived_probe* p = s.probes[i];
267 p->printsig (o);
268 o << endl;
269 if (p->locals.size() > 0)
270 o << " # locals" << endl;
271 for (unsigned j=0; j<p->locals.size(); j++)
272 {
273 vardecl* v = p->locals[j];
274 o << " ";
275 v->printsig (o);
276 o << endl;
277 }
278 if (s.verbose)
279 {
280 p->body->print (o);
281 o << endl;
282 }
283 }
284 }
277f2b79 285}
1b78aef5 286
49abf162
FCE
287
288int pending_interrupts;
289
290extern "C"
82737bef 291void handle_interrupt (int sig)
49abf162 292{
4cc40e82 293 kill_stap_spawn(sig);
49abf162 294 pending_interrupts ++;
4cc40e82 295 if (pending_interrupts > 1) // XXX: should be configurable? time-based?
49abf162
FCE
296 {
297 char msg[] = "Too many interrupts received, exiting.\n";
298 int rc = write (2, msg, sizeof(msg)-1);
9ceec314 299 if (rc) {/* Do nothing; we don't care if our last gasp went out. */ ;}
49abf162
FCE
300 _exit (1);
301 }
302}
303
304
3972b443
DS
305void
306setup_signals (sighandler_t handler)
307{
308 struct sigaction sa;
309
310 sa.sa_handler = handler;
311 sigemptyset (&sa.sa_mask);
312 if (handler != SIG_IGN)
313 {
314 sigaddset (&sa.sa_mask, SIGHUP);
315 sigaddset (&sa.sa_mask, SIGPIPE);
316 sigaddset (&sa.sa_mask, SIGINT);
317 sigaddset (&sa.sa_mask, SIGTERM);
318 }
4cc40e82 319 sa.sa_flags = SA_RESTART;
3972b443
DS
320
321 sigaction (SIGHUP, &sa, NULL);
322 sigaction (SIGPIPE, &sa, NULL);
323 sigaction (SIGINT, &sa, NULL);
324 sigaction (SIGTERM, &sa, NULL);
325}
326
4d0a3330
KS
327void
328setup_kernel_release (systemtap_session &s, const char* kstr) {
329 if (kstr[0] == '/') // fully specified path
330 {
331 s.kernel_build_tree = kstr;
332 string version_file_name = s.kernel_build_tree + "/include/config/kernel.release";
333 // The file include/config/kernel.release within the
334 // build tree is used to pull out the version information
335 ifstream version_file (version_file_name.c_str());
336 if (version_file.fail ())
337 {
338 cerr << "Missing " << version_file_name << endl;
339 exit(1);
340 }
341 else
342 {
343 char c;
344 s.kernel_release = "";
345 while (version_file.get(c) && c != '\n')
346 s.kernel_release.push_back(c);
347 }
348 }
349 else
350 {
351 s.kernel_release = string (kstr);
352 s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
353 }
354}
3972b443 355
2b066ec1
FCE
356int
357main (int argc, char * const argv [])
358{
2b066ec1
FCE
359 string cmdline_script; // -e PROGRAM
360 string script_file; // FILE
361 bool have_script = false;
fc52ef5b 362 bool save_module = false;
f4b28491
FCE
363
364 // Initialize defaults
365 systemtap_session s;
366 struct utsname buf;
367 (void) uname (& buf);
368 s.kernel_release = string (buf.release);
b5e66ada
FCE
369 s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
370
44ce8ed5 371 s.architecture = string (buf.machine);
e0b4e89d 372 for (unsigned i=0; i<5; i++) s.perpass_verbose[i]=0;
a9e8f7e0 373 s.timing = false;
377b8831 374 s.guru_mode = false;
16d8de1b 375 s.bulk_mode = false;
cbfbbf69 376 s.unoptimized = false;
a9e8f7e0 377 s.suppress_warnings = false;
16442b90 378 s.listing_mode = false;
44f75386
FCE
379
380#ifdef ENABLE_PROLOGUES
381 s.prologue_searching = true;
382#else
383 s.prologue_searching = false;
384#endif
385
16d8de1b 386 s.buffer_size = 0;
f4b28491 387 s.last_pass = 5;
ae24723e 388 s.module_name = "stap_" + stringify(getpid());
de0db58a 389 s.stapconf_name = "stapconf_" + stringify(getpid()) + ".h";
08c68653 390 s.output_file = ""; // -o FILE
f4b28491 391 s.keep_tmpdir = false;
4c5ff1bb
MH
392 s.cmd = "";
393 s.target_pid = 0;
f272aacc 394 s.merge=true;
47dd066d 395 s.perfmon=0;
f1bad60c 396 s.symtab = false;
1b78aef5 397 s.use_cache = true;
c3a3c0c9 398 s.tapset_compile_coverage = false;
12dc24bc 399 s.need_uprobes = false;
5f0a03a6
JK
400 s.consult_symtab = false;
401 s.ignore_vmlinux = false;
402 s.ignore_dwarf = false;
2fa2a091 403 s.load_only = false;
28f569c2 404 s.skip_badvars = false;
24cb178f 405
2035bcd4
DB
406 // Location of our signing certificate.
407 // If we're root, use the database in SYSCONFDIR, otherwise
408 // use the one in our $HOME directory. */
409 if (geteuid() == 0)
410 s.cert_db_path = SYSCONFDIR "/systemtap/ssl/server";
411 else
412 s.cert_db_path = getenv("HOME") + string ("/.systemtap/ssl/server");
413
24cb178f 414 const char* s_p = getenv ("SYSTEMTAP_TAPSET");
dff50e09 415 if (s_p != NULL)
ec819dc3 416 {
24cb178f 417 s.include_path.push_back (s_p);
ec819dc3 418 }
24cb178f 419 else
ec819dc3 420 {
24cb178f 421 s.include_path.push_back (string(PKGDATADIR) + "/tapset");
ec819dc3 422 }
24cb178f
FCE
423
424 const char* s_r = getenv ("SYSTEMTAP_RUNTIME");
425 if (s_r != NULL)
426 s.runtime_path = s_r;
427 else
428 s.runtime_path = string(PKGDATADIR) + "/runtime";
f4b28491 429
1b78aef5
DS
430 const char* s_d = getenv ("SYSTEMTAP_DIR");
431 if (s_d != NULL)
432 s.data_path = s_d;
433 else
434 s.data_path = get_home_directory() + string("/.systemtap");
435 if (create_dir(s.data_path.c_str()) == 1)
436 {
437 const char* e = strerror (errno);
f4d5049b
FCE
438 if (! s.suppress_warnings)
439 cerr << "Warning: failed to create systemtap data directory (\""
440 << s.data_path << "\"): " << e
441 << ", disabling cache support." << endl;
1b78aef5
DS
442 s.use_cache = false;
443 }
444
445 if (s.use_cache)
446 {
447 s.cache_path = s.data_path + "/cache";
448 if (create_dir(s.cache_path.c_str()) == 1)
449 {
450 const char* e = strerror (errno);
f4d5049b
FCE
451 if (! s.suppress_warnings)
452 cerr << "Warning: failed to create cache directory (\""
453 << s.cache_path << "\"): " << e
454 << ", disabling cache support." << endl;
1b78aef5
DS
455 s.use_cache = false;
456 }
457 }
458
c3a3c0c9
WC
459 const char* s_tc = getenv ("SYSTEMTAP_COVERAGE");
460 if (s_tc != NULL)
461 s.tapset_compile_coverage = true;
462
755cdd9b
KS
463 const char* s_kr = getenv ("SYSTEMTAP_RELEASE");
464 if (s_kr != NULL) {
4d0a3330 465 setup_kernel_release(s, s_kr);
755cdd9b
KS
466 }
467
468
2b066ec1
FCE
469 while (true)
470 {
5f0a03a6
JK
471 int long_opt;
472#define LONG_OPT_KELF 1
473#define LONG_OPT_KMAP 2
474#define LONG_OPT_IGNORE_VMLINUX 3
475#define LONG_OPT_IGNORE_DWARF 4
e0b4e89d 476#define LONG_OPT_VERBOSE_PASS 5
3bd0d4df 477#define LONG_OPT_SKIP_BADVARS 6
a9e8f7e0 478 // NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
5f0a03a6
JK
479 static struct option long_options[] = {
480 { "kelf", 0, &long_opt, LONG_OPT_KELF },
481 { "kmap", 2, &long_opt, LONG_OPT_KMAP },
482 { "ignore-vmlinux", 0, &long_opt, LONG_OPT_IGNORE_VMLINUX },
483 { "ignore-dwarf", 0, &long_opt, LONG_OPT_IGNORE_DWARF },
3bd0d4df 484 { "skip-badvars", 0, &long_opt, LONG_OPT_SKIP_BADVARS },
e0b4e89d 485 { "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS },
5f0a03a6
JK
486 { NULL, 0, NULL, 0 }
487 };
701c41be 488 int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:",
5f0a03a6 489 long_options, NULL);
2b066ec1
FCE
490 if (grc < 0)
491 break;
492 switch (grc)
493 {
c0de7a8d
FCE
494 case 'V':
495 version ();
496 exit (0);
497
f272aacc
LG
498 case 'M':
499 s.merge = false;
500 break;
501
bd2b1e68 502 case 'v':
e0b4e89d
FCE
503 for (unsigned i=0; i<5; i++)
504 s.perpass_verbose[i] ++;
bd2b1e68
GH
505 break;
506
4b17d6af 507 case 't':
a9e8f7e0
FCE
508 s.timing = true;
509 break;
510
511 case 'w':
512 s.suppress_warnings = true;
4b17d6af
WC
513 break;
514
2b066ec1 515 case 'p':
16442b90
FCE
516 if (s.listing_mode)
517 {
518 cerr << "Listing (-l) mode implies pass 2." << endl;
519 usage (s, 1);
520 }
f4b28491
FCE
521 s.last_pass = atoi (optarg);
522 if (s.last_pass < 1 || s.last_pass > 5)
2b066ec1 523 {
277c1957
DS
524 cerr << "Invalid pass number (should be 1-5)." << endl;
525 usage (s, 1);
2b066ec1
FCE
526 }
527 break;
528
529 case 'I':
f4b28491 530 s.include_path.push_back (string (optarg));
2b066ec1
FCE
531 break;
532
a8368458 533 case 'd':
1a0dbc5a 534 s.unwindsym_modules.insert (string (optarg));
a8368458
FCE
535 break;
536
2b066ec1
FCE
537 case 'e':
538 if (have_script)
277c1957
DS
539 {
540 cerr << "Only one script can be given on the command line."
541 << endl;
542 usage (s, 1);
543 }
2b066ec1
FCE
544 cmdline_script = string (optarg);
545 have_script = true;
546 break;
547
548 case 'o':
08c68653 549 s.output_file = string (optarg);
2b066ec1
FCE
550 break;
551
f4b28491
FCE
552 case 'R':
553 s.runtime_path = string (optarg);
554 break;
555
556 case 'm':
557 s.module_name = string (optarg);
fc52ef5b 558 save_module = true;
3b942fed
DS
559 {
560 string::size_type len = s.module_name.length();
561
562 // If the module name ends with '.ko', chop it off since
563 // modutils doesn't like modules named 'foo.ko.ko'.
564 if (len > 3 && s.module_name.substr(len - 3, 3) == ".ko")
565 {
566 s.module_name.erase(len - 3);
567 len -= 3;
568 cerr << "Truncating module name to '" << s.module_name
569 << "'" << endl;
570 }
571
572 // Make sure an empty module name wasn't specified (-m "")
573 if (len == 0)
574 {
575 cerr << "Module name cannot be empty." << endl;
576 usage (s, 1);
577 }
578
579 // Make sure the module name is only composed of the
580 // following chars: [_a-zA-Z0-9]
581 const string identchars("_" "abcdefghijklmnopqrstuvwxyz"
582 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789");
583 if (s.module_name.find_first_not_of(identchars) != string::npos)
584 {
585 cerr << "Invalid module name (must only be composed of"
586 " characters [_a-zA-Z0-9])." << endl;
587 usage (s, 1);
588 }
98aab489
DS
589
590 // Make sure module name isn't too long.
591 if (s.module_name.size() >= (MODULE_NAME_LEN - 1))
592 {
593 s.module_name.resize(MODULE_NAME_LEN - 1);
594 cerr << "Truncating module name to '" << s.module_name
595 << "'" << endl;
596 }
3b942fed
DS
597 }
598
1b78aef5 599 s.use_cache = false;
f4b28491
FCE
600 break;
601
602 case 'r':
4d0a3330 603 setup_kernel_release(s, optarg);
f4b28491
FCE
604 break;
605
606 case 'k':
607 s.keep_tmpdir = true;
f53a92f9 608 s.use_cache = false; /* User wants to keep a usable build tree. */
f4b28491
FCE
609 break;
610
377b8831
FCE
611 case 'g':
612 s.guru_mode = true;
613 break;
614
44f75386
FCE
615 case 'P':
616 s.prologue_searching = true;
617 break;
618
16d8de1b
TZ
619 case 'b':
620 s.bulk_mode = true;
16d8de1b
TZ
621 break;
622
cbfbbf69
FCE
623 case 'u':
624 s.unoptimized = true;
625 break;
626
16d8de1b
TZ
627 case 's':
628 s.buffer_size = atoi (optarg);
453b58ed 629 if (s.buffer_size < 1 || s.buffer_size > 4095)
16d8de1b 630 {
453b58ed 631 cerr << "Invalid buffer size (should be 1-4095)." << endl;
277c1957 632 usage (s, 1);
16d8de1b
TZ
633 }
634 break;
635
4c5ff1bb
MH
636 case 'c':
637 s.cmd = string (optarg);
638 break;
639
640 case 'x':
641 s.target_pid = atoi(optarg);
642 break;
643
ed10c639
FCE
644 case 'D':
645 s.macros.push_back (string (optarg));
646 break;
647
701c41be
MH
648 case 'S':
649 s.size_option = string (optarg);
650 break;
651
c3a3c0c9
WC
652 case 'q':
653 s.tapset_compile_coverage = true;
654 break;
655
2b066ec1 656 case 'h':
277c1957
DS
657 usage (s, 0);
658 break;
659
d4e35ac8 660 case 'L':
1044139f 661 s.unoptimized = true; // This causes retention of variables for listing_mode
d4e35ac8 662
16442b90 663 case 'l':
4bd48e4b 664 s.suppress_warnings = true;
16442b90
FCE
665 s.listing_mode = true;
666 s.last_pass = 2;
667 if (have_script)
668 {
669 cerr << "Only one script can be given on the command line."
670 << endl;
671 usage (s, 1);
672 }
673 cmdline_script = string("probe ") + string(optarg) + " {}";
674 have_script = true;
675 break;
676
2fa2a091
NT
677 case 'F':
678 s.load_only = true;
679 break;
680
5f0a03a6
JK
681 case 0:
682 switch (long_opt)
683 {
684 case LONG_OPT_KELF:
685 s.consult_symtab = true;
686 break;
687 case LONG_OPT_KMAP:
688 // Leave s.consult_symtab unset for now, to ease error checking.
689 if (!s.kernel_symtab_path.empty())
690 {
691 cerr << "You can't specify multiple --kmap options." << endl;
692 usage(s, 1);
693 }
694 if (optarg)
695 s.kernel_symtab_path = optarg;
696 else
697#define PATH_TBD string("__TBD__")
698 s.kernel_symtab_path = PATH_TBD;
699 break;
700 case LONG_OPT_IGNORE_VMLINUX:
701 s.ignore_vmlinux = true;
702 break;
703 case LONG_OPT_IGNORE_DWARF:
704 s.ignore_dwarf = true;
705 break;
e0b4e89d
FCE
706 case LONG_OPT_VERBOSE_PASS:
707 {
708 bool ok = true;
709 if (strlen(optarg) < 1 || strlen(optarg) > 5)
710 ok = false;
711 if (ok)
b688229d 712 for (unsigned i=0; i<strlen(optarg); i++)
e0b4e89d
FCE
713 if (isdigit (optarg[i]))
714 s.perpass_verbose[i] += optarg[i]-'0';
715 else
716 ok = false;
717
718 if (! ok)
719 {
720 cerr << "Invalid --vp argument: it takes 1 to 5 digits." << endl;
721 usage (s, 1);
722 }
723 // NB: we don't do this: s.last_pass = strlen(optarg);
724 break;
725 }
3bd0d4df
RA
726 case LONG_OPT_SKIP_BADVARS:
727 s.skip_badvars = true;
728 break;
5f0a03a6
JK
729 default:
730 cerr << "Internal error parsing command arguments." << endl;
731 usage(s, 1);
732 }
733 break;
734
2b066ec1 735 default:
277c1957
DS
736 usage (s, 1);
737 break;
2b066ec1
FCE
738 }
739 }
740
f272aacc
LG
741 if(!s.bulk_mode && !s.merge)
742 {
743 cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
277c1957 744 usage (s, 1);
f272aacc
LG
745 }
746
747 if(!s.output_file.empty() && s.bulk_mode && !s.merge)
748 {
749 cerr << "You can't specify -M, -b and -o options together." <<endl;
277c1957 750 usage (s, 1);
f272aacc
LG
751 }
752
54dec22d
DS
753 if((s.cmd != "") && (s.target_pid))
754 {
755 cerr << "You can't specify -c and -x options together." <<endl;
756 usage (s, 1);
757 }
758
5f0a03a6
JK
759 if (!s.kernel_symtab_path.empty())
760 {
761 if (s.consult_symtab)
762 {
763 cerr << "You can't specify --kelf and --kmap together." << endl;
764 usage (s, 1);
765 }
766 s.consult_symtab = true;
767 if (s.kernel_symtab_path == PATH_TBD)
768 s.kernel_symtab_path = string("/boot/System.map-") + s.kernel_release;
769 }
770
b5e66ada
FCE
771 // Warn in case the target kernel release doesn't match the running one.
772 if (s.last_pass > 4 &&
773 (string(buf.release) != s.kernel_release ||
774 string(buf.machine) != s.architecture))
775 {
776 if(! s.suppress_warnings)
777 cerr << "WARNING: kernel release/architecture mismatch with host forces last-pass 4." << endl;
778 s.last_pass = 4;
779 }
ea3f75ae 780
2b066ec1
FCE
781 for (int i = optind; i < argc; i++)
782 {
783 if (! have_script)
784 {
785 script_file = string (argv[i]);
786 have_script = true;
787 }
788 else
f4b28491 789 s.args.push_back (string (argv[i]));
2b066ec1
FCE
790 }
791
792 // need a user file
793 if (! have_script)
277c1957
DS
794 {
795 cerr << "A script must be specified." << endl;
796 usage(s, 1);
797 }
f4b28491 798
a929fd0f
Z
799 // translate path of runtime to absolute path
800 if (s.runtime_path[0] != '/')
801 {
802 char cwd[PATH_MAX];
803 if (getcwd(cwd, sizeof(cwd)))
804 {
805 s.runtime_path = string(cwd) + "/" + s.runtime_path;
806 }
807 }
808
f4b28491 809 int rc = 0;
c31df222
FCE
810
811 // PASS 0: setting up
812 s.verbose = s.perpass_verbose[0];
2b066ec1 813
d0a7f5a9
FCE
814 // For PR1477, we used to override $PATH and $LC_ALL and other stuff
815 // here. We seem to use complete pathnames in
816 // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
817 // it interferes with util.cxx:find_executable(), used for $PATH
818 // resolution.
861c2f28 819
197a4d62
JS
820 s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
821
2b066ec1 822 // arguments parsed; get down to business
72d18b98 823 if (s.verbose > 1)
c0e526f0
FCE
824 {
825 version ();
826 clog << "Session arch: " << s.architecture
827 << " release: " << s.kernel_release
828 << endl;
829 }
2b066ec1 830
f4b28491
FCE
831 // Create a temporary directory to build within.
832 // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
833 {
c72dc86c 834 const char* tmpdir_env = getenv("TMPDIR");
ea8ea02c
FCE
835 if (! tmpdir_env)
836 tmpdir_env = "/tmp";
dff50e09 837
ea8ea02c
FCE
838 string stapdir = "/stapXXXXXX";
839 string tmpdirt = tmpdir_env + stapdir;
533af4f0 840 mode_t mask = umask(0);
ea8ea02c 841 const char* tmpdir = mkdtemp((char *)tmpdirt.c_str());
533af4f0 842 umask(mask);
f4b28491
FCE
843 if (! tmpdir)
844 {
845 const char* e = strerror (errno);
ea8ea02c
FCE
846 cerr << "ERROR: cannot create temporary directory (\"" << tmpdirt << "\"): " << e << endl;
847 exit (1); // die
f4b28491
FCE
848 }
849 else
850 s.tmpdir = tmpdir;
0d49d7bc 851
b0ee93c4 852 if (s.verbose>1)
0d49d7bc 853 clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491 854 }
2b066ec1 855
1b78aef5
DS
856 // Create the name of the C source file within the temporary
857 // directory.
858 s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
859
dff50e09 860 // Set up our handler to catch routine signals, to allow clean
49abf162 861 // and reasonably timely exit.
3972b443 862 setup_signals(&handle_interrupt);
49abf162 863
5ee1c56b
FCE
864 struct tms tms_before;
865 times (& tms_before);
1d738eed
FCE
866 struct timeval tv_before;
867 gettimeofday (&tv_before, NULL);
2b066ec1
FCE
868
869 // PASS 1a: PARSING USER SCRIPT
f59e98c4
FCE
870
871 struct stat user_file_stat;
872 int user_file_stat_rc = -1;
873
69c68955 874 if (script_file == "-")
129be0ac
FCE
875 {
876 s.user_file = parser::parse (s, cin, s.guru_mode);
877 user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
878 }
69c68955 879 else if (script_file != "")
f59e98c4
FCE
880 {
881 s.user_file = parser::parse (s, script_file, s.guru_mode);
882 user_file_stat_rc = stat (script_file.c_str(), & user_file_stat);
883 }
2b066ec1
FCE
884 else
885 {
886 istringstream ii (cmdline_script);
177a8ead 887 s.user_file = parser::parse (s, ii, s.guru_mode);
2b066ec1
FCE
888 }
889 if (s.user_file == 0)
890 // syntax errors already printed
891 rc ++;
377b8831 892
5519d363 893 // Construct arch / kernel-versioning search path
377b8831 894 vector<string> version_suffixes;
6f9f33e2 895 string kvr = s.kernel_release;
5519d363
KS
896 const string& arch = s.architecture;
897 // add full kernel-version-release (2.6.NN-FOOBAR) + arch
898 version_suffixes.push_back ("/" + kvr + "/" + arch);
377b8831 899 version_suffixes.push_back ("/" + kvr);
5519d363 900 // add kernel version (2.6.NN) + arch
197a4d62
JS
901 if (kvr != s.kernel_base_release) {
902 kvr = s.kernel_base_release;
6f9f33e2
JS
903 version_suffixes.push_back ("/" + kvr + "/" + arch);
904 version_suffixes.push_back ("/" + kvr);
5519d363
KS
905 }
906 // add kernel family (2.6) + arch
6f9f33e2
JS
907 string::size_type dot1_index = kvr.find ('.');
908 string::size_type dot2_index = kvr.rfind ('.');
909 while (dot2_index > dot1_index && dot2_index != string::npos) {
910 kvr.erase(dot2_index);
911 version_suffixes.push_back ("/" + kvr + "/" + arch);
912 version_suffixes.push_back ("/" + kvr);
913 dot2_index = kvr.rfind ('.');
5519d363
KS
914 }
915 // add architecture search path
916 version_suffixes.push_back("/" + arch);
377b8831
FCE
917 // add empty string as last element
918 version_suffixes.push_back ("");
2b066ec1
FCE
919
920 // PASS 1b: PARSING LIBRARY SCRIPTS
f4b28491 921 for (unsigned i=0; i<s.include_path.size(); i++)
2b066ec1 922 {
377b8831
FCE
923 // now iterate upon it
924 for (unsigned k=0; k<version_suffixes.size(); k++)
2b066ec1 925 {
377b8831
FCE
926 glob_t globbuf;
927 string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
928 int r = glob(dir.c_str (), 0, NULL, & globbuf);
929 if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
2b066ec1 930 rc ++;
377b8831
FCE
931 // GLOB_NOMATCH is acceptable
932
c4a94c1a 933 if (s.verbose>1 && globbuf.gl_pathc > 0)
377b8831 934 clog << "Searched '" << dir << "', "
c4a94c1a 935 << "found " << globbuf.gl_pathc << endl;
2b066ec1 936
377b8831
FCE
937 for (unsigned j=0; j<globbuf.gl_pathc; j++)
938 {
49abf162
FCE
939 if (pending_interrupts)
940 break;
941
942 // XXX: privilege only for /usr/share/systemtap?
177a8ead 943 stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true);
377b8831
FCE
944 if (f == 0)
945 rc ++;
946 else
24cb178f 947 s.library_files.push_back (f);
f59e98c4
FCE
948
949 struct stat tapset_file_stat;
950 int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
951 if (stat_rc == 0 && user_file_stat_rc == 0 &&
952 user_file_stat.st_dev == tapset_file_stat.st_dev &&
953 user_file_stat.st_ino == tapset_file_stat.st_ino)
954 {
129be0ac
FCE
955 clog << "usage error: tapset file '" << globbuf.gl_pathv[j]
956 << "' cannot be run directly as a session script." << endl;
f59e98c4
FCE
957 rc ++;
958 }
959
377b8831 960 }
d54d4661 961
377b8831
FCE
962 globfree (& globbuf);
963 }
2b066ec1
FCE
964 }
965
f4b28491 966 if (rc == 0 && s.last_pass == 1)
2b066ec1 967 {
f4b28491
FCE
968 cout << "# parse tree dump" << endl;
969 s.user_file->print (cout);
970 cout << endl;
ae56fddd
FCE
971 if (s.verbose)
972 for (unsigned i=0; i<s.library_files.size(); i++)
973 {
974 s.library_files[i]->print (cout);
975 cout << endl;
976 }
2b066ec1
FCE
977 }
978
5ee1c56b
FCE
979 struct tms tms_after;
980 times (& tms_after);
981 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
1d738eed
FCE
982 struct timeval tv_after;
983 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
984
985#define TIMESPRINT \
986 (tms_after.tms_cutime + tms_after.tms_utime \
1d738eed 987 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
5ee1c56b 988 << (tms_after.tms_cstime + tms_after.tms_stime \
1d738eed
FCE
989 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
990 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
991 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
5ee1c56b 992
eaf134e7 993 // syntax errors, if any, are already printed
5ee1c56b
FCE
994 if (s.verbose)
995 {
996 clog << "Pass 1: parsed user script and "
997 << s.library_files.size()
998 << " library script(s) in "
999 << TIMESPRINT
1000 << endl;
1001 }
0d49d7bc 1002
708ce1f3 1003 if (rc && !s.listing_mode)
2cfb0e46 1004 cerr << "Pass 1: parse failed. "
c3157bcd 1005 << "Try again with another '--vp 1' option."
2cfb0e46
FCE
1006 << endl;
1007
49abf162 1008 if (rc || s.last_pass == 1 || pending_interrupts) goto cleanup;
f4b28491 1009
5ee1c56b 1010 times (& tms_before);
1d738eed 1011 gettimeofday (&tv_before, NULL);
5ee1c56b 1012
2b066ec1 1013 // PASS 2: ELABORATION
e0b4e89d 1014 s.verbose = s.perpass_verbose[1];
0d49d7bc 1015 rc = semantic_pass (s);
f4b28491 1016
16442b90 1017 if (s.listing_mode || (rc == 0 && s.last_pass == 2))
1b78aef5 1018 printscript(s, cout);
2b066ec1 1019
5ee1c56b 1020 times (& tms_after);
1d738eed
FCE
1021 gettimeofday (&tv_after, NULL);
1022
b0ee93c4 1023 if (s.verbose) clog << "Pass 2: analyzed script: "
0d49d7bc
FCE
1024 << s.probes.size() << " probe(s), "
1025 << s.functions.size() << " function(s), "
b20febf3 1026 << s.embeds.size() << " embed(s), "
5ee1c56b
FCE
1027 << s.globals.size() << " global(s) in "
1028 << TIMESPRINT
1029 << endl;
0d49d7bc 1030
708ce1f3 1031 if (rc && !s.listing_mode)
377b8831 1032 cerr << "Pass 2: analysis failed. "
c3157bcd 1033 << "Try again with another '--vp 01' option."
2cfb0e46 1034 << endl;
1b78aef5
DS
1035 // Generate hash. There isn't any point in generating the hash
1036 // if last_pass is 2, since we'll quit before using it.
1037 else if (s.last_pass != 2 && s.use_cache)
1038 {
1039 ostringstream o;
1040 unsigned saved_verbose;
1b78aef5 1041
9abec538
FCE
1042 {
1043 // Make sure we're in verbose mode, so that printscript()
1044 // will output function/probe bodies.
1045 saved_verbose = s.verbose;
1046 s.verbose = 3;
1047 printscript(s, o); // Print script to 'o'
1048 s.verbose = saved_verbose;
1049 }
1b78aef5
DS
1050
1051 // Generate hash
1052 find_hash (s, o.str());
1053
1054 // See if we can use cached source/module.
1055 if (get_from_cache(s))
1056 {
db3a383b
JK
1057 // If our last pass isn't 5, we're done (since passes 3 and
1058 // 4 just generate what we just pulled out of the cache).
49abf162 1059 if (s.last_pass < 5 || pending_interrupts) goto cleanup;
1b78aef5 1060
db3a383b
JK
1061 // Short-circuit to pass 5.
1062 goto pass_5;
1b78aef5
DS
1063 }
1064 }
377b8831 1065
16442b90 1066 if (rc || s.listing_mode || s.last_pass == 2 || pending_interrupts) goto cleanup;
f4b28491 1067
2b066ec1 1068 // PASS 3: TRANSLATION
e0b4e89d 1069 s.verbose = s.perpass_verbose[2];
5ee1c56b 1070 times (& tms_before);
1d738eed
FCE
1071 gettimeofday (&tv_before, NULL);
1072
0d49d7bc 1073 rc = translate_pass (s);
f4b28491
FCE
1074
1075 if (rc == 0 && s.last_pass == 3)
1076 {
1077 ifstream i (s.translated_source.c_str());
1078 cout << i.rdbuf();
1079 }
0d49d7bc 1080
5ee1c56b 1081 times (& tms_after);
1d738eed 1082 gettimeofday (&tv_after, NULL);
5ee1c56b 1083
0d49d7bc
FCE
1084 if (s.verbose) clog << "Pass 3: translated to C into \""
1085 << s.translated_source
5ee1c56b
FCE
1086 << "\" in "
1087 << TIMESPRINT
1088 << endl;
0d49d7bc 1089
377b8831 1090 if (rc)
2cfb0e46 1091 cerr << "Pass 3: translation failed. "
c3157bcd 1092 << "Try again with another '--vp 001' option."
2cfb0e46 1093 << endl;
377b8831 1094
49abf162 1095 if (rc || s.last_pass == 3 || pending_interrupts) goto cleanup;
d54d4661 1096
f4b28491 1097 // PASS 4: COMPILATION
e0b4e89d 1098 s.verbose = s.perpass_verbose[3];
5ee1c56b 1099 times (& tms_before);
1d738eed 1100 gettimeofday (&tv_before, NULL);
0d49d7bc 1101 rc = compile_pass (s);
9abec538
FCE
1102
1103 if (rc == 0 && s.last_pass == 4)
422dc4e1
FCE
1104 {
1105 cout << ((s.hash_path == "") ? (s.module_name + string(".ko")) : s.hash_path);
1106 cout << endl;
1107 }
9abec538 1108
5ee1c56b 1109 times (& tms_after);
1d738eed 1110 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
1111
1112 if (s.verbose) clog << "Pass 4: compiled C into \""
1113 << s.module_name << ".ko"
1114 << "\" in "
1115 << TIMESPRINT
1116 << endl;
f4b28491 1117
eaf134e7
FCE
1118 if (rc)
1119 cerr << "Pass 4: compilation failed. "
c3157bcd 1120 << "Try again with another '--vp 0001' option."
2cfb0e46 1121 << endl;
fc52ef5b 1122 else
1b78aef5 1123 {
06c7e057 1124 // Update cache. Cache cleaning is kicked off at the end of this function.
fc52ef5b 1125 if (s.use_cache)
f4d5049b 1126 add_to_cache(s);
fc52ef5b 1127
f4d5049b
FCE
1128 // We may need to save the module in $CWD if the cache was
1129 // inaccessible for some reason.
1130 if (! s.use_cache && s.last_pass == 4)
1131 save_module = true;
1132
fc52ef5b 1133 // Copy module to the current directory.
49abf162 1134 if (save_module && !pending_interrupts)
fc52ef5b
DS
1135 {
1136 string module_src_path = s.tmpdir + "/" + s.module_name + ".ko";
1137 string module_dest_path = s.module_name + ".ko";
1138
1139 if (s.verbose > 1)
1140 clog << "Copying " << module_src_path << " to "
1141 << module_dest_path << endl;
1142 if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
1143 cerr << "Copy failed (\"" << module_src_path << "\" to \""
1144 << module_dest_path << "\"): " << strerror(errno) << endl;
2035bcd4
DB
1145
1146#if HAVE_NSS
1147 // Save the signature as well.
1148 assert (! s.cert_db_path.empty());
1149 module_src_path += ".sgn";
1150 module_dest_path += ".sgn";
1151
1152 if (s.verbose > 1)
1153 clog << "Copying " << module_src_path << " to "
1154 << module_dest_path << endl;
1155 if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
1156 cerr << "Copy failed (\"" << module_src_path << "\" to \""
1157 << module_dest_path << "\"): " << strerror(errno) << endl;
1158#endif
fc52ef5b 1159 }
1b78aef5 1160 }
eaf134e7 1161
49abf162 1162 if (rc || s.last_pass == 4 || pending_interrupts) goto cleanup;
f4b28491 1163
9abec538 1164
0d49d7bc 1165 // PASS 5: RUN
1b78aef5 1166pass_5:
e0b4e89d 1167 s.verbose = s.perpass_verbose[4];
5ee1c56b 1168 times (& tms_before);
1d738eed 1169 gettimeofday (&tv_before, NULL);
03d569d3
FCE
1170 // NB: this message is a judgement call. The other passes don't emit
1171 // a "hello, I'm starting" message, but then the others aren't interactive
1172 // and don't take an indefinite amount of time.
1173 if (s.verbose) clog << "Pass 5: starting run." << endl;
0d49d7bc 1174 rc = run_pass (s);
5ee1c56b 1175 times (& tms_after);
1d738eed 1176 gettimeofday (&tv_after, NULL);
5ee1c56b
FCE
1177 if (s.verbose) clog << "Pass 5: run completed in "
1178 << TIMESPRINT
1179 << endl;
f4b28491 1180
eaf134e7
FCE
1181 if (rc)
1182 cerr << "Pass 5: run failed. "
c3157bcd 1183 << "Try again with another '--vp 00001' option."
2cfb0e46 1184 << endl;
eaf134e7 1185
0d49d7bc 1186 // if (rc) goto cleanup;
2b066ec1 1187
c31df222 1188 // PASS 6: cleaning up
0d49d7bc 1189 cleanup:
c3a3c0c9
WC
1190
1191 // update the database information
49abf162 1192 if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
1c0b94ef 1193#ifdef HAVE_LIBSQLITE3
c3a3c0c9 1194 update_coverage_db(s);
1c0b94ef
FCE
1195#else
1196 cerr << "Coverage database not available without libsqlite3" << endl;
1197#endif
c3a3c0c9
WC
1198 }
1199
f4b28491
FCE
1200 // Clean up temporary directory. Obviously, be careful with this.
1201 if (s.tmpdir == "")
1202 ; // do nothing
1203 else
1204 {
1205 if (s.keep_tmpdir)
0d49d7bc 1206 clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl;
f4b28491
FCE
1207 else
1208 {
3972b443
DS
1209 // Ignore signals while we're deleting the temporary directory.
1210 setup_signals (SIG_IGN);
1211
1212 // Remove the temporary directory.
ce3187ac 1213 string cleanupcmd = "rm -rf ";
f4b28491 1214 cleanupcmd += s.tmpdir;
b0ee93c4 1215 if (s.verbose>1) clog << "Running " << cleanupcmd << endl;
4cc40e82 1216 int status = stap_system (cleanupcmd.c_str());
b0ee93c4 1217 if (status != 0 && s.verbose>1)
d54d4661 1218 clog << "Cleanup command failed, status: " << status << endl;
f4b28491
FCE
1219 }
1220 }
2b066ec1 1221
49abf162 1222 return (rc||pending_interrupts) ? EXIT_FAILURE : EXIT_SUCCESS;
2b066ec1 1223}
73267b89
JS
1224
1225/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.219993 seconds and 5 git commands to generate.