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