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