]> sourceware.org Git - systemtap.git/blame - buildrun.cxx
* release prep: 0.6.2 version bump
[systemtap.git] / buildrun.cxx
CommitLineData
f4b28491 1// build/run probes
255e4c68 2// Copyright (C) 2005-2007 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"
f4b28491 13
3b579393 14#include <cstdlib>
f4b28491 15#include <fstream>
d04cf5ff
FCE
16#include <sstream>
17
18extern "C" {
49abf162 19#include <signal.h>
0c6296b2 20#include <sys/wait.h>
70404fc5 21#include <pwd.h>
b40af7ee
DS
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <string.h>
26#include <errno.h>
d04cf5ff
FCE
27}
28
f4b28491
FCE
29
30using namespace std;
31
db3a383b
JK
32static int uprobes_pass (systemtap_session& s);
33
6274464e
JK
34/* Adjust and run make_cmd to build a kernel module. */
35static int
36run_make_cmd(systemtap_session& s, string& make_cmd)
37{
38 // Before running make, fix up the environment a bit. PATH should
39 // already be overridden. Clean out a few variables that
40 // /lib/modules/${KVER}/build/Makefile uses.
41 int rc = unsetenv("ARCH") || unsetenv("KBUILD_EXTMOD")
42 || unsetenv("CROSS_COMPILE") || unsetenv("KBUILD_IMAGE")
43 || unsetenv("KCONFIG_CONFIG") || unsetenv("INSTALL_PATH");
44 if (rc)
45 {
46 const char* e = strerror (errno);
47 cerr << "unsetenv failed: " << e << endl;
48 }
49
b54581ce 50 if (s.verbose > 2)
6274464e 51 make_cmd += " V=1";
b54581ce
FCE
52 else if (s.verbose > 1)
53 make_cmd += " >/dev/null";
6274464e
JK
54 else
55 make_cmd += " -s >/dev/null 2>&1";
56
57 if (s.verbose > 1) clog << "Running " << make_cmd << endl;
58 rc = system (make_cmd.c_str());
59
60 return rc;
61}
f4b28491
FCE
62
63int
64compile_pass (systemtap_session& s)
65{
db3a383b
JK
66 int rc = uprobes_pass (s);
67 if (rc)
68 return rc;
69
f4b28491 70 // fill in a quick Makefile
92ade41d
FCE
71 string makefile_nm = s.tmpdir + "/Makefile";
72 ofstream o (makefile_nm.c_str());
92ade41d
FCE
73
74 // Create makefile
ed10c639 75
255e4c68
FCE
76 // Clever hacks copied from vmware modules
77 o << "stap_check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo \"$(1)\"; else echo \"$(2)\"; fi)" << endl;
b54581ce 78 o << "stap_check_build = $(shell if $(CC) $(KBUILD_CPPFLAGS) $(CPPFLAGS) $(KBUILD_CFLAGS) $(CFLAGS_KERNEL) $(EXTRA_CFLAGS) $(CFLAGS) -DKBUILD_BASENAME=\\\"" << s.module_name << "\\\" -Werror -S -o /dev/null -xc $(1) > /dev/null 2>&1 ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl;
522518f1 79
255e4c68
FCE
80
81 o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl;
82
83 // "autoconf" options go here
84
85 // enum hrtimer_mode renaming near 2.6.21; see tapsets.cxx hrtimer_derived_probe_group::emit_module_decls
522518f1
FCE
86 string module_cflags = "CFLAGS_" + s.module_name + ".o";
87 o << module_cflags << " :=" << endl;
88 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-hrtimer-rel.c, -DSTAPCONF_HRTIMER_REL,)" << endl;
89 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-inode-private.c, -DSTAPCONF_INODE_PRIVATE,)" << endl;
ca99ed19
MH
90 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-constant-tsc.c, -DSTAPCONF_CONSTANT_TSC,)" << endl;
91 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-tsc-khz.c, -DSTAPCONF_TSC_KHZ,)" << endl;
92 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-ktime-get-real.c, -DSTAPCONF_KTIME_GET_REAL,)" << endl;
c7bcf451
SD
93 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-x86-uniregs.c, -DSTAPCONF_X86_UNIREGS,)" << endl;
94
95 o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-nameidata.c, -DSTAPCONF_NAMEIDATA_CLEANUP,)" << endl;
255e4c68 96
ed10c639 97 for (unsigned i=0; i<s.macros.size(); i++)
0986ac38 98 o << "EXTRA_CFLAGS += -D " << lex_cast_qstring(s.macros[i]) << endl;
ed10c639 99
e4c58386 100 if (s.verbose > 3)
0986ac38 101 o << "EXTRA_CFLAGS += -ftime-report -Q" << endl;
db22e55f 102
ee6dda6f
FCE
103 // XXX: unfortunately, -save-temps can't work since linux kbuild cwd
104 // is not writeable.
105 //
106 // if (s.keep_tmpdir)
107 // o << "CFLAGS += -fverbose-asm -save-temps" << endl;
108
0986ac38 109 o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os
35d4ab18
FCE
110
111 // o << "CFLAGS += -fno-unit-at-a-time" << endl;
112
cbfbbf69 113 // Assumes linux 2.6 kbuild
0986ac38
DS
114 o << "EXTRA_CFLAGS += -Wno-unused -Werror" << endl;
115 o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl;
4b2c4ab5
FCE
116 // XXX: this may help ppc toc overflow
117 // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl;
cbfbbf69 118 o << "obj-m := " << s.module_name << ".o" << endl;
f4b28491 119
ed10c639
FCE
120 o.close ();
121
b40af7ee 122 // Generate module directory pathname and make sure it exists.
cbfbbf69
FCE
123 string module_dir = string("/lib/modules/")
124 + s.kernel_release + "/build";
b40af7ee
DS
125 struct stat st;
126 rc = stat(module_dir.c_str(), &st);
127 if (rc != 0)
128 {
129 clog << "Module directory " << module_dir << " check failed: "
130 << strerror(errno) << endl
131 << "Make sure kernel devel is installed." << endl;
132 return rc;
133 }
134
135 // Run make
cbfbbf69
FCE
136 string make_cmd = string("make")
137 + string (" -C \"") + module_dir + string("\"");
138 make_cmd += string(" M=\"") + s.tmpdir + string("\" modules");
522518f1 139
6274464e 140 rc = run_make_cmd(s, make_cmd);
cbfbbf69 141
f4b28491
FCE
142 return rc;
143}
144
db3a383b 145static const string uprobes_home = string(PKGDATADIR "/runtime/uprobes");
f4b28491 146
db3a383b
JK
147/*
148 * If uprobes was built as part of the kernel build (either built-in
149 * or as a module), the uprobes exports should show up in
150 * /lib/modules/`uname -r`/build/Module.symvers. Return true if so.
151 */
152static bool
153kernel_built_uprobes (systemtap_session& s)
6274464e 154{
db3a383b
JK
155 string grep_cmd = string ("/bin/grep -q unregister_uprobe /lib/modules/")
156 + s.kernel_release + string ("/build/Module.symvers");
157 int rc = system (grep_cmd.c_str());
6274464e
JK
158 return (rc == 0);
159}
160
db3a383b
JK
161static bool
162verify_uprobes_uptodate (systemtap_session& s)
6274464e 163{
db3a383b
JK
164 if (s.verbose)
165 clog << "Pass 4, preamble: "
166 << "verifying that SystemTap's version of uprobes is up to date."
167 << endl;
168
169 string make_cmd = string("make -q -C ") + uprobes_home
170 + string(" uprobes.ko");
171 int rc = run_make_cmd(s, make_cmd);
172 if (rc) {
173 clog << "SystemTap's version of uprobes is out of date." << endl;
174 clog << "As root, run \"make\" in " << uprobes_home << "." << endl;
175 }
6274464e 176
db3a383b
JK
177 return rc;
178}
6274464e 179
db3a383b
JK
180static int
181make_uprobes (systemtap_session& s)
182{
6274464e 183 if (s.verbose)
db3a383b 184 clog << "Pass 4, preamble: "
6274464e
JK
185 << "(re)building SystemTap's version of uprobes."
186 << endl;
187
188 string make_cmd = string("make -C ") + uprobes_home;
189 int rc = run_make_cmd(s, make_cmd);
db3a383b
JK
190 if (s.verbose) {
191 if (rc)
192 clog << "Uprobes (re)build failed." << endl;
193 else
194 clog << "Uprobes (re)build complete." << endl;
195 }
6274464e
JK
196
197 return rc;
198}
199
db3a383b
JK
200/*
201 * Copy uprobes' exports (in Module.symvers) into the temporary directory
202 * so the script-module build can find them.
203 */
204static int
205copy_uprobes_symbols (systemtap_session& s)
206{
207 string cp_cmd = string("/bin/cp ") + uprobes_home +
208 string("/Module.symvers ") + s.tmpdir;
209 int rc = system (cp_cmd.c_str());
210 return rc;
211}
212
213static int
214uprobes_pass (systemtap_session& s)
215{
216 if (!s.need_uprobes || kernel_built_uprobes(s))
217 return 0;
218 /*
219 * We need to use the version of uprobes that comes with SystemTap, so
220 * we may need to rebuild uprobes.ko there. Unfortunately, this is
221 * never a no-op; e.g., the modpost step gets run every time. We don't
222 * want non-root users modifying uprobes, so we keep the uprobes
223 * directory writable only by root. But that means a non-root member
224 * of group stapdev can't run the make even if everything's up to date.
225 *
226 * So for non-root users, we just use "make -q" with a fake target to
227 * verify that uprobes doesn't need to be rebuilt. If that's not so,
228 * stap must fail.
229 */
230 int rc;
231 if (geteuid() == 0) {
232 rc = make_uprobes(s);
233 if (rc == 0)
234 rc = copy_uprobes_symbols(s);
235 } else
236 rc = verify_uprobes_uptodate(s);
237 return rc;
238}
239
f4b28491
FCE
240int
241run_pass (systemtap_session& s)
242{
92ade41d
FCE
243 int rc = 0;
244
70404fc5
MH
245 struct passwd *pw = getpwuid(getuid());
246 string username = string(pw->pw_name);
247
a63a95dc 248 // for now, just spawn staprun
98aab489 249 string staprun_cmd = string(BINDIR) + "/staprun "
e65b03c1 250 + (s.verbose>1 ? "-v " : "")
639948b1 251 + (s.verbose>2 ? "-v " : "")
cbfbbf69
FCE
252 + (s.output_file.empty() ? "" : "-o " + s.output_file + " ");
253
a63a95dc 254 staprun_cmd += "-d " + stringify(getpid()) + " ";
cbfbbf69
FCE
255
256 if (s.cmd != "")
8c711d30 257 staprun_cmd += "-c " + cmdstr_quoted(s.cmd) + " ";
cbfbbf69
FCE
258
259 if (s.target_pid)
a63a95dc 260 staprun_cmd += "-t " + stringify(s.target_pid) + " ";
cbfbbf69
FCE
261
262 if (s.buffer_size)
a63a95dc 263 staprun_cmd += "-b " + stringify(s.buffer_size) + " ";
cbfbbf69 264
6274464e
JK
265 if (s.need_uprobes)
266 staprun_cmd += "-u ";
267
a63a95dc 268 staprun_cmd += s.tmpdir + "/" + s.module_name + ".ko";
cbfbbf69 269
a63a95dc 270 if (s.verbose>1) clog << "Running " << staprun_cmd << endl;
cbfbbf69 271
a63a95dc 272 rc = system (staprun_cmd.c_str ());
92ade41d 273 return rc;
f4b28491 274}
This page took 0.082797 seconds and 5 git commands to generate.