lkml.org 
[lkml]   [2010]   [May]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH v2 11/11] Uprobes traceevents patch.
    On Wed, Mar 31, 2010 at 09:23:11PM +0530, Srikar Dronamraju wrote:
    > Uprobes Trace_events interface
    >
    > The following patch implements trace_event support for uprobes. In its
    > current form it can be used to put probes at a specified text address
    > in a process and dump the required registers when the code flow reaches
    > the probed address.
    >
    > This is based on trace_events for kprobes to the extent that it may
    > resemble that file on 2.6.34-rc3.
    >
    > The following example shows how to dump the instruction pointer and %ax a
    > register at the probed text address.
    >
    > Start a process to trace. Get the address to trace.
    > [Here pid is asssumed as 3548]
    > [Address to trace is 0x0000000000446420]
    > [Registers to be dumped are %ip and %ax]
    >
    > # cd /sys/kernel/debug/tracing/
    > # echo 'p 3548:0x0000000000446420 %ip %ax' > uprobe_events
    > # cat uprobe_events
    > p:uprobes/p_3548_0x0000000000446420 3548:0x0000000000446420 %ip=%ip %ax=%ax
    > # cat events/uprobes/p_3548_0x0000000000446420/enable
    > 0
    > [enable the event]
    > # echo 1 > events/uprobes/p_3548_0x0000000000446420/enable
    > # cat events/uprobes/p_3548_0x0000000000446420/enable
    > 1
    > # #### do some activity on the program so that it hits the breakpoint
    > # cat uprobe_profile
    > 3548 p_3548_0x0000000000446420 234
    > # head trace
    > # tracer: nop
    > #
    > # TASK-PID CPU# TIMESTAMP FUNCTION
    > # | | | | |
    > zsh-3548 [001] 294.285812: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
    > zsh-3548 [001] 294.285884: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
    > zsh-3548 [001] 294.285894: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
    > zsh-3548 [001] 294.285903: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
    > zsh-3548 [001] 294.285912: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
    > zsh-3548 [001] 294.285922: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
    >
    > TODO: Documentation/trace/uprobetrace.txt
    >
    > Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
    > ---
    >
    > kernel/trace/Kconfig | 8
    > kernel/trace/Makefile | 1
    > kernel/trace/trace.h | 12 +
    > kernel/trace/trace_uprobe.c | 926 +++++++++++++++++++++++++++++++++++++++++++
    > 4 files changed, 947 insertions(+), 0 deletions(-)
    > create mode 100644 kernel/trace/trace_uprobe.c
    >
    >
    > diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
    > index 13e13d4..1435e09 100644
    > --- a/kernel/trace/Kconfig
    > +++ b/kernel/trace/Kconfig
    > @@ -557,6 +557,14 @@ config RING_BUFFER_BENCHMARK
    >
    > If unsure, say N.
    >
    > +config UPROBE_EVENT
    > + depends on UPROBES
    > + bool "Enable uprobes-based dynamic events"
    > + select TRACING
    > + default y
    > + help
    > + This allows the user to add tracing events (similar to tracepoints)
    > + on the fly via the traceevents interface.



    That doesn't explain much what it does. Please explain its goal of
    creating a trace event on top of a userspace dynamic probe.



    > +#define MAX_TRACE_ARGS 128
    > +#define MAX_ARGSTR_LEN 63
    > +#define MAX_EVENT_NAME_LEN 64


    This can be shared with kprobes in a new kernel/trace/dyn_probes.h
    or something.




    > +const char *ureserved_field_names[] = {
    > + "common_type",
    > + "common_flags",
    > + "common_preempt_count",
    > + "common_pid",
    > + "common_tgid",
    > + "common_lock_depth",


    Same here.



    > +/* Register a trace_uprobe and probe_event */
    > +static int register_trace_uprobe(struct trace_uprobe *tp)
    > +{
    > + struct trace_uprobe *old_tp;
    > + int ret;
    > +
    > + mutex_lock(&uprobe_lock);
    > +
    > + /* register as an event */
    > + old_tp = find_probe_event(tp->call.name, tp->call.system);
    > + if (old_tp) {
    > + /* delete old event */
    > + unregister_trace_uprobe(old_tp);
    > + free_trace_uprobe(old_tp);
    > + }
    > + ret = register_uprobe_event(tp);
    > + if (ret) {
    > + pr_warning("Faild to register probe event(%d)\n", ret);


    "Failed"


    > +static int create_trace_uprobe(int argc, char **argv)
    > +{
    > + /*
    > + * Argument syntax:
    > + * - Add uprobe: p[:[GRP/]EVENT] VADDR@PID [%REG]
    > + *
    > + * - Remove uprobe: -:[GRP/]EVENT
    > + */
    > + struct trace_uprobe *tp;
    > + int i, ret = 0;
    > + int is_delete = 0;
    > + char *arg = NULL, *event = NULL, *group = NULL;
    > + void *addr = NULL;
    > + pid_t pid = 0;
    > + char buf[MAX_EVENT_NAME_LEN];
    > +
    > + /* argc must be >= 1 */
    > + if (argv[0][0] == '-')
    > + is_delete = 1;
    > + else if (argv[0][0] != 'p') {
    > + pr_info("Probe definition must be started with 'p', 'r' or"
    > + " '-'.\n");
    > + return -EINVAL;
    > + }
    > +
    > + if (argv[0][1] == ':') {
    > + event = &argv[0][2];
    > + if (strchr(event, '/')) {
    > + group = event;
    > + event = strchr(group, '/') + 1;
    > + event[-1] = '\0';
    > + if (strlen(group) == 0) {
    > + pr_info("Group name is not specified\n");
    > + return -EINVAL;
    > + }
    > + }
    > + if (strlen(event) == 0) {
    > + pr_info("Event name is not specified\n");
    > + return -EINVAL;
    > + }
    > + }
    > + if (!group)
    > + group = UPROBE_EVENT_SYSTEM;
    > +
    > + if (is_delete) {
    > + if (!event) {
    > + pr_info("Delete command needs an event name.\n");
    > + return -EINVAL;
    > + }
    > + tp = find_probe_event(event, group);
    > + if (!tp) {
    > + pr_info("Event %s/%s doesn't exist.\n", group, event);
    > + return -ENOENT;
    > + }
    > + /* delete an event */
    > + unregister_trace_uprobe(tp);



    Doesn't seem to be under uprobe_lock.



    > +/* Make a debugfs interface for controling probe points */
    > +static __init int init_uprobe_trace(void)
    > +{
    > + struct dentry *d_tracer;
    > + struct dentry *entry;
    > +
    > + d_tracer = tracing_init_dentry();
    > + if (!d_tracer)
    > + return 0;
    > +
    > + entry = debugfs_create_file("uprobe_events", 0644, d_tracer,
    > + NULL, &uprobe_events_ops);
    > +
    > + /* Event list interface */
    > + if (!entry)
    > + pr_warning("Could not create debugfs "
    > + "'uprobe_events' entry\n");



    You can use trace_create_file I think.



    > +
    > + /* Profile interface */
    > + entry = debugfs_create_file("uprobe_profile", 0444, d_tracer,
    > + NULL, &uprobe_profile_ops);
    > +
    > + if (!entry)
    > + pr_warning("Could not create debugfs "
    > + "'uprobe_profile' entry\n");
    > + return 0;
    > +}
    > +fs_initcall(init_uprobe_trace);



    Thanks.



    \
     
     \ /
      Last update: 2010-05-12 13:05    [W:0.068 / U:0.196 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site