]> sourceware.org Git - systemtap.git/blame - buildrun.cxx
PR14632: Some typos in documents
[systemtap.git] / buildrun.cxx
CommitLineData
f4b28491 1// build/run probes
150f2075 2// Copyright (C) 2005-2012 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"
a4b9c3b3 14#include "translate.h"
f4b28491 15
3b579393 16#include <cstdlib>
f4b28491 17#include <fstream>
d04cf5ff
FCE
18#include <sstream>
19
20extern "C" {
49abf162 21#include <signal.h>
0c6296b2 22#include <sys/wait.h>
70404fc5 23#include <pwd.h>
0da3e7a0 24#include <grp.h>
b40af7ee
DS
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
28#include <string.h>
29#include <errno.h>
d04cf5ff
FCE
30}
31
f4b28491
FCE
32
33using namespace std;
34
6274464e
JK
35/* Adjust and run make_cmd to build a kernel module. */
36static int
ff520ff4
JS
37run_make_cmd(systemtap_session& s, vector<string>& make_cmd,
38 bool null_out=false, bool null_err=false)
6274464e 39{
e19ebcf7 40 assert_no_interrupts();
576acc1a 41
e8474d2a
FCE
42 // PR14168: we used to unsetenv values here; instead do it via
43 // env(1) in make_any_make_cmd().
6274464e 44
b51455af
JS
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
b54581ce 51 if (s.verbose > 2)
ff520ff4 52 make_cmd.push_back("V=1");
b54581ce 53 else if (s.verbose > 1)
ff520ff4 54 make_cmd.push_back("--no-print-directory");
6274464e 55 else
ff520ff4
JS
56 {
57 make_cmd.push_back("-s");
58 make_cmd.push_back("--no-print-directory");
59 }
dff50e09 60
70fb16aa 61 // Exploit SMP parallelism, if available.
9fa0ffac 62 long smp = sysconf(_SC_NPROCESSORS_ONLN);
70fb16aa
FCE
63 if (smp >= 1)
64 make_cmd.push_back("-j" + lex_cast(smp+1));
9fa0ffac 65
e0ccd368
FCE
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.
ff520ff4 71 null_out = true;
e0ccd368
FCE
72 }
73
b13c6a37 74 int rc = stap_system (s.verbose, "kbuild", make_cmd, null_out, null_err);
3e1ec884
DB
75 if (rc != 0)
76 s.set_try_server ();
77 return rc;
6274464e 78}
f4b28491 79
7d26ee02 80static vector<string>
8e0a2563 81make_any_make_cmd(systemtap_session& s, const string& dir, const string& target)
7d26ee02
JS
82{
83 vector<string> make_cmd;
e8474d2a
FCE
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
7d26ee02
JS
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?
8e0a2563 100 make_cmd.push_back(target);
7d26ee02
JS
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
150f2075
FCE
107 // PR13847: suppress debuginfo creation by default
108 make_cmd.insert(make_cmd.end(), "CONFIG_DEBUG_INFO=");
109
7d26ee02
JS
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
8e0a2563
JS
116static vector<string>
117make_make_cmd(systemtap_session& s, const string& dir)
118{
119 return make_any_make_cmd(s, dir, "modules");
120}
121
122static vector<string>
123make_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
de0db58a
JS
137static void
138output_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 << "@";
2ba1736a 144 o << "if $(CHECK_BUILD) $(SYSTEMTAP_RUNTIME)/linux/" << autoconf_c;
de0db58a
JS
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
9e62f7ba
FCE
155
156void output_exportconf(systemtap_session& s, ofstream& o, const char *symbol,
157 const char *deftrue)
e25ab03c 158{
9e62f7ba
FCE
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;
e25ab03c
WH
165}
166
9e62f7ba 167
08c29612
DS
168void 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
13128684
JS
182void 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
3a894f7e
JS
196static int
197compile_dyninst (systemtap_session& s)
198{
4441e344 199 const string module = s.tmpdir + "/" + s.module_filename();
3a894f7e
JS
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");
2466bf70
JS
209 cmd.push_back("-I" + s.runtime_path);
210 cmd.push_back("-D__DYNINST__");
8140a78d
JS
211 for (size_t i = 0; i < s.c_macros.size(); ++i)
212 cmd.push_back("-D" + s.c_macros[i]);
3a894f7e
JS
213 cmd.push_back(s.translated_source);
214 cmd.push_back("-pthread");
215 cmd.push_back("-fPIC");
216 cmd.push_back("-shared");
217 cmd.push_back("-o");
218 cmd.push_back(module);
8140a78d
JS
219 if (s.verbose > 3)
220 {
221 cmd.push_back("-ftime-report");
222 cmd.push_back("-Q");
223 }
3a894f7e 224
6da8678d 225 int rc = stap_system (s.verbose, cmd);
3a894f7e
JS
226 if (rc)
227 s.set_try_server ();
228 return rc;
229}
3a894f7e
JS
230
231
f4b28491
FCE
232int
233compile_pass (systemtap_session& s)
234{
ac3af990 235 if (s.runtime_usermode_p())
4441e344 236 return compile_dyninst (s);
3a894f7e 237
db3a383b
JK
238 int rc = uprobes_pass (s);
239 if (rc)
3e1ec884
DB
240 {
241 s.set_try_server ();
242 return rc;
243 }
db3a383b 244
f4b28491 245 // fill in a quick Makefile
92ade41d
FCE
246 string makefile_nm = s.tmpdir + "/Makefile";
247 ofstream o (makefile_nm.c_str());
92ade41d
FCE
248
249 // Create makefile
ed10c639 250
255e4c68 251 // Clever hacks copied from vmware modules
ecf19454
FCE
252 string superverbose;
253 if (s.verbose > 3)
254 superverbose = "set -x;";
522518f1 255
e9737939
MM
256 string redirecterrors = "> /dev/null 2>&1";
257 if (s.verbose > 6)
258 redirecterrors = "";
259
e5976ba0
MH
260 // Support O= (or KBUILD_OUTPUT) option
261 o << "_KBUILD_CFLAGS := $(call flags,KBUILD_CFLAGS)" << endl;
262
ecf19454 263 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 264 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 265 o << "stap_check_build = $(shell " << superverbose << " if $(CHECK_BUILD) $(1) " << redirecterrors << " ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl;
255e4c68
FCE
266
267 o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl;
268
269 // "autoconf" options go here
270
18222191
FCE
271 // RHBZ 543529: early rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
272 o << "CONFIG_MODULE_SIG := n" << endl;
273
ecf19454 274 string module_cflags = "EXTRA_CFLAGS";
522518f1 275 o << module_cflags << " :=" << endl;
84c4da88
FCE
276
277 // XXX: This gruesome hack is needed on some kernels built with separate O=directory,
278 // where files like 2.6.27 x86's asm/mach-*/mach_mpspec.h are not found on the cpp path.
279 // This could be a bug in arch/x86/Makefile that names
280 // mflags-y += -Iinclude/asm-x86/mach-default
281 // but that path does not exist in an O= build tree.
282 o << module_cflags << " += -Iinclude2/asm/mach-default" << endl;
d4393459
FCE
283 if (s.kernel_source_tree != "")
284 o << module_cflags << " += -I" + s.kernel_source_tree << endl;
84c4da88 285
6046b840
FCE
286 // NB: don't try
287 // o << module_cflags << " += -Iusr/include" << endl;
288 // since such headers are cleansed of _KERNEL_ pieces that we need
289
de0db58a 290 o << "STAPCONF_HEADER := " << s.tmpdir << "/" << s.stapconf_name << endl;
de0db58a
JS
291 o << "$(STAPCONF_HEADER):" << endl;
292 o << "\t@echo -n > $@" << endl;
293 output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL);
1d381a0d 294 output_autoconf(s, o, "autoconf-generated-compile.c", "STAPCONF_GENERATED_COMPILE", NULL);
de0db58a
JS
295 output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL);
296 output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL);
297 output_autoconf(s, o, "autoconf-constant-tsc.c", "STAPCONF_CONSTANT_TSC", NULL);
de0db58a
JS
298 output_autoconf(s, o, "autoconf-ktime-get-real.c", "STAPCONF_KTIME_GET_REAL", NULL);
299 output_autoconf(s, o, "autoconf-x86-uniregs.c", "STAPCONF_X86_UNIREGS", NULL);
300 output_autoconf(s, o, "autoconf-nameidata.c", "STAPCONF_NAMEIDATA_CLEANUP", NULL);
08c29612 301 output_dual_exportconf(s, o, "unregister_kprobes", "unregister_kretprobes", "STAPCONF_UNREGISTER_KPROBES");
766cee5f 302 output_autoconf(s, o, "autoconf-kprobe-symbol-name.c", "STAPCONF_KPROBE_SYMBOL_NAME", NULL);
de0db58a
JS
303 output_autoconf(s, o, "autoconf-real-parent.c", "STAPCONF_REAL_PARENT", NULL);
304 output_autoconf(s, o, "autoconf-uaccess.c", "STAPCONF_LINUX_UACCESS_H", NULL);
305 output_autoconf(s, o, "autoconf-oneachcpu-retry.c", "STAPCONF_ONEACHCPU_RETRY", NULL);
306 output_autoconf(s, o, "autoconf-dpath-path.c", "STAPCONF_DPATH_PATH", NULL);
08c29612 307 output_exportconf(s, o, "synchronize_sched", "STAPCONF_SYNCHRONIZE_SCHED");
de0db58a 308 output_autoconf(s, o, "autoconf-task-uid.c", "STAPCONF_TASK_UID", NULL);
08c29612 309 output_dual_exportconf(s, o, "alloc_vm_area", "free_vm_area", "STAPCONF_VM_AREA");
de0db58a 310 output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL);
b1f85b93 311 output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL);
5cad2d3b 312 output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL);
f098eb6d 313 output_autoconf(s, o, "autoconf-grsecurity.c", "STAPCONF_GRSECURITY", NULL);
450718c9 314 output_autoconf(s, o, "autoconf-trace-printk.c", "STAPCONF_TRACE_PRINTK", NULL);
be004140
FCE
315 output_autoconf(s, o, "autoconf-regset.c", "STAPCONF_REGSET", NULL);
316 output_autoconf(s, o, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL);
23258335 317 output_autoconf(s, o, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL);
b09417ad 318 output_exportconf(s, o, "tsc_khz", "STAPCONF_TSC_KHZ");
9e62f7ba 319 output_exportconf(s, o, "cpu_khz", "STAPCONF_CPU_KHZ");
031fda59 320 output_exportconf(s, o, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS");
af6c651f 321 output_exportconf(s, o, "add_timer_on", "STAPCONF_ADD_TIMER_ON");
8d59b39f 322
08c29612 323 output_dual_exportconf(s, o, "probe_kernel_read", "probe_kernel_write", "STAPCONF_PROBE_KERNEL");
b273669e
MW
324 output_autoconf(s, o, "autoconf-hw_breakpoint_context.c",
325 "STAPCONF_HW_BREAKPOINT_CONTEXT", NULL);
8c5905d0
TM
326 output_autoconf(s, o, "autoconf-save-stack-trace.c",
327 "STAPCONF_KERNEL_STACKTRACE", NULL);
9957bbd2
MW
328 output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c",
329 "STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL);
d5cd287f
DS
330 output_autoconf(s, o, "autoconf-asm-syscall.c",
331 "STAPCONF_ASM_SYSCALL_H", NULL);
c145b9cb 332 output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL);
0d0f0d84 333 output_autoconf(s, o, "autoconf-ring_buffer_lost_events.c", "STAPCONF_RING_BUFFER_LOST_EVENTS", NULL);
c38602b5 334 output_autoconf(s, o, "autoconf-ring_buffer_read_prepare.c", "STAPCONF_RING_BUFFER_READ_PREPARE", NULL);
03a4ec63 335 output_autoconf(s, o, "autoconf-kallsyms-on-each-symbol.c", "STAPCONF_KALLSYMS_ON_EACH_SYMBOL", NULL);
c265cd25 336 output_autoconf(s, o, "autoconf-walk-stack.c", "STAPCONF_WALK_STACK", NULL);
0bbb8009
JS
337 output_autoconf(s, o, "autoconf-stacktrace_ops-warning.c",
338 "STAPCONF_STACKTRACE_OPS_WARNING", NULL);
18da5887 339 output_autoconf(s, o, "autoconf-mm-context-vdso.c", "STAPCONF_MM_CONTEXT_VDSO", NULL);
3b62d74b 340 output_autoconf(s, o, "autoconf-mm-context-vdso-base.c", "STAPCONF_MM_CONTEXT_VDSO_BASE", NULL);
c1d2d085 341 output_autoconf(s, o, "autoconf-blk-types.c", "STAPCONF_BLK_TYPES", NULL);
aec17ca6 342 output_autoconf(s, o, "autoconf-perf-structpid.c", "STAPCONF_PERF_STRUCTPID", NULL);
2f3df331
MW
343 output_autoconf(s, o, "perf_event_counter_context.c",
344 "STAPCONF_PERF_COUNTER_CONTEXT", NULL);
345 output_autoconf(s, o, "perf_probe_handler_nmi.c",
346 "STAPCONF_PERF_HANDLER_NMI", NULL);
7f2d56c3
DS
347 output_exportconf(s, o, "path_lookup", "STAPCONF_PATH_LOOKUP");
348 output_exportconf(s, o, "kern_path_parent", "STAPCONF_KERN_PATH_PARENT");
349 output_exportconf(s, o, "vfs_path_lookup", "STAPCONF_VFS_PATH_LOOKUP");
2c9caccb 350 output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
255e4c68 351
db7dcdff 352 output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL);
0e0e60b2 353 output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL);
abc69bab 354 output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL);
56111fdc 355 output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL);
52dea427 356 output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL);
db7dcdff 357
de5f477b
JS
358 // used by tapset/timestamp_monotonic.stp
359 output_exportconf(s, o, "cpu_clock", "STAPCONF_CPU_CLOCK");
360 output_exportconf(s, o, "local_clock", "STAPCONF_LOCAL_CLOCK");
361
64e807c2 362 // used by runtime/uprobe-inode.c
13128684
JS
363 output_either_exportconf(s, o, "uprobe_register", "register_uprobe",
364 "STAPCONF_UPROBE_REGISTER_EXPORTED");
365 output_either_exportconf(s, o, "uprobe_unregister", "unregister_uprobe",
366 "STAPCONF_UPROBE_UNREGISTER_EXPORTED");
367 output_autoconf(s, o, "autoconf-old-inode-uprobes.c", "STAPCONF_OLD_INODE_UPROBES", NULL);
39e63bae
DS
368
369 // used by tapsets.cxx inode uprobe generated code
370 output_exportconf(s, o, "uprobe_get_swbp_addr", "STAPCONF_UPROBE_GET_SWBP_ADDR_EXPORTED");
371
fe6feb40 372 // used by runtime/loc2c-runtime.h
64e807c2
FCE
373 output_exportconf(s, o, "task_user_regset_view", "STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED");
374
36de3b61
DS
375 // used by runtime/stp_utrace.c
376 output_exportconf(s, o, "task_work_add", "STAPCONF_TASK_WORK_ADD_EXPORTED");
377
8fee9cc5
FCE
378 output_autoconf(s, o, "autoconf-pagefault_disable.c", "STAPCONF_PAGEFAULT_DISABLE", NULL);
379
de0db58a 380 o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
5c54d49e 381
08fce398
SM
382 for (unsigned i=0; i<s.c_macros.size(); i++)
383 o << "EXTRA_CFLAGS += -D " << lex_cast_qstring(s.c_macros[i]) << endl; // XXX right quoting?
ed10c639 384
e4c58386 385 if (s.verbose > 3)
0986ac38 386 o << "EXTRA_CFLAGS += -ftime-report -Q" << endl;
db22e55f 387
ee6dda6f 388 // XXX: unfortunately, -save-temps can't work since linux kbuild cwd
100a540e 389 // is not writable.
ee6dda6f
FCE
390 //
391 // if (s.keep_tmpdir)
392 // o << "CFLAGS += -fverbose-asm -save-temps" << endl;
393
ec6fdef5
MW
394 // Kernels can be compiled with CONFIG_CC_OPTIMIZE_FOR_SIZE to select
395 // -Os, otherwise -O2 is the default.
396 o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os
397
01116596
MW
398 // We used to allow the user to override default optimization when so
399 // requested by adding a -O[0123s] so they could determine the
400 // time/space/speed tradeoffs themselves, but we cannot guantantee that
401 // the (un)optimized code actually compiles and/or generates functional
402 // code, so we had to remove it.
403 // o << "EXTRA_CFLAGS += " << s.gcc_flags << endl; // Add -O[0123s]
35d4ab18
FCE
404
405 // o << "CFLAGS += -fno-unit-at-a-time" << endl;
dff50e09 406
01a2eba8
JS
407 // 256 bytes should be enough for anybody
408 // XXX this doesn't validate varargs, per gcc bug #41633
409 o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=256)" << endl;
730c3efc 410
cbfbbf69 411 // Assumes linux 2.6 kbuild
c72dd3c7 412 o << "EXTRA_CFLAGS += -Wno-unused" << (s.omit_werror ? "" : " -Werror") << endl;
29bdbdb1
FCE
413 #if CHECK_POINTER_ARITH_PR5947
414 o << "EXTRA_CFLAGS += -Wpointer-arith" << endl;
415 #endif
0986ac38 416 o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl;
4b2c4ab5
FCE
417 // XXX: this may help ppc toc overflow
418 // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl;
cbfbbf69 419 o << "obj-m := " << s.module_name << ".o" << endl;
f4b28491 420
a4b9c3b3
FCE
421 // print out all the auxiliary source (->object) file names
422 o << s.module_name << "-y := ";
423 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
424 {
425 string srcname = s.auxiliary_outputs[i]->filename;
426 assert (srcname != "" && srcname.rfind('/') != string::npos);
427 string objname = srcname.substr(srcname.rfind('/')+1); // basename
428 assert (objname != "" && objname[objname.size()-1] == 'c');
429 objname[objname.size()-1] = 'o'; // now objname
430 o << " " + objname;
431 }
432 // and once again, for the translated_source file. It can't simply
433 // be named MODULENAME.c, since kbuild doesn't allow a foo.ko file
434 // consisting of multiple .o's to have foo.o/foo.c as a source.
435 // (It uses ld -r -o foo.o EACH.o EACH.o).
436 {
437 string srcname = s.translated_source;
438 assert (srcname != "" && srcname.rfind('/') != string::npos);
439 string objname = srcname.substr(srcname.rfind('/')+1); // basename
440 assert (objname != "" && objname[objname.size()-1] == 'c');
441 objname[objname.size()-1] = 'o'; // now objname
442 o << " " + objname;
443 }
444 o << endl;
445
446 // add all stapconf dependencies
447 o << s.translated_source << ": $(STAPCONF_HEADER)" << endl;
448 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
449 o << s.auxiliary_outputs[i]->filename << ": $(STAPCONF_HEADER)" << endl;
450
451
ed10c639
FCE
452 o.close ();
453
b40af7ee 454 // Generate module directory pathname and make sure it exists.
4d34dac1
FCE
455 string module_dir = s.kernel_build_tree;
456 string module_dir_makefile = module_dir + "/Makefile";
b40af7ee 457 struct stat st;
4d34dac1 458 rc = stat(module_dir_makefile.c_str(), &st);
b40af7ee
DS
459 if (rc != 0)
460 {
ce0f6648 461 clog << _F("Checking \" %s \" failed with error: %s\nEnsure kernel development headers & makefiles are installed.",
46a1a151 462 module_dir_makefile.c_str(), strerror(errno)) << endl;
3e1ec884 463 s.set_try_server ();
b40af7ee 464 return rc;
dff50e09 465 }
b40af7ee
DS
466
467 // Run make
7d26ee02 468 vector<string> make_cmd = make_make_cmd(s, s.tmpdir);
6274464e 469 rc = run_make_cmd(s, make_cmd);
3e1ec884
DB
470 if (rc)
471 s.set_try_server ();
f4b28491
FCE
472 return rc;
473}
474
db3a383b
JK
475/*
476 * If uprobes was built as part of the kernel build (either built-in
dbb9345d
FCE
477 * or as a module), the uprobes exports should show up. This is to be
478 * as distinct from the stap-built uprobes.ko from the runtime.
db3a383b
JK
479 */
480static bool
481kernel_built_uprobes (systemtap_session& s)
6274464e 482{
ac3af990 483 if (s.runtime_usermode_p())
4441e344
JS
484 return true; // sort of, via dyninst
485
95113339
FCE
486 // see also tapsets.cxx:kernel_supports_inode_uprobes()
487 return ((s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y" && s.kernel_config["CONFIG_UPROBES"] == "y") ||
488 (s.kernel_exports.find("unregister_uprobe") != s.kernel_exports.end()));
6274464e
JK
489}
490
7d26ee02
JS
491static int
492make_uprobes (systemtap_session& s)
6274464e 493{
7ef486ad 494 if (s.verbose > 1)
7d26ee02 495 clog << _("Pass 4, preamble: (re)building SystemTap's version of uprobes.")
db3a383b
JK
496 << endl;
497
7d26ee02
JS
498 // create a subdirectory for the uprobes module
499 string dir(s.tmpdir + "/uprobes");
500 if (create_dir(dir.c_str()) != 0)
501 {
2713ea24 502 s.print_warning("failed to create directory for build uprobes.");
7d26ee02
JS
503 s.set_try_server ();
504 return 1;
0da3e7a0 505 }
6274464e 506
7d26ee02
JS
507 // create a simple Makefile
508 string makefile(dir + "/Makefile");
509 ofstream omf(makefile.c_str());
510 omf << "obj-m := uprobes.o" << endl;
511 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
512 omf << "CONFIG_MODULE_SIG := n" << endl;
513 omf.close();
6274464e 514
7d26ee02 515 // create a simple #include-chained source file
2ba1736a 516 string runtimesourcefile(s.runtime_path + "/linux/uprobes/uprobes.c");
7d26ee02
JS
517 string sourcefile(dir + "/uprobes.c");
518 ofstream osrc(sourcefile.c_str());
519 osrc << "#include \"" << runtimesourcefile << "\"" << endl;
76d01f36
FCE
520
521 // pass --modinfo k=v to uprobes build too
522 for (unsigned i = 0; i < s.modinfos.size(); i++)
523 {
524 const string& mi = s.modinfos[i];
525 size_t loc = mi.find('=');
526 string tag = mi.substr (0, loc);
527 string value = mi.substr (loc+1);
528 osrc << "MODULE_INFO(" << tag << "," << lex_cast_qstring(value) << ");" << endl;
529 }
530
7d26ee02
JS
531 osrc.close();
532
533 // make the module
534 vector<string> make_cmd = make_make_cmd(s, dir);
ae5e0bbb 535 int rc = run_make_cmd(s, make_cmd);
7d26ee02
JS
536 if (!rc && !copy_file(dir + "/Module.symvers",
537 s.tmpdir + "/Module.symvers"))
538 rc = -1;
6274464e 539
f4d5049b 540 if (s.verbose > 1)
ce0f6648 541 clog << _("uprobes rebuild exit code: ") << rc << endl;
3e1ec884
DB
542 if (rc)
543 s.set_try_server ();
7d26ee02
JS
544 else
545 s.uprobes_path = dir + "/uprobes.ko";
6274464e
JK
546 return rc;
547}
548
7d26ee02
JS
549static bool
550get_cached_uprobes(systemtap_session& s)
551{
552 s.uprobes_hash = s.use_cache ? find_uprobes_hash(s) : "";
553 if (!s.uprobes_hash.empty())
554 {
555 // NB: We always put uprobes.ko in its own directory, especially so
556 // stap-serverd can more easily locate it.
557 string dir(s.tmpdir + "/uprobes");
558 if (create_dir(dir.c_str()) != 0)
559 return false;
560
561 string cacheko = s.uprobes_hash + ".ko";
562 string tmpko = dir + "/uprobes.ko";
563
564 // The symvers file still needs to go in the script module's directory.
565 string cachesyms = s.uprobes_hash + ".symvers";
566 string tmpsyms = s.tmpdir + "/Module.symvers";
567
568 if (get_file_size(cacheko) > 0 && copy_file(cacheko, tmpko) &&
569 get_file_size(cachesyms) > 0 && copy_file(cachesyms, tmpsyms))
570 {
571 s.uprobes_path = tmpko;
572 return true;
573 }
574 }
575 return false;
576}
577
578static void
579set_cached_uprobes(systemtap_session& s)
db3a383b 580{
7d26ee02
JS
581 if (s.use_cache && !s.uprobes_hash.empty())
582 {
583 string cacheko = s.uprobes_hash + ".ko";
584 string tmpko = s.tmpdir + "/uprobes/uprobes.ko";
585 copy_file(tmpko, cacheko);
36ef6d6a 586
7d26ee02
JS
587 string cachesyms = s.uprobes_hash + ".symvers";
588 string tmpsyms = s.tmpdir + "/uprobes/Module.symvers";
589 copy_file(tmpsyms, cachesyms);
590 }
db3a383b
JK
591}
592
7d26ee02 593int
db3a383b
JK
594uprobes_pass (systemtap_session& s)
595{
596 if (!s.need_uprobes || kernel_built_uprobes(s))
597 return 0;
0944a81e 598
6c7e2241 599 if (s.kernel_config["CONFIG_UTRACE"] != string("y"))
01fa08f2
DS
600 {
601 clog << _("user-space facilities not available without kernel CONFIG_UTRACE or CONFIG_TRACEPOINTS/CONFIG_ARCH_SUPPORTS_UPROBES/CONFIG_UPROBES") << endl;
602 s.set_try_server ();
603 return 1;
604 }
0944a81e 605
db3a383b 606 /*
7d26ee02
JS
607 * We need to use the version of uprobes that comes with SystemTap. Try to
608 * get it from the cache first. If not found, build it and try to save it to
609 * the cache for future reuse.
db3a383b 610 */
7d26ee02
JS
611 int rc = 0;
612 if (!get_cached_uprobes(s))
613 {
614 rc = make_uprobes(s);
615 if (!rc)
616 set_cached_uprobes(s);
617 }
3e1ec884
DB
618 if (rc)
619 s.set_try_server ();
db3a383b
JK
620 return rc;
621}
622
3a894f7e
JS
623static
624vector<string>
625make_dyninst_run_command (systemtap_session& s, const string& remotedir,
626 const string& version)
627{
628 vector<string> cmd;
56658530 629 cmd.push_back(getenv("SYSTEMTAP_STAPDYN") ?: BINDIR "/stapdyn");
41300e6d
JS
630 if (s.verbose > 1)
631 cmd.push_back("-v");
632 if (s.verbose > 2)
633 cmd.push_back("-v");
634 if (s.suppress_warnings)
635 cmd.push_back("-w");
3a894f7e
JS
636
637 if (!s.cmd.empty())
638 {
639 cmd.push_back("-c");
640 cmd.push_back(s.cmd);
641 }
642
643 cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
4441e344 644 + "/" + s.module_filename());
3a894f7e
JS
645
646 return cmd;
647}
3a894f7e 648
5eea6ed1 649vector<string>
18630fb8 650make_run_command (systemtap_session& s, const string& remotedir,
4112f219 651 const string& version)
f4b28491 652{
ac3af990 653 if (s.runtime_usermode_p())
4441e344
JS
654 return make_dyninst_run_command(s, remotedir, version);
655
a63a95dc 656 // for now, just spawn staprun
5eea6ed1
JS
657 vector<string> staprun_cmd;
658 staprun_cmd.push_back(getenv("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun");
659 if (s.verbose>1)
660 staprun_cmd.push_back("-v");
661 if (s.verbose>2)
662 staprun_cmd.push_back("-v");
663 if (s.suppress_warnings)
664 staprun_cmd.push_back("-w");
665
666 if (!s.output_file.empty())
667 {
668 staprun_cmd.push_back("-o");
669 staprun_cmd.push_back(s.output_file);
670 }
dff50e09 671
5eea6ed1
JS
672 if (!s.cmd.empty())
673 {
674 staprun_cmd.push_back("-c");
675 staprun_cmd.push_back(s.cmd);
676 }
dff50e09 677
cbfbbf69 678 if (s.target_pid)
5eea6ed1
JS
679 {
680 staprun_cmd.push_back("-t");
681 staprun_cmd.push_back(lex_cast(s.target_pid));
682 }
dff50e09 683
cbfbbf69 684 if (s.buffer_size)
5eea6ed1
JS
685 {
686 staprun_cmd.push_back("-b");
687 staprun_cmd.push_back(lex_cast(s.buffer_size));
688 }
dff50e09 689
13128684 690 if (s.need_uprobes && !kernel_built_uprobes(s))
5eea6ed1 691 {
18630fb8
JS
692 string opt_u = "-u";
693 if (!s.uprobes_path.empty() &&
694 strverscmp("1.4", version.c_str()) <= 0)
695 {
696 if (remotedir.empty())
697 opt_u.append(s.uprobes_path);
698 else
699 opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str()));
700 }
701 staprun_cmd.push_back(opt_u);
5eea6ed1 702 }
6274464e 703
2fa2a091 704 if (s.load_only)
5eea6ed1 705 staprun_cmd.push_back(s.output_file.empty() ? "-L" : "-D");
701c41be 706
4112f219 707 if(!s.modname_given && (strverscmp("1.6", version.c_str()) <= 0))
5c854d7c
CM
708 staprun_cmd.push_back("-R");
709
701c41be 710 if (!s.size_option.empty())
5eea6ed1
JS
711 {
712 staprun_cmd.push_back("-S");
713 staprun_cmd.push_back(s.size_option);
714 }
2fa2a091 715
18630fb8 716 staprun_cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
4441e344 717 + "/" + s.module_filename());
dff50e09 718
bb25d08f 719 // add module arguments
5eea6ed1
JS
720 staprun_cmd.insert(staprun_cmd.end(),
721 s.globalopts.begin(), s.globalopts.end());
bb25d08f 722
daa75206 723 return staprun_cmd;
f4b28491 724}
73267b89 725
0a6f5a3f 726
c9ccb642
FCE
727// Build tiny kernel modules to query tracepoints.
728// Given a (header-file -> test-contents) map, compile them ASAP, and return
2a0e62a8 729// a (header-file -> obj-filename) map.
c9ccb642
FCE
730
731map<string,string>
732make_tracequeries(systemtap_session& s, const map<string,string>& contents)
0a6f5a3f 733{
f982c59b 734 static unsigned tick = 0;
aca66a36 735 string basename("tracequery_kmod_" + lex_cast(++tick));
2a0e62a8 736 map<string,string> objs;
f982c59b 737
0a6f5a3f 738 // create a subdirectory for the module
f982c59b 739 string dir(s.tmpdir + "/" + basename);
0a6f5a3f
JS
740 if (create_dir(dir.c_str()) != 0)
741 {
2713ea24 742 s.print_warning("failed to create directory for querying tracepoints.");
3e1ec884 743 s.set_try_server ();
2a0e62a8 744 return objs;
0a6f5a3f
JS
745 }
746
0a6f5a3f
JS
747 // create a simple Makefile
748 string makefile(dir + "/Makefile");
749 ofstream omf(makefile.c_str());
9ccda279 750 // force debuginfo generation, and relax implicit functions
c72dd3c7 751 omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << (s.omit_werror ? "" : " -Werror") << endl;
a7ec2317
FCE
752 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
753 omf << "CONFIG_MODULE_SIG := n" << endl;
754
c9ccb642
FCE
755 if (s.kernel_source_tree != "")
756 omf << "EXTRA_CFLAGS += -I" + s.kernel_source_tree << endl;
0a6f5a3f 757
c9ccb642
FCE
758 omf << "obj-m := " << endl;
759 // write out each header-specific source file into a separate file
760 for (map<string,string>::const_iterator it = contents.begin(); it != contents.end(); it++)
761 {
762 string sbasename = basename + "_" + lex_cast(++tick); // suffixed
763
764 // write out source code
765 string srcname = dir + "/" + sbasename + ".c";
766 string src = it->second;
767 ofstream osrc(srcname.c_str());
768 osrc << src;
769 osrc.close();
770
771 // arrange to build it
772 omf << "obj-m += " + sbasename + ".o" << endl; // NB: without <dir> prefix
2a0e62a8 773 objs[it->first] = dir + "/" + sbasename + ".o";
c9ccb642
FCE
774 }
775 omf.close();
0a6f5a3f
JS
776
777 // make the module
8e0a2563 778 vector<string> make_cmd = make_make_objs_cmd(s, dir);
e86f32ee 779 make_cmd.push_back ("-i"); // ignore errors, give rc 0 even in case of tracepoint header nits
ff520ff4
JS
780 bool quiet = (s.verbose < 4);
781 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
3e1ec884
DB
782 if (rc)
783 s.set_try_server ();
c2cf1b87 784
e86f32ee
FCE
785 // Sometimes we fail a tracequery due to PR9993 / PR11649 type
786 // kernel trace header problems. In this case, due to PR12729, we
787 // used to get a lovely "Warning: make exited with status: 2" but no
c2cf1b87
FCE
788 // other useful diagnostic. -vvvv would let a user see what's up,
789 // but the user can't fix the problem even with that.
790
2a0e62a8 791 return objs;
0a6f5a3f
JS
792}
793
3e1c25aa
JS
794
795// Build a tiny kernel module to query type information
d90053e7 796static int
da9e11bd 797make_typequery_kmod(systemtap_session& s, const vector<string>& headers, string& name)
3e1c25aa
JS
798{
799 static unsigned tick = 0;
aca66a36 800 string basename("typequery_kmod_" + lex_cast(++tick));
3e1c25aa
JS
801
802 // create a subdirectory for the module
803 string dir(s.tmpdir + "/" + basename);
804 if (create_dir(dir.c_str()) != 0)
805 {
2713ea24 806 s.print_warning("failed to create directory for querying types.");
3e1ec884 807 s.set_try_server ();
3e1c25aa
JS
808 return 1;
809 }
810
811 name = dir + "/" + basename + ".ko";
812
813 // create a simple Makefile
814 string makefile(dir + "/Makefile");
815 ofstream omf(makefile.c_str());
816 omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl;
3ae4cdf9 817
a7ec2317
FCE
818 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
819 omf << "CONFIG_MODULE_SIG := n" << endl;
820
3ae4cdf9
JS
821 // NB: We use -include instead of #include because that gives us more power.
822 // Using #include searches relative to the source's path, which in this case
823 // is /tmp/..., so that's not helpful. Using -include will search relative
824 // to the cwd, which will be the kernel build root. This means if you have a
825 // full kernel build tree, it's possible to get at types that aren't in the
826 // normal include path, e.g.:
827 // @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->...
da9e11bd
JS
828 omf << "CFLAGS_" << basename << ".o :=";
829 for (size_t i = 0; i < headers.size(); ++i)
ff520ff4 830 omf << " -include " << lex_cast_qstring(headers[i]); // XXX right quoting?
da9e11bd 831 omf << endl;
3ae4cdf9 832
3e1c25aa
JS
833 omf << "obj-m := " + basename + ".o" << endl;
834 omf.close();
835
836 // create our empty source file
837 string source(dir + "/" + basename + ".c");
838 ofstream osrc(source.c_str());
839 osrc.close();
840
841 // make the module
7d26ee02 842 vector<string> make_cmd = make_make_cmd(s, dir);
ff520ff4
JS
843 bool quiet = (s.verbose < 4);
844 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
3e1ec884
DB
845 if (rc)
846 s.set_try_server ();
847 return rc;
3e1c25aa
JS
848}
849
850
851// Build a tiny user module to query type information
d90053e7 852static int
da9e11bd 853make_typequery_umod(systemtap_session& s, const vector<string>& headers, string& name)
3e1c25aa
JS
854{
855 static unsigned tick = 0;
856
aca66a36 857 name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so";
3e1c25aa
JS
858
859 // make the module
3ae4cdf9
JS
860 //
861 // NB: As with kmod, using -include makes relative paths more useful. The
862 // cwd in this case will be the cwd of stap itself though, which may be
863 // trickier to deal with. It might be better to "cd `dirname $script`"
864 // first...
ff520ff4
JS
865 vector<string> cmd;
866 cmd.push_back("gcc");
867 cmd.push_back("-shared");
868 cmd.push_back("-g");
869 cmd.push_back("-fno-eliminate-unused-debug-types");
870 cmd.push_back("-xc");
871 cmd.push_back("/dev/null");
872 cmd.push_back("-o");
873 cmd.push_back(name);
da9e11bd 874 for (size_t i = 0; i < headers.size(); ++i)
ff520ff4
JS
875 {
876 cmd.push_back("-include");
877 cmd.push_back(headers[i]);
878 }
879 bool quiet = (s.verbose < 4);
880 int rc = stap_system (s.verbose, cmd, quiet, quiet);
3e1ec884
DB
881 if (rc)
882 s.set_try_server ();
883 return rc;
3e1c25aa
JS
884}
885
d90053e7
JS
886
887int
888make_typequery(systemtap_session& s, string& module)
889{
890 int rc;
891 string new_module;
da9e11bd 892 vector<string> headers;
60d98537 893 bool kernel = startswith(module, "kernel");
d90053e7 894
da9e11bd 895 for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1)
d90053e7 896 {
da9e11bd
JS
897 if (module[i] != '<')
898 return -1;
899 end = module.find('>', ++i);
900 if (end == string::npos)
901 return -1;
902 string header = module.substr(i, end - i);
504d2b61 903 vector<string> matches;
5ef28d5a 904 if (regexp_match(header, "^[a-zA-Z0-9/_.+-]+$", matches))
2713ea24 905 s.print_warning("skipping malformed @cast header \""+ header + "\"");
504d2b61
JS
906 else
907 headers.push_back(header);
d90053e7 908 }
da9e11bd 909 if (headers.empty())
d90053e7
JS
910 return -1;
911
da9e11bd
JS
912 if (kernel)
913 rc = make_typequery_kmod(s, headers, new_module);
914 else
915 rc = make_typequery_umod(s, headers, new_module);
916
d90053e7
JS
917 if (!rc)
918 module = new_module;
919
920 return rc;
921}
922
73267b89 923/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.216415 seconds and 5 git commands to generate.