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