* Yannick Brosseau ([email protected]) wrote: > 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)
Asking Masami and looking at perf might help us add support for lookup by file/lineno (using dwarf info). I think in terms of usability this is really important, and should appear in tools at the same time as the basic feature based on file/offset (or at least appear in the same LTTng release). We should keep in mind that liblttng-ctl is LGPLv2.1, so we cannot use perf code as-is without asking for the author's permission first. Nothing prevents us from writing this support ourself if need be though. Thanks, Mathieu > > 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 -- Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com _______________________________________________ lttng-dev mailing list [email protected] http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
