]> sourceware.org Git - systemtap.git/blame - buildrun.cxx
Fix PR20158 by updating the runtime for the 4.6 kernel.
[systemtap.git] / buildrun.cxx
CommitLineData
f4b28491 1// build/run probes
16bbba23 2// Copyright (C) 2005-2016 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 18#include <sstream>
636e55b8 19#include <thread>
d04cf5ff
FCE
20
21extern "C" {
49abf162 22#include <signal.h>
0c6296b2 23#include <sys/wait.h>
70404fc5 24#include <pwd.h>
0da3e7a0 25#include <grp.h>
b40af7ee
DS
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29#include <string.h>
30#include <errno.h>
3c4476ac 31#include <sys/resource.h>
d04cf5ff
FCE
32}
33
2537a880
JS
34// A bit of obfuscation for Gentoo's sake.
35// We *need* -Werror for stapconf to work correctly.
b586ab77 36// https://bugs.gentoo.org/show_bug.cgi?id=522908
2537a880 37#define WERROR ("-W" "error")
f4b28491
FCE
38
39using namespace std;
40
6274464e
JK
41/* Adjust and run make_cmd to build a kernel module. */
42static int
ff520ff4
JS
43run_make_cmd(systemtap_session& s, vector<string>& make_cmd,
44 bool null_out=false, bool null_err=false)
6274464e 45{
e19ebcf7 46 assert_no_interrupts();
576acc1a 47
e8474d2a
FCE
48 // PR14168: we used to unsetenv values here; instead do it via
49 // env(1) in make_any_make_cmd().
6274464e 50
b51455af
JS
51 // Disable ccache to avoid saving files that will never be reused.
52 // (ccache is useless to us, because our compiler commands always
53 // include the randomized tmpdir path.)
54 // It's not critical if this fails, so the return is ignored.
55 (void) setenv("CCACHE_DISABLE", "1", 0);
56
b54581ce 57 if (s.verbose > 2)
ff520ff4 58 make_cmd.push_back("V=1");
b54581ce 59 else if (s.verbose > 1)
ff520ff4 60 make_cmd.push_back("--no-print-directory");
6274464e 61 else
ff520ff4
JS
62 {
63 make_cmd.push_back("-s");
64 make_cmd.push_back("--no-print-directory");
65 }
dff50e09 66
70fb16aa 67 // Exploit SMP parallelism, if available.
636e55b8 68 long smp = thread::hardware_concurrency();
3c4476ac
FCE
69 if (smp <= 0) smp = 1;
70 // PR16276: but only if we're not running severely nproc-rlimited
71 struct rlimit rlim;
72 int rlimit_rc = getrlimit(RLIMIT_NPROC, &rlim);
5dd70393 73 const unsigned int severely_limited = smp*30; // WAG at number of gcc+make etc. nested processes
3c4476ac
FCE
74 bool nproc_limited = (rlimit_rc == 0 && (rlim.rlim_max <= severely_limited ||
75 rlim.rlim_cur <= severely_limited));
76 if (smp >= 1 && !nproc_limited)
70fb16aa 77 make_cmd.push_back("-j" + lex_cast(smp+1));
9fa0ffac 78
e0ccd368
FCE
79 if (strverscmp (s.kernel_base_release.c_str(), "2.6.29") < 0)
80 {
81 // Older kernels, before linux commit #fd54f502841c1, include
82 // gratuitous "echo"s in their Makefile. We need to suppress
83 // that with this bluntness.
ff520ff4 84 null_out = true;
e0ccd368
FCE
85 }
86
b13c6a37 87 int rc = stap_system (s.verbose, "kbuild", make_cmd, null_out, null_err);
3e1ec884
DB
88 if (rc != 0)
89 s.set_try_server ();
90 return rc;
6274464e 91}
f4b28491 92
7d26ee02 93static vector<string>
8e0a2563 94make_any_make_cmd(systemtap_session& s, const string& dir, const string& target)
7d26ee02 95{
c2f14e64
JS
96 string newpath("PATH=/usr/bin:/bin");
97 const char *oldpath = getenv("PATH");
98 if (oldpath != NULL)
99 {
100 newpath += ':';
101 newpath += oldpath;
102 }
103
104 vector<string> make_cmd
105 {
106 // PR14168: sanitize environment variables for kbuild invocation
107 "env", "-uARCH", "-uKBUILD_EXTMOD", "-uCROSS_COMPILE", "-uKBUILD_IMAGE",
37a4150f 108 "-uKCONFIG_CONFIG", "-uINSTALL_PATH", "-uLD_LIBRARY_PATH", newpath,
c2f14e64
JS
109
110 "make", "-C", s.kernel_build_tree,
111 "M=" + dir, // need make-quoting?
112 target,
113
114 // PR13847: suppress debuginfo creation by default
115 "CONFIG_DEBUG_INFO=",
116
117 // RHBZ1321628: suppress stack validation; expected to be temporary
118 "CONFIG_STACK_VALIDATION=",
119 };
7d26ee02
JS
120
121 // Add architecture, except for old powerpc (RHBZ669082)
122 if (s.architecture != "powerpc" ||
123 (strverscmp (s.kernel_base_release.c_str(), "2.6.15") >= 0))
124 make_cmd.push_back("ARCH=" + s.architecture); // need make-quoting?
125
126 // Add any custom kbuild flags
127 make_cmd.insert(make_cmd.end(), s.kbuildflags.begin(), s.kbuildflags.end());
128
129 return make_cmd;
130}
131
8e0a2563
JS
132static vector<string>
133make_make_cmd(systemtap_session& s, const string& dir)
134{
135 return make_any_make_cmd(s, dir, "modules");
136}
137
138static vector<string>
139make_make_objs_cmd(systemtap_session& s, const string& dir)
140{
141 // Kbuild uses these rules to build external modules:
142 //
143 // module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
144 // modules: $(module-dirs)
145 // @$(kecho) ' Building modules, stage 2.';
146 // $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
147 //
148 // So if we're only interested in the stage 1 objects, we can
149 // cheat and make only the $(module-dirs) part.
150 return make_any_make_cmd(s, dir, "_module_" + dir);
151}
152
de0db58a
JS
153static void
154output_autoconf(systemtap_session& s, ofstream& o, const char *autoconf_c,
155 const char *deftrue, const char *deffalse)
156{
157 o << "\t";
158 if (s.verbose < 4)
159 o << "@";
2ba1736a 160 o << "if $(CHECK_BUILD) $(SYSTEMTAP_RUNTIME)/linux/" << autoconf_c;
de0db58a
JS
161 if (s.verbose < 5)
162 o << " > /dev/null 2>&1";
163 o << "; then ";
164 if (deftrue)
165 o << "echo \"#define " << deftrue << " 1\"";
166 if (deffalse)
167 o << "; else echo \"#define " << deffalse << " 1\"";
168 o << "; fi >> $@" << endl;
169}
170
9e62f7ba
FCE
171
172void output_exportconf(systemtap_session& s, ofstream& o, const char *symbol,
173 const char *deftrue)
e25ab03c 174{
9e62f7ba
FCE
175 o << "\t";
176 if (s.verbose < 4)
177 o << "@";
178 if (s.kernel_exports.find(symbol) != s.kernel_exports.end())
179 o << "echo \"#define " << deftrue << " 1\"";
180 o << ">> $@" << endl;
e25ab03c
WH
181}
182
9e62f7ba 183
08c29612
DS
184void output_dual_exportconf(systemtap_session& s, ofstream& o,
185 const char *symbol1, const char *symbol2,
186 const char *deftrue)
187{
188 o << "\t";
189 if (s.verbose < 4)
190 o << "@";
191 if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
192 && s.kernel_exports.find(symbol2) != s.kernel_exports.end())
193 o << "echo \"#define " << deftrue << " 1\"";
194 o << ">> $@" << endl;
195}
196
197
13128684
JS
198void output_either_exportconf(systemtap_session& s, ofstream& o,
199 const char *symbol1, const char *symbol2,
200 const char *deftrue)
201{
202 o << "\t";
203 if (s.verbose < 4)
204 o << "@";
205 if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
206 || s.kernel_exports.find(symbol2) != s.kernel_exports.end())
207 o << "echo \"#define " << deftrue << " 1\"";
208 o << ">> $@" << endl;
209}
210
211
3a894f7e
JS
212static int
213compile_dyninst (systemtap_session& s)
214{
4441e344 215 const string module = s.tmpdir + "/" + s.module_filename();
3a894f7e 216
c2f14e64
JS
217 vector<string> cmd
218 {
219 "gcc", "--std=gnu99", s.translated_source, "-o", module,
220 "-fvisibility=hidden", "-O2", "-I" + s.runtime_path, "-D__DYNINST__",
221 "-Wall", WERROR, "-Wno-unused", "-Wno-strict-aliasing",
222 "-pthread", "-lrt", "-fPIC", "-shared",
223 };
ba2daa43
FCE
224
225 // BZ855981/948279. Since dyninst/runtime.h includes __sync_* calls,
226 // the compiler may generate different code for it depending on -march.
227 // For example, if the default is i386, we may get references to auxiliary
228 // functions like __sync_add_and_fetch_4, which appear to be defined
229 // nowhere. We hack around this problem thusly:
230 if (s.architecture == "i386")
e1c3538b 231 cmd.push_back("-march=i586");
ba2daa43 232
8140a78d
JS
233 for (size_t i = 0; i < s.c_macros.size(); ++i)
234 cmd.push_back("-D" + s.c_macros[i]);
c2f14e64 235
8140a78d 236 if (s.verbose > 3)
c2f14e64 237 cmd.insert(cmd.end(), { "-ftime-report", "-Q" });
3a894f7e 238
16bbba23
FCE
239 // Add any custom kbuild flags
240 cmd.insert(cmd.end(), s.kbuildflags.begin(), s.kbuildflags.end());
241
6da8678d 242 int rc = stap_system (s.verbose, cmd);
3a894f7e
JS
243 if (rc)
244 s.set_try_server ();
245 return rc;
246}
3a894f7e
JS
247
248
f4b28491
FCE
249int
250compile_pass (systemtap_session& s)
251{
ac3af990 252 if (s.runtime_usermode_p())
4441e344 253 return compile_dyninst (s);
3a894f7e 254
db3a383b
JK
255 int rc = uprobes_pass (s);
256 if (rc)
3e1ec884
DB
257 {
258 s.set_try_server ();
259 return rc;
260 }
db3a383b 261
f4b28491 262 // fill in a quick Makefile
92ade41d
FCE
263 string makefile_nm = s.tmpdir + "/Makefile";
264 ofstream o (makefile_nm.c_str());
92ade41d
FCE
265
266 // Create makefile
ed10c639 267
255e4c68 268 // Clever hacks copied from vmware modules
ecf19454
FCE
269 string superverbose;
270 if (s.verbose > 3)
271 superverbose = "set -x;";
522518f1 272
e9737939
MM
273 string redirecterrors = "> /dev/null 2>&1";
274 if (s.verbose > 6)
275 redirecterrors = "";
276
e5976ba0
MH
277 // Support O= (or KBUILD_OUTPUT) option
278 o << "_KBUILD_CFLAGS := $(call flags,KBUILD_CFLAGS)" << endl;
279
2537a880
JS
280 o << "stap_check_gcc = $(shell " << superverbose
281 << " if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then "
282 << "echo \"$(1)\"; else echo \"$(2)\"; fi)" << endl;
283 o << "CHECK_BUILD := $(CC) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) $(CPPFLAGS) "
284 << "$(LINUXINCLUDE) $(_KBUILD_CFLAGS) $(CFLAGS_KERNEL) $(EXTRA_CFLAGS) "
285 << "$(CFLAGS) -DKBUILD_BASENAME=\\\"" << s.module_name << "\\\" "
286 << WERROR << " -S -o /dev/null -xc " << endl;
287 o << "stap_check_build = $(shell " << superverbose << " if $(CHECK_BUILD) $(1) "
288 << redirecterrors << " ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl;
255e4c68
FCE
289
290 o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl;
291
292 // "autoconf" options go here
293
18222191
FCE
294 // RHBZ 543529: early rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
295 o << "CONFIG_MODULE_SIG := n" << endl;
296
ecf19454 297 string module_cflags = "EXTRA_CFLAGS";
522518f1 298 o << module_cflags << " :=" << endl;
84c4da88
FCE
299
300 // XXX: This gruesome hack is needed on some kernels built with separate O=directory,
301 // where files like 2.6.27 x86's asm/mach-*/mach_mpspec.h are not found on the cpp path.
302 // This could be a bug in arch/x86/Makefile that names
303 // mflags-y += -Iinclude/asm-x86/mach-default
304 // but that path does not exist in an O= build tree.
305 o << module_cflags << " += -Iinclude2/asm/mach-default" << endl;
18b13994 306 o << module_cflags << " += -I" + s.kernel_build_tree << endl;
d4393459
FCE
307 if (s.kernel_source_tree != "")
308 o << module_cflags << " += -I" + s.kernel_source_tree << endl;
ac4f2837
DS
309 for (unsigned i = 0; i < s.kernel_extra_cflags.size(); i++)
310 o << module_cflags << " += " + s.kernel_extra_cflags[i] << endl;
84c4da88 311
6046b840
FCE
312 // NB: don't try
313 // o << module_cflags << " += -Iusr/include" << endl;
314 // since such headers are cleansed of _KERNEL_ pieces that we need
315
de0db58a 316 o << "STAPCONF_HEADER := " << s.tmpdir << "/" << s.stapconf_name << endl;
de0db58a 317 o << "$(STAPCONF_HEADER):" << endl;
b03e7089 318 o << "\t@> $@" << endl;
de0db58a 319 output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL);
86f726b7 320 output_exportconf(s, o, "hrtimer_get_res", "STAPCONF_HRTIMER_GET_RES");
1d381a0d 321 output_autoconf(s, o, "autoconf-generated-compile.c", "STAPCONF_GENERATED_COMPILE", NULL);
de0db58a
JS
322 output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL);
323 output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL);
8f888904 324 output_autoconf(s, o, "autoconf-inode-rwsem.c", "STAPCONF_INODE_RWSEM", NULL);
de0db58a 325 output_autoconf(s, o, "autoconf-constant-tsc.c", "STAPCONF_CONSTANT_TSC", NULL);
de0db58a
JS
326 output_autoconf(s, o, "autoconf-ktime-get-real.c", "STAPCONF_KTIME_GET_REAL", NULL);
327 output_autoconf(s, o, "autoconf-x86-uniregs.c", "STAPCONF_X86_UNIREGS", NULL);
328 output_autoconf(s, o, "autoconf-nameidata.c", "STAPCONF_NAMEIDATA_CLEANUP", NULL);
08c29612 329 output_dual_exportconf(s, o, "unregister_kprobes", "unregister_kretprobes", "STAPCONF_UNREGISTER_KPROBES");
766cee5f 330 output_autoconf(s, o, "autoconf-kprobe-symbol-name.c", "STAPCONF_KPROBE_SYMBOL_NAME", NULL);
de0db58a
JS
331 output_autoconf(s, o, "autoconf-real-parent.c", "STAPCONF_REAL_PARENT", NULL);
332 output_autoconf(s, o, "autoconf-uaccess.c", "STAPCONF_LINUX_UACCESS_H", NULL);
333 output_autoconf(s, o, "autoconf-oneachcpu-retry.c", "STAPCONF_ONEACHCPU_RETRY", NULL);
334 output_autoconf(s, o, "autoconf-dpath-path.c", "STAPCONF_DPATH_PATH", NULL);
b9197b0f
JS
335 output_exportconf(s, o, "synchronize_kernel", "STAPCONF_SYNCHRONIZE_KERNEL");
336 output_exportconf(s, o, "synchronize_rcu", "STAPCONF_SYNCHRONIZE_RCU");
08c29612 337 output_exportconf(s, o, "synchronize_sched", "STAPCONF_SYNCHRONIZE_SCHED");
de0db58a 338 output_autoconf(s, o, "autoconf-task-uid.c", "STAPCONF_TASK_UID", NULL);
ca89d289 339 output_autoconf(s, o, "autoconf-from_kuid_munged.c", "STAPCONF_FROM_KUID_MUNGED", NULL);
1c70d655 340 output_exportconf(s, o, "get_mm_exe_file", "STAPCONF_GET_MM_EXE_FILE");
08c29612 341 output_dual_exportconf(s, o, "alloc_vm_area", "free_vm_area", "STAPCONF_VM_AREA");
de0db58a 342 output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL);
b1f85b93 343 output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL);
6ddf07ac
JS
344 output_autoconf(s, o, "autoconf-x86-fs.c", "STAPCONF_X86_FS", NULL);
345 output_autoconf(s, o, "autoconf-x86-xfs.c", "STAPCONF_X86_XFS", NULL);
5cad2d3b 346 output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL);
f098eb6d 347 output_autoconf(s, o, "autoconf-grsecurity.c", "STAPCONF_GRSECURITY", NULL);
450718c9 348 output_autoconf(s, o, "autoconf-trace-printk.c", "STAPCONF_TRACE_PRINTK", NULL);
be004140
FCE
349 output_autoconf(s, o, "autoconf-regset.c", "STAPCONF_REGSET", NULL);
350 output_autoconf(s, o, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL);
23258335 351 output_autoconf(s, o, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL);
85804472 352 output_autoconf(s, o, "autoconf-hlist-4args.c", "STAPCONF_HLIST_4ARGS", NULL);
b09417ad 353 output_exportconf(s, o, "tsc_khz", "STAPCONF_TSC_KHZ");
9e62f7ba 354 output_exportconf(s, o, "cpu_khz", "STAPCONF_CPU_KHZ");
031fda59 355 output_exportconf(s, o, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS");
af6c651f 356 output_exportconf(s, o, "add_timer_on", "STAPCONF_ADD_TIMER_ON");
8d59b39f 357
08c29612 358 output_dual_exportconf(s, o, "probe_kernel_read", "probe_kernel_write", "STAPCONF_PROBE_KERNEL");
b273669e
MW
359 output_autoconf(s, o, "autoconf-hw_breakpoint_context.c",
360 "STAPCONF_HW_BREAKPOINT_CONTEXT", NULL);
8c5905d0
TM
361 output_autoconf(s, o, "autoconf-save-stack-trace.c",
362 "STAPCONF_KERNEL_STACKTRACE", NULL);
9957bbd2
MW
363 output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c",
364 "STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL);
d5cd287f
DS
365 output_autoconf(s, o, "autoconf-asm-syscall.c",
366 "STAPCONF_ASM_SYSCALL_H", NULL);
c145b9cb 367 output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL);
0d0f0d84 368 output_autoconf(s, o, "autoconf-ring_buffer_lost_events.c", "STAPCONF_RING_BUFFER_LOST_EVENTS", NULL);
c38602b5 369 output_autoconf(s, o, "autoconf-ring_buffer_read_prepare.c", "STAPCONF_RING_BUFFER_READ_PREPARE", NULL);
03a4ec63 370 output_autoconf(s, o, "autoconf-kallsyms-on-each-symbol.c", "STAPCONF_KALLSYMS_ON_EACH_SYMBOL", NULL);
c265cd25 371 output_autoconf(s, o, "autoconf-walk-stack.c", "STAPCONF_WALK_STACK", NULL);
0bbb8009
JS
372 output_autoconf(s, o, "autoconf-stacktrace_ops-warning.c",
373 "STAPCONF_STACKTRACE_OPS_WARNING", NULL);
15de83a3
DS
374 output_autoconf(s, o, "autoconf-stacktrace_ops-int-address.c",
375 "STAPCONF_STACKTRACE_OPS_INT_ADDRESS", NULL);
18da5887 376 output_autoconf(s, o, "autoconf-mm-context-vdso.c", "STAPCONF_MM_CONTEXT_VDSO", NULL);
3b62d74b 377 output_autoconf(s, o, "autoconf-mm-context-vdso-base.c", "STAPCONF_MM_CONTEXT_VDSO_BASE", NULL);
c1d2d085 378 output_autoconf(s, o, "autoconf-blk-types.c", "STAPCONF_BLK_TYPES", NULL);
aec17ca6 379 output_autoconf(s, o, "autoconf-perf-structpid.c", "STAPCONF_PERF_STRUCTPID", NULL);
2f3df331
MW
380 output_autoconf(s, o, "perf_event_counter_context.c",
381 "STAPCONF_PERF_COUNTER_CONTEXT", NULL);
382 output_autoconf(s, o, "perf_probe_handler_nmi.c",
383 "STAPCONF_PERF_HANDLER_NMI", NULL);
7f2d56c3
DS
384 output_exportconf(s, o, "path_lookup", "STAPCONF_PATH_LOOKUP");
385 output_exportconf(s, o, "kern_path_parent", "STAPCONF_KERN_PATH_PARENT");
386 output_exportconf(s, o, "vfs_path_lookup", "STAPCONF_VFS_PATH_LOOKUP");
33f02716 387 output_exportconf(s, o, "kern_path", "STAPCONF_KERN_PATH");
b85e750d
DS
388 output_exportconf(s, o, "proc_create_data", "STAPCONF_PROC_CREATE_DATA");
389 output_exportconf(s, o, "PDE_DATA", "STAPCONF_PDE_DATA");
2c9caccb 390 output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
04ffc218 391
db7dcdff 392 output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL);
0e0e60b2 393 output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL);
abc69bab 394 output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL);
56111fdc 395 output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL);
52dea427 396 output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL);
fce34f35 397 output_autoconf(s, o, "autoconf-compat_sigaction.c", "STAPCONF_COMPAT_SIGACTION", NULL);
4d914c37 398 output_autoconf(s, o, "autoconf-netfilter.c", "STAPCONF_NETFILTER_V313", NULL);
7cfb10ec 399 output_autoconf(s, o, "autoconf-netfilter-313b.c", "STAPCONF_NETFILTER_V313B", NULL);
502f3816 400 output_autoconf(s, o, "autoconf-netfilter-4_1.c", "STAPCONF_NETFILTER_V41", NULL);
2736131d 401 output_autoconf(s, o, "autoconf-netfilter-4_4.c", "STAPCONF_NETFILTER_V44", NULL);
590a9ae1 402 output_autoconf(s, o, "autoconf-smpcall-5args.c", "STAPCONF_SMPCALL_5ARGS", NULL);
ceeaa82b 403 output_autoconf(s, o, "autoconf-smpcall-4args.c", "STAPCONF_SMPCALL_4ARGS", NULL);
db7dcdff 404
de5f477b
JS
405 // used by tapset/timestamp_monotonic.stp
406 output_exportconf(s, o, "cpu_clock", "STAPCONF_CPU_CLOCK");
407 output_exportconf(s, o, "local_clock", "STAPCONF_LOCAL_CLOCK");
408
64e807c2 409 // used by runtime/uprobe-inode.c
13128684
JS
410 output_either_exportconf(s, o, "uprobe_register", "register_uprobe",
411 "STAPCONF_UPROBE_REGISTER_EXPORTED");
412 output_either_exportconf(s, o, "uprobe_unregister", "unregister_uprobe",
413 "STAPCONF_UPROBE_UNREGISTER_EXPORTED");
414 output_autoconf(s, o, "autoconf-old-inode-uprobes.c", "STAPCONF_OLD_INODE_UPROBES", NULL);
79af55c3 415 output_autoconf(s, o, "autoconf-inode-uretprobes.c", "STAPCONF_INODE_URETPROBES", NULL);
39e63bae
DS
416
417 // used by tapsets.cxx inode uprobe generated code
418 output_exportconf(s, o, "uprobe_get_swbp_addr", "STAPCONF_UPROBE_GET_SWBP_ADDR_EXPORTED");
419
fe6feb40 420 // used by runtime/loc2c-runtime.h
64e807c2
FCE
421 output_exportconf(s, o, "task_user_regset_view", "STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED");
422
36de3b61
DS
423 // used by runtime/stp_utrace.c
424 output_exportconf(s, o, "task_work_add", "STAPCONF_TASK_WORK_ADD_EXPORTED");
d9d07e99
DS
425 output_exportconf(s, o, "wake_up_state", "STAPCONF_WAKE_UP_STATE_EXPORTED");
426 output_exportconf(s, o, "try_to_wake_up", "STAPCONF_TRY_TO_WAKE_UP_EXPORTED");
dfdbaa3d 427 output_exportconf(s, o, "signal_wake_up_state", "STAPCONF_SIGNAL_WAKE_UP_STATE_EXPORTED");
f346b8b3
DS
428 output_exportconf(s, o, "signal_wake_up", "STAPCONF_SIGNAL_WAKE_UP_EXPORTED");
429 output_exportconf(s, o, "__lock_task_sighand", "STAPCONF___LOCK_TASK_SIGHAND_EXPORTED");
36de3b61 430
8fee9cc5 431 output_autoconf(s, o, "autoconf-pagefault_disable.c", "STAPCONF_PAGEFAULT_DISABLE", NULL);
15cf9503 432 output_exportconf(s, o, "kallsyms_lookup_name", "STAPCONF_KALLSYMS");
85716315 433 output_autoconf(s, o, "autoconf-uidgid.c", "STAPCONF_LINUX_UIDGID_H", NULL);
4fe11374 434 output_exportconf(s, o, "sigset_from_compat", "STAPCONF_SIGSET_FROM_COMPAT_EXPORTED");
42c2d1ed
DS
435 output_exportconf(s, o, "vzalloc", "STAPCONF_VZALLOC");
436 output_exportconf(s, o, "vzalloc_node", "STAPCONF_VZALLOC_NODE");
c9c633a8 437 output_exportconf(s, o, "vmalloc_node", "STAPCONF_VMALLOC_NODE");
8fee9cc5 438
bbeb74db
FCE
439 // RHBZ1233912 - s390 temporary workaround for non-atomic udelay()
440 output_exportconf(s, o, "udelay_simple", "STAPCONF_UDELAY_SIMPLE");
441
3ef9830a 442 output_autoconf(s, o, "autoconf-tracepoint-strings.c", "STAPCONF_TRACEPOINT_STRINGS", NULL);
bac8aa5a 443 output_autoconf(s, o, "autoconf-timerfd.c", "STAPCONF_TIMERFD_H", NULL);
3ef9830a 444
3f040971
DS
445 output_autoconf(s, o, "autoconf-module_layout.c",
446 "STAPCONF_MODULE_LAYOUT", NULL);
64ffc49b
DS
447 output_autoconf(s, o, "autoconf-mod_kallsyms.c",
448 "STAPCONF_MOD_KALLSYMS", NULL);
e7c42c3a 449 output_exportconf(s, o, "get_user_pages_remote", "STAPCONF_GET_USER_PAGES_REMOTE");
3f040971 450
de0db58a 451 o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
5c54d49e 452
08fce398
SM
453 for (unsigned i=0; i<s.c_macros.size(); i++)
454 o << "EXTRA_CFLAGS += -D " << lex_cast_qstring(s.c_macros[i]) << endl; // XXX right quoting?
ed10c639 455
e4c58386 456 if (s.verbose > 3)
0986ac38 457 o << "EXTRA_CFLAGS += -ftime-report -Q" << endl;
db22e55f 458
ee6dda6f 459 // XXX: unfortunately, -save-temps can't work since linux kbuild cwd
100a540e 460 // is not writable.
ee6dda6f
FCE
461 //
462 // if (s.keep_tmpdir)
463 // o << "CFLAGS += -fverbose-asm -save-temps" << endl;
464
ec6fdef5
MW
465 // Kernels can be compiled with CONFIG_CC_OPTIMIZE_FOR_SIZE to select
466 // -Os, otherwise -O2 is the default.
467 o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os
977b259e
JS
468
469 // Generate eh_frame for self-backtracing
470 o << "EXTRA_CFLAGS += -fasynchronous-unwind-tables" << endl;
ec6fdef5 471
01116596
MW
472 // We used to allow the user to override default optimization when so
473 // requested by adding a -O[0123s] so they could determine the
474 // time/space/speed tradeoffs themselves, but we cannot guantantee that
475 // the (un)optimized code actually compiles and/or generates functional
476 // code, so we had to remove it.
477 // o << "EXTRA_CFLAGS += " << s.gcc_flags << endl; // Add -O[0123s]
35d4ab18
FCE
478
479 // o << "CFLAGS += -fno-unit-at-a-time" << endl;
dff50e09 480
de4123d6 481 // 256^W512 bytes should be enough for anybody
01a2eba8 482 // XXX this doesn't validate varargs, per gcc bug #41633
de4123d6 483 o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=512)" << endl;
730c3efc 484
c1e83543
FCE
485 // gcc 5.0.0-0.13.fc23 ipa-icf seems to consume gigacpu on stap-generated code
486 o << "EXTRA_CFLAGS += $(call cc-option,-fno-ipa-icf)" << endl;
487
cbfbbf69 488 // Assumes linux 2.6 kbuild
2537a880 489 o << "EXTRA_CFLAGS += -Wno-unused " << WERROR << endl;
29bdbdb1
FCE
490 #if CHECK_POINTER_ARITH_PR5947
491 o << "EXTRA_CFLAGS += -Wpointer-arith" << endl;
492 #endif
0986ac38 493 o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl;
4b2c4ab5
FCE
494 // XXX: this may help ppc toc overflow
495 // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl;
cbfbbf69 496 o << "obj-m := " << s.module_name << ".o" << endl;
f4b28491 497
a4b9c3b3
FCE
498 // print out all the auxiliary source (->object) file names
499 o << s.module_name << "-y := ";
500 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
501 {
80d74c6b 502 if (s.auxiliary_outputs[i]->trailer_p) continue;
a4b9c3b3
FCE
503 string srcname = s.auxiliary_outputs[i]->filename;
504 assert (srcname != "" && srcname.rfind('/') != string::npos);
505 string objname = srcname.substr(srcname.rfind('/')+1); // basename
506 assert (objname != "" && objname[objname.size()-1] == 'c');
507 objname[objname.size()-1] = 'o'; // now objname
508 o << " " + objname;
509 }
510 // and once again, for the translated_source file. It can't simply
511 // be named MODULENAME.c, since kbuild doesn't allow a foo.ko file
512 // consisting of multiple .o's to have foo.o/foo.c as a source.
513 // (It uses ld -r -o foo.o EACH.o EACH.o).
514 {
515 string srcname = s.translated_source;
516 assert (srcname != "" && srcname.rfind('/') != string::npos);
517 string objname = srcname.substr(srcname.rfind('/')+1); // basename
518 assert (objname != "" && objname[objname.size()-1] == 'c');
519 objname[objname.size()-1] = 'o'; // now objname
520 o << " " + objname;
521 }
80d74c6b
FCE
522 // and once again, for the trailer type auxiliary outputs.
523 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
524 {
525 if (! s.auxiliary_outputs[i]->trailer_p) continue;
526 string srcname = s.auxiliary_outputs[i]->filename;
527 assert (srcname != "" && srcname.rfind('/') != string::npos);
528 string objname = srcname.substr(srcname.rfind('/')+1); // basename
529 assert (objname != "" && objname[objname.size()-1] == 'c');
530 objname[objname.size()-1] = 'o'; // now objname
531 o << " " + objname;
532 }
a4b9c3b3
FCE
533 o << endl;
534
535 // add all stapconf dependencies
536 o << s.translated_source << ": $(STAPCONF_HEADER)" << endl;
537 for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
538 o << s.auxiliary_outputs[i]->filename << ": $(STAPCONF_HEADER)" << endl;
539
540
ed10c639
FCE
541 o.close ();
542
b40af7ee 543 // Generate module directory pathname and make sure it exists.
4d34dac1
FCE
544 string module_dir = s.kernel_build_tree;
545 string module_dir_makefile = module_dir + "/Makefile";
b40af7ee 546 struct stat st;
4d34dac1 547 rc = stat(module_dir_makefile.c_str(), &st);
b40af7ee
DS
548 if (rc != 0)
549 {
ce0f6648 550 clog << _F("Checking \" %s \" failed with error: %s\nEnsure kernel development headers & makefiles are installed.",
46a1a151 551 module_dir_makefile.c_str(), strerror(errno)) << endl;
3e1ec884 552 s.set_try_server ();
b40af7ee 553 return rc;
dff50e09 554 }
b40af7ee
DS
555
556 // Run make
7d26ee02 557 vector<string> make_cmd = make_make_cmd(s, s.tmpdir);
6274464e 558 rc = run_make_cmd(s, make_cmd);
3e1ec884
DB
559 if (rc)
560 s.set_try_server ();
f4b28491
FCE
561 return rc;
562}
563
db3a383b
JK
564/*
565 * If uprobes was built as part of the kernel build (either built-in
dbb9345d
FCE
566 * or as a module), the uprobes exports should show up. This is to be
567 * as distinct from the stap-built uprobes.ko from the runtime.
db3a383b
JK
568 */
569static bool
570kernel_built_uprobes (systemtap_session& s)
6274464e 571{
ac3af990 572 if (s.runtime_usermode_p())
4441e344
JS
573 return true; // sort of, via dyninst
574
95113339
FCE
575 // see also tapsets.cxx:kernel_supports_inode_uprobes()
576 return ((s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y" && s.kernel_config["CONFIG_UPROBES"] == "y") ||
577 (s.kernel_exports.find("unregister_uprobe") != s.kernel_exports.end()));
6274464e
JK
578}
579
7d26ee02
JS
580static int
581make_uprobes (systemtap_session& s)
6274464e 582{
7ef486ad 583 if (s.verbose > 1)
7d26ee02 584 clog << _("Pass 4, preamble: (re)building SystemTap's version of uprobes.")
db3a383b
JK
585 << endl;
586
7d26ee02
JS
587 // create a subdirectory for the uprobes module
588 string dir(s.tmpdir + "/uprobes");
589 if (create_dir(dir.c_str()) != 0)
590 {
2713ea24 591 s.print_warning("failed to create directory for build uprobes.");
7d26ee02
JS
592 s.set_try_server ();
593 return 1;
0da3e7a0 594 }
6274464e 595
7d26ee02
JS
596 // create a simple Makefile
597 string makefile(dir + "/Makefile");
598 ofstream omf(makefile.c_str());
599 omf << "obj-m := uprobes.o" << endl;
600 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
601 omf << "CONFIG_MODULE_SIG := n" << endl;
602 omf.close();
6274464e 603
7d26ee02 604 // create a simple #include-chained source file
2ba1736a 605 string runtimesourcefile(s.runtime_path + "/linux/uprobes/uprobes.c");
7d26ee02
JS
606 string sourcefile(dir + "/uprobes.c");
607 ofstream osrc(sourcefile.c_str());
608 osrc << "#include \"" << runtimesourcefile << "\"" << endl;
76d01f36
FCE
609
610 // pass --modinfo k=v to uprobes build too
611 for (unsigned i = 0; i < s.modinfos.size(); i++)
612 {
613 const string& mi = s.modinfos[i];
614 size_t loc = mi.find('=');
615 string tag = mi.substr (0, loc);
616 string value = mi.substr (loc+1);
617 osrc << "MODULE_INFO(" << tag << "," << lex_cast_qstring(value) << ");" << endl;
618 }
619
7d26ee02
JS
620 osrc.close();
621
622 // make the module
623 vector<string> make_cmd = make_make_cmd(s, dir);
ae5e0bbb 624 int rc = run_make_cmd(s, make_cmd);
7d26ee02
JS
625 if (!rc && !copy_file(dir + "/Module.symvers",
626 s.tmpdir + "/Module.symvers"))
627 rc = -1;
6274464e 628
f4d5049b 629 if (s.verbose > 1)
ce0f6648 630 clog << _("uprobes rebuild exit code: ") << rc << endl;
3e1ec884
DB
631 if (rc)
632 s.set_try_server ();
91ea0ce6 633 else
7d26ee02 634 s.uprobes_path = dir + "/uprobes.ko";
6274464e
JK
635 return rc;
636}
637
7d26ee02
JS
638static bool
639get_cached_uprobes(systemtap_session& s)
640{
641 s.uprobes_hash = s.use_cache ? find_uprobes_hash(s) : "";
642 if (!s.uprobes_hash.empty())
643 {
644 // NB: We always put uprobes.ko in its own directory, especially so
645 // stap-serverd can more easily locate it.
646 string dir(s.tmpdir + "/uprobes");
647 if (create_dir(dir.c_str()) != 0)
648 return false;
649
650 string cacheko = s.uprobes_hash + ".ko";
651 string tmpko = dir + "/uprobes.ko";
652
653 // The symvers file still needs to go in the script module's directory.
654 string cachesyms = s.uprobes_hash + ".symvers";
655 string tmpsyms = s.tmpdir + "/Module.symvers";
656
657 if (get_file_size(cacheko) > 0 && copy_file(cacheko, tmpko) &&
658 get_file_size(cachesyms) > 0 && copy_file(cachesyms, tmpsyms))
659 {
660 s.uprobes_path = tmpko;
661 return true;
662 }
663 }
664 return false;
665}
666
667static void
668set_cached_uprobes(systemtap_session& s)
db3a383b 669{
7d26ee02
JS
670 if (s.use_cache && !s.uprobes_hash.empty())
671 {
672 string cacheko = s.uprobes_hash + ".ko";
673 string tmpko = s.tmpdir + "/uprobes/uprobes.ko";
674 copy_file(tmpko, cacheko);
36ef6d6a 675
7d26ee02
JS
676 string cachesyms = s.uprobes_hash + ".symvers";
677 string tmpsyms = s.tmpdir + "/uprobes/Module.symvers";
678 copy_file(tmpsyms, cachesyms);
679 }
db3a383b
JK
680}
681
7d26ee02 682int
db3a383b
JK
683uprobes_pass (systemtap_session& s)
684{
685 if (!s.need_uprobes || kernel_built_uprobes(s))
686 return 0;
0944a81e 687
6c7e2241 688 if (s.kernel_config["CONFIG_UTRACE"] != string("y"))
01fa08f2 689 {
6c9f0b7b 690 clog << _("user-space process-tracking facilities not available [man error::process-tracking]") << endl;
01fa08f2
DS
691 s.set_try_server ();
692 return 1;
693 }
0944a81e 694
db3a383b 695 /*
7d26ee02
JS
696 * We need to use the version of uprobes that comes with SystemTap. Try to
697 * get it from the cache first. If not found, build it and try to save it to
698 * the cache for future reuse.
db3a383b 699 */
7d26ee02
JS
700 int rc = 0;
701 if (!get_cached_uprobes(s))
702 {
703 rc = make_uprobes(s);
704 if (!rc)
705 set_cached_uprobes(s);
706 }
3e1ec884
DB
707 if (rc)
708 s.set_try_server ();
db3a383b
JK
709 return rc;
710}
711
3a894f7e
JS
712static
713vector<string>
714make_dyninst_run_command (systemtap_session& s, const string& remotedir,
dabd71bb 715 const string&)
3a894f7e 716{
c2f14e64 717 vector<string> cmd { getenv("SYSTEMTAP_STAPDYN") ?: BINDIR "/stapdyn" };
e75a4464
JS
718
719 // use slightly less verbosity
c2f14e64
JS
720 if (s.verbose > 0)
721 cmd.insert(cmd.end(), s.verbose - 1, "-v");
722
41300e6d
JS
723 if (s.suppress_warnings)
724 cmd.push_back("-w");
3a894f7e
JS
725
726 if (!s.cmd.empty())
c2f14e64 727 cmd.insert(cmd.end(), { "-c", s.cmd });
3a894f7e 728
02bff028 729 if (s.target_pid)
c2f14e64 730 cmd.insert(cmd.end(), { "-x", lex_cast(s.target_pid) });
02bff028 731
6d842dc7 732 if (!s.output_file.empty())
c2f14e64 733 cmd.insert(cmd.end(), { "-o", s.output_file });
6d842dc7 734
192130b3
JL
735 if (s.color_mode != s.color_auto)
736 {
c2f14e64
JS
737 auto mode = s.color_mode == s.color_always ? "always" : "never";
738 cmd.insert(cmd.end(), { "-C", mode });
192130b3
JL
739 }
740
3a894f7e 741 cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
4441e344 742 + "/" + s.module_filename());
3a894f7e 743
bd268288
SM
744 // add module arguments
745 cmd.insert(cmd.end(), s.globalopts.begin(), s.globalopts.end());
746
3a894f7e
JS
747 return cmd;
748}
3a894f7e 749
5eea6ed1 750vector<string>
18630fb8 751make_run_command (systemtap_session& s, const string& remotedir,
4112f219 752 const string& version)
f4b28491 753{
ac3af990 754 if (s.runtime_usermode_p())
4441e344
JS
755 return make_dyninst_run_command(s, remotedir, version);
756
a63a95dc 757 // for now, just spawn staprun
c2f14e64 758 vector<string> cmd { getenv("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun" };
e75a4464
JS
759
760 // use slightly less verbosity
c2f14e64
JS
761 if (s.verbose > 0)
762 cmd.insert(cmd.end(), s.verbose - 1, "-v");
763
5eea6ed1 764 if (s.suppress_warnings)
c2f14e64 765 cmd.push_back("-w");
5eea6ed1
JS
766
767 if (!s.output_file.empty())
c2f14e64 768 cmd.insert(cmd.end(), { "-o", s.output_file });
dff50e09 769
5eea6ed1 770 if (!s.cmd.empty())
c2f14e64 771 cmd.insert(cmd.end(), { "-c", s.cmd });
dff50e09 772
cbfbbf69 773 if (s.target_pid)
c2f14e64 774 cmd.insert(cmd.end(), { "-t", lex_cast(s.target_pid) });
dff50e09 775
e9bb2221 776 if (s.target_namespaces_pid)
c2f14e64 777 cmd.insert(cmd.end(), { "-N", lex_cast(s.target_namespaces_pid) });
e9bb2221 778
cbfbbf69 779 if (s.buffer_size)
c2f14e64 780 cmd.insert(cmd.end(), { "-b", lex_cast(s.buffer_size) });
dff50e09 781
13128684 782 if (s.need_uprobes && !kernel_built_uprobes(s))
5eea6ed1 783 {
18630fb8
JS
784 string opt_u = "-u";
785 if (!s.uprobes_path.empty() &&
786 strverscmp("1.4", version.c_str()) <= 0)
787 {
788 if (remotedir.empty())
789 opt_u.append(s.uprobes_path);
790 else
791 opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str()));
792 }
c2f14e64 793 cmd.push_back(opt_u);
5eea6ed1 794 }
6274464e 795
2fa2a091 796 if (s.load_only)
c2f14e64 797 cmd.push_back(s.output_file.empty() ? "-L" : "-D");
701c41be 798
b3367f63
DS
799 // Note that if this system requires signed modules, we can't rename
800 // it after it has been signed.
801 if (!s.modname_given && (strverscmp("1.6", version.c_str()) <= 0)
cd1418c7 802 && s.mok_fingerprints.empty())
c2f14e64 803 cmd.push_back("-R");
5c854d7c 804
701c41be 805 if (!s.size_option.empty())
c2f14e64 806 cmd.insert(cmd.end(), { "-S", s.size_option });
2fa2a091 807
192130b3 808 if (s.color_mode != s.color_auto)
579f0947 809 {
c2f14e64
JS
810 auto mode = s.color_mode == s.color_always ? "always" : "never";
811 cmd.insert(cmd.end(), { "-C", mode });
579f0947
JL
812 }
813
10bb5efc 814 if (s.monitor)
c2f14e64 815 cmd.insert(cmd.end(), { "-M", lex_cast(s.monitor_interval) });
10bb5efc 816
c2f14e64 817 cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
4441e344 818 + "/" + s.module_filename());
dff50e09 819
bb25d08f 820 // add module arguments
c2f14e64 821 cmd.insert(cmd.end(), s.globalopts.begin(), s.globalopts.end());
bb25d08f 822
c2f14e64 823 return cmd;
f4b28491 824}
73267b89 825
0a6f5a3f 826
c9ccb642
FCE
827// Build tiny kernel modules to query tracepoints.
828// Given a (header-file -> test-contents) map, compile them ASAP, and return
2a0e62a8 829// a (header-file -> obj-filename) map.
c9ccb642
FCE
830
831map<string,string>
832make_tracequeries(systemtap_session& s, const map<string,string>& contents)
0a6f5a3f 833{
f982c59b 834 static unsigned tick = 0;
aca66a36 835 string basename("tracequery_kmod_" + lex_cast(++tick));
2a0e62a8 836 map<string,string> objs;
f982c59b 837
0a6f5a3f 838 // create a subdirectory for the module
f982c59b 839 string dir(s.tmpdir + "/" + basename);
0a6f5a3f
JS
840 if (create_dir(dir.c_str()) != 0)
841 {
2713ea24 842 s.print_warning("failed to create directory for querying tracepoints.");
3e1ec884 843 s.set_try_server ();
2a0e62a8 844 return objs;
0a6f5a3f
JS
845 }
846
0a6f5a3f
JS
847 // create a simple Makefile
848 string makefile(dir + "/Makefile");
849 ofstream omf(makefile.c_str());
9ccda279 850 // force debuginfo generation, and relax implicit functions
2537a880 851 omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration " << WERROR << endl;
a7ec2317
FCE
852 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
853 omf << "CONFIG_MODULE_SIG := n" << endl;
854
8bb62408
JS
855 // PR18389: disable GCC's Identical Code Folding, since the stubs may look identical
856 omf << "EXTRA_CFLAGS += $(call cc-option,-fno-ipa-icf)" << endl;
857
18b13994 858 omf << "EXTRA_CFLAGS += -I" + s.kernel_build_tree << endl;
c9ccb642
FCE
859 if (s.kernel_source_tree != "")
860 omf << "EXTRA_CFLAGS += -I" + s.kernel_source_tree << endl;
ac4f2837
DS
861 for (unsigned i = 0; i < s.kernel_extra_cflags.size(); i++)
862 omf << "EXTRA_CFLAGS += " + s.kernel_extra_cflags[i] << endl;
0a6f5a3f 863
c9ccb642
FCE
864 omf << "obj-m := " << endl;
865 // write out each header-specific source file into a separate file
866 for (map<string,string>::const_iterator it = contents.begin(); it != contents.end(); it++)
867 {
868 string sbasename = basename + "_" + lex_cast(++tick); // suffixed
869
870 // write out source code
871 string srcname = dir + "/" + sbasename + ".c";
872 string src = it->second;
873 ofstream osrc(srcname.c_str());
874 osrc << src;
875 osrc.close();
876
77b163ae
FCE
877 if (s.verbose > 2)
878 clog << _F("Processing tracepoint header %s with query %s",
879 it->first.c_str(), srcname.c_str())
880 << endl;
881
c9ccb642
FCE
882 // arrange to build it
883 omf << "obj-m += " + sbasename + ".o" << endl; // NB: without <dir> prefix
2a0e62a8 884 objs[it->first] = dir + "/" + sbasename + ".o";
c9ccb642
FCE
885 }
886 omf.close();
0a6f5a3f
JS
887
888 // make the module
8e0a2563 889 vector<string> make_cmd = make_make_objs_cmd(s, dir);
e86f32ee 890 make_cmd.push_back ("-i"); // ignore errors, give rc 0 even in case of tracepoint header nits
ff520ff4
JS
891 bool quiet = (s.verbose < 4);
892 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
3e1ec884
DB
893 if (rc)
894 s.set_try_server ();
c2cf1b87 895
e86f32ee
FCE
896 // Sometimes we fail a tracequery due to PR9993 / PR11649 type
897 // kernel trace header problems. In this case, due to PR12729, we
898 // used to get a lovely "Warning: make exited with status: 2" but no
c2cf1b87
FCE
899 // other useful diagnostic. -vvvv would let a user see what's up,
900 // but the user can't fix the problem even with that.
901
2a0e62a8 902 return objs;
0a6f5a3f
JS
903}
904
3e1c25aa
JS
905
906// Build a tiny kernel module to query type information
d90053e7 907static int
da9e11bd 908make_typequery_kmod(systemtap_session& s, const vector<string>& headers, string& name)
3e1c25aa
JS
909{
910 static unsigned tick = 0;
aca66a36 911 string basename("typequery_kmod_" + lex_cast(++tick));
3e1c25aa
JS
912
913 // create a subdirectory for the module
914 string dir(s.tmpdir + "/" + basename);
915 if (create_dir(dir.c_str()) != 0)
916 {
2713ea24 917 s.print_warning("failed to create directory for querying types.");
3e1ec884 918 s.set_try_server ();
3e1c25aa
JS
919 return 1;
920 }
921
922 name = dir + "/" + basename + ".ko";
923
924 // create a simple Makefile
925 string makefile(dir + "/Makefile");
926 ofstream omf(makefile.c_str());
927 omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl;
3ae4cdf9 928
a7ec2317
FCE
929 // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
930 omf << "CONFIG_MODULE_SIG := n" << endl;
931
3ae4cdf9
JS
932 // NB: We use -include instead of #include because that gives us more power.
933 // Using #include searches relative to the source's path, which in this case
934 // is /tmp/..., so that's not helpful. Using -include will search relative
935 // to the cwd, which will be the kernel build root. This means if you have a
936 // full kernel build tree, it's possible to get at types that aren't in the
937 // normal include path, e.g.:
938 // @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->...
da9e11bd
JS
939 omf << "CFLAGS_" << basename << ".o :=";
940 for (size_t i = 0; i < headers.size(); ++i)
ff520ff4 941 omf << " -include " << lex_cast_qstring(headers[i]); // XXX right quoting?
da9e11bd 942 omf << endl;
3ae4cdf9 943
3e1c25aa
JS
944 omf << "obj-m := " + basename + ".o" << endl;
945 omf.close();
946
947 // create our empty source file
948 string source(dir + "/" + basename + ".c");
949 ofstream osrc(source.c_str());
950 osrc.close();
951
952 // make the module
7d26ee02 953 vector<string> make_cmd = make_make_cmd(s, dir);
ff520ff4
JS
954 bool quiet = (s.verbose < 4);
955 int rc = run_make_cmd(s, make_cmd, quiet, quiet);
3e1ec884
DB
956 if (rc)
957 s.set_try_server ();
958 return rc;
3e1c25aa
JS
959}
960
961
962// Build a tiny user module to query type information
d90053e7 963static int
da9e11bd 964make_typequery_umod(systemtap_session& s, const vector<string>& headers, string& name)
3e1c25aa
JS
965{
966 static unsigned tick = 0;
967
aca66a36 968 name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so";
3e1c25aa
JS
969
970 // make the module
3ae4cdf9
JS
971 //
972 // NB: As with kmod, using -include makes relative paths more useful. The
973 // cwd in this case will be the cwd of stap itself though, which may be
974 // trickier to deal with. It might be better to "cd `dirname $script`"
975 // first...
c2f14e64 976 vector<string> cmd
ff520ff4 977 {
c2f14e64
JS
978 "gcc", "-shared", "-g", "-fno-eliminate-unused-debug-types",
979 "-xc", "/dev/null", "-o", name,
980 };
981 for (size_t i = 0; i < headers.size(); ++i)
982 cmd.insert(cmd.end(), { "-include", headers[i] });
983
ff520ff4
JS
984 bool quiet = (s.verbose < 4);
985 int rc = stap_system (s.verbose, cmd, quiet, quiet);
3e1ec884
DB
986 if (rc)
987 s.set_try_server ();
988 return rc;
3e1c25aa
JS
989}
990
d90053e7
JS
991
992int
993make_typequery(systemtap_session& s, string& module)
994{
995 int rc;
996 string new_module;
da9e11bd 997 vector<string> headers;
60d98537 998 bool kernel = startswith(module, "kernel");
d90053e7 999
da9e11bd 1000 for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1)
d90053e7 1001 {
da9e11bd
JS
1002 if (module[i] != '<')
1003 return -1;
1004 end = module.find('>', ++i);
1005 if (end == string::npos)
1006 return -1;
1007 string header = module.substr(i, end - i);
504d2b61 1008 vector<string> matches;
5ef28d5a 1009 if (regexp_match(header, "^[a-zA-Z0-9/_.+-]+$", matches))
2713ea24 1010 s.print_warning("skipping malformed @cast header \""+ header + "\"");
504d2b61
JS
1011 else
1012 headers.push_back(header);
d90053e7 1013 }
da9e11bd 1014 if (headers.empty())
d90053e7
JS
1015 return -1;
1016
da9e11bd
JS
1017 if (kernel)
1018 rc = make_typequery_kmod(s, headers, new_module);
1019 else
1020 rc = make_typequery_umod(s, headers, new_module);
1021
d90053e7
JS
1022 if (!rc)
1023 module = new_module;
1024
1025 return rc;
1026}
1027
73267b89 1028/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.296975 seconds and 5 git commands to generate.