Inspired by the k*probe support. It add a new option to enable-event --uprobe which require a path name and an offset in the specified file.
(The file Documentation/trace/uprobetracer.txt in the kernel source provides and example on how to extract the offset for a symbol in a program) Signed-off-by: Yannick Brosseau <[email protected]> --- include/lttng/lttng.h | 15 +++++++++ src/bin/lttng-sessiond/cmd.c | 5 +++ src/bin/lttng-sessiond/modprobe.c | 1 + src/bin/lttng-sessiond/trace-kernel.c | 7 ++++ src/bin/lttng/commands/enable_events.c | 55 ++++++++++++++++++++++++++++++++ src/bin/lttng/commands/list.c | 8 +++++ src/common/lttng-kernel.h | 7 ++++ 7 files changed, 98 insertions(+) diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index e21b479..c790e7b 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -72,6 +72,7 @@ enum lttng_event_type { LTTNG_EVENT_FUNCTION_ENTRY = 3, LTTNG_EVENT_NOOP = 4, LTTNG_EVENT_SYSCALL = 5, + LTTNG_EVENT_UPROBE = 6, }; /* @@ -219,6 +220,19 @@ struct lttng_event_function_attr { }; /* + * Event uprobe. + * + * The structures should be initialized to zero before use. + */ +#define LTTNG_EVENT_UPROBE_PADDING1 24 +struct lttng_event_uprobe_attr { + char path[LTTNG_SYMBOL_NAME_LEN]; + uint64_t offset; + + char padding[LTTNG_EVENT_UPROBE_PADDING1]; +}; + +/* * Generic lttng event * * The structures should be initialized to zero before use. @@ -242,6 +256,7 @@ struct lttng_event { union { struct lttng_event_probe_attr probe; struct lttng_event_function_attr ftrace; + struct lttng_event_uprobe_attr uprobe; char padding[LTTNG_EVENT_PADDING2]; } attr; diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 491acde..d7fee70 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -315,6 +315,11 @@ static int list_lttng_kernel_events(char *channel_name, memcpy(&((*events)[i].attr.ftrace), &event->event->u.ftrace, sizeof(struct lttng_kernel_function)); break; + case LTTNG_KERNEL_UPROBE: + (*events)[i].type = LTTNG_EVENT_UPROBE; + memcpy(&(*events)[i].attr.uprobe, &event->event->u.uprobe, + sizeof(struct lttng_kernel_uprobe)); + break; case LTTNG_KERNEL_NOOP: (*events)[i].type = LTTNG_EVENT_NOOP; break; diff --git a/src/bin/lttng-sessiond/modprobe.c b/src/bin/lttng-sessiond/modprobe.c index 1a5a1b7..805e127 100644 --- a/src/bin/lttng-sessiond/modprobe.c +++ b/src/bin/lttng-sessiond/modprobe.c @@ -35,6 +35,7 @@ const struct kern_modules_param kern_modules_list[] = { { "lttng-ftrace", 0 }, { "lttng-kprobes", 0 }, { "lttng-kretprobes", 0 }, + { "lttng-uprobes", 0 }, { "lttng-lib-ring-buffer", 1 }, { "lttng-ring-buffer-client-discard", 1 }, { "lttng-ring-buffer-client-overwrite", 1 }, diff --git a/src/bin/lttng-sessiond/trace-kernel.c b/src/bin/lttng-sessiond/trace-kernel.c index f38cf3d..24f33f9 100644 --- a/src/bin/lttng-sessiond/trace-kernel.c +++ b/src/bin/lttng-sessiond/trace-kernel.c @@ -207,6 +207,13 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev) ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); attr->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; break; + case LTTNG_EVENT_UPROBE: + attr->instrumentation = LTTNG_KERNEL_UPROBE; + attr->u.uprobe.offset = ev->attr.uprobe.offset; + strncpy(attr->u.uprobe.path, + ev->attr.uprobe.path, LTTNG_KERNEL_SYM_NAME_LEN); + attr->u.uprobe.path[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; + break; case LTTNG_EVENT_FUNCTION: attr->instrumentation = LTTNG_KERNEL_KRETPROBE; attr->u.kretprobe.addr = ev->attr.probe.addr; diff --git a/src/bin/lttng/commands/enable_events.c b/src/bin/lttng/commands/enable_events.c index b6c18e1..61cb15b 100644 --- a/src/bin/lttng/commands/enable_events.c +++ b/src/bin/lttng/commands/enable_events.c @@ -38,6 +38,7 @@ static char *opt_session_name; static int opt_userspace; static int opt_enable_all; static char *opt_probe; +static char *opt_uprobe; static char *opt_function; static char *opt_function_entry_symbol; static char *opt_channel_name; @@ -52,6 +53,7 @@ enum { OPT_HELP = 1, OPT_TRACEPOINT, OPT_PROBE, + OPT_UPROBE, OPT_FUNCTION, OPT_FUNCTION_ENTRY, OPT_SYSCALL, @@ -74,6 +76,7 @@ static struct poptOption long_options[] = { {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0}, {"tracepoint", 0, POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0}, {"probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, 0, 0}, + {"uprobe", 0, POPT_ARG_STRING, &opt_uprobe, OPT_UPROBE, 0, 0}, {"function", 0, POPT_ARG_STRING, &opt_function, OPT_FUNCTION, 0, 0}, #if 0 /* @@ -117,6 +120,10 @@ static void usage(FILE *ofp) fprintf(ofp, " Dynamic probe.\n"); fprintf(ofp, " Addr and offset can be octal (0NNN...),\n"); fprintf(ofp, " decimal (NNN...) or hexadecimal (0xNNN...)\n"); + fprintf(ofp, " --uprobe [path+offset]\n"); + fprintf(ofp, " Dynamic uprobe.\n"); + fprintf(ofp, " offset can be octal (0NNN...),\n"); + fprintf(ofp, " decimal (NNN...) or hexadecimal (0xNNN...)\n"); fprintf(ofp, " --function [addr | symbol | symbol+offset]\n"); fprintf(ofp, " Dynamic function entry/return probe.\n"); fprintf(ofp, " Addr and offset can be octal (0NNN...),\n"); @@ -245,6 +252,42 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) end: return ret; } +/* + * Parse uprobe options. + */ +static int parse_uprobe_opts(struct lttng_event *ev, char *opt) +{ + int ret; + char s_hex[19]; + char name[LTTNG_SYMBOL_NAME_LEN]; + + if (opt == NULL) { + ret = -1; + goto end; + } + + /* Check for path+offset */ + ret = sscanf(opt, "%[^'+']+%s", name, s_hex); + if (ret == 2) { + strncpy(ev->attr.uprobe.path, name, LTTNG_SYMBOL_NAME_LEN); + ev->attr.uprobe.path[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + DBG("probe path %s", ev->attr.uprobe.path); + if (strlen(s_hex) == 0) { + ERR("Invalid uprobe offset %s", s_hex); + ret = -1; + goto end; + } + ev->attr.uprobe.offset = strtoul(s_hex, NULL, 0); + DBG("uprobe offset %" PRIu64, ev->attr.uprobe.offset); + goto end; + } + + /* No match */ + ret = -1; + +end: + return ret; +} /* * Maps loglevel from string to value @@ -471,6 +514,14 @@ static int enable_events(char *session_name) goto error; } break; + case LTTNG_EVENT_UPROBE: + ret = parse_uprobe_opts(&ev, opt_uprobe); + if (ret < 0) { + ERR("Unable to parse uprobe options"); + ret = 0; + goto error; + } + break; case LTTNG_EVENT_FUNCTION: ret = parse_probe_opts(&ev, opt_function); if (ret < 0) { @@ -522,6 +573,7 @@ static int enable_events(char *session_name) ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_PROBE: + case LTTNG_EVENT_UPROBE: case LTTNG_EVENT_FUNCTION: case LTTNG_EVENT_FUNCTION_ENTRY: case LTTNG_EVENT_SYSCALL: @@ -636,6 +688,9 @@ int cmd_enable_events(int argc, const char **argv) case OPT_PROBE: opt_event_type = LTTNG_EVENT_PROBE; break; + case OPT_UPROBE: + opt_event_type = LTTNG_EVENT_UPROBE; + break; case OPT_FUNCTION: opt_event_type = LTTNG_EVENT_FUNCTION; break; diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index a6ea6b8..ffae239 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -231,6 +231,14 @@ static void print_events(struct lttng_event *event) MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name); } break; + case LTTNG_EVENT_UPROBE: + MSG("%s%s (type: uprobe)%s%s", indent6, + event->name, enabled_string(event->enabled), + filter_string(event->filter)); + + MSG("%spath: %s", indent8, event->attr.uprobe.path); + MSG("%soffset: 0x%" PRIx64, indent8, event->attr.uprobe.offset); + break; case LTTNG_EVENT_FUNCTION: case LTTNG_EVENT_FUNCTION_ENTRY: MSG("%s%s (type: function)%s%s", indent6, diff --git a/src/common/lttng-kernel.h b/src/common/lttng-kernel.h index fa8ba61..a43b956 100644 --- a/src/common/lttng-kernel.h +++ b/src/common/lttng-kernel.h @@ -38,6 +38,7 @@ enum lttng_kernel_instrumentation { LTTNG_KERNEL_KRETPROBE = 3, LTTNG_KERNEL_NOOP = 4, /* not hooked */ LTTNG_KERNEL_SYSCALL = 5, + LTTNG_KERNEL_UPROBE = 6, }; enum lttng_kernel_context_type { @@ -96,6 +97,11 @@ struct lttng_kernel_function { char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN]; }__attribute__((packed)); +struct lttng_kernel_uprobe { + char path[LTTNG_KERNEL_SYM_NAME_LEN]; + uint64_t offset; +}__attribute__((packed)); + #define LTTNG_KERNEL_EVENT_PADDING1 16 #define LTTNG_KERNEL_EVENT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32 struct lttng_kernel_event { @@ -108,6 +114,7 @@ struct lttng_kernel_event { struct lttng_kernel_kretprobe kretprobe; struct lttng_kernel_kprobe kprobe; struct lttng_kernel_function ftrace; + struct lttng_kernel_uprobe uprobe; char padding[LTTNG_KERNEL_EVENT_PADDING2]; } u; }__attribute__((packed)); -- 1.7.10.4 _______________________________________________ lttng-dev mailing list [email protected] http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
