diff options
author | kenistoj <kenistoj> | 2007-10-08 21:52:12 +0000 |
---|---|---|
committer | kenistoj <kenistoj> | 2007-10-08 21:52:12 +0000 |
commit | 6274464ec4e095cd42238d0b4b5dc1d45bf100da (patch) | |
tree | e640a94f014c692f57e95ce087e87e1b2b301779 | |
parent | a9e8f7e0533811be2cd7c9a88d9058da8caa1d11 (diff) | |
download | systemtap-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.am | 2 | ||||
-rw-r--r-- | buildrun.cxx | 82 | ||||
-rw-r--r-- | buildrun.h | 2 | ||||
-rw-r--r-- | main.cxx | 26 | ||||
-rw-r--r-- | runtime/staprun/common.c | 7 | ||||
-rw-r--r-- | runtime/staprun/staprun.c | 77 | ||||
-rw-r--r-- | runtime/staprun/staprun.h | 4 | ||||
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 27 | ||||
-rw-r--r-- | runtime/uprobes/Makefile | 10 | ||||
-rw-r--r-- | runtime/uprobes/uprobes.c | 112 | ||||
-rw-r--r-- | runtime/uprobes/uprobes.h | 8 | ||||
-rw-r--r-- | runtime/uprobes/uprobes_i386.c | 6 | ||||
-rw-r--r-- | session.h | 1 | ||||
-rw-r--r-- | tapsets.cxx | 8 |
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; @@ -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); @@ -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 */ @@ -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 {"; |