]> sourceware.org Git - systemtap.git/blob - buildrun.cxx
PR15290: remove additional uretprobe cruft
[systemtap.git] / buildrun.cxx
1 // build/run probes
2 // Copyright (C) 2005-2013 Red Hat Inc.
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"
11 #include "session.h"
12 #include "util.h"
13 #include "hash.h"
14 #include "translate.h"
15
16 #include <cstdlib>
17 #include <fstream>
18 #include <sstream>
19
20 extern "C" {
21 #include <signal.h>
22 #include <sys/wait.h>
23 #include <pwd.h>
24 #include <grp.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 }
31
32
33 using namespace std;
34
35 /* Adjust and run make_cmd to build a kernel module. */
36 static int
37 run_make_cmd(systemtap_session& s, vector<string>& make_cmd,
38 bool null_out=false, bool null_err=false)
39 {
40 assert_no_interrupts();
41
42 // PR14168: we used to unsetenv values here; instead do it via
43 // env(1) in make_any_make_cmd().
44
45 // Disable ccache to avoid saving files that will never be reused.
46 // (ccache is useless to us, because our compiler commands always
47 // include the randomized tmpdir path.)
48 // It's not critical if this fails, so the return is ignored.
49 (void) setenv("CCACHE_DISABLE", "1", 0);
50
51 if (s.verbose > 2)
52 make_cmd.push_back("V=1");
53 else if (s.verbose > 1)
54 make_cmd.push_back("--no-print-directory");
55 else
56 {
57 make_cmd.push_back("-s");
58 make_cmd.push_back("--no-print-directory");
59 }
60
61 // Exploit SMP parallelism, if available.
62 long smp = sysconf(_SC_NPROCESSORS_ONLN);
63 if (smp >= 1)
64 make_cmd.push_back("-j" + lex_cast(smp+1));
65
66 if (strverscmp (s.kernel_base_release.c_str(), "2.6.29") < 0)
67 {
68 // Older kernels, before linux commit #fd54f502841c1, include
69 // gratuitous "echo"s in their Makefile. We need to suppress
70 // that with this bluntness.
71 null_out = true;
72 }
73
74 int rc = stap_system (s.verbose, "kbuild", make_cmd, null_out, null_err);
75 if (rc != 0)
76 s.set_try_server ();
77 return rc;
78 }
79
80 static vector<string>
81 make_any_make_cmd(systemtap_session& s, const string& dir, const string& target)
82 {
83 vector<string> make_cmd;
84
85 // PR14168: sanitize environment variables for kbuild invocation
86 make_cmd.push_back("env");
87 make_cmd.push_back("-uARCH");
88 make_cmd.push_back("-uKBUILD_EXTMOD");
89 make_cmd.push_back("-uCROSS_COMPILE");
90 make_cmd.push_back("-uKBUILD_IMAGE");
91 make_cmd.push_back("-uKCONFIG_CONFIG");
92 make_cmd.push_back("-uINSTALL_PATH");
93 string newpath = string("PATH=/usr/bin:/bin:") + (getenv("PATH") ?: "");
94 make_cmd.push_back(newpath.c_str());
95
96 make_cmd.push_back("make");
97 make_cmd.push_back("-C");
98 make_cmd.push_back(s.kernel_build_tree);
99 make_cmd.push_back("M=" + dir); // need make-quoting?
100 make_cmd.push_back(target);
101
102 // Add architecture, except for old powerpc (RHBZ669082)
103 if (s.architecture != "powerpc" ||
104 (strverscmp (s.kernel_base_release.c_str(), "2.6.15") >= 0))
105 make_cmd.push_back("ARCH=" + s.architecture); // need make-quoting?
106
107 // PR13847: suppress debuginfo creation by default
108 make_cmd.insert(make_cmd.end(), "CONFIG_DEBUG_INFO=");
109
110 // Add any custom kbuild flags
111 make_cmd.insert(make_cmd.end(), s.kbuildflags.begin(), s.kbuildflags.end());
112
113 return make_cmd;
114 }
115
116 static vector<string>
117 make_make_cmd(systemtap_session& s, const string& dir)
118 {
119 return make_any_make_cmd(s, dir, "modules");
120 }
121
122 static vector<string>
123 make_make_objs_cmd(systemtap_session& s, const string& dir)
124 {
125 // Kbuild uses these rules to build external modules:
126 //
127 // module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
128 // modules: $(module-dirs)
129 // @$(kecho) ' Building modules, stage 2.';
130 // $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
131 //
132 // So if we're only interested in the stage 1 objects, we can
133 // cheat and make only the $(module-dirs) part.
134 return make_any_make_cmd(s, dir, "_module_" + dir);
135 }
136
137 static void
138 output_autoconf(systemtap_session& s, ofstream& o, const char *autoconf_c,
139 const char *deftrue, const char *deffalse)
140 {
141 o << "\t";
142 if (s.verbose < 4)
143 o << "@";
144 o << "if $(CHECK_BUILD) $(SYSTEMTAP_RUNTIME)/linux/" << autoconf_c;
145 if (s.verbose < 5)
146 o << " > /dev/null 2>&1";
147 o << "; then ";
148 if (deftrue)
149 o << "echo \"#define " << deftrue << " 1\"";
150 if (deffalse)
151 o << "; else echo \"#define " << deffalse << " 1\"";
152 o << "; fi >> $@" << endl;
153 }
154
155
156 void output_exportconf(systemtap_session& s, ofstream& o, const char *symbol,
157 const char *deftrue)
158 {
159 o << "\t";
160 if (s.verbose < 4)
161 o << "@";
162 if (s.kernel_exports.find(symbol) != s.kernel_exports.end())
163 o << "echo \"#define " << deftrue << " 1\"";
164 o << ">> $@" << endl;
165 }
166
167
168 void output_dual_exportconf(systemtap_session& s, ofstream& o,
169 const char *symbol1, const char *symbol2,
170 const char *deftrue)
171 {
172 o << "\t";
173 if (s.verbose < 4)
174 o << "@";
175 if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
176 && s.kernel_exports.find(symbol2) != s.kernel_exports.end())
177 o << "echo \"#define " << deftrue << " 1\"";
178 o << ">> $@" << endl;
179 }
180
181
182 void output_either_exportconf(systemtap_session& s, ofstream& o,
183 const char *symbol1, const char *symbol2,
184 const char *deftrue)
185 {
186 o << "\t";
187 if (s.verbose < 4)
188 o << "@";
189 if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
190 || s.kernel_exports.find(symbol2) != s.kernel_exports.end())
191 o << "echo \"#define " << deftrue << " 1\"";
192 o << ">> $@" << endl;
193 }
194
195
196 static int
197 compile_dyninst (systemtap_session& s)
198 {
199 const string module = s.tmpdir + "/" + s.module_filename();
200
201 vector<string> cmd;
202 cmd.push_back("gcc");
203 cmd.push_back("--std=gnu99");
204 cmd.push_back("-Wall");
205 cmd.push_back("-Werror");
206 cmd.push_back("-Wno-unused");
207 cmd.push_back("-Wno-strict-aliasing");
208 cmd.push_back("-O2");
209 cmd.push_back("-I" + s.runtime_path);
210 cmd.push_back("-D__DYNINST__");
211 for (size_t i = 0; i < s.c_macros.size(); ++i)
212 cmd.push_back("-D" + s.c_macros[i]);
213 cmd.push_back(s.translated_source);
214 cmd.push_back("-pthread");
215 cmd.push_back("-lrt");
216 cmd.push_back("-fPIC");
217 cmd.push_back("-shared");
218 cmd.push_back("-o");
219 cmd.push_back(module);
220 if (s.verbose > 3)
221 {
222 cmd.push_back("-ftime-report");
223 cmd.push_back("-Q");
224 }
225
226 int rc = stap_system (s.verbose, cmd);
227 if (rc)
228 s.set_try_server ();
229 return rc;
230 }
231
232
233 int
234 compile_pass (systemtap_session& s)
235 {
236 if (s.runtime_usermode_p())
237 return compile_dyninst (s);
238
239 int rc = uprobes_pass (s);
240 if (rc)
241 {
242 s.set_try_server ();
243 return rc;
244 }
245
246 // fill in a quick Makefile
247 string makefile_nm = s.tmpdir + "/Makefile";
248 ofstream o (makefile_nm.c_str());
249
250 // Create makefile
251
252 // Clever hacks copied from vmware modules
253 string superverbose;
254 if (s.verbose > 3)
255 superverbose = "set -x;";
256
257 string redirecterrors = "> /dev/null 2>&1";
258 if (s.verbose > 6)
259 redirecterrors = "";
260
261 // Support O= (or KBUILD_OUTPUT) option
262 o << "_KBUILD_CFLAGS := $(call flags,KBUILD_CFLAGS)" << endl;
263
264 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;
265 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;
266 o << "stap_check_build = $(shell " << superverbose << " if $(CHECK_BUILD) $(1) " << redirecterrors << " ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl;
267
268 o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl;
269
270 // "autoconf" options go here
271
272 // RHBZ 543529: early rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
273 o << "CONFIG_MODULE_SIG := n" << endl;
274
275 string module_cflags = "EXTRA_CFLAGS";
276 o << module_cflags << " :=" << endl;
277
278 // XXX: This gruesome hack is needed on some kernels built with separate O=directory,
279 // where files like 2.6.27 x86's asm/mach-*/mach_mpspec.h are not found on the cpp path.
280 // This could be a bug in arch/x86/Makefile that names
281 // mflags-y += -Iinclude/asm-x86/mach-default
282 // but that path does not exist in an O= build tree.
283 o << module_cflags << " += -Iinclude2/asm/mach-default" << endl;
284 if (s.kernel_source_tree != "")
285 o << module_cflags << " += -I" + s.kernel_source_tree << endl;
286
287 // NB: don't try
288 // o << module_cflags << " += -Iusr/include" << endl;
289 // since such headers are cleansed of _KERNEL_ pieces that we need
290
291 o << "STAPCONF_HEADER := " << s.tmpdir << "/" << s.stapconf_name << endl;
292 o << "$(STAPCONF_HEADER):" << endl;
293 o << "\t@echo -n > $@" << endl;
294 output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL);
295 output_autoconf(s, o, "autoconf-generated-compile.c", "STAPCONF_GENERATED_COMPILE", NULL);
296 output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL);
297 output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL);
298 output_autoconf(s, o, "autoconf-constant-tsc.c", "STAPCONF_CONSTANT_TSC", NULL);
299 output_autoconf(s, o, "autoconf-ktime-get-real.c", "STAPCONF_KTIME_GET_REAL", NULL);
300 output_autoconf(s, o, "autoconf-x86-uniregs.c", "STAPCONF_X86_UNIREGS", NULL);
301 output_autoconf(s, o, "autoconf-nameidata.c", "STAPCONF_NAMEIDATA_CLEANUP", NULL);
302 output_dual_exportconf(s, o, "unregister_kprobes", "unregister_kretprobes", "STAPCONF_UNREGISTER_KPROBES");
303 output_autoconf(s, o, "autoconf-kprobe-symbol-name.c", "STAPCONF_KPROBE_SYMBOL_NAME", NULL);
304 output_autoconf(s, o, "autoconf-real-parent.c", "STAPCONF_REAL_PARENT", NULL);
305 output_autoconf(s, o, "autoconf-uaccess.c", "STAPCONF_LINUX_UACCESS_H", NULL);
306 output_autoconf(s, o, "autoconf-oneachcpu-retry.c", "STAPCONF_ONEACHCPU_RETRY", NULL);
307 output_autoconf(s, o, "autoconf-dpath-path.c", "STAPCONF_DPATH_PATH", NULL);
308 output_exportconf(s, o, "synchronize_sched", "STAPCONF_SYNCHRONIZE_SCHED");
309 output_autoconf(s, o, "autoconf-task-uid.c", "STAPCONF_TASK_UID", NULL);
310 output_dual_exportconf(s, o, "alloc_vm_area", "free_vm_area", "STAPCONF_VM_AREA");
311 output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL);
312 output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL);
313 output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL);
314 output_autoconf(s, o, "autoconf-grsecurity.c", "STAPCONF_GRSECURITY", NULL);
315 output_autoconf(s, o, "autoconf-trace-printk.c", "STAPCONF_TRACE_PRINTK", NULL);
316 output_autoconf(s, o, "autoconf-regset.c", "STAPCONF_REGSET", NULL);
317 output_autoconf(s, o, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL);
318 output_autoconf(s, o, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL);
319 output_autoconf(s, o, "autoconf-hlist-4args.c", "STAPCONF_HLIST_4ARGS", NULL);
320 output_exportconf(s, o, "tsc_khz", "STAPCONF_TSC_KHZ");
321 output_exportconf(s, o, "cpu_khz", "STAPCONF_CPU_KHZ");
322 output_exportconf(s, o, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS");
323 output_exportconf(s, o, "add_timer_on", "STAPCONF_ADD_TIMER_ON");
324
325 output_dual_exportconf(s, o, "probe_kernel_read", "probe_kernel_write", "STAPCONF_PROBE_KERNEL");
326 output_autoconf(s, o, "autoconf-hw_breakpoint_context.c",
327 "STAPCONF_HW_BREAKPOINT_CONTEXT", NULL);
328 output_autoconf(s, o, "autoconf-save-stack-trace.c",
329 "STAPCONF_KERNEL_STACKTRACE", NULL);
330 output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c",
331 "STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL);
332 output_autoconf(s, o, "autoconf-asm-syscall.c",
333 "STAPCONF_ASM_SYSCALL_H", NULL);
334 output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL);
335 output_autoconf(s, o, "autoconf-ring_buffer_lost_events.c", "STAPCONF_RING_BUFFER_LOST_EVENTS", NULL);
336 output_autoconf(s, o, "autoconf-ring_buffer_read_prepare.c", "STAPCONF_RING_BUFFER_READ_PREPARE", NULL);
337 output_autoconf(s, o, "autoconf-kallsyms-on-each-symbol.c", "STAPCONF_KALLSYMS_ON_EACH_SYMBOL", NULL);
338 output_autoconf(s, o, "autoconf-walk-stack.c", "STAPCONF_WALK_STACK", NULL);
339 output_autoconf(s, o, "autoconf-stacktrace_ops-warning.c",
340 "STAPCONF_STACKTRACE_OPS_WARNING", NULL);
341 output_autoconf(s, o, "autoconf-mm-context-vdso.c", "STAPCONF_MM_CONTEXT_VDSO", NULL);
342 output_autoconf(s, o, "autoconf-mm-context-vdso-base.c", "STAPCONF_MM_CONTEXT_VDSO_BASE", NULL);
343 output_autoconf(s, o, "autoconf-blk-types.c", "STAPCONF_BLK_TYPES", NULL);
344 output_autoconf(s, o, "autoconf-perf-structpid.c", "STAPCONF_PERF_STRUCTPID", NULL);
345 output_autoconf(s, o, "perf_event_counter_context.c",
346 "STAPCONF_PERF_COUNTER_CONTEXT", NULL);
347 output_autoconf(s, o, "perf_probe_handler_nmi.c",
348 "STAPCONF_PERF_HANDLER_NMI", NULL);
349 output_exportconf(s, o, "path_lookup", "STAPCONF_PATH_LOOKUP");
350 output_exportconf(s, o, "kern_path_parent", "STAPCONF_KERN_PATH_PARENT");
351 output_exportconf(s, o, "vfs_path_lookup", "STAPCONF_VFS_PATH_LOOKUP");
352 output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
353
354 output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL);
355 output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL);
356 output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL);
357 output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL);
358 output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL);
359
360 // used by tapset/timestamp_monotonic.stp
361 output_exportconf(s, o, "cpu_clock", "STAPCONF_CPU_CLOCK");
362 output_exportconf(s, o, "local_clock", "STAPCONF_LOCAL_CLOCK");
363
364 // used by runtime/uprobe-inode.c
365 output_either_exportconf(s, o, "uprobe_register", "register_uprobe",
366 "STAPCONF_UPROBE_REGISTER_EXPORTED");
367 output_either_exportconf(s, o, "uprobe_unregister", "unregister_uprobe",
368 "STAPCONF_UPROBE_UNREGISTER_EXPORTED");
369 output_autoconf(s, o, "autoconf-old-inode-uprobes.c", "STAPCONF_OLD_INODE_UPROBES", NULL);
370 output_autoconf(s, o, "autoconf-inode-uprobes-noaddr.c", "STAPCONF_INODE_UPROBES_NOADDR", NULL);
371 output_autoconf(s, o, "autoconf-inode-uretprobes.c", "STAPCONF_INODE_URETPROBES", NULL);
372
373 // used by tapsets.cxx inode uprobe generated code
374 output_exportconf(s, o, "uprobe_get_swbp_addr", "STAPCONF_UPROBE_GET_SWBP_ADDR_EXPORTED");
375
376 // used by runtime/loc2c-runtime.h
377 output_exportconf(s, o, "task_user_regset_view", "STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED");
378
379 // used by runtime/stp_utrace.c
380 output_exportconf(s, o, "task_work_add", "STAPCONF_TASK_WORK_ADD_EXPORTED");
381 output_exportconf(s, o, "signal_wake_up_state", "STAPCONF_SIGNAL_WAKE_UP_STATE_EXPORTED");
382 output_exportconf(s, o, "signal_wake_up", "STAPCONF_SIGNAL_WAKE_UP_EXPORTED");
383 output_exportconf(s, o, "__lock_task_sighand", "STAPCONF___LOCK_TASK_SIGHAND_EXPORTED");
384
385 output_autoconf(s, o, "autoconf-pagefault_disable.c", "STAPCONF_PAGEFAULT_DISABLE", NULL);
386 output_exportconf(s, o, "kallsyms_lookup_name", "STAPCONF_KALLSYMS");
387
388 o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
389
390 for (unsigned i=0; i<s.c_macros.size(); i++)
391 o << "EXTRA_CFLAGS += -D " << lex_cast_qstring(s.c_macros[i]) << endl; // XXX right quoting?
392
393 if (s.verbose > 3)
394 o << "EXTRA_CFLAGS += -ftime-report -Q" << endl;
395
396 // XXX: unfortunately, -save-temps can't work since linux kbuild cwd
397 // is not writable.
398 //
399 // if (s.keep_tmpdir)
400 // o << "CFLAGS += -fverbose-asm -save-temps" << endl;
401
402 // Kernels can be compiled with CONFIG_CC_OPTIMIZE_FOR_SIZE to select
403 // -Os, otherwise -O2 is the default.
404 o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os
405
406 // We used to allow the user to override default optimization when so
407 // requested by adding a -O[0123s] so they could determine the
408 // time/space/speed tradeoffs themselves, but we cannot guantantee that
409 // the (un)optimized code actually compiles and/or generates functional
410 // code, so we had to remove it.
411 // o << "EXTRA_CFLAGS += " << s.gcc_flags << endl; // Add -O[0123s]
412
413 // o << "CFLAGS += -fno-unit-at-a-time" << endl;
414
415 // 256 bytes should be enough for anybody
416 // XXX this doesn't validate varargs, per gcc bug #41633
417 o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=256)" << endl;
418
419 // Assumes linux 2.6 kbuild
420 o << "EXTRA_CFLAGS += -Wno-unused" << (s.omit_werror ? "" : " -Werror") << endl;
421 #if CHECK_POINTER_ARITH_PR5947
422 o << "EXTRA_CFLAGS += -Wpointer-arith" << endl;
423 #endif
424 o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl;
425 // XXX: this may help ppc toc overflow
426 // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl;
427 o << "obj-m := " << s.module_name << ".o" << endl;
428
429 // print out all the auxiliary source (->object) file names
430 o << s.module_name << "-y := ";
431 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
432 {
433 string srcname = s.auxiliary_outputs[i]->filename;
434 assert (srcname != "" && srcname.rfind('/') != string::npos);
435 string objname = srcname.substr(srcname.rfind('/')+1); // basename
436 assert (objname != "" && objname[objname.size()-1] == 'c');
437 objname[objname.size()-1] = 'o'; // now objname
438 o << " " + objname;
439 }
440 // and once again, for the translated_source file. It can't simply
441 // be named MODULENAME.c, since kbuild doesn't allow a foo.ko file
442 // consisting of multiple .o's to have foo.o/foo.c as a source.
443 // (It uses ld -r -o foo.o EACH.o EACH.o).
444 {
445 string srcname = s.translated_source;
446 assert (srcname != "" && srcname.rfind('/') != string::npos);
447 string objname = srcname.substr(srcname.rfind('/')+1); // basename
448 assert (objname != "" && objname[objname.size()-1] == 'c');
449 objname[objname.size()-1] = 'o'; // now objname
450 o << " " + objname;
451 }
452 o << endl;
453
454 // add all stapconf dependencies
455 o << s.translated_source << ": $(STAPCONF_HEADER)" << endl;
456 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
457 o << s.auxiliary_outputs[i]->filename << ": $(STAPCONF_HEADER)" << endl;
458
459
460 o.close ();
461
462 // Generate module directory pathname and make sure it exists.
463 string module_dir = s.kernel_build_tree;
464 string module_dir_makefile = module_dir + "/Makefile";
465 struct stat st;
466 rc = stat(module_dir_makefile.c_str(), &st);
467 if (rc != 0)
468 {
469 clog << _F("Checking \" %s \" failed with error: %s\nEnsure kernel development headers & makefiles are installed.",
470 module_dir_makefile.c_str(), strerror(errno)) << endl;
471 s.set_try_server ();
472 return rc;
473 }
474
475 // Run make
476 vector<string> make_cmd = make_make_cmd(s, s.tmpdir);
477 rc = run_make_cmd(s, make_cmd);
478 if (rc)
479 s.set_try_server ();
480 return rc;
481 }
482
483 /*
484 * If uprobes was built as part of the kernel build (either built-in
485 * or as a module), the uprobes exports should show up. This is to be
486 * as distinct from the stap-built uprobes.ko from the runtime.
487 */
488 static bool
489 kernel_built_uprobes (systemtap_session& s)
490 {
491 if (s.runtime_usermode_p())
492 return true; // sort of, via dyninst
493
494 // see also tapsets.cxx:kernel_supports_inode_uprobes()
495 return ((s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y" && s.kernel_config["CONFIG_UPROBES"] == "y") ||
496 (s.kernel_exports.find("unregister_uprobe") != s.kernel_exports.end()));
497 }
498
499 static int
500 make_uprobes (systemtap_session& s)
501 {
502 if (s.verbose > 1)
503 clog << _("Pass 4, preamble: (re)building SystemTap's version of uprobes.")
504 << endl;
505
506 // create a subdirectory for the uprobes module
507 string dir(s.tmpdir + "/uprobes");
508 if (create_dir(dir.c_str()) != 0)
509 {
510 s.print_warning("failed to create directory for build uprobes.");
511 s.set_try_server ();
512 return 1;
513 }
514
515 // create a simple Makefile
516 string makefile(dir + "/Makefile");
517 ofstream omf(makefile.c_str());
518 omf << "obj-m := uprobes.o" << endl;
519 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
520 omf << "CONFIG_MODULE_SIG := n" << endl;
521 omf.close();
522
523 // create a simple #include-chained source file
524 string runtimesourcefile(s.runtime_path + "/linux/uprobes/uprobes.c");
525 string sourcefile(dir + "/uprobes.c");
526 ofstream osrc(sourcefile.c_str());
527 osrc << "#include \"" << runtimesourcefile << "\"" << endl;
528
529 // pass --modinfo k=v to uprobes build too
530 for (unsigned i = 0; i < s.modinfos.size(); i++)
531 {
532 const string& mi = s.modinfos[i];
533 size_t loc = mi.find('=');
534 string tag = mi.substr (0, loc);
535 string value = mi.substr (loc+1);
536 osrc << "MODULE_INFO(" << tag << "," << lex_cast_qstring(value) << ");" << endl;
537 }
538
539 osrc.close();
540
541 // make the module
542 vector<string> make_cmd = make_make_cmd(s, dir);
543 int rc = run_make_cmd(s, make_cmd);
544 if (!rc && !copy_file(dir + "/Module.symvers",
545 s.tmpdir + "/Module.symvers"))
546 rc = -1;
547
548 if (s.verbose > 1)
549 clog << _("uprobes rebuild exit code: ") << rc << endl;
550 if (rc)
551 s.set_try_server ();
552 else
553 s.uprobes_path = dir + "/uprobes.ko";
554 return rc;
555 }
556
557 static bool
558 get_cached_uprobes(systemtap_session& s)
559 {
560 s.uprobes_hash = s.use_cache ? find_uprobes_hash(s) : "";
561 if (!s.uprobes_hash.empty())
562 {
563 // NB: We always put uprobes.ko in its own directory, especially so
564 // stap-serverd can more easily locate it.
565 string dir(s.tmpdir + "/uprobes");
566 if (create_dir(dir.c_str()) != 0)
567 return false;
568
569 string cacheko = s.uprobes_hash + ".ko";
570 string tmpko = dir + "/uprobes.ko";
571
572 // The symvers file still needs to go in the script module's directory.
573 string cachesyms = s.uprobes_hash + ".symvers";
574 string tmpsyms = s.tmpdir + "/Module.symvers";
575
576 if (get_file_size(cacheko) > 0 && copy_file(cacheko, tmpko) &&
577 get_file_size(cachesyms) > 0 && copy_file(cachesyms, tmpsyms))
578 {
579 s.uprobes_path = tmpko;
580 return true;
581 }
582 }
583 return false;
584 }
585
586 static void
587 set_cached_uprobes(systemtap_session& s)
588 {
589 if (s.use_cache && !s.uprobes_hash.empty())
590 {
591 string cacheko = s.uprobes_hash + ".ko";
592 string tmpko = s.tmpdir + "/uprobes/uprobes.ko";
593 copy_file(tmpko, cacheko);
594
595 string cachesyms = s.uprobes_hash + ".symvers";
596 string tmpsyms = s.tmpdir + "/uprobes/Module.symvers";
597 copy_file(tmpsyms, cachesyms);
598 }
599 }
600
601 int
602 uprobes_pass (systemtap_session& s)
603 {
604 if (!s.need_uprobes || kernel_built_uprobes(s))
605 return 0;
606
607 if (s.kernel_config["CONFIG_UTRACE"] != string("y"))
608 {
609 clog << _("user-space process-tracking facilities not available [man error::process-tracking]") << endl;
610 s.set_try_server ();
611 return 1;
612 }
613
614 /*
615 * We need to use the version of uprobes that comes with SystemTap. Try to
616 * get it from the cache first. If not found, build it and try to save it to
617 * the cache for future reuse.
618 */
619 int rc = 0;
620 if (!get_cached_uprobes(s))
621 {
622 rc = make_uprobes(s);
623 if (!rc)
624 set_cached_uprobes(s);
625 }
626 if (rc)
627 s.set_try_server ();
628 return rc;
629 }
630
631 static
632 vector<string>
633 make_dyninst_run_command (systemtap_session& s, const string& remotedir,
634 const string& version)
635 {
636 vector<string> cmd;
637 cmd.push_back(getenv("SYSTEMTAP_STAPDYN") ?: BINDIR "/stapdyn");
638
639 // use slightly less verbosity
640 for (unsigned i=1; i<s.verbose; i++)
641 cmd.push_back("-v");
642 if (s.suppress_warnings)
643 cmd.push_back("-w");
644
645 if (!s.cmd.empty())
646 {
647 cmd.push_back("-c");
648 cmd.push_back(s.cmd);
649 }
650
651 if (s.target_pid)
652 {
653 cmd.push_back("-x");
654 cmd.push_back(lex_cast(s.target_pid));
655 }
656
657 cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
658 + "/" + s.module_filename());
659
660 return cmd;
661 }
662
663 vector<string>
664 make_run_command (systemtap_session& s, const string& remotedir,
665 const string& version)
666 {
667 if (s.runtime_usermode_p())
668 return make_dyninst_run_command(s, remotedir, version);
669
670 // for now, just spawn staprun
671 vector<string> staprun_cmd;
672 staprun_cmd.push_back(getenv("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun");
673
674 // use slightly less verbosity
675 for (unsigned i=1; i<s.verbose; i++)
676 staprun_cmd.push_back("-v");
677 if (s.suppress_warnings)
678 staprun_cmd.push_back("-w");
679
680 if (!s.output_file.empty())
681 {
682 staprun_cmd.push_back("-o");
683 staprun_cmd.push_back(s.output_file);
684 }
685
686 if (!s.cmd.empty())
687 {
688 staprun_cmd.push_back("-c");
689 staprun_cmd.push_back(s.cmd);
690 }
691
692 if (s.target_pid)
693 {
694 staprun_cmd.push_back("-t");
695 staprun_cmd.push_back(lex_cast(s.target_pid));
696 }
697
698 if (s.buffer_size)
699 {
700 staprun_cmd.push_back("-b");
701 staprun_cmd.push_back(lex_cast(s.buffer_size));
702 }
703
704 if (s.need_uprobes && !kernel_built_uprobes(s))
705 {
706 string opt_u = "-u";
707 if (!s.uprobes_path.empty() &&
708 strverscmp("1.4", version.c_str()) <= 0)
709 {
710 if (remotedir.empty())
711 opt_u.append(s.uprobes_path);
712 else
713 opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str()));
714 }
715 staprun_cmd.push_back(opt_u);
716 }
717
718 if (s.load_only)
719 staprun_cmd.push_back(s.output_file.empty() ? "-L" : "-D");
720
721 if(!s.modname_given && (strverscmp("1.6", version.c_str()) <= 0))
722 staprun_cmd.push_back("-R");
723
724 if (!s.size_option.empty())
725 {
726 staprun_cmd.push_back("-S");
727 staprun_cmd.push_back(s.size_option);
728 }
729
730 staprun_cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
731 + "/" + s.module_filename());
732
733 // add module arguments
734 staprun_cmd.insert(staprun_cmd.end(),
735 s.globalopts.begin(), s.globalopts.end());
736
737 return staprun_cmd;
738 }
739
740
741 // Build tiny kernel modules to query tracepoints.
742 // Given a (header-file -> test-contents) map, compile them ASAP, and return
743 // a (header-file -> obj-filename) map.
744
745 map<string,string>
746 make_tracequeries(systemtap_session& s, const map<string,string>& contents)
747 {
748 static unsigned tick = 0;
749 string basename("tracequery_kmod_" + lex_cast(++tick));
750 map<string,string> objs;
751
752 // create a subdirectory for the module
753 string dir(s.tmpdir + "/" + basename);
754 if (create_dir(dir.c_str()) != 0)
755 {
756 s.print_warning("failed to create directory for querying tracepoints.");
757 s.set_try_server ();
758 return objs;
759 }
760
761 // create a simple Makefile
762 string makefile(dir + "/Makefile");
763 ofstream omf(makefile.c_str());
764 // force debuginfo generation, and relax implicit functions
765 omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << (s.omit_werror ? "" : " -Werror") << endl;
766 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
767 omf << "CONFIG_MODULE_SIG := n" << endl;
768
769 if (s.kernel_source_tree != "")
770 omf << "EXTRA_CFLAGS += -I" + s.kernel_source_tree << endl;
771
772 omf << "obj-m := " << endl;
773 // write out each header-specific source file into a separate file
774 for (map<string,string>::const_iterator it = contents.begin(); it != contents.end(); it++)
775 {
776 string sbasename = basename + "_" + lex_cast(++tick); // suffixed
777
778 // write out source code
779 string srcname = dir + "/" + sbasename + ".c";
780 string src = it->second;
781 ofstream osrc(srcname.c_str());
782 osrc << src;
783 osrc.close();
784
785 if (s.verbose > 2)
786 clog << _F("Processing tracepoint header %s with query %s",
787 it->first.c_str(), srcname.c_str())
788 << endl;
789
790 // arrange to build it
791 omf << "obj-m += " + sbasename + ".o" << endl; // NB: without <dir> prefix
792 objs[it->first] = dir + "/" + sbasename + ".o";
793 }
794 omf.close();
795
796 // make the module
797 vector<string> make_cmd = make_make_objs_cmd(s, dir);
798 make_cmd.push_back ("-i"); // ignore errors, give rc 0 even in case of tracepoint header nits
799 bool quiet = (s.verbose < 4);
800 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
801 if (rc)
802 s.set_try_server ();
803
804 // Sometimes we fail a tracequery due to PR9993 / PR11649 type
805 // kernel trace header problems. In this case, due to PR12729, we
806 // used to get a lovely "Warning: make exited with status: 2" but no
807 // other useful diagnostic. -vvvv would let a user see what's up,
808 // but the user can't fix the problem even with that.
809
810 return objs;
811 }
812
813
814 // Build a tiny kernel module to query type information
815 static int
816 make_typequery_kmod(systemtap_session& s, const vector<string>& headers, string& name)
817 {
818 static unsigned tick = 0;
819 string basename("typequery_kmod_" + lex_cast(++tick));
820
821 // create a subdirectory for the module
822 string dir(s.tmpdir + "/" + basename);
823 if (create_dir(dir.c_str()) != 0)
824 {
825 s.print_warning("failed to create directory for querying types.");
826 s.set_try_server ();
827 return 1;
828 }
829
830 name = dir + "/" + basename + ".ko";
831
832 // create a simple Makefile
833 string makefile(dir + "/Makefile");
834 ofstream omf(makefile.c_str());
835 omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl;
836
837 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
838 omf << "CONFIG_MODULE_SIG := n" << endl;
839
840 // NB: We use -include instead of #include because that gives us more power.
841 // Using #include searches relative to the source's path, which in this case
842 // is /tmp/..., so that's not helpful. Using -include will search relative
843 // to the cwd, which will be the kernel build root. This means if you have a
844 // full kernel build tree, it's possible to get at types that aren't in the
845 // normal include path, e.g.:
846 // @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->...
847 omf << "CFLAGS_" << basename << ".o :=";
848 for (size_t i = 0; i < headers.size(); ++i)
849 omf << " -include " << lex_cast_qstring(headers[i]); // XXX right quoting?
850 omf << endl;
851
852 omf << "obj-m := " + basename + ".o" << endl;
853 omf.close();
854
855 // create our empty source file
856 string source(dir + "/" + basename + ".c");
857 ofstream osrc(source.c_str());
858 osrc.close();
859
860 // make the module
861 vector<string> make_cmd = make_make_cmd(s, dir);
862 bool quiet = (s.verbose < 4);
863 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
864 if (rc)
865 s.set_try_server ();
866 return rc;
867 }
868
869
870 // Build a tiny user module to query type information
871 static int
872 make_typequery_umod(systemtap_session& s, const vector<string>& headers, string& name)
873 {
874 static unsigned tick = 0;
875
876 name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so";
877
878 // make the module
879 //
880 // NB: As with kmod, using -include makes relative paths more useful. The
881 // cwd in this case will be the cwd of stap itself though, which may be
882 // trickier to deal with. It might be better to "cd `dirname $script`"
883 // first...
884 vector<string> cmd;
885 cmd.push_back("gcc");
886 cmd.push_back("-shared");
887 cmd.push_back("-g");
888 cmd.push_back("-fno-eliminate-unused-debug-types");
889 cmd.push_back("-xc");
890 cmd.push_back("/dev/null");
891 cmd.push_back("-o");
892 cmd.push_back(name);
893 for (size_t i = 0; i < headers.size(); ++i)
894 {
895 cmd.push_back("-include");
896 cmd.push_back(headers[i]);
897 }
898 bool quiet = (s.verbose < 4);
899 int rc = stap_system (s.verbose, cmd, quiet, quiet);
900 if (rc)
901 s.set_try_server ();
902 return rc;
903 }
904
905
906 int
907 make_typequery(systemtap_session& s, string& module)
908 {
909 int rc;
910 string new_module;
911 vector<string> headers;
912 bool kernel = startswith(module, "kernel");
913
914 for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1)
915 {
916 if (module[i] != '<')
917 return -1;
918 end = module.find('>', ++i);
919 if (end == string::npos)
920 return -1;
921 string header = module.substr(i, end - i);
922 vector<string> matches;
923 if (regexp_match(header, "^[a-zA-Z0-9/_.+-]+$", matches))
924 s.print_warning("skipping malformed @cast header \""+ header + "\"");
925 else
926 headers.push_back(header);
927 }
928 if (headers.empty())
929 return -1;
930
931 if (kernel)
932 rc = make_typequery_kmod(s, headers, new_module);
933 else
934 rc = make_typequery_umod(s, headers, new_module);
935
936 if (!rc)
937 module = new_module;
938
939 return rc;
940 }
941
942 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.092781 seconds and 6 git commands to generate.