linux/kernel/trace/trace_probe.c
<<
>>
Prefs
   1/*
   2 * Common code for probe-based Dynamic 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 * This code was copied from kernel/trace/trace_kprobe.c written by
  18 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
  19 *
  20 * Updates to make this generic:
  21 * Copyright (C) IBM Corporation, 2010-2011
  22 * Author:     Srikar Dronamraju
  23 */
  24
  25#include "trace_probe.h"
  26
  27const char *reserved_field_names[] = {
  28        "common_type",
  29        "common_flags",
  30        "common_preempt_count",
  31        "common_pid",
  32        "common_tgid",
  33        FIELD_STRING_IP,
  34        FIELD_STRING_RETIP,
  35        FIELD_STRING_FUNC,
  36};
  37
  38/* Printing  in basic type function template */
  39#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt)                         \
  40int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, const char *name,   \
  41                                void *data, void *ent)                  \
  42{                                                                       \
  43        trace_seq_printf(s, " %s=" fmt, name, *(type *)data);           \
  44        return !trace_seq_has_overflowed(s);                            \
  45}                                                                       \
  46const char PRINT_TYPE_FMT_NAME(type)[] = fmt;                           \
  47NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(type));
  48
  49DEFINE_BASIC_PRINT_TYPE_FUNC(u8 , "0x%x")
  50DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "0x%x")
  51DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "0x%x")
  52DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "0x%Lx")
  53DEFINE_BASIC_PRINT_TYPE_FUNC(s8,  "%d")
  54DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d")
  55DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%d")
  56DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%Ld")
  57
  58/* Print type function for string type */
  59int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, const char *name,
  60                                 void *data, void *ent)
  61{
  62        int len = *(u32 *)data >> 16;
  63
  64        if (!len)
  65                trace_seq_printf(s, " %s=(fault)", name);
  66        else
  67                trace_seq_printf(s, " %s=\"%s\"", name,
  68                                 (const char *)get_loc_data(data, ent));
  69        return !trace_seq_has_overflowed(s);
  70}
  71NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(string));
  72
  73const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\"";
  74
  75#define CHECK_FETCH_FUNCS(method, fn)                   \
  76        (((FETCH_FUNC_NAME(method, u8) == fn) ||        \
  77          (FETCH_FUNC_NAME(method, u16) == fn) ||       \
  78          (FETCH_FUNC_NAME(method, u32) == fn) ||       \
  79          (FETCH_FUNC_NAME(method, u64) == fn) ||       \
  80          (FETCH_FUNC_NAME(method, string) == fn) ||    \
  81          (FETCH_FUNC_NAME(method, string_size) == fn)) \
  82         && (fn != NULL))
  83
  84/* Data fetch function templates */
  85#define DEFINE_FETCH_reg(type)                                          \
  86void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, void *offset, void *dest) \
  87{                                                                       \
  88        *(type *)dest = (type)regs_get_register(regs,                   \
  89                                (unsigned int)((unsigned long)offset)); \
  90}                                                                       \
  91NOKPROBE_SYMBOL(FETCH_FUNC_NAME(reg, type));
  92DEFINE_BASIC_FETCH_FUNCS(reg)
  93/* No string on the register */
  94#define fetch_reg_string        NULL
  95#define fetch_reg_string_size   NULL
  96
  97#define DEFINE_FETCH_retval(type)                                       \
  98void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,                \
  99                                   void *dummy, void *dest)             \
 100{                                                                       \
 101        *(type *)dest = (type)regs_return_value(regs);                  \
 102}                                                                       \
 103NOKPROBE_SYMBOL(FETCH_FUNC_NAME(retval, type));
 104DEFINE_BASIC_FETCH_FUNCS(retval)
 105/* No string on the retval */
 106#define fetch_retval_string             NULL
 107#define fetch_retval_string_size        NULL
 108
 109/* Dereference memory access function */
 110struct deref_fetch_param {
 111        struct fetch_param      orig;
 112        long                    offset;
 113        fetch_func_t            fetch;
 114        fetch_func_t            fetch_size;
 115};
 116
 117#define DEFINE_FETCH_deref(type)                                        \
 118void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,                 \
 119                                  void *data, void *dest)               \
 120{                                                                       \
 121        struct deref_fetch_param *dprm = data;                          \
 122        unsigned long addr;                                             \
 123        call_fetch(&dprm->orig, regs, &addr);                           \
 124        if (addr) {                                                     \
 125                addr += dprm->offset;                                   \
 126                dprm->fetch(regs, (void *)addr, dest);                  \
 127        } else                                                          \
 128                *(type *)dest = 0;                                      \
 129}                                                                       \
 130NOKPROBE_SYMBOL(FETCH_FUNC_NAME(deref, type));
 131DEFINE_BASIC_FETCH_FUNCS(deref)
 132DEFINE_FETCH_deref(string)
 133
 134void FETCH_FUNC_NAME(deref, string_size)(struct pt_regs *regs,
 135                                         void *data, void *dest)
 136{
 137        struct deref_fetch_param *dprm = data;
 138        unsigned long addr;
 139
 140        call_fetch(&dprm->orig, regs, &addr);
 141        if (addr && dprm->fetch_size) {
 142                addr += dprm->offset;
 143                dprm->fetch_size(regs, (void *)addr, dest);
 144        } else
 145                *(string_size *)dest = 0;
 146}
 147NOKPROBE_SYMBOL(FETCH_FUNC_NAME(deref, string_size));
 148
 149static void update_deref_fetch_param(struct deref_fetch_param *data)
 150{
 151        if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
 152                update_deref_fetch_param(data->orig.data);
 153        else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
 154                update_symbol_cache(data->orig.data);
 155}
 156NOKPROBE_SYMBOL(update_deref_fetch_param);
 157
 158static void free_deref_fetch_param(struct deref_fetch_param *data)
 159{
 160        if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
 161                free_deref_fetch_param(data->orig.data);
 162        else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
 163                free_symbol_cache(data->orig.data);
 164        kfree(data);
 165}
 166NOKPROBE_SYMBOL(free_deref_fetch_param);
 167
 168/* Bitfield fetch function */
 169struct bitfield_fetch_param {
 170        struct fetch_param      orig;
 171        unsigned char           hi_shift;
 172        unsigned char           low_shift;
 173};
 174
 175#define DEFINE_FETCH_bitfield(type)                                     \
 176void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,              \
 177                                     void *data, void *dest)            \
 178{                                                                       \
 179        struct bitfield_fetch_param *bprm = data;                       \
 180        type buf = 0;                                                   \
 181        call_fetch(&bprm->orig, regs, &buf);                            \
 182        if (buf) {                                                      \
 183                buf <<= bprm->hi_shift;                                 \
 184                buf >>= bprm->low_shift;                                \
 185        }                                                               \
 186        *(type *)dest = buf;                                            \
 187}                                                                       \
 188NOKPROBE_SYMBOL(FETCH_FUNC_NAME(bitfield, type));
 189DEFINE_BASIC_FETCH_FUNCS(bitfield)
 190#define fetch_bitfield_string           NULL
 191#define fetch_bitfield_string_size      NULL
 192
 193static void
 194update_bitfield_fetch_param(struct bitfield_fetch_param *data)
 195{
 196        /*
 197         * Don't check the bitfield itself, because this must be the
 198         * last fetch function.
 199         */
 200        if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
 201                update_deref_fetch_param(data->orig.data);
 202        else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
 203                update_symbol_cache(data->orig.data);
 204}
 205
 206static void
 207free_bitfield_fetch_param(struct bitfield_fetch_param *data)
 208{
 209        /*
 210         * Don't check the bitfield itself, because this must be the
 211         * last fetch function.
 212         */
 213        if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
 214                free_deref_fetch_param(data->orig.data);
 215        else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
 216                free_symbol_cache(data->orig.data);
 217
 218        kfree(data);
 219}
 220
 221static const struct fetch_type *find_fetch_type(const char *type,
 222                                                const struct fetch_type *ftbl)
 223{
 224        int i;
 225
 226        if (!type)
 227                type = DEFAULT_FETCH_TYPE_STR;
 228
 229        /* Special case: bitfield */
 230        if (*type == 'b') {
 231                unsigned long bs;
 232
 233                type = strchr(type, '/');
 234                if (!type)
 235                        goto fail;
 236
 237                type++;
 238                if (kstrtoul(type, 0, &bs))
 239                        goto fail;
 240
 241                switch (bs) {
 242                case 8:
 243                        return find_fetch_type("u8", ftbl);
 244                case 16:
 245                        return find_fetch_type("u16", ftbl);
 246                case 32:
 247                        return find_fetch_type("u32", ftbl);
 248                case 64:
 249                        return find_fetch_type("u64", ftbl);
 250                default:
 251                        goto fail;
 252                }
 253        }
 254
 255        for (i = 0; ftbl[i].name; i++) {
 256                if (strcmp(type, ftbl[i].name) == 0)
 257                        return &ftbl[i];
 258        }
 259
 260fail:
 261        return NULL;
 262}
 263
 264/* Special function : only accept unsigned long */
 265static void fetch_kernel_stack_address(struct pt_regs *regs, void *dummy, void *dest)
 266{
 267        *(unsigned long *)dest = kernel_stack_pointer(regs);
 268}
 269NOKPROBE_SYMBOL(fetch_kernel_stack_address);
 270
 271static void fetch_user_stack_address(struct pt_regs *regs, void *dummy, void *dest)
 272{
 273        *(unsigned long *)dest = user_stack_pointer(regs);
 274}
 275NOKPROBE_SYMBOL(fetch_user_stack_address);
 276
 277static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
 278                                            fetch_func_t orig_fn,
 279                                            const struct fetch_type *ftbl)
 280{
 281        int i;
 282
 283        if (type != &ftbl[FETCH_TYPE_STRING])
 284                return NULL;    /* Only string type needs size function */
 285
 286        for (i = 0; i < FETCH_MTD_END; i++)
 287                if (type->fetch[i] == orig_fn)
 288                        return ftbl[FETCH_TYPE_STRSIZE].fetch[i];
 289
 290        WARN_ON(1);     /* This should not happen */
 291
 292        return NULL;
 293}
 294
 295/* Split symbol and offset. */
 296int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset)
 297{
 298        char *tmp;
 299        int ret;
 300
 301        if (!offset)
 302                return -EINVAL;
 303
 304        tmp = strchr(symbol, '+');
 305        if (tmp) {
 306                /* skip sign because kstrtoul doesn't accept '+' */
 307                ret = kstrtoul(tmp + 1, 0, offset);
 308                if (ret)
 309                        return ret;
 310
 311                *tmp = '\0';
 312        } else
 313                *offset = 0;
 314
 315        return 0;
 316}
 317
 318#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
 319
 320static int parse_probe_vars(char *arg, const struct fetch_type *t,
 321                            struct fetch_param *f, bool is_return,
 322                            bool is_kprobe)
 323{
 324        int ret = 0;
 325        unsigned long param;
 326
 327        if (strcmp(arg, "retval") == 0) {
 328                if (is_return)
 329                        f->fn = t->fetch[FETCH_MTD_retval];
 330                else
 331                        ret = -EINVAL;
 332        } else if (strncmp(arg, "stack", 5) == 0) {
 333                if (arg[5] == '\0') {
 334                        if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR))
 335                                return -EINVAL;
 336
 337                        if (is_kprobe)
 338                                f->fn = fetch_kernel_stack_address;
 339                        else
 340                                f->fn = fetch_user_stack_address;
 341                } else if (isdigit(arg[5])) {
 342                        ret = kstrtoul(arg + 5, 10, &param);
 343                        if (ret || (is_kprobe && param > PARAM_MAX_STACK))
 344                                ret = -EINVAL;
 345                        else {
 346                                f->fn = t->fetch[FETCH_MTD_stack];
 347                                f->data = (void *)param;
 348                        }
 349                } else
 350                        ret = -EINVAL;
 351        } else
 352                ret = -EINVAL;
 353
 354        return ret;
 355}
 356
 357/* Recursive argument parser */
 358static int parse_probe_arg(char *arg, const struct fetch_type *t,
 359                     struct fetch_param *f, bool is_return, bool is_kprobe,
 360                     const struct fetch_type *ftbl)
 361{
 362        unsigned long param;
 363        long offset;
 364        char *tmp;
 365        int ret = 0;
 366
 367        switch (arg[0]) {
 368        case '$':
 369                ret = parse_probe_vars(arg + 1, t, f, is_return, is_kprobe);
 370                break;
 371
 372        case '%':       /* named register */
 373                ret = regs_query_register_offset(arg + 1);
 374                if (ret >= 0) {
 375                        f->fn = t->fetch[FETCH_MTD_reg];
 376                        f->data = (void *)(unsigned long)ret;
 377                        ret = 0;
 378                }
 379                break;
 380
 381        case '@':       /* memory, file-offset or symbol */
 382                if (isdigit(arg[1])) {
 383                        ret = kstrtoul(arg + 1, 0, &param);
 384                        if (ret)
 385                                break;
 386
 387                        f->fn = t->fetch[FETCH_MTD_memory];
 388                        f->data = (void *)param;
 389                } else if (arg[1] == '+') {
 390                        /* kprobes don't support file offsets */
 391                        if (is_kprobe)
 392                                return -EINVAL;
 393
 394                        ret = kstrtol(arg + 2, 0, &offset);
 395                        if (ret)
 396                                break;
 397
 398                        f->fn = t->fetch[FETCH_MTD_file_offset];
 399                        f->data = (void *)offset;
 400                } else {
 401                        /* uprobes don't support symbols */
 402                        if (!is_kprobe)
 403                                return -EINVAL;
 404
 405                        ret = traceprobe_split_symbol_offset(arg + 1, &offset);
 406                        if (ret)
 407                                break;
 408
 409                        f->data = alloc_symbol_cache(arg + 1, offset);
 410                        if (f->data)
 411                                f->fn = t->fetch[FETCH_MTD_symbol];
 412                }
 413                break;
 414
 415        case '+':       /* deref memory */
 416                arg++;  /* Skip '+', because kstrtol() rejects it. */
 417        case '-':
 418                tmp = strchr(arg, '(');
 419                if (!tmp)
 420                        break;
 421
 422                *tmp = '\0';
 423                ret = kstrtol(arg, 0, &offset);
 424
 425                if (ret)
 426                        break;
 427
 428                arg = tmp + 1;
 429                tmp = strrchr(arg, ')');
 430
 431                if (tmp) {
 432                        struct deref_fetch_param        *dprm;
 433                        const struct fetch_type         *t2;
 434
 435                        t2 = find_fetch_type(NULL, ftbl);
 436                        *tmp = '\0';
 437                        dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL);
 438
 439                        if (!dprm)
 440                                return -ENOMEM;
 441
 442                        dprm->offset = offset;
 443                        dprm->fetch = t->fetch[FETCH_MTD_memory];
 444                        dprm->fetch_size = get_fetch_size_function(t,
 445                                                        dprm->fetch, ftbl);
 446                        ret = parse_probe_arg(arg, t2, &dprm->orig, is_return,
 447                                                        is_kprobe, ftbl);
 448                        if (ret)
 449                                kfree(dprm);
 450                        else {
 451                                f->fn = t->fetch[FETCH_MTD_deref];
 452                                f->data = (void *)dprm;
 453                        }
 454                }
 455                break;
 456        }
 457        if (!ret && !f->fn) {   /* Parsed, but do not find fetch method */
 458                pr_info("%s type has no corresponding fetch method.\n", t->name);
 459                ret = -EINVAL;
 460        }
 461
 462        return ret;
 463}
 464
 465#define BYTES_TO_BITS(nb)       ((BITS_PER_LONG * (nb)) / sizeof(long))
 466
 467/* Bitfield type needs to be parsed into a fetch function */
 468static int __parse_bitfield_probe_arg(const char *bf,
 469                                      const struct fetch_type *t,
 470                                      struct fetch_param *f)
 471{
 472        struct bitfield_fetch_param *bprm;
 473        unsigned long bw, bo;
 474        char *tail;
 475
 476        if (*bf != 'b')
 477                return 0;
 478
 479        bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
 480        if (!bprm)
 481                return -ENOMEM;
 482
 483        bprm->orig = *f;
 484        f->fn = t->fetch[FETCH_MTD_bitfield];
 485        f->data = (void *)bprm;
 486        bw = simple_strtoul(bf + 1, &tail, 0);  /* Use simple one */
 487
 488        if (bw == 0 || *tail != '@')
 489                return -EINVAL;
 490
 491        bf = tail + 1;
 492        bo = simple_strtoul(bf, &tail, 0);
 493
 494        if (tail == bf || *tail != '/')
 495                return -EINVAL;
 496
 497        bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo);
 498        bprm->low_shift = bprm->hi_shift + bo;
 499
 500        return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
 501}
 502
 503/* String length checking wrapper */
 504int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
 505                struct probe_arg *parg, bool is_return, bool is_kprobe,
 506                const struct fetch_type *ftbl)
 507{
 508        const char *t;
 509        int ret;
 510
 511        if (strlen(arg) > MAX_ARGSTR_LEN) {
 512                pr_info("Argument is too long.: %s\n",  arg);
 513                return -ENOSPC;
 514        }
 515        parg->comm = kstrdup(arg, GFP_KERNEL);
 516        if (!parg->comm) {
 517                pr_info("Failed to allocate memory for command '%s'.\n", arg);
 518                return -ENOMEM;
 519        }
 520        t = strchr(parg->comm, ':');
 521        if (t) {
 522                arg[t - parg->comm] = '\0';
 523                t++;
 524        }
 525        parg->type = find_fetch_type(t, ftbl);
 526        if (!parg->type) {
 527                pr_info("Unsupported type: %s\n", t);
 528                return -EINVAL;
 529        }
 530        parg->offset = *size;
 531        *size += parg->type->size;
 532        ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return,
 533                              is_kprobe, ftbl);
 534
 535        if (ret >= 0 && t != NULL)
 536                ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
 537
 538        if (ret >= 0) {
 539                parg->fetch_size.fn = get_fetch_size_function(parg->type,
 540                                                              parg->fetch.fn,
 541                                                              ftbl);
 542                parg->fetch_size.data = parg->fetch.data;
 543        }
 544
 545        return ret;
 546}
 547
 548/* Return 1 if name is reserved or already used by another argument */
 549int traceprobe_conflict_field_name(const char *name,
 550                               struct probe_arg *args, int narg)
 551{
 552        int i;
 553
 554        for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++)
 555                if (strcmp(reserved_field_names[i], name) == 0)
 556                        return 1;
 557
 558        for (i = 0; i < narg; i++)
 559                if (strcmp(args[i].name, name) == 0)
 560                        return 1;
 561
 562        return 0;
 563}
 564
 565void traceprobe_update_arg(struct probe_arg *arg)
 566{
 567        if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
 568                update_bitfield_fetch_param(arg->fetch.data);
 569        else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
 570                update_deref_fetch_param(arg->fetch.data);
 571        else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
 572                update_symbol_cache(arg->fetch.data);
 573}
 574
 575void traceprobe_free_probe_arg(struct probe_arg *arg)
 576{
 577        if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
 578                free_bitfield_fetch_param(arg->fetch.data);
 579        else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
 580                free_deref_fetch_param(arg->fetch.data);
 581        else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
 582                free_symbol_cache(arg->fetch.data);
 583
 584        kfree(arg->name);
 585        kfree(arg->comm);
 586}
 587
 588int traceprobe_command(const char *buf, int (*createfn)(int, char **))
 589{
 590        char **argv;
 591        int argc, ret;
 592
 593        argc = 0;
 594        ret = 0;
 595        argv = argv_split(GFP_KERNEL, buf, &argc);
 596        if (!argv)
 597                return -ENOMEM;
 598
 599        if (argc)
 600                ret = createfn(argc, argv);
 601
 602        argv_free(argv);
 603
 604        return ret;
 605}
 606
 607#define WRITE_BUFSIZE  4096
 608
 609ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer,
 610                                size_t count, loff_t *ppos,
 611                                int (*createfn)(int, char **))
 612{
 613        char *kbuf, *tmp;
 614        int ret = 0;
 615        size_t done = 0;
 616        size_t size;
 617
 618        kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
 619        if (!kbuf)
 620                return -ENOMEM;
 621
 622        while (done < count) {
 623                size = count - done;
 624
 625                if (size >= WRITE_BUFSIZE)
 626                        size = WRITE_BUFSIZE - 1;
 627
 628                if (copy_from_user(kbuf, buffer + done, size)) {
 629                        ret = -EFAULT;
 630                        goto out;
 631                }
 632                kbuf[size] = '\0';
 633                tmp = strchr(kbuf, '\n');
 634
 635                if (tmp) {
 636                        *tmp = '\0';
 637                        size = tmp - kbuf + 1;
 638                } else if (done + size < count) {
 639                        pr_warn("Line length is too long: Should be less than %d\n",
 640                                WRITE_BUFSIZE);
 641                        ret = -EINVAL;
 642                        goto out;
 643                }
 644                done += size;
 645                /* Remove comments */
 646                tmp = strchr(kbuf, '#');
 647
 648                if (tmp)
 649                        *tmp = '\0';
 650
 651                ret = traceprobe_command(kbuf, createfn);
 652                if (ret)
 653                        goto out;
 654        }
 655        ret = done;
 656
 657out:
 658        kfree(kbuf);
 659
 660        return ret;
 661}
 662
 663static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
 664                           bool is_return)
 665{
 666        int i;
 667        int pos = 0;
 668
 669        const char *fmt, *arg;
 670
 671        if (!is_return) {
 672                fmt = "(%lx)";
 673                arg = "REC->" FIELD_STRING_IP;
 674        } else {
 675                fmt = "(%lx <- %lx)";
 676                arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP;
 677        }
 678
 679        /* When len=0, we just calculate the needed length */
 680#define LEN_OR_ZERO (len ? len - pos : 0)
 681
 682        pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
 683
 684        for (i = 0; i < tp->nr_args; i++) {
 685                pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s",
 686                                tp->args[i].name, tp->args[i].type->fmt);
 687        }
 688
 689        pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
 690
 691        for (i = 0; i < tp->nr_args; i++) {
 692                if (strcmp(tp->args[i].type->name, "string") == 0)
 693                        pos += snprintf(buf + pos, LEN_OR_ZERO,
 694                                        ", __get_str(%s)",
 695                                        tp->args[i].name);
 696                else
 697                        pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s",
 698                                        tp->args[i].name);
 699        }
 700
 701#undef LEN_OR_ZERO
 702
 703        /* return the length of print_fmt */
 704        return pos;
 705}
 706
 707int set_print_fmt(struct trace_probe *tp, bool is_return)
 708{
 709        int len;
 710        char *print_fmt;
 711
 712        /* First: called with 0 length to calculate the needed length */
 713        len = __set_print_fmt(tp, NULL, 0, is_return);
 714        print_fmt = kmalloc(len + 1, GFP_KERNEL);
 715        if (!print_fmt)
 716                return -ENOMEM;
 717
 718        /* Second: actually write the @print_fmt */
 719        __set_print_fmt(tp, print_fmt, len + 1, is_return);
 720        tp->call.print_fmt = print_fmt;
 721
 722        return 0;
 723}
 724