]> sourceware.org Git - systemtap.git/blame - buildrun.cxx
PR13210 vma/vdso tracking is broken testcase
[systemtap.git] / buildrun.cxx
CommitLineData
f4b28491 1// build/run probes
3e1ec884 2// Copyright (C) 2005-2011 Red Hat Inc.
f4b28491
FCE
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
8
9#include "config.h"
10#include "buildrun.h"
dc38c0ae 11#include "session.h"
72dbc915 12#include "util.h"
7d26ee02 13#include "hash.h"
f4b28491 14
3b579393 15#include <cstdlib>
f4b28491 16#include <fstream>
d04cf5ff
FCE
17#include <sstream>
18
19extern "C" {
49abf162 20#include <signal.h>
0c6296b2 21#include <sys/wait.h>
70404fc5 22#include <pwd.h>
0da3e7a0 23#include <grp.h>
b40af7ee
DS
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <string.h>
28#include <errno.h>
d04cf5ff
FCE
29}
30
f4b28491
FCE
31
32using namespace std;
33
6274464e
JK
34/* Adjust and run make_cmd to build a kernel module. */
35static int
ff520ff4
JS
36run_make_cmd(systemtap_session& s, vector<string>& make_cmd,
37 bool null_out=false, bool null_err=false)
6274464e
JK
38{
39 // Before running make, fix up the environment a bit. PATH should
40 // already be overridden. Clean out a few variables that
b5e66ada 41 // s.kernel_build_tree/Makefile uses.
6274464e
JK
42 int rc = unsetenv("ARCH") || unsetenv("KBUILD_EXTMOD")
43 || unsetenv("CROSS_COMPILE") || unsetenv("KBUILD_IMAGE")
44 || unsetenv("KCONFIG_CONFIG") || unsetenv("INSTALL_PATH");
45 if (rc)
46 {
47 const char* e = strerror (errno);
48 cerr << "unsetenv failed: " << e << endl;
3e1ec884 49 s.set_try_server ();
6274464e
JK
50 }
51
b51455af
JS
52 // Disable ccache to avoid saving files that will never be reused.
53 // (ccache is useless to us, because our compiler commands always
54 // include the randomized tmpdir path.)
55 // It's not critical if this fails, so the return is ignored.
56 (void) setenv("CCACHE_DISABLE", "1", 0);
57
b54581ce 58 if (s.verbose > 2)
ff520ff4 59 make_cmd.push_back("V=1");
b54581ce 60 else if (s.verbose > 1)
ff520ff4 61 make_cmd.push_back("--no-print-directory");
6274464e 62 else
ff520ff4
JS
63 {
64 make_cmd.push_back("-s");
65 make_cmd.push_back("--no-print-directory");
66 }
dff50e09 67
9fa0ffac
FCE
68 // NB: there appears to be no parallelism opportunity in the
69 // module-building makefiles, so while the following works, it
70 // doesn't seem to accomplish anything measurable as of F13.
71#if 0
72 long smp = sysconf(_SC_NPROCESSORS_ONLN);
73 if (smp > 1)
ff520ff4 74 make_cmd.push_back("-j" + lex_cast(smp));
9fa0ffac
FCE
75#endif
76
e0ccd368
FCE
77 if (strverscmp (s.kernel_base_release.c_str(), "2.6.29") < 0)
78 {
79 // Older kernels, before linux commit #fd54f502841c1, include
80 // gratuitous "echo"s in their Makefile. We need to suppress
81 // that with this bluntness.
ff520ff4 82 null_out = true;
e0ccd368
FCE
83 }
84
ff520ff4 85 rc = stap_system (s.verbose, make_cmd, null_out, null_err);
3e1ec884
DB
86 if (rc != 0)
87 s.set_try_server ();
88 return rc;
6274464e 89}
f4b28491 90
7d26ee02
JS
91static vector<string>
92make_make_cmd(systemtap_session& s, const string& dir)
93{
94 vector<string> make_cmd;
95 make_cmd.push_back("make");
96 make_cmd.push_back("-C");
97 make_cmd.push_back(s.kernel_build_tree);
98 make_cmd.push_back("M=" + dir); // need make-quoting?
99 make_cmd.push_back("modules");
100
101 // Add architecture, except for old powerpc (RHBZ669082)
102 if (s.architecture != "powerpc" ||
103 (strverscmp (s.kernel_base_release.c_str(), "2.6.15") >= 0))
104 make_cmd.push_back("ARCH=" + s.architecture); // need make-quoting?
105
106 // Add any custom kbuild flags
107 make_cmd.insert(make_cmd.end(), s.kbuildflags.begin(), s.kbuildflags.end());
108
109 return make_cmd;
110}
111
de0db58a
JS
112static void
113output_autoconf(systemtap_session& s, ofstream& o, const char *autoconf_c,
114 const char *deftrue, const char *deffalse)
115{
116 o << "\t";
117 if (s.verbose < 4)
118 o << "@";
119 o << "if $(CHECK_BUILD) $(SYSTEMTAP_RUNTIME)/" << autoconf_c;
120 if (s.verbose < 5)
121 o << " > /dev/null 2>&1";
122 o << "; then ";
123 if (deftrue)
124 o << "echo \"#define " << deftrue << " 1\"";
125 if (deffalse)
126 o << "; else echo \"#define " << deffalse << " 1\"";
127 o << "; fi >> $@" << endl;
128}
129
9e62f7ba
FCE
130
131void output_exportconf(systemtap_session& s, ofstream& o, const char *symbol,
132 const char *deftrue)
e25ab03c 133{
9e62f7ba
FCE
134 o << "\t";
135 if (s.verbose < 4)
136 o << "@";
137 if (s.kernel_exports.find(symbol) != s.kernel_exports.end())
138 o << "echo \"#define " << deftrue << " 1\"";
139 o << ">> $@" << endl;
e25ab03c
WH
140}
141
9e62f7ba 142
08c29612
DS
143void output_dual_exportconf(systemtap_session& s, ofstream& o,
144 const char *symbol1, const char *symbol2,
145 const char *deftrue)
146{
147 o << "\t";
148 if (s.verbose < 4)
149 o << "@";
150 if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
151 && s.kernel_exports.find(symbol2) != s.kernel_exports.end())
152 o << "echo \"#define " << deftrue << " 1\"";
153 o << ">> $@" << endl;
154}
155
156
f4b28491
FCE
157int
158compile_pass (systemtap_session& s)
159{
db3a383b
JK
160 int rc = uprobes_pass (s);
161 if (rc)
3e1ec884
DB
162 {
163 s.set_try_server ();
164 return rc;
165 }
db3a383b 166
f4b28491 167 // fill in a quick Makefile
92ade41d
FCE
168 string makefile_nm = s.tmpdir + "/Makefile";
169 ofstream o (makefile_nm.c_str());
92ade41d
FCE
170
171 // Create makefile
ed10c639 172
255e4c68 173 // Clever hacks copied from vmware modules
ecf19454
FCE
174 string superverbose;
175 if (s.verbose > 3)
176 superverbose = "set -x;";
522518f1 177
e9737939
MM
178 string redirecterrors = "> /dev/null 2>&1";
179 if (s.verbose > 6)
180 redirecterrors = "";
181
e5976ba0
MH
182 // Support O= (or KBUILD_OUTPUT) option
183 o << "_KBUILD_CFLAGS := $(call flags,KBUILD_CFLAGS)" << endl;
184
ecf19454 185 o << "stap_check_gcc = $(shell " << superverbose << " if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo \"$(1)\"; else echo \"$(2)\"; fi)" << endl;
fab6097f 186 o << "CHECK_BUILD := $(CC) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) $(CPPFLAGS) $(LINUXINCLUDE) $(_KBUILD_CFLAGS) $(CFLAGS_KERNEL) $(EXTRA_CFLAGS) $(CFLAGS) -DKBUILD_BASENAME=\\\"" << s.module_name << "\\\"" << (s.omit_werror ? "" : " -Werror") << " -S -o /dev/null -xc " << endl;
de0db58a 187 o << "stap_check_build = $(shell " << superverbose << " if $(CHECK_BUILD) $(1) " << redirecterrors << " ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl;
255e4c68
FCE
188
189 o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl;
190
191 // "autoconf" options go here
192
18222191
FCE
193 // RHBZ 543529: early rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
194 o << "CONFIG_MODULE_SIG := n" << endl;
195
ecf19454 196 string module_cflags = "EXTRA_CFLAGS";
522518f1 197 o << module_cflags << " :=" << endl;
84c4da88
FCE
198
199 // XXX: This gruesome hack is needed on some kernels built with separate O=directory,
200 // where files like 2.6.27 x86's asm/mach-*/mach_mpspec.h are not found on the cpp path.
201 // This could be a bug in arch/x86/Makefile that names
202 // mflags-y += -Iinclude/asm-x86/mach-default
203 // but that path does not exist in an O= build tree.
204 o << module_cflags << " += -Iinclude2/asm/mach-default" << endl;
d4393459
FCE
205 if (s.kernel_source_tree != "")
206 o << module_cflags << " += -I" + s.kernel_source_tree << endl;
84c4da88 207
6046b840
FCE
208 // NB: don't try
209 // o << module_cflags << " += -Iusr/include" << endl;
210 // since such headers are cleansed of _KERNEL_ pieces that we need
211
de0db58a
JS
212 o << "STAPCONF_HEADER := " << s.tmpdir << "/" << s.stapconf_name << endl;
213 o << s.translated_source << ": $(STAPCONF_HEADER)" << endl;
214 o << "$(STAPCONF_HEADER):" << endl;
215 o << "\t@echo -n > $@" << endl;
216 output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL);
217 output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL);
218 output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL);
219 output_autoconf(s, o, "autoconf-constant-tsc.c", "STAPCONF_CONSTANT_TSC", NULL);
de0db58a
JS
220 output_autoconf(s, o, "autoconf-ktime-get-real.c", "STAPCONF_KTIME_GET_REAL", NULL);
221 output_autoconf(s, o, "autoconf-x86-uniregs.c", "STAPCONF_X86_UNIREGS", NULL);
222 output_autoconf(s, o, "autoconf-nameidata.c", "STAPCONF_NAMEIDATA_CLEANUP", NULL);
08c29612 223 output_dual_exportconf(s, o, "unregister_kprobes", "unregister_kretprobes", "STAPCONF_UNREGISTER_KPROBES");
766cee5f 224 output_autoconf(s, o, "autoconf-kprobe-symbol-name.c", "STAPCONF_KPROBE_SYMBOL_NAME", NULL);
de0db58a
JS
225 output_autoconf(s, o, "autoconf-real-parent.c", "STAPCONF_REAL_PARENT", NULL);
226 output_autoconf(s, o, "autoconf-uaccess.c", "STAPCONF_LINUX_UACCESS_H", NULL);
227 output_autoconf(s, o, "autoconf-oneachcpu-retry.c", "STAPCONF_ONEACHCPU_RETRY", NULL);
228 output_autoconf(s, o, "autoconf-dpath-path.c", "STAPCONF_DPATH_PATH", NULL);
08c29612 229 output_exportconf(s, o, "synchronize_sched", "STAPCONF_SYNCHRONIZE_SCHED");
de0db58a 230 output_autoconf(s, o, "autoconf-task-uid.c", "STAPCONF_TASK_UID", NULL);
08c29612 231 output_dual_exportconf(s, o, "alloc_vm_area", "free_vm_area", "STAPCONF_VM_AREA");
de0db58a 232 output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL);
b1f85b93 233 output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL);
5cad2d3b 234 output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL);
f098eb6d 235 output_autoconf(s, o, "autoconf-grsecurity.c", "STAPCONF_GRSECURITY", NULL);
450718c9 236 output_autoconf(s, o, "autoconf-trace-printk.c", "STAPCONF_TRACE_PRINTK", NULL);
be004140
FCE
237 output_autoconf(s, o, "autoconf-regset.c", "STAPCONF_REGSET", NULL);
238 output_autoconf(s, o, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL);
23258335 239 output_autoconf(s, o, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL);
b09417ad 240 output_exportconf(s, o, "tsc_khz", "STAPCONF_TSC_KHZ");
9e62f7ba 241 output_exportconf(s, o, "cpu_khz", "STAPCONF_CPU_KHZ");
031fda59 242 output_exportconf(s, o, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS");
af6c651f 243 output_exportconf(s, o, "add_timer_on", "STAPCONF_ADD_TIMER_ON");
8d59b39f 244
08c29612 245 output_dual_exportconf(s, o, "probe_kernel_read", "probe_kernel_write", "STAPCONF_PROBE_KERNEL");
b273669e
MW
246 output_autoconf(s, o, "autoconf-hw_breakpoint_context.c",
247 "STAPCONF_HW_BREAKPOINT_CONTEXT", NULL);
8c5905d0
TM
248 output_autoconf(s, o, "autoconf-save-stack-trace.c",
249 "STAPCONF_KERNEL_STACKTRACE", NULL);
d5cd287f
DS
250 output_autoconf(s, o, "autoconf-asm-syscall.c",
251 "STAPCONF_ASM_SYSCALL_H", NULL);
c145b9cb 252 output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL);
0d0f0d84 253 output_autoconf(s, o, "autoconf-ring_buffer_lost_events.c", "STAPCONF_RING_BUFFER_LOST_EVENTS", NULL);
c38602b5 254 output_autoconf(s, o, "autoconf-ring_buffer_read_prepare.c", "STAPCONF_RING_BUFFER_READ_PREPARE", NULL);
03a4ec63 255 output_autoconf(s, o, "autoconf-kallsyms-on-each-symbol.c", "STAPCONF_KALLSYMS_ON_EACH_SYMBOL", NULL);
c265cd25 256 output_autoconf(s, o, "autoconf-walk-stack.c", "STAPCONF_WALK_STACK", NULL);
0bbb8009
JS
257 output_autoconf(s, o, "autoconf-stacktrace_ops-warning.c",
258 "STAPCONF_STACKTRACE_OPS_WARNING", NULL);
18da5887 259 output_autoconf(s, o, "autoconf-mm-context-vdso.c", "STAPCONF_MM_CONTEXT_VDSO", NULL);
c1d2d085 260 output_autoconf(s, o, "autoconf-blk-types.c", "STAPCONF_BLK_TYPES", NULL);
aec17ca6 261 output_autoconf(s, o, "autoconf-perf-structpid.c", "STAPCONF_PERF_STRUCTPID", NULL);
2f3df331
MW
262 output_autoconf(s, o, "perf_event_counter_context.c",
263 "STAPCONF_PERF_COUNTER_CONTEXT", NULL);
264 output_autoconf(s, o, "perf_probe_handler_nmi.c",
265 "STAPCONF_PERF_HANDLER_NMI", NULL);
7f2d56c3
DS
266 output_exportconf(s, o, "path_lookup", "STAPCONF_PATH_LOOKUP");
267 output_exportconf(s, o, "kern_path_parent", "STAPCONF_KERN_PATH_PARENT");
268 output_exportconf(s, o, "vfs_path_lookup", "STAPCONF_VFS_PATH_LOOKUP");
2c9caccb 269 output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
255e4c68 270
de5f477b
JS
271 // used by tapset/timestamp_monotonic.stp
272 output_exportconf(s, o, "cpu_clock", "STAPCONF_CPU_CLOCK");
273 output_exportconf(s, o, "local_clock", "STAPCONF_LOCAL_CLOCK");
274
de0db58a 275 o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
5c54d49e 276
ed10c639 277 for (unsigned i=0; i<s.macros.size(); i++)
ff520ff4 278 o << "EXTRA_CFLAGS += -D " << lex_cast_qstring(s.macros[i]) << endl; // XXX right quoting?
ed10c639 279
e4c58386 280 if (s.verbose > 3)
0986ac38 281 o << "EXTRA_CFLAGS += -ftime-report -Q" << endl;
db22e55f 282
ee6dda6f
FCE
283 // XXX: unfortunately, -save-temps can't work since linux kbuild cwd
284 // is not writeable.
285 //
286 // if (s.keep_tmpdir)
287 // o << "CFLAGS += -fverbose-asm -save-temps" << endl;
288
ec6fdef5
MW
289 // Kernels can be compiled with CONFIG_CC_OPTIMIZE_FOR_SIZE to select
290 // -Os, otherwise -O2 is the default.
291 o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os
292
01116596
MW
293 // We used to allow the user to override default optimization when so
294 // requested by adding a -O[0123s] so they could determine the
295 // time/space/speed tradeoffs themselves, but we cannot guantantee that
296 // the (un)optimized code actually compiles and/or generates functional
297 // code, so we had to remove it.
298 // o << "EXTRA_CFLAGS += " << s.gcc_flags << endl; // Add -O[0123s]
35d4ab18
FCE
299
300 // o << "CFLAGS += -fno-unit-at-a-time" << endl;
dff50e09 301
01a2eba8
JS
302 // 256 bytes should be enough for anybody
303 // XXX this doesn't validate varargs, per gcc bug #41633
304 o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=256)" << endl;
730c3efc 305
cbfbbf69 306 // Assumes linux 2.6 kbuild
c72dd3c7 307 o << "EXTRA_CFLAGS += -Wno-unused" << (s.omit_werror ? "" : " -Werror") << endl;
29bdbdb1
FCE
308 #if CHECK_POINTER_ARITH_PR5947
309 o << "EXTRA_CFLAGS += -Wpointer-arith" << endl;
310 #endif
0986ac38 311 o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl;
4b2c4ab5
FCE
312 // XXX: this may help ppc toc overflow
313 // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl;
cbfbbf69 314 o << "obj-m := " << s.module_name << ".o" << endl;
f4b28491 315
ed10c639
FCE
316 o.close ();
317
b40af7ee 318 // Generate module directory pathname and make sure it exists.
4d34dac1
FCE
319 string module_dir = s.kernel_build_tree;
320 string module_dir_makefile = module_dir + "/Makefile";
b40af7ee 321 struct stat st;
4d34dac1 322 rc = stat(module_dir_makefile.c_str(), &st);
b40af7ee
DS
323 if (rc != 0)
324 {
ce0f6648 325 clog << _F("Checking \" %s \" failed with error: %s\nEnsure kernel development headers & makefiles are installed.",
46a1a151 326 module_dir_makefile.c_str(), strerror(errno)) << endl;
3e1ec884 327 s.set_try_server ();
b40af7ee 328 return rc;
dff50e09 329 }
b40af7ee
DS
330
331 // Run make
7d26ee02 332 vector<string> make_cmd = make_make_cmd(s, s.tmpdir);
6274464e 333 rc = run_make_cmd(s, make_cmd);
3e1ec884
DB
334 if (rc)
335 s.set_try_server ();
f4b28491
FCE
336 return rc;
337}
338
db3a383b
JK
339/*
340 * If uprobes was built as part of the kernel build (either built-in
dbb9345d
FCE
341 * or as a module), the uprobes exports should show up. This is to be
342 * as distinct from the stap-built uprobes.ko from the runtime.
db3a383b
JK
343 */
344static bool
345kernel_built_uprobes (systemtap_session& s)
6274464e 346{
dbb9345d 347 return (s.kernel_exports.find("unregister_uprobe") != s.kernel_exports.end());
6274464e
JK
348}
349
7d26ee02
JS
350static int
351make_uprobes (systemtap_session& s)
6274464e 352{
7ef486ad 353 if (s.verbose > 1)
7d26ee02 354 clog << _("Pass 4, preamble: (re)building SystemTap's version of uprobes.")
db3a383b
JK
355 << endl;
356
7d26ee02
JS
357 // create a subdirectory for the uprobes module
358 string dir(s.tmpdir + "/uprobes");
359 if (create_dir(dir.c_str()) != 0)
360 {
361 if (! s.suppress_warnings)
362 cerr << _("Warning: failed to create directory for build uprobes.") << endl;
363 s.set_try_server ();
364 return 1;
0da3e7a0 365 }
6274464e 366
7d26ee02
JS
367 // create a simple Makefile
368 string makefile(dir + "/Makefile");
369 ofstream omf(makefile.c_str());
370 omf << "obj-m := uprobes.o" << endl;
371 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
372 omf << "CONFIG_MODULE_SIG := n" << endl;
373 omf.close();
6274464e 374
7d26ee02
JS
375 // create a simple #include-chained source file
376 string runtimesourcefile(s.runtime_path + "/uprobes/uprobes.c");
377 string sourcefile(dir + "/uprobes.c");
378 ofstream osrc(sourcefile.c_str());
379 osrc << "#include \"" << runtimesourcefile << "\"" << endl;
380 osrc.close();
381
382 // make the module
383 vector<string> make_cmd = make_make_cmd(s, dir);
384 bool quiet = (s.verbose < 4);
385 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
386 if (!rc && !copy_file(dir + "/Module.symvers",
387 s.tmpdir + "/Module.symvers"))
388 rc = -1;
6274464e 389
f4d5049b 390 if (s.verbose > 1)
ce0f6648 391 clog << _("uprobes rebuild exit code: ") << rc << endl;
3e1ec884
DB
392 if (rc)
393 s.set_try_server ();
7d26ee02
JS
394 else
395 s.uprobes_path = dir + "/uprobes.ko";
6274464e
JK
396 return rc;
397}
398
7d26ee02
JS
399static bool
400get_cached_uprobes(systemtap_session& s)
401{
402 s.uprobes_hash = s.use_cache ? find_uprobes_hash(s) : "";
403 if (!s.uprobes_hash.empty())
404 {
405 // NB: We always put uprobes.ko in its own directory, especially so
406 // stap-serverd can more easily locate it.
407 string dir(s.tmpdir + "/uprobes");
408 if (create_dir(dir.c_str()) != 0)
409 return false;
410
411 string cacheko = s.uprobes_hash + ".ko";
412 string tmpko = dir + "/uprobes.ko";
413
414 // The symvers file still needs to go in the script module's directory.
415 string cachesyms = s.uprobes_hash + ".symvers";
416 string tmpsyms = s.tmpdir + "/Module.symvers";
417
418 if (get_file_size(cacheko) > 0 && copy_file(cacheko, tmpko) &&
419 get_file_size(cachesyms) > 0 && copy_file(cachesyms, tmpsyms))
420 {
421 s.uprobes_path = tmpko;
422 return true;
423 }
424 }
425 return false;
426}
427
428static void
429set_cached_uprobes(systemtap_session& s)
db3a383b 430{
7d26ee02
JS
431 if (s.use_cache && !s.uprobes_hash.empty())
432 {
433 string cacheko = s.uprobes_hash + ".ko";
434 string tmpko = s.tmpdir + "/uprobes/uprobes.ko";
435 copy_file(tmpko, cacheko);
36ef6d6a 436
7d26ee02
JS
437 string cachesyms = s.uprobes_hash + ".symvers";
438 string tmpsyms = s.tmpdir + "/uprobes/Module.symvers";
439 copy_file(tmpsyms, cachesyms);
440 }
db3a383b
JK
441}
442
7d26ee02 443int
db3a383b
JK
444uprobes_pass (systemtap_session& s)
445{
446 if (!s.need_uprobes || kernel_built_uprobes(s))
447 return 0;
0944a81e
FCE
448
449 if (s.kernel_config["CONFIG_UTRACE"] != string("y")) {
94d05135 450 clog << _("user-space facilities not available without kernel CONFIG_UTRACE") << endl;
3e1ec884 451 s.set_try_server ();
0944a81e
FCE
452 return 1;
453 }
454
db3a383b 455 /*
7d26ee02
JS
456 * We need to use the version of uprobes that comes with SystemTap. Try to
457 * get it from the cache first. If not found, build it and try to save it to
458 * the cache for future reuse.
db3a383b 459 */
7d26ee02
JS
460 int rc = 0;
461 if (!get_cached_uprobes(s))
462 {
463 rc = make_uprobes(s);
464 if (!rc)
465 set_cached_uprobes(s);
466 }
3e1ec884
DB
467 if (rc)
468 s.set_try_server ();
db3a383b
JK
469 return rc;
470}
471
5eea6ed1 472vector<string>
18630fb8 473make_run_command (systemtap_session& s, const string& remotedir,
4112f219 474 const string& version)
f4b28491 475{
a63a95dc 476 // for now, just spawn staprun
5eea6ed1
JS
477 vector<string> staprun_cmd;
478 staprun_cmd.push_back(getenv("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun");
479 if (s.verbose>1)
480 staprun_cmd.push_back("-v");
481 if (s.verbose>2)
482 staprun_cmd.push_back("-v");
483 if (s.suppress_warnings)
484 staprun_cmd.push_back("-w");
485
486 if (!s.output_file.empty())
487 {
488 staprun_cmd.push_back("-o");
489 staprun_cmd.push_back(s.output_file);
490 }
dff50e09 491
5eea6ed1
JS
492 if (!s.cmd.empty())
493 {
494 staprun_cmd.push_back("-c");
495 staprun_cmd.push_back(s.cmd);
496 }
dff50e09 497
cbfbbf69 498 if (s.target_pid)
5eea6ed1
JS
499 {
500 staprun_cmd.push_back("-t");
501 staprun_cmd.push_back(lex_cast(s.target_pid));
502 }
dff50e09 503
cbfbbf69 504 if (s.buffer_size)
5eea6ed1
JS
505 {
506 staprun_cmd.push_back("-b");
507 staprun_cmd.push_back(lex_cast(s.buffer_size));
508 }
dff50e09 509
6274464e 510 if (s.need_uprobes)
5eea6ed1 511 {
18630fb8
JS
512 string opt_u = "-u";
513 if (!s.uprobes_path.empty() &&
514 strverscmp("1.4", version.c_str()) <= 0)
515 {
516 if (remotedir.empty())
517 opt_u.append(s.uprobes_path);
518 else
519 opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str()));
520 }
521 staprun_cmd.push_back(opt_u);
5eea6ed1 522 }
6274464e 523
2fa2a091 524 if (s.load_only)
5eea6ed1 525 staprun_cmd.push_back(s.output_file.empty() ? "-L" : "-D");
701c41be 526
4112f219 527 if(!s.modname_given && (strverscmp("1.6", version.c_str()) <= 0))
5c854d7c
CM
528 staprun_cmd.push_back("-R");
529
701c41be 530 if (!s.size_option.empty())
5eea6ed1
JS
531 {
532 staprun_cmd.push_back("-S");
533 staprun_cmd.push_back(s.size_option);
534 }
2fa2a091 535
18630fb8
JS
536 staprun_cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
537 + "/" + s.module_name + ".ko");
dff50e09 538
bb25d08f 539 // add module arguments
5eea6ed1
JS
540 staprun_cmd.insert(staprun_cmd.end(),
541 s.globalopts.begin(), s.globalopts.end());
bb25d08f 542
daa75206 543 return staprun_cmd;
f4b28491 544}
73267b89 545
0a6f5a3f
JS
546
547// Build a tiny kernel module to query tracepoints
548int
f982c59b 549make_tracequery(systemtap_session& s, string& name,
d4393459 550 const vector<string>& decls)
0a6f5a3f 551{
f982c59b 552 static unsigned tick = 0;
aca66a36 553 string basename("tracequery_kmod_" + lex_cast(++tick));
f982c59b 554
0a6f5a3f 555 // create a subdirectory for the module
f982c59b 556 string dir(s.tmpdir + "/" + basename);
0a6f5a3f
JS
557 if (create_dir(dir.c_str()) != 0)
558 {
559 if (! s.suppress_warnings)
94d05135 560 cerr << _("Warning: failed to create directory for querying tracepoints.") << endl;
3e1ec884 561 s.set_try_server ();
0a6f5a3f
JS
562 return 1;
563 }
564
f982c59b 565 name = dir + "/" + basename + ".ko";
0a6f5a3f
JS
566
567 // create a simple Makefile
568 string makefile(dir + "/Makefile");
569 ofstream omf(makefile.c_str());
9ccda279 570 // force debuginfo generation, and relax implicit functions
c72dd3c7 571 omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << (s.omit_werror ? "" : " -Werror") << endl;
d4393459
FCE
572 if (s.kernel_source_tree != "")
573 omf << "EXTRA_CFLAGS += -I" + s.kernel_source_tree << endl;
f982c59b 574 omf << "obj-m := " + basename + ".o" << endl;
a7ec2317
FCE
575
576 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
577 omf << "CONFIG_MODULE_SIG := n" << endl;
578
0a6f5a3f
JS
579 omf.close();
580
581 // create our source file
f982c59b 582 string source(dir + "/" + basename + ".c");
0a6f5a3f 583 ofstream osrc(source.c_str());
0a6f5a3f
JS
584 osrc << "#ifdef CONFIG_TRACEPOINTS" << endl;
585 osrc << "#include <linux/tracepoint.h>" << endl;
586
587 // override DECLARE_TRACE to synthesize probe functions for us
588 osrc << "#undef DECLARE_TRACE" << endl;
589 osrc << "#define DECLARE_TRACE(name, proto, args) \\" << endl;
590 osrc << " void stapprobe_##name(proto) {}" << endl;
591
5f73a260
JS
592 // 2.6.35 added the NOARGS variant, but it's the same for us
593 osrc << "#undef DECLARE_TRACE_NOARGS" << endl;
594 osrc << "#define DECLARE_TRACE_NOARGS(name) \\" << endl;
595 osrc << " DECLARE_TRACE(name, void, )" << endl;
596
d99d8819
JS
597 // older tracepoints used DEFINE_TRACE, so redirect that too
598 osrc << "#undef DEFINE_TRACE" << endl;
599 osrc << "#define DEFINE_TRACE(name, proto, args) \\" << endl;
600 osrc << " DECLARE_TRACE(name, TPPROTO(proto), TPARGS(args))" << endl;
601
d4393459
FCE
602 // add the specified decls/#includes
603 for (unsigned z=0; z<decls.size(); z++)
915ad99a 604 osrc << "#undef TRACE_INCLUDE_FILE\n"
d4393459
FCE
605 << "#undef TRACE_INCLUDE_PATH\n"
606 << decls[z] << "\n";
0a6f5a3f
JS
607
608 // finish up the module source
609 osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl;
0a6f5a3f
JS
610 osrc.close();
611
612 // make the module
7d26ee02 613 vector<string> make_cmd = make_make_cmd(s, dir);
e86f32ee 614 make_cmd.push_back ("-i"); // ignore errors, give rc 0 even in case of tracepoint header nits
ff520ff4
JS
615 bool quiet = (s.verbose < 4);
616 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
3e1ec884
DB
617 if (rc)
618 s.set_try_server ();
c2cf1b87 619
e86f32ee
FCE
620 // Sometimes we fail a tracequery due to PR9993 / PR11649 type
621 // kernel trace header problems. In this case, due to PR12729, we
622 // used to get a lovely "Warning: make exited with status: 2" but no
c2cf1b87
FCE
623 // other useful diagnostic. -vvvv would let a user see what's up,
624 // but the user can't fix the problem even with that.
625
3e1ec884 626 return rc;
0a6f5a3f
JS
627}
628
3e1c25aa
JS
629
630// Build a tiny kernel module to query type information
d90053e7 631static int
da9e11bd 632make_typequery_kmod(systemtap_session& s, const vector<string>& headers, string& name)
3e1c25aa
JS
633{
634 static unsigned tick = 0;
aca66a36 635 string basename("typequery_kmod_" + lex_cast(++tick));
3e1c25aa
JS
636
637 // create a subdirectory for the module
638 string dir(s.tmpdir + "/" + basename);
639 if (create_dir(dir.c_str()) != 0)
640 {
641 if (! s.suppress_warnings)
94d05135 642 cerr << _("Warning: failed to create directory for querying types.") << endl;
3e1ec884 643 s.set_try_server ();
3e1c25aa
JS
644 return 1;
645 }
646
647 name = dir + "/" + basename + ".ko";
648
649 // create a simple Makefile
650 string makefile(dir + "/Makefile");
651 ofstream omf(makefile.c_str());
652 omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl;
3ae4cdf9 653
a7ec2317
FCE
654 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
655 omf << "CONFIG_MODULE_SIG := n" << endl;
656
3ae4cdf9
JS
657 // NB: We use -include instead of #include because that gives us more power.
658 // Using #include searches relative to the source's path, which in this case
659 // is /tmp/..., so that's not helpful. Using -include will search relative
660 // to the cwd, which will be the kernel build root. This means if you have a
661 // full kernel build tree, it's possible to get at types that aren't in the
662 // normal include path, e.g.:
663 // @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->...
da9e11bd
JS
664 omf << "CFLAGS_" << basename << ".o :=";
665 for (size_t i = 0; i < headers.size(); ++i)
ff520ff4 666 omf << " -include " << lex_cast_qstring(headers[i]); // XXX right quoting?
da9e11bd 667 omf << endl;
3ae4cdf9 668
3e1c25aa
JS
669 omf << "obj-m := " + basename + ".o" << endl;
670 omf.close();
671
672 // create our empty source file
673 string source(dir + "/" + basename + ".c");
674 ofstream osrc(source.c_str());
675 osrc.close();
676
677 // make the module
7d26ee02 678 vector<string> make_cmd = make_make_cmd(s, dir);
ff520ff4
JS
679 bool quiet = (s.verbose < 4);
680 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
3e1ec884
DB
681 if (rc)
682 s.set_try_server ();
683 return rc;
3e1c25aa
JS
684}
685
686
687// Build a tiny user module to query type information
d90053e7 688static int
da9e11bd 689make_typequery_umod(systemtap_session& s, const vector<string>& headers, string& name)
3e1c25aa
JS
690{
691 static unsigned tick = 0;
692
aca66a36 693 name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so";
3e1c25aa
JS
694
695 // make the module
3ae4cdf9
JS
696 //
697 // NB: As with kmod, using -include makes relative paths more useful. The
698 // cwd in this case will be the cwd of stap itself though, which may be
699 // trickier to deal with. It might be better to "cd `dirname $script`"
700 // first...
ff520ff4
JS
701 vector<string> cmd;
702 cmd.push_back("gcc");
703 cmd.push_back("-shared");
704 cmd.push_back("-g");
705 cmd.push_back("-fno-eliminate-unused-debug-types");
706 cmd.push_back("-xc");
707 cmd.push_back("/dev/null");
708 cmd.push_back("-o");
709 cmd.push_back(name);
da9e11bd 710 for (size_t i = 0; i < headers.size(); ++i)
ff520ff4
JS
711 {
712 cmd.push_back("-include");
713 cmd.push_back(headers[i]);
714 }
715 bool quiet = (s.verbose < 4);
716 int rc = stap_system (s.verbose, cmd, quiet, quiet);
3e1ec884
DB
717 if (rc)
718 s.set_try_server ();
719 return rc;
3e1c25aa
JS
720}
721
d90053e7
JS
722
723int
724make_typequery(systemtap_session& s, string& module)
725{
726 int rc;
727 string new_module;
da9e11bd 728 vector<string> headers;
60d98537 729 bool kernel = startswith(module, "kernel");
d90053e7 730
da9e11bd 731 for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1)
d90053e7 732 {
da9e11bd
JS
733 if (module[i] != '<')
734 return -1;
735 end = module.find('>', ++i);
736 if (end == string::npos)
737 return -1;
738 string header = module.substr(i, end - i);
504d2b61 739 vector<string> matches;
5ef28d5a 740 if (regexp_match(header, "^[a-zA-Z0-9/_.+-]+$", matches))
504d2b61
JS
741 {
742 if (! s.suppress_warnings)
e5f690c7 743 cerr << _F("Warning: skipping malformed @cast header \"%s\"",
ce0f6648 744 header.c_str()) << endl;
504d2b61
JS
745 }
746 else
747 headers.push_back(header);
d90053e7 748 }
da9e11bd 749 if (headers.empty())
d90053e7
JS
750 return -1;
751
da9e11bd
JS
752 if (kernel)
753 rc = make_typequery_kmod(s, headers, new_module);
754 else
755 rc = make_typequery_umod(s, headers, new_module);
756
d90053e7
JS
757 if (!rc)
758 module = new_module;
759
760 return rc;
761}
762
73267b89 763/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.187549 seconds and 5 git commands to generate.