linux/kernel/trace/trace_uprobe.c
<<
>>
Prefs
   1/*
   2 * uprobes-based tracing events
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software
  15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  16 *
  17 * Copyright (C) IBM Corporation, 2010-2012
  18 * Author:      Srikar Dronamraju <srikar@linux.vnet.ibm.com>
  19 */
  20
  21#include <linux/module.h>
  22#include <linux/uaccess.h>
  23#include <linux/uprobes.h>
  24#include <linux/namei.h>
  25
  26#include "trace_probe.h"
  27
  28#define UPROBE_EVENT_SYSTEM     "uprobes"
  29
  30/*
  31 * uprobe event core functions
  32 */
  33struct trace_uprobe;
  34struct uprobe_trace_consumer {
  35        struct uprobe_consumer          cons;
  36        struct trace_uprobe             *tu;
  37};
  38
  39struct trace_uprobe {
  40        struct list_head                list;
  41        struct ftrace_event_class       class;
  42        struct ftrace_event_call        call;
  43        struct uprobe_trace_consumer    *consumer;
  44        struct inode                    *inode;
  45        char                            *filename;
  46        unsigned long                   offset;
  47        unsigned long                   nhit;
  48        unsigned int                    flags;  /* For TP_FLAG_* */
  49        ssize_t                         size;   /* trace entry size */
  50        unsigned int                    nr_args;
  51        struct probe_arg                args[];
  52};
  53
  54#define SIZEOF_TRACE_UPROBE(n)                  \
  55        (offsetof(struct trace_uprobe, args) +  \
  56        (sizeof(struct probe_arg) * (n)))
  57
  58static int register_uprobe_event(struct trace_uprobe *tu);
  59static void unregister_uprobe_event(struct trace_uprobe *tu);
  60
  61static DEFINE_MUTEX(uprobe_lock);
  62static LIST_HEAD(uprobe_list);
  63
  64static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
  65
  66/*
  67 * Allocate new trace_uprobe and initialize it (including uprobes).
  68 */
  69static struct trace_uprobe *
  70alloc_trace_uprobe(const char *group, const char *event, int nargs)
  71{
  72        struct trace_uprobe *tu;
  73
  74        if (!event || !is_good_name(event))
  75                return ERR_PTR(-EINVAL);
  76
  77        if (!group || !is_good_name(group))
  78                return ERR_PTR(-EINVAL);
  79
  80        tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL);
  81        if (!tu)
  82                return ERR_PTR(-ENOMEM);
  83
  84        tu->call.class = &tu->class;
  85        tu->call.name = kstrdup(event, GFP_KERNEL);
  86        if (!tu->call.name)
  87                goto error;
  88
  89        tu->class.system = kstrdup(group, GFP_KERNEL);
  90        if (!tu->class.system)
  91                goto error;
  92
  93        INIT_LIST_HEAD(&tu->list);
  94        return tu;
  95
  96error:
  97        kfree(tu->call.name);
  98        kfree(tu);
  99
 100        return ERR_PTR(-ENOMEM);
 101}
 102
 103static void free_trace_uprobe(struct trace_uprobe *tu)
 104{
 105        int i;
 106
 107        for (i = 0; i < tu->nr_args; i++)
 108                traceprobe_free_probe_arg(&tu->args[i]);
 109
 110        iput(tu->inode);
 111        kfree(tu->call.class->system);
 112        kfree(tu->call.name);
 113        kfree(tu->filename);
 114        kfree(tu);
 115}
 116
 117static struct trace_uprobe *find_probe_event(const char *event, const char *group)
 118{
 119        struct trace_uprobe *tu;
 120
 121        list_for_each_entry(tu, &uprobe_list, list)
 122                if (strcmp(tu->call.name, event) == 0 &&
 123                    strcmp(tu->call.class->system, group) == 0)
 124                        return tu;
 125
 126        return NULL;
 127}
 128
 129/* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */
 130static void unregister_trace_uprobe(struct trace_uprobe *tu)
 131{
 132        list_del(&tu->list);
 133        unregister_uprobe_event(tu);
 134        free_trace_uprobe(tu);
 135}
 136
 137/* Register a trace_uprobe and probe_event */
 138static int register_trace_uprobe(struct trace_uprobe *tu)
 139{
 140        struct trace_uprobe *old_tp;
 141        int ret;
 142
 143        mutex_lock(&uprobe_lock);
 144
 145        /* register as an event */
 146        old_tp = find_probe_event(tu->call.name, tu->call.class->system);
 147        if (old_tp)
 148                /* delete old event */
 149                unregister_trace_uprobe(old_tp);
 150
 151        ret = register_uprobe_event(tu);
 152        if (ret) {
 153                pr_warning("Failed to register probe event(%d)\n", ret);
 154                goto end;
 155        }
 156
 157        list_add_tail(&tu->list, &uprobe_list);
 158
 159end:
 160        mutex_unlock(&uprobe_lock);
 161
 162        return ret;
 163}
 164
 165/*
 166 * Argument syntax:
 167 *  - Add uprobe: p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS]
 168 *
 169 *  - Remove uprobe: -:[GRP/]EVENT
 170 */
 171static int create_trace_uprobe(int argc, char **argv)
 172{
 173        struct trace_uprobe *tu;
 174        struct inode *inode;
 175        char *arg, *event, *group, *filename;
 176        char buf[MAX_EVENT_NAME_LEN];
 177        struct path path;
 178        unsigned long offset;
 179        bool is_delete;
 180        int i, ret;
 181
 182        inode = NULL;
 183        ret = 0;
 184        is_delete = false;
 185        event = NULL;
 186        group = NULL;
 187
 188        /* argc must be >= 1 */
 189        if (argv[0][0] == '-')
 190                is_delete = true;
 191        else if (argv[0][0] != 'p') {
 192                pr_info("Probe definition must be started with 'p', 'r' or" " '-'.\n");
 193                return -EINVAL;
 194        }
 195
 196        if (argv[0][1] == ':') {
 197                event = &argv[0][2];
 198                arg = strchr(event, '/');
 199
 200                if (arg) {
 201                        group = event;
 202                        event = arg + 1;
 203                        event[-1] = '\0';
 204
 205                        if (strlen(group) == 0) {
 206                                pr_info("Group name is not specified\n");
 207                                return -EINVAL;
 208                        }
 209                }
 210                if (strlen(event) == 0) {
 211                        pr_info("Event name is not specified\n");
 212                        return -EINVAL;
 213                }
 214        }
 215        if (!group)
 216                group = UPROBE_EVENT_SYSTEM;
 217
 218        if (is_delete) {
 219                if (!event) {
 220                        pr_info("Delete command needs an event name.\n");
 221                        return -EINVAL;
 222                }
 223                mutex_lock(&uprobe_lock);
 224                tu = find_probe_event(event, group);
 225
 226                if (!tu) {
 227                        mutex_unlock(&uprobe_lock);
 228                        pr_info("Event %s/%s doesn't exist.\n", group, event);
 229                        return -ENOENT;
 230                }
 231                /* delete an event */
 232                unregister_trace_uprobe(tu);
 233                mutex_unlock(&uprobe_lock);
 234                return 0;
 235        }
 236
 237        if (argc < 2) {
 238                pr_info("Probe point is not specified.\n");
 239                return -EINVAL;
 240        }
 241        if (isdigit(argv[1][0])) {
 242                pr_info("probe point must be have a filename.\n");
 243                return -EINVAL;
 244        }
 245        arg = strchr(argv[1], ':');
 246        if (!arg)
 247                goto fail_address_parse;
 248
 249        *arg++ = '\0';
 250        filename = argv[1];
 251        ret = kern_path(filename, LOOKUP_FOLLOW, &path);
 252        if (ret)
 253                goto fail_address_parse;
 254
 255        ret = strict_strtoul(arg, 0, &offset);
 256        if (ret)
 257                goto fail_address_parse;
 258
 259        inode = igrab(path.dentry->d_inode);
 260
 261        argc -= 2;
 262        argv += 2;
 263
 264        /* setup a probe */
 265        if (!event) {
 266                char *tail = strrchr(filename, '/');
 267                char *ptr;
 268
 269                ptr = kstrdup((tail ? tail + 1 : filename), GFP_KERNEL);
 270                if (!ptr) {
 271                        ret = -ENOMEM;
 272                        goto fail_address_parse;
 273                }
 274
 275                tail = ptr;
 276                ptr = strpbrk(tail, ".-_");
 277                if (ptr)
 278                        *ptr = '\0';
 279
 280                snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail, offset);
 281                event = buf;
 282                kfree(tail);
 283        }
 284
 285        tu = alloc_trace_uprobe(group, event, argc);
 286        if (IS_ERR(tu)) {
 287                pr_info("Failed to allocate trace_uprobe.(%d)\n", (int)PTR_ERR(tu));
 288                ret = PTR_ERR(tu);
 289                goto fail_address_parse;
 290        }
 291        tu->offset = offset;
 292        tu->inode = inode;
 293        tu->filename = kstrdup(filename, GFP_KERNEL);
 294
 295        if (!tu->filename) {
 296                pr_info("Failed to allocate filename.\n");
 297                ret = -ENOMEM;
 298                goto error;
 299        }
 300
 301        /* parse arguments */
 302        ret = 0;
 303        for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
 304                /* Increment count for freeing args in error case */
 305                tu->nr_args++;
 306
 307                /* Parse argument name */
 308                arg = strchr(argv[i], '=');
 309                if (arg) {
 310                        *arg++ = '\0';
 311                        tu->args[i].name = kstrdup(argv[i], GFP_KERNEL);
 312                } else {
 313                        arg = argv[i];
 314                        /* If argument name is omitted, set "argN" */
 315                        snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1);
 316                        tu->args[i].name = kstrdup(buf, GFP_KERNEL);
 317                }
 318
 319                if (!tu->args[i].name) {
 320                        pr_info("Failed to allocate argument[%d] name.\n", i);
 321                        ret = -ENOMEM;
 322                        goto error;
 323                }
 324
 325                if (!is_good_name(tu->args[i].name)) {
 326                        pr_info("Invalid argument[%d] name: %s\n", i, tu->args[i].name);
 327                        ret = -EINVAL;
 328                        goto error;
 329                }
 330
 331                if (traceprobe_conflict_field_name(tu->args[i].name, tu->args, i)) {
 332                        pr_info("Argument[%d] name '%s' conflicts with "
 333                                "another field.\n", i, argv[i]);
 334                        ret = -EINVAL;
 335                        goto error;
 336                }
 337
 338                /* Parse fetch argument */
 339                ret = traceprobe_parse_probe_arg(arg, &tu->size, &tu->args[i], false, false);
 340                if (ret) {
 341                        pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
 342                        goto error;
 343                }
 344        }
 345
 346        ret = register_trace_uprobe(tu);
 347        if (ret)
 348                goto error;
 349        return 0;
 350
 351error:
 352        free_trace_uprobe(tu);
 353        return ret;
 354
 355fail_address_parse:
 356        if (inode)
 357                iput(inode);
 358
 359        pr_info("Failed to parse address.\n");
 360
 361        return ret;
 362}
 363
 364static void cleanup_all_probes(void)
 365{
 366        struct trace_uprobe *tu;
 367
 368        mutex_lock(&uprobe_lock);
 369        while (!list_empty(&uprobe_list)) {
 370                tu = list_entry(uprobe_list.next, struct trace_uprobe, list);
 371                unregister_trace_uprobe(tu);
 372        }
 373        mutex_unlock(&uprobe_lock);
 374}
 375
 376/* Probes listing interfaces */
 377static void *probes_seq_start(struct seq_file *m, loff_t *pos)
 378{
 379        mutex_lock(&uprobe_lock);
 380        return seq_list_start(&uprobe_list, *pos);
 381}
 382
 383static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos)
 384{
 385        return seq_list_next(v, &uprobe_list, pos);
 386}
 387
 388static void probes_seq_stop(struct seq_file *m, void *v)
 389{
 390        mutex_unlock(&uprobe_lock);
 391}
 392
 393static int probes_seq_show(struct seq_file *m, void *v)
 394{
 395        struct trace_uprobe *tu = v;
 396        int i;
 397
 398        seq_printf(m, "p:%s/%s", tu->call.class->system, tu->call.name);
 399        seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset);
 400
 401        for (i = 0; i < tu->nr_args; i++)
 402                seq_printf(m, " %s=%s", tu->args[i].name, tu->args[i].comm);
 403
 404        seq_printf(m, "\n");
 405        return 0;
 406}
 407
 408static const struct seq_operations probes_seq_op = {
 409        .start  = probes_seq_start,
 410        .next   = probes_seq_next,
 411        .stop   = probes_seq_stop,
 412        .show   = probes_seq_show
 413};
 414
 415static int probes_open(struct inode *inode, struct file *file)
 416{
 417        if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
 418                cleanup_all_probes();
 419
 420        return seq_open(file, &probes_seq_op);
 421}
 422
 423static ssize_t probes_write(struct file *file, const char __user *buffer,
 424                            size_t count, loff_t *ppos)
 425{
 426        return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe);
 427}
 428
 429static const struct file_operations uprobe_events_ops = {
 430        .owner          = THIS_MODULE,
 431        .open           = probes_open,
 432        .read           = seq_read,
 433        .llseek         = seq_lseek,
 434        .release        = seq_release,
 435        .write          = probes_write,
 436};
 437
 438/* Probes profiling interfaces */
 439static int probes_profile_seq_show(struct seq_file *m, void *v)
 440{
 441        struct trace_uprobe *tu = v;
 442
 443        seq_printf(m, "  %s %-44s %15lu\n", tu->filename, tu->call.name, tu->nhit);
 444        return 0;
 445}
 446
 447static const struct seq_operations profile_seq_op = {
 448        .start  = probes_seq_start,
 449        .next   = probes_seq_next,
 450        .stop   = probes_seq_stop,
 451        .show   = probes_profile_seq_show
 452};
 453
 454static int profile_open(struct inode *inode, struct file *file)
 455{
 456        return seq_open(file, &profile_seq_op);
 457}
 458
 459static const struct file_operations uprobe_profile_ops = {
 460        .owner          = THIS_MODULE,
 461        .open           = profile_open,
 462        .read           = seq_read,
 463        .llseek         = seq_lseek,
 464        .release        = seq_release,
 465};
 466
 467/* uprobe handler */
 468static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs)
 469{
 470        struct uprobe_trace_entry_head *entry;
 471        struct ring_buffer_event *event;
 472        struct ring_buffer *buffer;
 473        u8 *data;
 474        int size, i, pc;
 475        unsigned long irq_flags;
 476        struct ftrace_event_call *call = &tu->call;
 477
 478        tu->nhit++;
 479
 480        local_save_flags(irq_flags);
 481        pc = preempt_count();
 482
 483        size = sizeof(*entry) + tu->size;
 484
 485        event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
 486                                                  size, irq_flags, pc);
 487        if (!event)
 488                return;
 489
 490        entry = ring_buffer_event_data(event);
 491        entry->ip = uprobe_get_swbp_addr(task_pt_regs(current));
 492        data = (u8 *)&entry[1];
 493        for (i = 0; i < tu->nr_args; i++)
 494                call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset);
 495
 496        if (!filter_current_check_discard(buffer, call, entry, event))
 497                trace_buffer_unlock_commit(buffer, event, irq_flags, pc);
 498}
 499
 500/* Event entry printers */
 501static enum print_line_t
 502print_uprobe_event(struct trace_iterator *iter, int flags, struct trace_event *event)
 503{
 504        struct uprobe_trace_entry_head *field;
 505        struct trace_seq *s = &iter->seq;
 506        struct trace_uprobe *tu;
 507        u8 *data;
 508        int i;
 509
 510        field = (struct uprobe_trace_entry_head *)iter->ent;
 511        tu = container_of(event, struct trace_uprobe, call.event);
 512
 513        if (!trace_seq_printf(s, "%s: (", tu->call.name))
 514                goto partial;
 515
 516        if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
 517                goto partial;
 518
 519        if (!trace_seq_puts(s, ")"))
 520                goto partial;
 521
 522        data = (u8 *)&field[1];
 523        for (i = 0; i < tu->nr_args; i++) {
 524                if (!tu->args[i].type->print(s, tu->args[i].name,
 525                                             data + tu->args[i].offset, field))
 526                        goto partial;
 527        }
 528
 529        if (trace_seq_puts(s, "\n"))
 530                return TRACE_TYPE_HANDLED;
 531
 532partial:
 533        return TRACE_TYPE_PARTIAL_LINE;
 534}
 535
 536static int probe_event_enable(struct trace_uprobe *tu, int flag)
 537{
 538        struct uprobe_trace_consumer *utc;
 539        int ret = 0;
 540
 541        if (!tu->inode || tu->consumer)
 542                return -EINTR;
 543
 544        utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL);
 545        if (!utc)
 546                return -EINTR;
 547
 548        utc->cons.handler = uprobe_dispatcher;
 549        utc->cons.filter = NULL;
 550        ret = uprobe_register(tu->inode, tu->offset, &utc->cons);
 551        if (ret) {
 552                kfree(utc);
 553                return ret;
 554        }
 555
 556        tu->flags |= flag;
 557        utc->tu = tu;
 558        tu->consumer = utc;
 559
 560        return 0;
 561}
 562
 563static void probe_event_disable(struct trace_uprobe *tu, int flag)
 564{
 565        if (!tu->inode || !tu->consumer)
 566                return;
 567
 568        uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons);
 569        tu->flags &= ~flag;
 570        kfree(tu->consumer);
 571        tu->consumer = NULL;
 572}
 573
 574static int uprobe_event_define_fields(struct ftrace_event_call *event_call)
 575{
 576        int ret, i;
 577        struct uprobe_trace_entry_head field;
 578        struct trace_uprobe *tu = (struct trace_uprobe *)event_call->data;
 579
 580        DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
 581        /* Set argument names as fields */
 582        for (i = 0; i < tu->nr_args; i++) {
 583                ret = trace_define_field(event_call, tu->args[i].type->fmttype,
 584                                         tu->args[i].name,
 585                                         sizeof(field) + tu->args[i].offset,
 586                                         tu->args[i].type->size,
 587                                         tu->args[i].type->is_signed,
 588                                         FILTER_OTHER);
 589
 590                if (ret)
 591                        return ret;
 592        }
 593        return 0;
 594}
 595
 596#define LEN_OR_ZERO             (len ? len - pos : 0)
 597static int __set_print_fmt(struct trace_uprobe *tu, char *buf, int len)
 598{
 599        const char *fmt, *arg;
 600        int i;
 601        int pos = 0;
 602
 603        fmt = "(%lx)";
 604        arg = "REC->" FIELD_STRING_IP;
 605
 606        /* When len=0, we just calculate the needed length */
 607
 608        pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
 609
 610        for (i = 0; i < tu->nr_args; i++) {
 611                pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s",
 612                                tu->args[i].name, tu->args[i].type->fmt);
 613        }
 614
 615        pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
 616
 617        for (i = 0; i < tu->nr_args; i++) {
 618                pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s",
 619                                tu->args[i].name);
 620        }
 621
 622        return pos;     /* return the length of print_fmt */
 623}
 624#undef LEN_OR_ZERO
 625
 626static int set_print_fmt(struct trace_uprobe *tu)
 627{
 628        char *print_fmt;
 629        int len;
 630
 631        /* First: called with 0 length to calculate the needed length */
 632        len = __set_print_fmt(tu, NULL, 0);
 633        print_fmt = kmalloc(len + 1, GFP_KERNEL);
 634        if (!print_fmt)
 635                return -ENOMEM;
 636
 637        /* Second: actually write the @print_fmt */
 638        __set_print_fmt(tu, print_fmt, len + 1);
 639        tu->call.print_fmt = print_fmt;
 640
 641        return 0;
 642}
 643
 644#ifdef CONFIG_PERF_EVENTS
 645/* uprobe profile handler */
 646static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
 647{
 648        struct ftrace_event_call *call = &tu->call;
 649        struct uprobe_trace_entry_head *entry;
 650        struct hlist_head *head;
 651        u8 *data;
 652        int size, __size, i;
 653        int rctx;
 654
 655        __size = sizeof(*entry) + tu->size;
 656        size = ALIGN(__size + sizeof(u32), sizeof(u64));
 657        size -= sizeof(u32);
 658        if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
 659                return;
 660
 661        preempt_disable();
 662
 663        entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
 664        if (!entry)
 665                goto out;
 666
 667        entry->ip = uprobe_get_swbp_addr(task_pt_regs(current));
 668        data = (u8 *)&entry[1];
 669        for (i = 0; i < tu->nr_args; i++)
 670                call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset);
 671
 672        head = this_cpu_ptr(call->perf_events);
 673        perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head, NULL);
 674
 675 out:
 676        preempt_enable();
 677}
 678#endif  /* CONFIG_PERF_EVENTS */
 679
 680static
 681int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data)
 682{
 683        struct trace_uprobe *tu = (struct trace_uprobe *)event->data;
 684
 685        switch (type) {
 686        case TRACE_REG_REGISTER:
 687                return probe_event_enable(tu, TP_FLAG_TRACE);
 688
 689        case TRACE_REG_UNREGISTER:
 690                probe_event_disable(tu, TP_FLAG_TRACE);
 691                return 0;
 692
 693#ifdef CONFIG_PERF_EVENTS
 694        case TRACE_REG_PERF_REGISTER:
 695                return probe_event_enable(tu, TP_FLAG_PROFILE);
 696
 697        case TRACE_REG_PERF_UNREGISTER:
 698                probe_event_disable(tu, TP_FLAG_PROFILE);
 699                return 0;
 700#endif
 701        default:
 702                return 0;
 703        }
 704        return 0;
 705}
 706
 707static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
 708{
 709        struct uprobe_trace_consumer *utc;
 710        struct trace_uprobe *tu;
 711
 712        utc = container_of(con, struct uprobe_trace_consumer, cons);
 713        tu = utc->tu;
 714        if (!tu || tu->consumer != utc)
 715                return 0;
 716
 717        if (tu->flags & TP_FLAG_TRACE)
 718                uprobe_trace_func(tu, regs);
 719
 720#ifdef CONFIG_PERF_EVENTS
 721        if (tu->flags & TP_FLAG_PROFILE)
 722                uprobe_perf_func(tu, regs);
 723#endif
 724        return 0;
 725}
 726
 727static struct trace_event_functions uprobe_funcs = {
 728        .trace          = print_uprobe_event
 729};
 730
 731static int register_uprobe_event(struct trace_uprobe *tu)
 732{
 733        struct ftrace_event_call *call = &tu->call;
 734        int ret;
 735
 736        /* Initialize ftrace_event_call */
 737        INIT_LIST_HEAD(&call->class->fields);
 738        call->event.funcs = &uprobe_funcs;
 739        call->class->define_fields = uprobe_event_define_fields;
 740
 741        if (set_print_fmt(tu) < 0)
 742                return -ENOMEM;
 743
 744        ret = register_ftrace_event(&call->event);
 745        if (!ret) {
 746                kfree(call->print_fmt);
 747                return -ENODEV;
 748        }
 749        call->flags = 0;
 750        call->class->reg = trace_uprobe_register;
 751        call->data = tu;
 752        ret = trace_add_event_call(call);
 753
 754        if (ret) {
 755                pr_info("Failed to register uprobe event: %s\n", call->name);
 756                kfree(call->print_fmt);
 757                unregister_ftrace_event(&call->event);
 758        }
 759
 760        return ret;
 761}
 762
 763static void unregister_uprobe_event(struct trace_uprobe *tu)
 764{
 765        /* tu->event is unregistered in trace_remove_event_call() */
 766        trace_remove_event_call(&tu->call);
 767        kfree(tu->call.print_fmt);
 768        tu->call.print_fmt = NULL;
 769}
 770
 771/* Make a trace interface for controling probe points */
 772static __init int init_uprobe_trace(void)
 773{
 774        struct dentry *d_tracer;
 775
 776        d_tracer = tracing_init_dentry();
 777        if (!d_tracer)
 778                return 0;
 779
 780        trace_create_file("uprobe_events", 0644, d_tracer,
 781                                    NULL, &uprobe_events_ops);
 782        /* Profile interface */
 783        trace_create_file("uprobe_profile", 0444, d_tracer,
 784                                    NULL, &uprobe_profile_ops);
 785        return 0;
 786}
 787
 788fs_initcall(init_uprobe_trace);
 789
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.