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