summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkenistoj <kenistoj>2007-10-08 21:52:12 +0000
committerkenistoj <kenistoj>2007-10-08 21:52:12 +0000
commit6274464ec4e095cd42238d0b4b5dc1d45bf100da (patch)
treee640a94f014c692f57e95ce087e87e1b2b301779
parenta9e8f7e0533811be2cd7c9a88d9058da8caa1d11 (diff)
downloadsystemtap-steved-6274464ec4e095cd42238d0b4b5dc1d45bf100da.tar.gz
systemtap-steved-6274464ec4e095cd42238d0b4b5dc1d45bf100da.tar.xz
systemtap-steved-6274464ec4e095cd42238d0b4b5dc1d45bf100da.zip
PR 5709
* main.cxx: Add pass 4.5: make uprobes.ko in runtime/uprobes * buildrun.cxx: Add uprobes_enabled() and make_uprobes(). Factor run_make_cmd() out of compile_pass(). * buildrun.h: Add uprobes_enabled and make_uprobes decls. * tapsets.cxx: Do correct #include for modprobed uprobes.ko; set need_uprobes in pass 2. * session.h: Add need_uprobes * runtime/staprun/common.c: Add -u option -> need_uprobes * runtime/staprun/staprun_funcs.c: Generalize insert_module() to support inserting uprobes.ko. * runtime/staprun/staprun.c: Add enable_uprobes(). insert_module call becomes insert_stap_module(). * runtime/staprun/staprun.h: Reflect insert_module() and need_uprobes changes * runtime/uprobes/*.[c,h]: uprobes is built as a module, rather than included into the source of the stap-generated module. * runtime/uprobes/Makefile: Added
-rw-r--r--Makefile.am2
-rw-r--r--buildrun.cxx82
-rw-r--r--buildrun.h2
-rw-r--r--main.cxx26
-rw-r--r--runtime/staprun/common.c7
-rw-r--r--runtime/staprun/staprun.c77
-rw-r--r--runtime/staprun/staprun.h4
-rw-r--r--runtime/staprun/staprun_funcs.c27
-rw-r--r--runtime/uprobes/Makefile10
-rw-r--r--runtime/uprobes/uprobes.c112
-rw-r--r--runtime/uprobes/uprobes.h8
-rw-r--r--runtime/uprobes/uprobes_i386.c6
-rw-r--r--session.h1
-rw-r--r--tapsets.cxx8
14 files changed, 227 insertions, 145 deletions
diff --git a/Makefile.am b/Makefile.am
index f9939685..7e28591c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -131,7 +131,7 @@ install-data-local:
(cd $(srcdir)/runtime; for f in *.[ch]; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/$$f; done)
(cd $(srcdir)/runtime/transport; for f in *.[ch]; \
do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/transport/$$f; done)
- (cd $(srcdir)/runtime/uprobes; for f in *.[ch]; \
+ (cd $(srcdir)/runtime/uprobes; for f in Makefile *.[ch]; \
do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/uprobes/$$f; done)
(cd $(srcdir)/tapset; find . \( -name '*.stp' -o -name README \) -print \
| while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/tapset/$$f; done)
diff --git a/buildrun.cxx b/buildrun.cxx
index 709a6e5e..3eeae794 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -29,6 +29,32 @@ extern "C" {
using namespace std;
+/* Adjust and run make_cmd to build a kernel module. */
+static int
+run_make_cmd(systemtap_session& s, string& make_cmd)
+{
+ // Before running make, fix up the environment a bit. PATH should
+ // already be overridden. Clean out a few variables that
+ // /lib/modules/${KVER}/build/Makefile uses.
+ int rc = unsetenv("ARCH") || unsetenv("KBUILD_EXTMOD")
+ || unsetenv("CROSS_COMPILE") || unsetenv("KBUILD_IMAGE")
+ || unsetenv("KCONFIG_CONFIG") || unsetenv("INSTALL_PATH");
+ if (rc)
+ {
+ const char* e = strerror (errno);
+ cerr << "unsetenv failed: " << e << endl;
+ }
+
+ if (s.verbose > 1)
+ make_cmd += " V=1";
+ else
+ make_cmd += " -s >/dev/null 2>&1";
+
+ if (s.verbose > 1) clog << "Running " << make_cmd << endl;
+ rc = system (make_cmd.c_str());
+
+ return rc;
+}
int
compile_pass (systemtap_session& s)
@@ -96,35 +122,50 @@ compile_pass (systemtap_session& s)
return rc;
}
- // Before running make, fix up the environment a bit. PATH should
- // already be overridden. Clean out a few variables that
- // /lib/modules/${KVER}/build/Makefile uses.
- rc = unsetenv("ARCH") || unsetenv("KBUILD_EXTMOD")
- || unsetenv("CROSS_COMPILE") || unsetenv("KBUILD_IMAGE")
- || unsetenv("KCONFIG_CONFIG") || unsetenv("INSTALL_PATH");
- if (rc)
- {
- const char* e = strerror (errno);
- cerr << "unsetenv failed: " << e << endl;
- }
-
// Run make
string make_cmd = string("make")
+ string (" -C \"") + module_dir + string("\"");
make_cmd += string(" M=\"") + s.tmpdir + string("\" modules");
- if (s.verbose > 1)
- make_cmd += " V=1";
- else
- make_cmd += " -s >/dev/null 2>&1";
-
- if (s.verbose > 1) clog << "Running " << make_cmd << endl;
- rc = system (make_cmd.c_str());
+ rc = run_make_cmd(s, make_cmd);
return rc;
}
+bool
+uprobes_enabled (void)
+{
+ int rc = system ("/bin/grep -q unregister_uprobe /proc/kallsyms");
+ return (rc == 0);
+}
+
+int
+make_uprobes (systemtap_session& s)
+{
+ string uprobes_home = string(PKGDATADIR "/runtime/uprobes");
+
+ // Quietly skip the build if the Makefile has been removed.
+ string makefile = uprobes_home + string("/Makefile");
+ struct stat buf;
+ if (stat(makefile.c_str(), &buf) != 0)
+ return 2; // make's exit value for No such file or directory.
+
+ if (s.verbose)
+ clog << "Pass 4, overtime: "
+ << "(re)building SystemTap's version of uprobes."
+ << endl;
+
+ string make_cmd = string("make -C ") + uprobes_home;
+ int rc = run_make_cmd(s, make_cmd);
+ if (rc && s.verbose)
+ clog << "Uprobes build failed. "
+ << "Hope uprobes is available at run time."
+ << endl;
+
+ return rc;
+}
+
int
run_pass (systemtap_session& s)
{
@@ -150,6 +191,9 @@ run_pass (systemtap_session& s)
if (s.buffer_size)
staprun_cmd += "-b " + stringify(s.buffer_size) + " ";
+ if (s.need_uprobes)
+ staprun_cmd += "-u ";
+
staprun_cmd += s.tmpdir + "/" + s.module_name + ".ko";
if (s.verbose>1) clog << "Running " << staprun_cmd << endl;
diff --git a/buildrun.h b/buildrun.h
index 88a63a5e..54e78c1a 100644
--- a/buildrun.h
+++ b/buildrun.h
@@ -12,6 +12,8 @@
#include "elaborate.h"
int compile_pass (systemtap_session& s);
+bool uprobes_enabled (void);
+int make_uprobes (systemtap_session& s);
int run_pass (systemtap_session& s);
diff --git a/main.cxx b/main.cxx
index 7d4b8133..97f089a8 100644
--- a/main.cxx
+++ b/main.cxx
@@ -225,6 +225,7 @@ main (int argc, char * const argv [])
s.symtab = false;
s.use_cache = true;
s.tapset_compile_coverage = false;
+ s.need_uprobes = false;
const char* s_p = getenv ("SYSTEMTAP_TAPSET");
if (s_p != NULL)
@@ -728,12 +729,13 @@ main (int argc, char * const argv [])
// See if we can use cached source/module.
if (get_from_cache(s))
{
- // If our last pass isn't 5, we're done (since passes 3 and
- // 4 just generate what we just pulled out of the cache).
- if (s.last_pass < 5) goto cleanup;
+ // If our last pass isn't 5, and we don't need to build
+ // uprobes, we're done (since passes 3 and 4 just generate
+ // what we just pulled out of the cache).
+ if (s.last_pass < 4) goto cleanup;
- // Short-circuit to pass 5.
- goto pass_5;
+ // Short-circuit to pass 4.5.
+ goto pass_4point5;
}
}
@@ -810,8 +812,20 @@ main (int argc, char * const argv [])
}
}
- if (rc || s.last_pass == 4) goto cleanup;
+ if (rc) goto cleanup;
+ // PASS 4.5: BUILD SYSTEMTAP'S VERSION OF UPROBES (IF NECESSARY)
+pass_4point5:
+ if (s.need_uprobes)
+ {
+ if (s.last_pass == 5 && uprobes_enabled())
+ // Uprobes symbols are currently available in the kernel,
+ // so staprun won't use what we'd build anyway.
+ goto pass_5;
+
+ (void) make_uprobes(s);
+ }
+ if (s.last_pass == 4) goto cleanup;
// PASS 5: RUN
pass_5:
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index 9056c710..d3f8835a 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -23,6 +23,7 @@ char *target_cmd;
char *outfile_name;
int attach_mod;
int load_only;
+int need_uprobes;
/* module variables */
char *modname = NULL;
@@ -44,9 +45,13 @@ void parse_args(int argc, char **argv)
outfile_name = NULL;
attach_mod = 0;
load_only = 0;
+ need_uprobes = 0;
- while ((c = getopt(argc, argv, "ALvb:t:d:c:o:x:")) != EOF) {
+ while ((c = getopt(argc, argv, "ALuvb:t:d:c:o:x:")) != EOF) {
switch (c) {
+ case 'u':
+ need_uprobes = 1;
+ break;
case 'v':
verbose++;
break;
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index 71039e0b..67b01abb 100644
--- a/runtime/staprun/staprun.c
+++ b/runtime/staprun/staprun.c
@@ -35,6 +35,16 @@ run_as(uid_t uid, gid_t gid, const char *path, char *const argv[])
pid_t pid;
int rstatus;
+ if (verbose >= 2) {
+ int i = 0;
+ err("execing: ");
+ while (argv[i]) {
+ err("%s ", argv[i]);
+ i++;
+ }
+ err("\n");
+ }
+
if ((pid = fork()) < 0) {
_perr("fork");
return -1;
@@ -77,18 +87,63 @@ static int run_stapio(char **argv)
gid_t gid = getgid();
argv[0] = PKGLIBDIR "/stapio";
- if (verbose >= 2) {
- int i = 0;
- err("execing: ");
- while (argv[i]) {
- err("%s ", argv[i]);
- i++;
- }
- err("\n");
- }
return run_as(uid, gid, argv[0], argv);
}
+/*
+ * Module to be inserted has one or more user-space probes. Make sure
+ * uprobes is enabled.
+ * If /proc/kallsyms lists a symbol in uprobes (e.g. unregister_uprobe),
+ * we're done.
+ * Else try "modprobe uprobes" to load the uprobes module (if any)
+ * built with the kernel.
+ * If that fails, load the uprobes module built in runtime/uprobes.
+ */
+static int enable_uprobes(void)
+{
+ int i;
+ char *argv[10];
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+
+ i = 0;
+ argv[i++] = "/bin/grep";
+ argv[i++] = "-q";
+ argv[i++] = "unregister_uprobe";
+ argv[i++] = "/proc/kallsyms";
+ argv[i] = NULL;
+ if (run_as(uid, gid, argv[0], argv) == 0)
+ return 0;
+
+ /*
+ * TODO: If user can't setresuid to root here, staprun will exit.
+ * Is there a situation where that would fail but the subsequent
+ * attempt to use CAP_SYS_MODULE privileges (in insert_module())
+ * would succeed?
+ */
+ dbug(2, "Inserting uprobes module from /lib/modules, if any.\n");
+ i = 0;
+ argv[i++] = "/sbin/modprobe";
+ argv[i++] = "-q";
+ argv[i++] = "uprobes";
+ argv[i] = NULL;
+ if (run_as(0, 0, argv[0], argv) == 0)
+ return 0;
+
+ dbug(2, "Inserting uprobes module from SystemTap runtime.\n");
+ argv[0] = NULL;
+ return insert_module(PKGDATADIR "/runtime/uprobes/uprobes.ko",
+ NULL, argv);
+}
+
+static int insert_stap_module(void)
+{
+ char bufsize_option[128];
+ if (snprintf_chk(bufsize_option, 128, "_stp_bufsize=%d", buffer_size))
+ return -1;
+ return insert_module(modpath, bufsize_option, modoptions);
+}
+
int init_staprun(void)
{
@@ -101,7 +156,9 @@ int init_staprun(void)
drop_cap(CAP_SYS_ADMIN);
if (!attach_mod) {
- if (insert_module() < 0)
+ if (need_uprobes && enable_uprobes() != 0)
+ return -1;
+ if (insert_stap_module() < 0)
return -1;
else
inserted_module = 1;
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index cde44922..1b0f3221 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -141,7 +141,8 @@ void drop_cap(cap_value_t cap);
/* staprun_funcs.c */
void setup_staprun_signals(void);
const char *moderror(int err);
-int insert_module(void);
+int insert_module(const char *path, const char *special_options,
+ char **options);
int mountfs(void);
int check_permissions(void);
void handle_symbols(void);
@@ -171,6 +172,7 @@ extern char *target_cmd;
extern char *outfile_name;
extern int attach_mod;
extern int load_only;
+extern int need_uprobes;
/* getopt variables */
extern char *optarg;
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index 0747b530..eec4ae63 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -47,7 +47,7 @@ const char *moderror(int err)
}
}
-int insert_module(void)
+int insert_module(const char *path, const char *special_options, char **options)
{
int i;
long ret;
@@ -58,34 +58,35 @@ int insert_module(void)
dbug(2, "inserting module\n");
- opts = malloc(128);
+ if (special_options)
+ opts = strdup(special_options);
+ else
+ opts = strdup("");
if (opts == NULL) {
_perr("allocating memory failed");
return -1;
}
- if (snprintf_chk(opts, 128, "_stp_bufsize=%d", buffer_size))
- return -1;
- for (i = 0; modoptions[i] != NULL; i++) {
- opts = realloc(opts, strlen(opts) + strlen(modoptions[i]) + 2);
+ for (i = 0; options[i] != NULL; i++) {
+ opts = realloc(opts, strlen(opts) + strlen(options[i]) + 2);
if (opts == NULL) {
- _perr("reallocating memory failed");
+ _perr("[re]allocating memory failed");
return -1;
}
strcat(opts, " ");
- strcat(opts, modoptions[i]);
+ strcat(opts, options[i]);
}
dbug(2, "module options: %s\n", opts);
/* Open the module file. */
- fd = open(modpath, O_RDONLY);
+ fd = open(path, O_RDONLY);
if (fd < 0) {
- perr("Error opening '%s'", modpath);
+ perr("Error opening '%s'", path);
return -1;
}
/* Now that the file is open, figure out how big it is. */
if (fstat(fd, &sbuf) < 0) {
- _perr("Error stat'ing '%s'", modpath);
+ _perr("Error stat'ing '%s'", path);
close(fd);
return -1;
}
@@ -93,7 +94,7 @@ int insert_module(void)
/* mmap in the entire module. */
file = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (file == MAP_FAILED) {
- _perr("Error mapping '%s'", modpath);
+ _perr("Error mapping '%s'", path);
close(fd);
free(opts);
return -1;
@@ -109,7 +110,7 @@ int insert_module(void)
close(fd);
if (ret != 0) {
- err("Error inserting module '%s': %s\n", modpath, moderror(saved_errno));
+ err("Error inserting module '%s': %s\n", path, moderror(saved_errno));
return -1;
}
return 0;
diff --git a/runtime/uprobes/Makefile b/runtime/uprobes/Makefile
new file mode 100644
index 00000000..806f7c48
--- /dev/null
+++ b/runtime/uprobes/Makefile
@@ -0,0 +1,10 @@
+obj-m := uprobes.o
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+
+clean:
+ rm -f *.mod.c *.ko *.o .*.cmd *~
+ rm -rf .tmp_versions
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c
index 41d0ef11..16c5e046 100644
--- a/runtime/uprobes/uprobes.c
+++ b/runtime/uprobes/uprobes.c
@@ -59,36 +59,22 @@ typedef void (*uprobe_handler_t)(struct uprobe*, struct pt_regs*);
/* Point utask->active_probe at this while running uretprobe handler. */
static struct uprobe_probept uretprobe_trampoline_dummy_probe;
-/*
- * These data structures are shared by all SystemTap-generated modules
- * that use uprobes.
- */
-struct uprobe_globals {
- struct hlist_head uproc_table[UPROBE_TABLE_SIZE];
- struct mutex uproc_mutex;
- struct hlist_head utask_table[UPROBE_TABLE_SIZE];
- spinlock_t utask_table_lock;
-};
-static struct uprobe_globals *globals;
-static struct hlist_head *uproc_table; /* = globals->uproc_table */
-static struct hlist_head *utask_table; /* = globals->utask_table */
+/* Table of currently probed processes, hashed by tgid. */
+static struct hlist_head uproc_table[UPROBE_TABLE_SIZE];
-#define lock_uproc_table() mutex_lock(&globals->uproc_mutex)
-#define unlock_uproc_table() mutex_unlock(&globals->uproc_mutex)
+/* Protects uproc_table during uprobe (un)registration */
+static DEFINE_MUTEX(uproc_mutex);
-#define lock_utask_table(flags) \
- spin_lock_irqsave(&globals->utask_table_lock, (flags))
-#define unlock_utask_table(flags) \
- spin_unlock_irqrestore(&globals->utask_table_lock, (flags))
+/* Table of uprobe_tasks, hashed by task_struct pointer. */
+static struct hlist_head utask_table[UPROBE_TABLE_SIZE];
+static DEFINE_SPINLOCK(utask_table_lock);
-/*
- * uprobes_data and uprobes_mutex are the only uprobes hooks in the kernel.
- * A pointer to the uprobes_global area is stored in uprobe_data.
- */
-extern void *uprobes_data;
-extern struct mutex uprobes_mutex;
+#define lock_uproc_table() mutex_lock(&uproc_mutex)
+#define unlock_uproc_table() mutex_unlock(&uproc_mutex)
-static int verify_uprobes(void);
+#define lock_utask_table(flags) spin_lock_irqsave(&utask_table_lock, (flags))
+#define unlock_utask_table(flags) \
+ spin_unlock_irqrestore(&utask_table_lock, (flags))
/* p_uprobe_utrace_ops = &uprobe_utrace_ops. Fwd refs are a pain w/o this. */
static const struct utrace_engine_ops *p_uprobe_utrace_ops;
@@ -824,7 +810,6 @@ static int defer_registration(struct uprobe *u, int regflag,
}
/* See Documentation/uprobes.txt. */
-static
int register_uprobe(struct uprobe *u)
{
struct task_struct *p;
@@ -833,9 +818,6 @@ int register_uprobe(struct uprobe *u)
struct uprobe_probept *ppt;
struct uprobe_task *cur_utask, *cur_utask_quiescing = NULL;
int survivors, ret = 0, uproc_is_new = 0;
- if ((ret = verify_uprobes()) < 0)
- return ret;
-
if (!u || !u->handler)
return -EINVAL;
@@ -982,9 +964,9 @@ fail_tsk:
put_task_struct(p);
return ret;
}
+EXPORT_SYMBOL_GPL(register_uprobe);
/* See Documentation/uprobes.txt. */
-static
void unregister_uprobe(struct uprobe *u)
{
struct task_struct *p;
@@ -993,8 +975,6 @@ void unregister_uprobe(struct uprobe *u)
struct uprobe_probept *ppt;
struct uprobe_task *cur_utask, *cur_utask_quiescing = NULL;
- if (verify_uprobes() < 0)
- return;
if (!u)
return;
p = uprobe_get_task(u->pid);
@@ -1069,6 +1049,7 @@ done:
up_write(&uproc->rwsem);
uprobe_put_process(uproc);
}
+EXPORT_SYMBOL_GPL(unregister_uprobe);
/* Find a surviving thread in uproc. Runs with uproc->rwsem locked. */
static struct task_struct *find_surviving_thread(struct uprobe_process *uproc)
@@ -2071,64 +2052,26 @@ static const struct utrace_engine_ops uprobe_utrace_ops =
.report_exec = uprobe_report_exec
};
-/*
- * Initialize the uprobes global data area, and return a pointer
- * to it. Caller will initialize uprobes_data pointer afterward, to
- * ensure that no other module sees a non-null uprobes_data until it's
- * completely initialized.
- */
-static struct uprobe_globals *init_uprobes(void)
+static int __init init_uprobes(void)
{
int i;
- struct uprobe_globals *g = kmalloc(sizeof(*g), GFP_USER);
- if (!g)
- return ERR_PTR(-ENOMEM);
+
for (i = 0; i < UPROBE_TABLE_SIZE; i++) {
- INIT_HLIST_HEAD(&g->uproc_table[i]);
- INIT_HLIST_HEAD(&g->utask_table[i]);
+ INIT_HLIST_HEAD(&uproc_table[i]);
+ INIT_HLIST_HEAD(&utask_table[i]);
}
- mutex_init(&g->uproc_mutex);
- spin_lock_init(&g->utask_table_lock);
- return g;
+
+ p_uprobe_utrace_ops = &uprobe_utrace_ops;
+ return 0;
}
-/*
- * Verify that the uprobes globals area has been set up, and that the
- * current module's globals variable points at it. Returns 0 if the
- * area is successfully set up, or a negative erro otherwise.
- */
-static int verify_uprobes(void)
+static void __exit exit_uprobes(void)
{
- if (unlikely(!globals)) {
- /*
- * First time through for this instrumentation module.
- * uprobes_mutex protects both the global uprobes
- * initialization and this module's local initialization.
- */
- struct uprobe_globals *g;
-
- mutex_lock(&uprobes_mutex);
- if (!uprobes_data) {
- /* First time through since boot time */
- g = init_uprobes();
- uprobes_data = g;
- } else
- g = uprobes_data;
- if (!IS_ERR(g)) {
- p_uprobe_utrace_ops = &uprobe_utrace_ops;
- uproc_table = g->uproc_table;
- utask_table = g->utask_table;
- }
-
- /* Set globals pointer to signify all is initialized. */
- globals = g;
- mutex_unlock(&uprobes_mutex);
- }
- if (unlikely(IS_ERR(globals)))
- return (int) PTR_ERR(globals);
- return 0;
}
+module_init(init_uprobes);
+module_exit(exit_uprobes);
+
#ifdef CONFIG_URETPROBES
/* Called when the entry-point probe u is hit. */
@@ -2209,7 +2152,6 @@ static void uretprobe_handle_return(struct pt_regs *regs,
arch_restore_uret_addr(orig_ret_addr, regs);
}
-static
int register_uretprobe(struct uretprobe *rp)
{
if (!rp || !rp->handler)
@@ -2217,6 +2159,7 @@ int register_uretprobe(struct uretprobe *rp)
rp->u.handler = URETPROBE_HANDLE_ENTRY;
return register_uprobe(&rp->u);
}
+EXPORT_SYMBOL_GPL(register_uretprobe);
/*
* The uretprobe containing u is being unregistered. Its uretprobe_instances
@@ -2244,13 +2187,13 @@ static void zap_uretprobe_instances(struct uprobe *u,
}
}
-static
void unregister_uretprobe(struct uretprobe *rp)
{
if (!rp)
return;
unregister_uprobe(&rp->u);
}
+EXPORT_SYMBOL_GPL(unregister_uretprobe);
/*
* uproc->ssol_area has been successfully set up. Establish the
@@ -2295,3 +2238,4 @@ static void zap_uretprobe_instances(struct uprobe *u,
#endif /* CONFIG_URETPROBES */
#include "uprobes_arch.c"
+MODULE_LICENSE("GPL");
diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h
index 574bee62..84dd0b2a 100644
--- a/runtime/uprobes/uprobes.h
+++ b/runtime/uprobes/uprobes.h
@@ -72,11 +72,11 @@ struct uretprobe_instance {
unsigned long reserved2;
};
-static int register_uprobe(struct uprobe *u);
-static void unregister_uprobe(struct uprobe *u);
+extern int register_uprobe(struct uprobe *u);
+extern void unregister_uprobe(struct uprobe *u);
/* For runtime, assume uprobes support includes uretprobes. */
-static int register_uretprobe(struct uretprobe *rp);
-static void unregister_uretprobe(struct uretprobe *rp);
+extern int register_uretprobe(struct uretprobe *rp);
+extern void unregister_uretprobe(struct uretprobe *rp);
#ifdef UPROBES_IMPLEMENTATION
diff --git a/runtime/uprobes/uprobes_i386.c b/runtime/uprobes/uprobes_i386.c
index 90d50ba0..21420681 100644
--- a/runtime/uprobes/uprobes_i386.c
+++ b/runtime/uprobes/uprobes_i386.c
@@ -18,8 +18,10 @@
*
* Copyright (C) IBM Corporation, 2006
*/
-#define UPROBES_IMPLEMENTATION 1
-#include "uprobes.h"
+/*
+ * In versions of uprobes built in the SystemTap runtime, this file
+ * is #included at the end of uprobes.c.
+ */
#include <linux/uaccess.h>
/* Adapted from arch/x86_64/kprobes.c */
diff --git a/session.h b/session.h
index b7fb64ea..e2d7cd4f 100644
--- a/session.h
+++ b/session.h
@@ -97,6 +97,7 @@ struct systemtap_session
bool symtab; /* true: emit symbol table at translation time; false: let staprun do it. */
bool prologue_searching;
bool tapset_compile_coverage;
+ bool need_uprobes;
// Cache data
bool use_cache;
diff --git a/tapsets.cxx b/tapsets.cxx
index c4d6962e..2af94890 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -4027,11 +4027,12 @@ public:
};
-uprobe_derived_probe::uprobe_derived_probe (systemtap_session &,
+uprobe_derived_probe::uprobe_derived_probe (systemtap_session &s,
probe* p, probe_point* l,
uint64_t pp, uint64_t aa, bool rr):
derived_probe(p, l), process(pp), address(aa), return_p (rr)
{
+ s.need_uprobes = true;
}
@@ -4073,11 +4074,10 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "/* ---- user probes ---- */";
// If uprobes isn't in the kernel, pull it in from the runtime.
- // TODO: Consider detecting uprobes installed as a module.
- s.op->newline() << "#ifdef CONFIG_UPROBES";
+ s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)";
s.op->newline() << "#include <linux/uprobes.h>";
s.op->newline() << "#else";
- s.op->newline() << "#include \"uprobes/uprobes.c\"";
+ s.op->newline() << "#include \"uprobes/uprobes.h\"";
s.op->newline() << "#endif";
s.op->newline() << "struct stap_uprobe {";