linux/tools/perf/util/probe-event.c
<<
>>
Prefs
   1/*
   2 * probe-event.c : perf-probe definition to probe_events format converter
   3 *
   4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19 *
  20 */
  21
  22#include <sys/utsname.h>
  23#include <sys/types.h>
  24#include <sys/stat.h>
  25#include <fcntl.h>
  26#include <errno.h>
  27#include <stdio.h>
  28#include <unistd.h>
  29#include <stdlib.h>
  30#include <string.h>
  31#include <stdarg.h>
  32#include <limits.h>
  33#include <elf.h>
  34
  35#include "util.h"
  36#include "event.h"
  37#include "strlist.h"
  38#include "debug.h"
  39#include "cache.h"
  40#include "color.h"
  41#include "symbol.h"
  42#include "thread.h"
  43#include <lk/debugfs.h>
  44#include "trace-event.h"        /* For __maybe_unused */
  45#include "probe-event.h"
  46#include "probe-finder.h"
  47#include "session.h"
  48
  49#define MAX_CMDLEN 256
  50#define MAX_PROBE_ARGS 128
  51#define PERFPROBE_GROUP "probe"
  52
  53bool probe_event_dry_run;       /* Dry run flag */
  54
  55#define semantic_error(msg ...) pr_err("Semantic error :" msg)
  56
  57/* If there is no space to write, returns -E2BIG. */
  58static int e_snprintf(char *str, size_t size, const char *format, ...)
  59        __attribute__((format(printf, 3, 4)));
  60
  61static int e_snprintf(char *str, size_t size, const char *format, ...)
  62{
  63        int ret;
  64        va_list ap;
  65        va_start(ap, format);
  66        ret = vsnprintf(str, size, format, ap);
  67        va_end(ap);
  68        if (ret >= (int)size)
  69                ret = -E2BIG;
  70        return ret;
  71}
  72
  73static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
  74static int convert_name_to_addr(struct perf_probe_event *pev,
  75                                const char *exec);
  76static struct machine machine;
  77
  78/* Initialize symbol maps and path of vmlinux/modules */
  79static int init_vmlinux(void)
  80{
  81        int ret;
  82
  83        symbol_conf.sort_by_name = true;
  84        if (symbol_conf.vmlinux_name == NULL)
  85                symbol_conf.try_vmlinux_path = true;
  86        else
  87                pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
  88        ret = symbol__init();
  89        if (ret < 0) {
  90                pr_debug("Failed to init symbol map.\n");
  91                goto out;
  92        }
  93
  94        ret = machine__init(&machine, "", HOST_KERNEL_ID);
  95        if (ret < 0)
  96                goto out;
  97
  98        if (machine__create_kernel_maps(&machine) < 0) {
  99                pr_debug("machine__create_kernel_maps() failed.\n");
 100                goto out;
 101        }
 102out:
 103        if (ret < 0)
 104                pr_warning("Failed to init vmlinux path.\n");
 105        return ret;
 106}
 107
 108static struct symbol *__find_kernel_function_by_name(const char *name,
 109                                                     struct map **mapp)
 110{
 111        return machine__find_kernel_function_by_name(&machine, name, mapp,
 112                                                     NULL);
 113}
 114
 115static struct map *kernel_get_module_map(const char *module)
 116{
 117        struct rb_node *nd;
 118        struct map_groups *grp = &machine.kmaps;
 119
 120        /* A file path -- this is an offline module */
 121        if (module && strchr(module, '/'))
 122                return machine__new_module(&machine, 0, module);
 123
 124        if (!module)
 125                module = "kernel";
 126
 127        for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
 128                struct map *pos = rb_entry(nd, struct map, rb_node);
 129                if (strncmp(pos->dso->short_name + 1, module,
 130                            pos->dso->short_name_len - 2) == 0) {
 131                        return pos;
 132                }
 133        }
 134        return NULL;
 135}
 136
 137static struct dso *kernel_get_module_dso(const char *module)
 138{
 139        struct dso *dso;
 140        struct map *map;
 141        const char *vmlinux_name;
 142
 143        if (module) {
 144                list_for_each_entry(dso, &machine.kernel_dsos, node) {
 145                        if (strncmp(dso->short_name + 1, module,
 146                                    dso->short_name_len - 2) == 0)
 147                                goto found;
 148                }
 149                pr_debug("Failed to find module %s.\n", module);
 150                return NULL;
 151        }
 152
 153        map = machine.vmlinux_maps[MAP__FUNCTION];
 154        dso = map->dso;
 155
 156        vmlinux_name = symbol_conf.vmlinux_name;
 157        if (vmlinux_name) {
 158                if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
 159                        return NULL;
 160        } else {
 161                if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
 162                        pr_debug("Failed to load kernel map.\n");
 163                        return NULL;
 164                }
 165        }
 166found:
 167        return dso;
 168}
 169
 170const char *kernel_get_module_path(const char *module)
 171{
 172        struct dso *dso = kernel_get_module_dso(module);
 173        return (dso) ? dso->long_name : NULL;
 174}
 175
 176static int init_user_exec(void)
 177{
 178        int ret = 0;
 179
 180        symbol_conf.try_vmlinux_path = false;
 181        symbol_conf.sort_by_name = true;
 182        ret = symbol__init();
 183
 184        if (ret < 0)
 185                pr_debug("Failed to init symbol map.\n");
 186
 187        return ret;
 188}
 189
 190static int convert_to_perf_probe_point(struct probe_trace_point *tp,
 191                                        struct perf_probe_point *pp)
 192{
 193        pp->function = strdup(tp->symbol);
 194
 195        if (pp->function == NULL)
 196                return -ENOMEM;
 197
 198        pp->offset = tp->offset;
 199        pp->retprobe = tp->retprobe;
 200
 201        return 0;
 202}
 203
 204#ifdef DWARF_SUPPORT
 205/* Open new debuginfo of given module */
 206static struct debuginfo *open_debuginfo(const char *module)
 207{
 208        const char *path;
 209
 210        /* A file path -- this is an offline module */
 211        if (module && strchr(module, '/'))
 212                path = module;
 213        else {
 214                path = kernel_get_module_path(module);
 215
 216                if (!path) {
 217                        pr_err("Failed to find path of %s module.\n",
 218                               module ?: "kernel");
 219                        return NULL;
 220                }
 221        }
 222        return debuginfo__new(path);
 223}
 224
 225/*
 226 * Convert trace point to probe point with debuginfo
 227 * Currently only handles kprobes.
 228 */
 229static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 230                                        struct perf_probe_point *pp)
 231{
 232        struct symbol *sym;
 233        struct map *map;
 234        u64 addr;
 235        int ret = -ENOENT;
 236        struct debuginfo *dinfo;
 237
 238        sym = __find_kernel_function_by_name(tp->symbol, &map);
 239        if (sym) {
 240                addr = map->unmap_ip(map, sym->start + tp->offset);
 241                pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
 242                         tp->offset, addr);
 243
 244                dinfo = debuginfo__new_online_kernel(addr);
 245                if (dinfo) {
 246                        ret = debuginfo__find_probe_point(dinfo,
 247                                                 (unsigned long)addr, pp);
 248                        debuginfo__delete(dinfo);
 249                } else {
 250                        pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
 251                                 addr);
 252                        ret = -ENOENT;
 253                }
 254        }
 255        if (ret <= 0) {
 256                pr_debug("Failed to find corresponding probes from "
 257                         "debuginfo. Use kprobe event information.\n");
 258                return convert_to_perf_probe_point(tp, pp);
 259        }
 260        pp->retprobe = tp->retprobe;
 261
 262        return 0;
 263}
 264
 265static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
 266                                            int ntevs, const char *module)
 267{
 268        int i, ret = 0;
 269        char *tmp;
 270
 271        if (!module)
 272                return 0;
 273
 274        tmp = strrchr(module, '/');
 275        if (tmp) {
 276                /* This is a module path -- get the module name */
 277                module = strdup(tmp + 1);
 278                if (!module)
 279                        return -ENOMEM;
 280                tmp = strchr(module, '.');
 281                if (tmp)
 282                        *tmp = '\0';
 283                tmp = (char *)module;   /* For free() */
 284        }
 285
 286        for (i = 0; i < ntevs; i++) {
 287                tevs[i].point.module = strdup(module);
 288                if (!tevs[i].point.module) {
 289                        ret = -ENOMEM;
 290                        break;
 291                }
 292        }
 293
 294        if (tmp)
 295                free(tmp);
 296
 297        return ret;
 298}
 299
 300/* Try to find perf_probe_event with debuginfo */
 301static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 302                                          struct probe_trace_event **tevs,
 303                                          int max_tevs, const char *target)
 304{
 305        bool need_dwarf = perf_probe_event_need_dwarf(pev);
 306        struct debuginfo *dinfo;
 307        int ntevs, ret = 0;
 308
 309        if (pev->uprobes) {
 310                if (need_dwarf) {
 311                        pr_warning("Debuginfo-analysis is not yet supported"
 312                                        " with -x/--exec option.\n");
 313                        return -ENOSYS;
 314                }
 315                return convert_name_to_addr(pev, target);
 316        }
 317
 318        dinfo = open_debuginfo(target);
 319
 320        if (!dinfo) {
 321                if (need_dwarf) {
 322                        pr_warning("Failed to open debuginfo file.\n");
 323                        return -ENOENT;
 324                }
 325                pr_debug("Could not open debuginfo. Try to use symbols.\n");
 326                return 0;
 327        }
 328
 329        /* Searching trace events corresponding to a probe event */
 330        ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
 331
 332        debuginfo__delete(dinfo);
 333
 334        if (ntevs > 0) {        /* Succeeded to find trace events */
 335                pr_debug("find %d probe_trace_events.\n", ntevs);
 336                if (target)
 337                        ret = add_module_to_probe_trace_events(*tevs, ntevs,
 338                                                               target);
 339                return ret < 0 ? ret : ntevs;
 340        }
 341
 342        if (ntevs == 0) {       /* No error but failed to find probe point. */
 343                pr_warning("Probe point '%s' not found.\n",
 344                           synthesize_perf_probe_point(&pev->point));
 345                return -ENOENT;
 346        }
 347        /* Error path : ntevs < 0 */
 348        pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
 349        if (ntevs == -EBADF) {
 350                pr_warning("Warning: No dwarf info found in the vmlinux - "
 351                        "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
 352                if (!need_dwarf) {
 353                        pr_debug("Trying to use symbols.\n");
 354                        return 0;
 355                }
 356        }
 357        return ntevs;
 358}
 359
 360/*
 361 * Find a src file from a DWARF tag path. Prepend optional source path prefix
 362 * and chop off leading directories that do not exist. Result is passed back as
 363 * a newly allocated path on success.
 364 * Return 0 if file was found and readable, -errno otherwise.
 365 */
 366static int get_real_path(const char *raw_path, const char *comp_dir,
 367                         char **new_path)
 368{
 369        const char *prefix = symbol_conf.source_prefix;
 370
 371        if (!prefix) {
 372                if (raw_path[0] != '/' && comp_dir)
 373                        /* If not an absolute path, try to use comp_dir */
 374                        prefix = comp_dir;
 375                else {
 376                        if (access(raw_path, R_OK) == 0) {
 377                                *new_path = strdup(raw_path);
 378                                return 0;
 379                        } else
 380                                return -errno;
 381                }
 382        }
 383
 384        *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
 385        if (!*new_path)
 386                return -ENOMEM;
 387
 388        for (;;) {
 389                sprintf(*new_path, "%s/%s", prefix, raw_path);
 390
 391                if (access(*new_path, R_OK) == 0)
 392                        return 0;
 393
 394                if (!symbol_conf.source_prefix)
 395                        /* In case of searching comp_dir, don't retry */
 396                        return -errno;
 397
 398                switch (errno) {
 399                case ENAMETOOLONG:
 400                case ENOENT:
 401                case EROFS:
 402                case EFAULT:
 403                        raw_path = strchr(++raw_path, '/');
 404                        if (!raw_path) {
 405                                free(*new_path);
 406                                *new_path = NULL;
 407                                return -ENOENT;
 408                        }
 409                        continue;
 410
 411                default:
 412                        free(*new_path);
 413                        *new_path = NULL;
 414                        return -errno;
 415                }
 416        }
 417}
 418
 419#define LINEBUF_SIZE 256
 420#define NR_ADDITIONAL_LINES 2
 421
 422static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
 423{
 424        char buf[LINEBUF_SIZE];
 425        const char *color = show_num ? "" : PERF_COLOR_BLUE;
 426        const char *prefix = NULL;
 427
 428        do {
 429                if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
 430                        goto error;
 431                if (skip)
 432                        continue;
 433                if (!prefix) {
 434                        prefix = show_num ? "%7d  " : "         ";
 435                        color_fprintf(stdout, color, prefix, l);
 436                }
 437                color_fprintf(stdout, color, "%s", buf);
 438
 439        } while (strchr(buf, '\n') == NULL);
 440
 441        return 1;
 442error:
 443        if (ferror(fp)) {
 444                pr_warning("File read error: %s\n", strerror(errno));
 445                return -1;
 446        }
 447        return 0;
 448}
 449
 450static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
 451{
 452        int rv = __show_one_line(fp, l, skip, show_num);
 453        if (rv == 0) {
 454                pr_warning("Source file is shorter than expected.\n");
 455                rv = -1;
 456        }
 457        return rv;
 458}
 459
 460#define show_one_line_with_num(f,l)     _show_one_line(f,l,false,true)
 461#define show_one_line(f,l)              _show_one_line(f,l,false,false)
 462#define skip_one_line(f,l)              _show_one_line(f,l,true,false)
 463#define show_one_line_or_eof(f,l)       __show_one_line(f,l,false,false)
 464
 465/*
 466 * Show line-range always requires debuginfo to find source file and
 467 * line number.
 468 */
 469int show_line_range(struct line_range *lr, const char *module)
 470{
 471        int l = 1;
 472        struct line_node *ln;
 473        struct debuginfo *dinfo;
 474        FILE *fp;
 475        int ret;
 476        char *tmp;
 477
 478        /* Search a line range */
 479        ret = init_vmlinux();
 480        if (ret < 0)
 481                return ret;
 482
 483        dinfo = open_debuginfo(module);
 484        if (!dinfo) {
 485                pr_warning("Failed to open debuginfo file.\n");
 486                return -ENOENT;
 487        }
 488
 489        ret = debuginfo__find_line_range(dinfo, lr);
 490        debuginfo__delete(dinfo);
 491        if (ret == 0) {
 492                pr_warning("Specified source line is not found.\n");
 493                return -ENOENT;
 494        } else if (ret < 0) {
 495                pr_warning("Debuginfo analysis failed. (%d)\n", ret);
 496                return ret;
 497        }
 498
 499        /* Convert source file path */
 500        tmp = lr->path;
 501        ret = get_real_path(tmp, lr->comp_dir, &lr->path);
 502        free(tmp);      /* Free old path */
 503        if (ret < 0) {
 504                pr_warning("Failed to find source file. (%d)\n", ret);
 505                return ret;
 506        }
 507
 508        setup_pager();
 509
 510        if (lr->function)
 511                fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
 512                        lr->start - lr->offset);
 513        else
 514                fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
 515
 516        fp = fopen(lr->path, "r");
 517        if (fp == NULL) {
 518                pr_warning("Failed to open %s: %s\n", lr->path,
 519                           strerror(errno));
 520                return -errno;
 521        }
 522        /* Skip to starting line number */
 523        while (l < lr->start) {
 524                ret = skip_one_line(fp, l++);
 525                if (ret < 0)
 526                        goto end;
 527        }
 528
 529        list_for_each_entry(ln, &lr->line_list, list) {
 530                for (; ln->line > l; l++) {
 531                        ret = show_one_line(fp, l - lr->offset);
 532                        if (ret < 0)
 533                                goto end;
 534                }
 535                ret = show_one_line_with_num(fp, l++ - lr->offset);
 536                if (ret < 0)
 537                        goto end;
 538        }
 539
 540        if (lr->end == INT_MAX)
 541                lr->end = l + NR_ADDITIONAL_LINES;
 542        while (l <= lr->end) {
 543                ret = show_one_line_or_eof(fp, l++ - lr->offset);
 544                if (ret <= 0)
 545                        break;
 546        }
 547end:
 548        fclose(fp);
 549        return ret;
 550}
 551
 552static int show_available_vars_at(struct debuginfo *dinfo,
 553                                  struct perf_probe_event *pev,
 554                                  int max_vls, struct strfilter *_filter,
 555                                  bool externs)
 556{
 557        char *buf;
 558        int ret, i, nvars;
 559        struct str_node *node;
 560        struct variable_list *vls = NULL, *vl;
 561        const char *var;
 562
 563        buf = synthesize_perf_probe_point(&pev->point);
 564        if (!buf)
 565                return -EINVAL;
 566        pr_debug("Searching variables at %s\n", buf);
 567
 568        ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
 569                                                max_vls, externs);
 570        if (ret <= 0) {
 571                pr_err("Failed to find variables at %s (%d)\n", buf, ret);
 572                goto end;
 573        }
 574        /* Some variables are found */
 575        fprintf(stdout, "Available variables at %s\n", buf);
 576        for (i = 0; i < ret; i++) {
 577                vl = &vls[i];
 578                /*
 579                 * A probe point might be converted to
 580                 * several trace points.
 581                 */
 582                fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
 583                        vl->point.offset);
 584                free(vl->point.symbol);
 585                nvars = 0;
 586                if (vl->vars) {
 587                        strlist__for_each(node, vl->vars) {
 588                                var = strchr(node->s, '\t') + 1;
 589                                if (strfilter__compare(_filter, var)) {
 590                                        fprintf(stdout, "\t\t%s\n", node->s);
 591                                        nvars++;
 592                                }
 593                        }
 594                        strlist__delete(vl->vars);
 595                }
 596                if (nvars == 0)
 597                        fprintf(stdout, "\t\t(No matched variables)\n");
 598        }
 599        free(vls);
 600end:
 601        free(buf);
 602        return ret;
 603}
 604
 605/* Show available variables on given probe point */
 606int show_available_vars(struct perf_probe_event *pevs, int npevs,
 607                        int max_vls, const char *module,
 608                        struct strfilter *_filter, bool externs)
 609{
 610        int i, ret = 0;
 611        struct debuginfo *dinfo;
 612
 613        ret = init_vmlinux();
 614        if (ret < 0)
 615                return ret;
 616
 617        dinfo = open_debuginfo(module);
 618        if (!dinfo) {
 619                pr_warning("Failed to open debuginfo file.\n");
 620                return -ENOENT;
 621        }
 622
 623        setup_pager();
 624
 625        for (i = 0; i < npevs && ret >= 0; i++)
 626                ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
 627                                             externs);
 628
 629        debuginfo__delete(dinfo);
 630        return ret;
 631}
 632
 633#else   /* !DWARF_SUPPORT */
 634
 635static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 636                                        struct perf_probe_point *pp)
 637{
 638        struct symbol *sym;
 639
 640        sym = __find_kernel_function_by_name(tp->symbol, NULL);
 641        if (!sym) {
 642                pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
 643                return -ENOENT;
 644        }
 645
 646        return convert_to_perf_probe_point(tp, pp);
 647}
 648
 649static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 650                                struct probe_trace_event **tevs __maybe_unused,
 651                                int max_tevs __maybe_unused, const char *target)
 652{
 653        if (perf_probe_event_need_dwarf(pev)) {
 654                pr_warning("Debuginfo-analysis is not supported.\n");
 655                return -ENOSYS;
 656        }
 657
 658        if (pev->uprobes)
 659                return convert_name_to_addr(pev, target);
 660
 661        return 0;
 662}
 663
 664int show_line_range(struct line_range *lr __maybe_unused,
 665                    const char *module __maybe_unused)
 666{
 667        pr_warning("Debuginfo-analysis is not supported.\n");
 668        return -ENOSYS;
 669}
 670
 671int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
 672                        int npevs __maybe_unused, int max_vls __maybe_unused,
 673                        const char *module __maybe_unused,
 674                        struct strfilter *filter __maybe_unused,
 675                        bool externs __maybe_unused)
 676{
 677        pr_warning("Debuginfo-analysis is not supported.\n");
 678        return -ENOSYS;
 679}
 680#endif
 681
 682static int parse_line_num(char **ptr, int *val, const char *what)
 683{
 684        const char *start = *ptr;
 685
 686        errno = 0;
 687        *val = strtol(*ptr, ptr, 0);
 688        if (errno || *ptr == start) {
 689                semantic_error("'%s' is not a valid number.\n", what);
 690                return -EINVAL;
 691        }
 692        return 0;
 693}
 694
 695/*
 696 * Stuff 'lr' according to the line range described by 'arg'.
 697 * The line range syntax is described by:
 698 *
 699 *         SRC[:SLN[+NUM|-ELN]]
 700 *         FNC[@SRC][:SLN[+NUM|-ELN]]
 701 */
 702int parse_line_range_desc(const char *arg, struct line_range *lr)
 703{
 704        char *range, *file, *name = strdup(arg);
 705        int err;
 706
 707        if (!name)
 708                return -ENOMEM;
 709
 710        lr->start = 0;
 711        lr->end = INT_MAX;
 712
 713        range = strchr(name, ':');
 714        if (range) {
 715                *range++ = '\0';
 716
 717                err = parse_line_num(&range, &lr->start, "start line");
 718                if (err)
 719                        goto err;
 720
 721                if (*range == '+' || *range == '-') {
 722                        const char c = *range++;
 723
 724                        err = parse_line_num(&range, &lr->end, "end line");
 725                        if (err)
 726                                goto err;
 727
 728                        if (c == '+') {
 729                                lr->end += lr->start;
 730                                /*
 731                                 * Adjust the number of lines here.
 732                                 * If the number of lines == 1, the
 733                                 * the end of line should be equal to
 734                                 * the start of line.
 735                                 */
 736                                lr->end--;
 737                        }
 738                }
 739
 740                pr_debug("Line range is %d to %d\n", lr->start, lr->end);
 741
 742                err = -EINVAL;
 743                if (lr->start > lr->end) {
 744                        semantic_error("Start line must be smaller"
 745                                       " than end line.\n");
 746                        goto err;
 747                }
 748                if (*range != '\0') {
 749                        semantic_error("Tailing with invalid str '%s'.\n", range);
 750                        goto err;
 751                }
 752        }
 753
 754        file = strchr(name, '@');
 755        if (file) {
 756                *file = '\0';
 757                lr->file = strdup(++file);
 758                if (lr->file == NULL) {
 759                        err = -ENOMEM;
 760                        goto err;
 761                }
 762                lr->function = name;
 763        } else if (strchr(name, '.'))
 764                lr->file = name;
 765        else
 766                lr->function = name;
 767
 768        return 0;
 769err:
 770        free(name);
 771        return err;
 772}
 773
 774/* Check the name is good for event/group */
 775static bool check_event_name(const char *name)
 776{
 777        if (!isalpha(*name) && *name != '_')
 778                return false;
 779        while (*++name != '\0') {
 780                if (!isalpha(*name) && !isdigit(*name) && *name != '_')
 781                        return false;
 782        }
 783        return true;
 784}
 785
 786/* Parse probepoint definition. */
 787static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 788{
 789        struct perf_probe_point *pp = &pev->point;
 790        char *ptr, *tmp;
 791        char c, nc = 0;
 792        /*
 793         * <Syntax>
 794         * perf probe [EVENT=]SRC[:LN|;PTN]
 795         * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
 796         *
 797         * TODO:Group name support
 798         */
 799
 800        ptr = strpbrk(arg, ";=@+%");
 801        if (ptr && *ptr == '=') {       /* Event name */
 802                *ptr = '\0';
 803                tmp = ptr + 1;
 804                if (strchr(arg, ':')) {
 805                        semantic_error("Group name is not supported yet.\n");
 806                        return -ENOTSUP;
 807                }
 808                if (!check_event_name(arg)) {
 809                        semantic_error("%s is bad for event name -it must "
 810                                       "follow C symbol-naming rule.\n", arg);
 811                        return -EINVAL;
 812                }
 813                pev->event = strdup(arg);
 814                if (pev->event == NULL)
 815                        return -ENOMEM;
 816                pev->group = NULL;
 817                arg = tmp;
 818        }
 819
 820        ptr = strpbrk(arg, ";:+@%");
 821        if (ptr) {
 822                nc = *ptr;
 823                *ptr++ = '\0';
 824        }
 825
 826        tmp = strdup(arg);
 827        if (tmp == NULL)
 828                return -ENOMEM;
 829
 830        /* Check arg is function or file and copy it */
 831        if (strchr(tmp, '.'))   /* File */
 832                pp->file = tmp;
 833        else                    /* Function */
 834                pp->function = tmp;
 835
 836        /* Parse other options */
 837        while (ptr) {
 838                arg = ptr;
 839                c = nc;
 840                if (c == ';') { /* Lazy pattern must be the last part */
 841                        pp->lazy_line = strdup(arg);
 842                        if (pp->lazy_line == NULL)
 843                                return -ENOMEM;
 844                        break;
 845                }
 846                ptr = strpbrk(arg, ";:+@%");
 847                if (ptr) {
 848                        nc = *ptr;
 849                        *ptr++ = '\0';
 850                }
 851                switch (c) {
 852                case ':':       /* Line number */
 853                        pp->line = strtoul(arg, &tmp, 0);
 854                        if (*tmp != '\0') {
 855                                semantic_error("There is non-digit char"
 856                                               " in line number.\n");
 857                                return -EINVAL;
 858                        }
 859                        break;
 860                case '+':       /* Byte offset from a symbol */
 861                        pp->offset = strtoul(arg, &tmp, 0);
 862                        if (*tmp != '\0') {
 863                                semantic_error("There is non-digit character"
 864                                                " in offset.\n");
 865                                return -EINVAL;
 866                        }
 867                        break;
 868                case '@':       /* File name */
 869                        if (pp->file) {
 870                                semantic_error("SRC@SRC is not allowed.\n");
 871                                return -EINVAL;
 872                        }
 873                        pp->file = strdup(arg);
 874                        if (pp->file == NULL)
 875                                return -ENOMEM;
 876                        break;
 877                case '%':       /* Probe places */
 878                        if (strcmp(arg, "return") == 0) {
 879                                pp->retprobe = 1;
 880                        } else {        /* Others not supported yet */
 881                                semantic_error("%%%s is not supported.\n", arg);
 882                                return -ENOTSUP;
 883                        }
 884                        break;
 885                default:        /* Buggy case */
 886                        pr_err("This program has a bug at %s:%d.\n",
 887                                __FILE__, __LINE__);
 888                        return -ENOTSUP;
 889                        break;
 890                }
 891        }
 892
 893        /* Exclusion check */
 894        if (pp->lazy_line && pp->line) {
 895                semantic_error("Lazy pattern can't be used with"
 896                               " line number.\n");
 897                return -EINVAL;
 898        }
 899
 900        if (pp->lazy_line && pp->offset) {
 901                semantic_error("Lazy pattern can't be used with offset.\n");
 902                return -EINVAL;
 903        }
 904
 905        if (pp->line && pp->offset) {
 906                semantic_error("Offset can't be used with line number.\n");
 907                return -EINVAL;
 908        }
 909
 910        if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
 911                semantic_error("File always requires line number or "
 912                               "lazy pattern.\n");
 913                return -EINVAL;
 914        }
 915
 916        if (pp->offset && !pp->function) {
 917                semantic_error("Offset requires an entry function.\n");
 918                return -EINVAL;
 919        }
 920
 921        if (pp->retprobe && !pp->function) {
 922                semantic_error("Return probe requires an entry function.\n");
 923                return -EINVAL;
 924        }
 925
 926        if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
 927                semantic_error("Offset/Line/Lazy pattern can't be used with "
 928                               "return probe.\n");
 929                return -EINVAL;
 930        }
 931
 932        pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
 933                 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
 934                 pp->lazy_line);
 935        return 0;
 936}
 937
 938/* Parse perf-probe event argument */
 939static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
 940{
 941        char *tmp, *goodname;
 942        struct perf_probe_arg_field **fieldp;
 943
 944        pr_debug("parsing arg: %s into ", str);
 945
 946        tmp = strchr(str, '=');
 947        if (tmp) {
 948                arg->name = strndup(str, tmp - str);
 949                if (arg->name == NULL)
 950                        return -ENOMEM;
 951                pr_debug("name:%s ", arg->name);
 952                str = tmp + 1;
 953        }
 954
 955        tmp = strchr(str, ':');
 956        if (tmp) {      /* Type setting */
 957                *tmp = '\0';
 958                arg->type = strdup(tmp + 1);
 959                if (arg->type == NULL)
 960                        return -ENOMEM;
 961                pr_debug("type:%s ", arg->type);
 962        }
 963
 964        tmp = strpbrk(str, "-.[");
 965        if (!is_c_varname(str) || !tmp) {
 966                /* A variable, register, symbol or special value */
 967                arg->var = strdup(str);
 968                if (arg->var == NULL)
 969                        return -ENOMEM;
 970                pr_debug("%s\n", arg->var);
 971                return 0;
 972        }
 973
 974        /* Structure fields or array element */
 975        arg->var = strndup(str, tmp - str);
 976        if (arg->var == NULL)
 977                return -ENOMEM;
 978        goodname = arg->var;
 979        pr_debug("%s, ", arg->var);
 980        fieldp = &arg->field;
 981
 982        do {
 983                *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
 984                if (*fieldp == NULL)
 985                        return -ENOMEM;
 986                if (*tmp == '[') {      /* Array */
 987                        str = tmp;
 988                        (*fieldp)->index = strtol(str + 1, &tmp, 0);
 989                        (*fieldp)->ref = true;
 990                        if (*tmp != ']' || tmp == str + 1) {
 991                                semantic_error("Array index must be a"
 992                                                " number.\n");
 993                                return -EINVAL;
 994                        }
 995                        tmp++;
 996                        if (*tmp == '\0')
 997                                tmp = NULL;
 998                } else {                /* Structure */
 999                        if (*tmp == '.') {
1000                                str = tmp + 1;
1001                                (*fieldp)->ref = false;
1002                        } else if (tmp[1] == '>') {
1003                                str = tmp + 2;
1004                                (*fieldp)->ref = true;
1005                        } else {
1006                                semantic_error("Argument parse error: %s\n",
1007                                               str);
1008                                return -EINVAL;
1009                        }
1010                        tmp = strpbrk(str, "-.[");
1011                }
1012                if (tmp) {
1013                        (*fieldp)->name = strndup(str, tmp - str);
1014                        if ((*fieldp)->name == NULL)
1015                                return -ENOMEM;
1016                        if (*str != '[')
1017                                goodname = (*fieldp)->name;
1018                        pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
1019                        fieldp = &(*fieldp)->next;
1020                }
1021        } while (tmp);
1022        (*fieldp)->name = strdup(str);
1023        if ((*fieldp)->name == NULL)
1024                return -ENOMEM;
1025        if (*str != '[')
1026                goodname = (*fieldp)->name;
1027        pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
1028
1029        /* If no name is specified, set the last field name (not array index)*/
1030        if (!arg->name) {
1031                arg->name = strdup(goodname);
1032                if (arg->name == NULL)
1033                        return -ENOMEM;
1034        }
1035        return 0;
1036}
1037
1038/* Parse perf-probe event command */
1039int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
1040{
1041        char **argv;
1042        int argc, i, ret = 0;
1043
1044        argv = argv_split(cmd, &argc);
1045        if (!argv) {
1046                pr_debug("Failed to split arguments.\n");
1047                return -ENOMEM;
1048        }
1049        if (argc - 1 > MAX_PROBE_ARGS) {
1050                semantic_error("Too many probe arguments (%d).\n", argc - 1);
1051                ret = -ERANGE;
1052                goto out;
1053        }
1054        /* Parse probe point */
1055        ret = parse_perf_probe_point(argv[0], pev);
1056        if (ret < 0)
1057                goto out;
1058
1059        /* Copy arguments and ensure return probe has no C argument */
1060        pev->nargs = argc - 1;
1061        pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1062        if (pev->args == NULL) {
1063                ret = -ENOMEM;
1064                goto out;
1065        }
1066        for (i = 0; i < pev->nargs && ret >= 0; i++) {
1067                ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
1068                if (ret >= 0 &&
1069                    is_c_varname(pev->args[i].var) && pev->point.retprobe) {
1070                        semantic_error("You can't specify local variable for"
1071                                       " kretprobe.\n");
1072                        ret = -EINVAL;
1073                }
1074        }
1075out:
1076        argv_free(argv);
1077
1078        return ret;
1079}
1080
1081/* Return true if this perf_probe_event requires debuginfo */
1082bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1083{
1084        int i;
1085
1086        if (pev->point.file || pev->point.line || pev->point.lazy_line)
1087                return true;
1088
1089        for (i = 0; i < pev->nargs; i++)
1090                if (is_c_varname(pev->args[i].var))
1091                        return true;
1092
1093        return false;
1094}
1095
1096/* Parse probe_events event into struct probe_point */
1097static int parse_probe_trace_command(const char *cmd,
1098                                     struct probe_trace_event *tev)
1099{
1100        struct probe_trace_point *tp = &tev->point;
1101        char pr;
1102        char *p;
1103        char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str;
1104        int ret, i, argc;
1105        char **argv;
1106
1107        pr_debug("Parsing probe_events: %s\n", cmd);
1108        argv = argv_split(cmd, &argc);
1109        if (!argv) {
1110                pr_debug("Failed to split arguments.\n");
1111                return -ENOMEM;
1112        }
1113        if (argc < 2) {
1114                semantic_error("Too few probe arguments.\n");
1115                ret = -ERANGE;
1116                goto out;
1117        }
1118
1119        /* Scan event and group name. */
1120        argv0_str = strdup(argv[0]);
1121        if (argv0_str == NULL) {
1122                ret = -ENOMEM;
1123                goto out;
1124        }
1125        fmt1_str = strtok_r(argv0_str, ":", &fmt);
1126        fmt2_str = strtok_r(NULL, "/", &fmt);
1127        fmt3_str = strtok_r(NULL, " \t", &fmt);
1128        if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL
1129            || fmt3_str == NULL) {
1130                semantic_error("Failed to parse event name: %s\n", argv[0]);
1131                ret = -EINVAL;
1132                goto out;
1133        }
1134        pr = fmt1_str[0];
1135        tev->group = strdup(fmt2_str);
1136        tev->event = strdup(fmt3_str);
1137        if (tev->group == NULL || tev->event == NULL) {
1138                ret = -ENOMEM;
1139                goto out;
1140        }
1141        pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
1142
1143        tp->retprobe = (pr == 'r');
1144
1145        /* Scan module name(if there), function name and offset */
1146        p = strchr(argv[1], ':');
1147        if (p) {
1148                tp->module = strndup(argv[1], p - argv[1]);
1149                p++;
1150        } else
1151                p = argv[1];
1152        fmt1_str = strtok_r(p, "+", &fmt);
1153        tp->symbol = strdup(fmt1_str);
1154        if (tp->symbol == NULL) {
1155                ret = -ENOMEM;
1156                goto out;
1157        }
1158        fmt2_str = strtok_r(NULL, "", &fmt);
1159        if (fmt2_str == NULL)
1160                tp->offset = 0;
1161        else
1162                tp->offset = strtoul(fmt2_str, NULL, 10);
1163
1164        tev->nargs = argc - 2;
1165        tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1166        if (tev->args == NULL) {
1167                ret = -ENOMEM;
1168                goto out;
1169        }
1170        for (i = 0; i < tev->nargs; i++) {
1171                p = strchr(argv[i + 2], '=');
1172                if (p)  /* We don't need which register is assigned. */
1173                        *p++ = '\0';
1174                else
1175                        p = argv[i + 2];
1176                tev->args[i].name = strdup(argv[i + 2]);
1177                /* TODO: parse regs and offset */
1178                tev->args[i].value = strdup(p);
1179                if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
1180                        ret = -ENOMEM;
1181                        goto out;
1182                }
1183        }
1184        ret = 0;
1185out:
1186        free(argv0_str);
1187        argv_free(argv);
1188        return ret;
1189}
1190
1191/* Compose only probe arg */
1192int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1193{
1194        struct perf_probe_arg_field *field = pa->field;
1195        int ret;
1196        char *tmp = buf;
1197
1198        if (pa->name && pa->var)
1199                ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
1200        else
1201                ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
1202        if (ret <= 0)
1203                goto error;
1204        tmp += ret;
1205        len -= ret;
1206
1207        while (field) {
1208                if (field->name[0] == '[')
1209                        ret = e_snprintf(tmp, len, "%s", field->name);
1210                else
1211                        ret = e_snprintf(tmp, len, "%s%s",
1212                                         field->ref ? "->" : ".", field->name);
1213                if (ret <= 0)
1214                        goto error;
1215                tmp += ret;
1216                len -= ret;
1217                field = field->next;
1218        }
1219
1220        if (pa->type) {
1221                ret = e_snprintf(tmp, len, ":%s", pa->type);
1222                if (ret <= 0)
1223                        goto error;
1224                tmp += ret;
1225                len -= ret;
1226        }
1227
1228        return tmp - buf;
1229error:
1230        pr_debug("Failed to synthesize perf probe argument: %s\n",
1231                 strerror(-ret));
1232        return ret;
1233}
1234
1235/* Compose only probe point (not argument) */
1236static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1237{
1238        char *buf, *tmp;
1239        char offs[32] = "", line[32] = "", file[32] = "";
1240        int ret, len;
1241
1242        buf = zalloc(MAX_CMDLEN);
1243        if (buf == NULL) {
1244                ret = -ENOMEM;
1245                goto error;
1246        }
1247        if (pp->offset) {
1248                ret = e_snprintf(offs, 32, "+%lu", pp->offset);
1249                if (ret <= 0)
1250                        goto error;
1251        }
1252        if (pp->line) {
1253                ret = e_snprintf(line, 32, ":%d", pp->line);
1254                if (ret <= 0)
1255                        goto error;
1256        }
1257        if (pp->file) {
1258                tmp = pp->file;
1259                len = strlen(tmp);
1260                if (len > 30) {
1261                        tmp = strchr(pp->file + len - 30, '/');
1262                        tmp = tmp ? tmp + 1 : pp->file + len - 30;
1263                }
1264                ret = e_snprintf(file, 32, "@%s", tmp);
1265                if (ret <= 0)
1266                        goto error;
1267        }
1268
1269        if (pp->function)
1270                ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
1271                                 offs, pp->retprobe ? "%return" : "", line,
1272                                 file);
1273        else
1274                ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
1275        if (ret <= 0)
1276                goto error;
1277
1278        return buf;
1279error:
1280        pr_debug("Failed to synthesize perf probe point: %s\n",
1281                 strerror(-ret));
1282        if (buf)
1283                free(buf);
1284        return NULL;
1285}
1286
1287#if 0
1288char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1289{
1290        char *buf;
1291        int i, len, ret;
1292
1293        buf = synthesize_perf_probe_point(&pev->point);
1294        if (!buf)
1295                return NULL;
1296
1297        len = strlen(buf);
1298        for (i = 0; i < pev->nargs; i++) {
1299                ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
1300                                 pev->args[i].name);
1301                if (ret <= 0) {
1302                        free(buf);
1303                        return NULL;
1304                }
1305                len += ret;
1306        }
1307
1308        return buf;
1309}
1310#endif
1311
1312static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1313                                             char **buf, size_t *buflen,
1314                                             int depth)
1315{
1316        int ret;
1317        if (ref->next) {
1318                depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1319                                                         buflen, depth + 1);
1320                if (depth < 0)
1321                        goto out;
1322        }
1323
1324        ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1325        if (ret < 0)
1326                depth = ret;
1327        else {
1328                *buf += ret;
1329                *buflen -= ret;
1330        }
1331out:
1332        return depth;
1333
1334}
1335
1336static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1337                                       char *buf, size_t buflen)
1338{
1339        struct probe_trace_arg_ref *ref = arg->ref;
1340        int ret, depth = 0;
1341        char *tmp = buf;
1342
1343        /* Argument name or separator */
1344        if (arg->name)
1345                ret = e_snprintf(buf, buflen, " %s=", arg->name);
1346        else
1347                ret = e_snprintf(buf, buflen, " ");
1348        if (ret < 0)
1349                return ret;
1350        buf += ret;
1351        buflen -= ret;
1352
1353        /* Special case: @XXX */
1354        if (arg->value[0] == '@' && arg->ref)
1355                        ref = ref->next;
1356
1357        /* Dereferencing arguments */
1358        if (ref) {
1359                depth = __synthesize_probe_trace_arg_ref(ref, &buf,
1360                                                          &buflen, 1);
1361                if (depth < 0)
1362                        return depth;
1363        }
1364
1365        /* Print argument value */
1366        if (arg->value[0] == '@' && arg->ref)
1367                ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1368                                 arg->ref->offset);
1369        else
1370                ret = e_snprintf(buf, buflen, "%s", arg->value);
1371        if (ret < 0)
1372                return ret;
1373        buf += ret;
1374        buflen -= ret;
1375
1376        /* Closing */
1377        while (depth--) {
1378                ret = e_snprintf(buf, buflen, ")");
1379                if (ret < 0)
1380                        return ret;
1381                buf += ret;
1382                buflen -= ret;
1383        }
1384        /* Print argument type */
1385        if (arg->type) {
1386                ret = e_snprintf(buf, buflen, ":%s", arg->type);
1387                if (ret <= 0)
1388                        return ret;
1389                buf += ret;
1390        }
1391
1392        return buf - tmp;
1393}
1394
1395char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1396{
1397        struct probe_trace_point *tp = &tev->point;
1398        char *buf;
1399        int i, len, ret;
1400
1401        buf = zalloc(MAX_CMDLEN);
1402        if (buf == NULL)
1403                return NULL;
1404
1405        if (tev->uprobes)
1406                len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s",
1407                                 tp->retprobe ? 'r' : 'p',
1408                                 tev->group, tev->event,
1409                                 tp->module, tp->symbol);
1410        else
1411                len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
1412                                 tp->retprobe ? 'r' : 'p',
1413                                 tev->group, tev->event,
1414                                 tp->module ?: "", tp->module ? ":" : "",
1415                                 tp->symbol, tp->offset);
1416
1417        if (len <= 0)
1418                goto error;
1419
1420        for (i = 0; i < tev->nargs; i++) {
1421                ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
1422                                                  MAX_CMDLEN - len);
1423                if (ret <= 0)
1424                        goto error;
1425                len += ret;
1426        }
1427
1428        return buf;
1429error:
1430        free(buf);
1431        return NULL;
1432}
1433
1434static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1435                               struct perf_probe_event *pev, bool is_kprobe)
1436{
1437        char buf[64] = "";
1438        int i, ret;
1439
1440        /* Convert event/group name */
1441        pev->event = strdup(tev->event);
1442        pev->group = strdup(tev->group);
1443        if (pev->event == NULL || pev->group == NULL)
1444                return -ENOMEM;
1445
1446        /* Convert trace_point to probe_point */
1447        if (is_kprobe)
1448                ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
1449        else
1450                ret = convert_to_perf_probe_point(&tev->point, &pev->point);
1451
1452        if (ret < 0)
1453                return ret;
1454
1455        /* Convert trace_arg to probe_arg */
1456        pev->nargs = tev->nargs;
1457        pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1458        if (pev->args == NULL)
1459                return -ENOMEM;
1460        for (i = 0; i < tev->nargs && ret >= 0; i++) {
1461                if (tev->args[i].name)
1462                        pev->args[i].name = strdup(tev->args[i].name);
1463                else {
1464                        ret = synthesize_probe_trace_arg(&tev->args[i],
1465                                                          buf, 64);
1466                        pev->args[i].name = strdup(buf);
1467                }
1468                if (pev->args[i].name == NULL && ret >= 0)
1469                        ret = -ENOMEM;
1470        }
1471
1472        if (ret < 0)
1473                clear_perf_probe_event(pev);
1474
1475        return ret;
1476}
1477
1478void clear_perf_probe_event(struct perf_probe_event *pev)
1479{
1480        struct perf_probe_point *pp = &pev->point;
1481        struct perf_probe_arg_field *field, *next;
1482        int i;
1483
1484        if (pev->event)
1485                free(pev->event);
1486        if (pev->group)
1487                free(pev->group);
1488        if (pp->file)
1489                free(pp->file);
1490        if (pp->function)
1491                free(pp->function);
1492        if (pp->lazy_line)
1493                free(pp->lazy_line);
1494        for (i = 0; i < pev->nargs; i++) {
1495                if (pev->args[i].name)
1496                        free(pev->args[i].name);
1497                if (pev->args[i].var)
1498                        free(pev->args[i].var);
1499                if (pev->args[i].type)
1500                        free(pev->args[i].type);
1501                field = pev->args[i].field;
1502                while (field) {
1503                        next = field->next;
1504                        if (field->name)
1505                                free(field->name);
1506                        free(field);
1507                        field = next;
1508                }
1509        }
1510        if (pev->args)
1511                free(pev->args);
1512        memset(pev, 0, sizeof(*pev));
1513}
1514
1515static void clear_probe_trace_event(struct probe_trace_event *tev)
1516{
1517        struct probe_trace_arg_ref *ref, *next;
1518        int i;
1519
1520        if (tev->event)
1521                free(tev->event);
1522        if (tev->group)
1523                free(tev->group);
1524        if (tev->point.symbol)
1525                free(tev->point.symbol);
1526        if (tev->point.module)
1527                free(tev->point.module);
1528        for (i = 0; i < tev->nargs; i++) {
1529                if (tev->args[i].name)
1530                        free(tev->args[i].name);
1531                if (tev->args[i].value)
1532                        free(tev->args[i].value);
1533                if (tev->args[i].type)
1534                        free(tev->args[i].type);
1535                ref = tev->args[i].ref;
1536                while (ref) {
1537                        next = ref->next;
1538                        free(ref);
1539                        ref = next;
1540                }
1541        }
1542        if (tev->args)
1543                free(tev->args);
1544        memset(tev, 0, sizeof(*tev));
1545}
1546
1547static void print_warn_msg(const char *file, bool is_kprobe)
1548{
1549
1550        if (errno == ENOENT) {
1551                const char *config;
1552
1553                if (!is_kprobe)
1554                        config = "CONFIG_UPROBE_EVENTS";
1555                else
1556                        config = "CONFIG_KPROBE_EVENTS";
1557
1558                pr_warning("%s file does not exist - please rebuild kernel"
1559                                " with %s.\n", file, config);
1560        } else
1561                pr_warning("Failed to open %s file: %s\n", file,
1562                                strerror(errno));
1563}
1564
1565static int open_probe_events(const char *trace_file, bool readwrite,
1566                                bool is_kprobe)
1567{
1568        char buf[PATH_MAX];
1569        const char *__debugfs;
1570        int ret;
1571
1572        __debugfs = debugfs_find_mountpoint();
1573        if (__debugfs == NULL) {
1574                pr_warning("Debugfs is not mounted.\n");
1575                return -ENOENT;
1576        }
1577
1578        ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1579        if (ret >= 0) {
1580                pr_debug("Opening %s write=%d\n", buf, readwrite);
1581                if (readwrite && !probe_event_dry_run)
1582                        ret = open(buf, O_RDWR, O_APPEND);
1583                else
1584                        ret = open(buf, O_RDONLY, 0);
1585
1586                if (ret < 0)
1587                        print_warn_msg(buf, is_kprobe);
1588        }
1589        return ret;
1590}
1591
1592static int open_kprobe_events(bool readwrite)
1593{
1594        return open_probe_events("tracing/kprobe_events", readwrite, true);
1595}
1596
1597static int open_uprobe_events(bool readwrite)
1598{
1599        return open_probe_events("tracing/uprobe_events", readwrite, false);
1600}
1601
1602/* Get raw string list of current kprobe_events  or uprobe_events */
1603static struct strlist *get_probe_trace_command_rawlist(int fd)
1604{
1605        int ret, idx;
1606        FILE *fp;
1607        char buf[MAX_CMDLEN];
1608        char *p;
1609        struct strlist *sl;
1610
1611        sl = strlist__new(true, NULL);
1612
1613        fp = fdopen(dup(fd), "r");
1614        while (!feof(fp)) {
1615                p = fgets(buf, MAX_CMDLEN, fp);
1616                if (!p)
1617                        break;
1618
1619                idx = strlen(p) - 1;
1620                if (p[idx] == '\n')
1621                        p[idx] = '\0';
1622                ret = strlist__add(sl, buf);
1623                if (ret < 0) {
1624                        pr_debug("strlist__add failed: %s\n", strerror(-ret));
1625                        strlist__delete(sl);
1626                        return NULL;
1627                }
1628        }
1629        fclose(fp);
1630
1631        return sl;
1632}
1633
1634/* Show an event */
1635static int show_perf_probe_event(struct perf_probe_event *pev)
1636{
1637        int i, ret;
1638        char buf[128];
1639        char *place;
1640
1641        /* Synthesize only event probe point */
1642        place = synthesize_perf_probe_point(&pev->point);
1643        if (!place)
1644                return -EINVAL;
1645
1646        ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
1647        if (ret < 0)
1648                return ret;
1649
1650        printf("  %-20s (on %s", buf, place);
1651
1652        if (pev->nargs > 0) {
1653                printf(" with");
1654                for (i = 0; i < pev->nargs; i++) {
1655                        ret = synthesize_perf_probe_arg(&pev->args[i],
1656                                                        buf, 128);
1657                        if (ret < 0)
1658                                break;
1659                        printf(" %s", buf);
1660                }
1661        }
1662        printf(")\n");
1663        free(place);
1664        return ret;
1665}
1666
1667static int __show_perf_probe_events(int fd, bool is_kprobe)
1668{
1669        int ret = 0;
1670        struct probe_trace_event tev;
1671        struct perf_probe_event pev;
1672        struct strlist *rawlist;
1673        struct str_node *ent;
1674
1675        memset(&tev, 0, sizeof(tev));
1676        memset(&pev, 0, sizeof(pev));
1677
1678        rawlist = get_probe_trace_command_rawlist(fd);
1679        if (!rawlist)
1680                return -ENOENT;
1681
1682        strlist__for_each(ent, rawlist) {
1683                ret = parse_probe_trace_command(ent->s, &tev);
1684                if (ret >= 0) {
1685                        ret = convert_to_perf_probe_event(&tev, &pev,
1686                                                                is_kprobe);
1687                        if (ret >= 0)
1688                                ret = show_perf_probe_event(&pev);
1689                }
1690                clear_perf_probe_event(&pev);
1691                clear_probe_trace_event(&tev);
1692                if (ret < 0)
1693                        break;
1694        }
1695        strlist__delete(rawlist);
1696
1697        return ret;
1698}
1699
1700/* List up current perf-probe events */
1701int show_perf_probe_events(void)
1702{
1703        int fd, ret;
1704
1705        setup_pager();
1706        fd = open_kprobe_events(false);
1707
1708        if (fd < 0)
1709                return fd;
1710
1711        ret = init_vmlinux();
1712        if (ret < 0)
1713                return ret;
1714
1715        ret = __show_perf_probe_events(fd, true);
1716        close(fd);
1717
1718        fd = open_uprobe_events(false);
1719        if (fd >= 0) {
1720                ret = __show_perf_probe_events(fd, false);
1721                close(fd);
1722        }
1723
1724        return ret;
1725}
1726
1727/* Get current perf-probe event names */
1728static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1729{
1730        char buf[128];
1731        struct strlist *sl, *rawlist;
1732        struct str_node *ent;
1733        struct probe_trace_event tev;
1734        int ret = 0;
1735
1736        memset(&tev, 0, sizeof(tev));
1737        rawlist = get_probe_trace_command_rawlist(fd);
1738        sl = strlist__new(true, NULL);
1739        strlist__for_each(ent, rawlist) {
1740                ret = parse_probe_trace_command(ent->s, &tev);
1741                if (ret < 0)
1742                        break;
1743                if (include_group) {
1744                        ret = e_snprintf(buf, 128, "%s:%s", tev.group,
1745                                        tev.event);
1746                        if (ret >= 0)
1747                                ret = strlist__add(sl, buf);
1748                } else
1749                        ret = strlist__add(sl, tev.event);
1750                clear_probe_trace_event(&tev);
1751                if (ret < 0)
1752                        break;
1753        }
1754        strlist__delete(rawlist);
1755
1756        if (ret < 0) {
1757                strlist__delete(sl);
1758                return NULL;
1759        }
1760        return sl;
1761}
1762
1763static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
1764{
1765        int ret = 0;
1766        char *buf = synthesize_probe_trace_command(tev);
1767
1768        if (!buf) {
1769                pr_debug("Failed to synthesize probe trace event.\n");
1770                return -EINVAL;
1771        }
1772
1773        pr_debug("Writing event: %s\n", buf);
1774        if (!probe_event_dry_run) {
1775                ret = write(fd, buf, strlen(buf));
1776                if (ret <= 0)
1777                        pr_warning("Failed to write event: %s\n",
1778                                   strerror(errno));
1779        }
1780        free(buf);
1781        return ret;
1782}
1783
1784static int get_new_event_name(char *buf, size_t len, const char *base,
1785                              struct strlist *namelist, bool allow_suffix)
1786{
1787        int i, ret;
1788
1789        /* Try no suffix */
1790        ret = e_snprintf(buf, len, "%s", base);
1791        if (ret < 0) {
1792                pr_debug("snprintf() failed: %s\n", strerror(-ret));
1793                return ret;
1794        }
1795        if (!strlist__has_entry(namelist, buf))
1796                return 0;
1797
1798        if (!allow_suffix) {
1799                pr_warning("Error: event \"%s\" already exists. "
1800                           "(Use -f to force duplicates.)\n", base);
1801                return -EEXIST;
1802        }
1803
1804        /* Try to add suffix */
1805        for (i = 1; i < MAX_EVENT_INDEX; i++) {
1806                ret = e_snprintf(buf, len, "%s_%d", base, i);
1807                if (ret < 0) {
1808                        pr_debug("snprintf() failed: %s\n", strerror(-ret));
1809                        return ret;
1810                }
1811                if (!strlist__has_entry(namelist, buf))
1812                        break;
1813        }
1814        if (i == MAX_EVENT_INDEX) {
1815                pr_warning("Too many events are on the same function.\n");
1816                ret = -ERANGE;
1817        }
1818
1819        return ret;
1820}
1821
1822static int __add_probe_trace_events(struct perf_probe_event *pev,
1823                                     struct probe_trace_event *tevs,
1824                                     int ntevs, bool allow_suffix)
1825{
1826        int i, fd, ret;
1827        struct probe_trace_event *tev = NULL;
1828        char buf[64];
1829        const char *event, *group;
1830        struct strlist *namelist;
1831
1832        if (pev->uprobes)
1833                fd = open_uprobe_events(true);
1834        else
1835                fd = open_kprobe_events(true);
1836
1837        if (fd < 0)
1838                return fd;
1839        /* Get current event names */
1840        namelist = get_probe_trace_event_names(fd, false);
1841        if (!namelist) {
1842                pr_debug("Failed to get current event list.\n");
1843                return -EIO;
1844        }
1845
1846        ret = 0;
1847        printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
1848        for (i = 0; i < ntevs; i++) {
1849                tev = &tevs[i];
1850                if (pev->event)
1851                        event = pev->event;
1852                else
1853                        if (pev->point.function)
1854                                event = pev->point.function;
1855                        else
1856                                event = tev->point.symbol;
1857                if (pev->group)
1858                        group = pev->group;
1859                else
1860                        group = PERFPROBE_GROUP;
1861
1862                /* Get an unused new event name */
1863                ret = get_new_event_name(buf, 64, event,
1864                                         namelist, allow_suffix);
1865                if (ret < 0)
1866                        break;
1867                event = buf;
1868
1869                tev->event = strdup(event);
1870                tev->group = strdup(group);
1871                if (tev->event == NULL || tev->group == NULL) {
1872                        ret = -ENOMEM;
1873                        break;
1874                }
1875                ret = write_probe_trace_event(fd, tev);
1876                if (ret < 0)
1877                        break;
1878                /* Add added event name to namelist */
1879                strlist__add(namelist, event);
1880
1881                /* Trick here - save current event/group */
1882                event = pev->event;
1883                group = pev->group;
1884                pev->event = tev->event;
1885                pev->group = tev->group;
1886                show_perf_probe_event(pev);
1887                /* Trick here - restore current event/group */
1888                pev->event = (char *)event;
1889                pev->group = (char *)group;
1890
1891                /*
1892                 * Probes after the first probe which comes from same
1893                 * user input are always allowed to add suffix, because
1894                 * there might be several addresses corresponding to
1895                 * one code line.
1896                 */
1897                allow_suffix = true;
1898        }
1899
1900        if (ret >= 0) {
1901                /* Show how to use the event. */
1902                printf("\nYou can now use it in all perf tools, such as:\n\n");
1903                printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1904                         tev->event);
1905        }
1906
1907        strlist__delete(namelist);
1908        close(fd);
1909        return ret;
1910}
1911
1912static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1913                                          struct probe_trace_event **tevs,
1914                                          int max_tevs, const char *target)
1915{
1916        struct symbol *sym;
1917        int ret = 0, i;
1918        struct probe_trace_event *tev;
1919
1920        /* Convert perf_probe_event with debuginfo */
1921        ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
1922        if (ret != 0)
1923                return ret;     /* Found in debuginfo or got an error */
1924
1925        /* Allocate trace event buffer */
1926        tev = *tevs = zalloc(sizeof(struct probe_trace_event));
1927        if (tev == NULL)
1928                return -ENOMEM;
1929
1930        /* Copy parameters */
1931        tev->point.symbol = strdup(pev->point.function);
1932        if (tev->point.symbol == NULL) {
1933                ret = -ENOMEM;
1934                goto error;
1935        }
1936
1937        if (target) {
1938                tev->point.module = strdup(target);
1939                if (tev->point.module == NULL) {
1940                        ret = -ENOMEM;
1941                        goto error;
1942                }
1943        }
1944
1945        tev->point.offset = pev->point.offset;
1946        tev->point.retprobe = pev->point.retprobe;
1947        tev->nargs = pev->nargs;
1948        tev->uprobes = pev->uprobes;
1949
1950        if (tev->nargs) {
1951                tev->args = zalloc(sizeof(struct probe_trace_arg)
1952                                   * tev->nargs);
1953                if (tev->args == NULL) {
1954                        ret = -ENOMEM;
1955                        goto error;
1956                }
1957                for (i = 0; i < tev->nargs; i++) {
1958                        if (pev->args[i].name) {
1959                                tev->args[i].name = strdup(pev->args[i].name);
1960                                if (tev->args[i].name == NULL) {
1961                                        ret = -ENOMEM;
1962                                        goto error;
1963                                }
1964                        }
1965                        tev->args[i].value = strdup(pev->args[i].var);
1966                        if (tev->args[i].value == NULL) {
1967                                ret = -ENOMEM;
1968                                goto error;
1969                        }
1970                        if (pev->args[i].type) {
1971                                tev->args[i].type = strdup(pev->args[i].type);
1972                                if (tev->args[i].type == NULL) {
1973                                        ret = -ENOMEM;
1974                                        goto error;
1975                                }
1976                        }
1977                }
1978        }
1979
1980        if (pev->uprobes)
1981                return 1;
1982
1983        /* Currently just checking function name from symbol map */
1984        sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
1985        if (!sym) {
1986                pr_warning("Kernel symbol \'%s\' not found.\n",
1987                           tev->point.symbol);
1988                ret = -ENOENT;
1989                goto error;
1990        } else if (tev->point.offset > sym->end - sym->start) {
1991                pr_warning("Offset specified is greater than size of %s\n",
1992                           tev->point.symbol);
1993                ret = -ENOENT;
1994                goto error;
1995
1996        }
1997
1998        return 1;
1999error:
2000        clear_probe_trace_event(tev);
2001        free(tev);
2002        *tevs = NULL;
2003        return ret;
2004}
2005
2006struct __event_package {
2007        struct perf_probe_event         *pev;
2008        struct probe_trace_event        *tevs;
2009        int                             ntevs;
2010};
2011
2012int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2013                          int max_tevs, const char *target, bool force_add)
2014{
2015        int i, j, ret;
2016        struct __event_package *pkgs;
2017
2018        ret = 0;
2019        pkgs = zalloc(sizeof(struct __event_package) * npevs);
2020
2021        if (pkgs == NULL)
2022                return -ENOMEM;
2023
2024        if (!pevs->uprobes)
2025                /* Init vmlinux path */
2026                ret = init_vmlinux();
2027        else
2028                ret = init_user_exec();
2029
2030        if (ret < 0) {
2031                free(pkgs);
2032                return ret;
2033        }
2034
2035        /* Loop 1: convert all events */
2036        for (i = 0; i < npevs; i++) {
2037                pkgs[i].pev = &pevs[i];
2038                /* Convert with or without debuginfo */
2039                ret  = convert_to_probe_trace_events(pkgs[i].pev,
2040                                                     &pkgs[i].tevs,
2041                                                     max_tevs,
2042                                                     target);
2043                if (ret < 0)
2044                        goto end;
2045                pkgs[i].ntevs = ret;
2046        }
2047
2048        /* Loop 2: add all events */
2049        for (i = 0; i < npevs; i++) {
2050                ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
2051                                                pkgs[i].ntevs, force_add);
2052                if (ret < 0)
2053                        break;
2054        }
2055end:
2056        /* Loop 3: cleanup and free trace events  */
2057        for (i = 0; i < npevs; i++) {
2058                for (j = 0; j < pkgs[i].ntevs; j++)
2059                        clear_probe_trace_event(&pkgs[i].tevs[j]);
2060                free(pkgs[i].tevs);
2061        }
2062        free(pkgs);
2063
2064        return ret;
2065}
2066
2067static int __del_trace_probe_event(int fd, struct str_node *ent)
2068{
2069        char *p;
2070        char buf[128];
2071        int ret;
2072
2073        /* Convert from perf-probe event to trace-probe event */
2074        ret = e_snprintf(buf, 128, "-:%s", ent->s);
2075        if (ret < 0)
2076                goto error;
2077
2078        p = strchr(buf + 2, ':');
2079        if (!p) {
2080                pr_debug("Internal error: %s should have ':' but not.\n",
2081                         ent->s);
2082                ret = -ENOTSUP;
2083                goto error;
2084        }
2085        *p = '/';
2086
2087        pr_debug("Writing event: %s\n", buf);
2088        ret = write(fd, buf, strlen(buf));
2089        if (ret < 0) {
2090                ret = -errno;
2091                goto error;
2092        }
2093
2094        printf("Removed event: %s\n", ent->s);
2095        return 0;
2096error:
2097        pr_warning("Failed to delete event: %s\n", strerror(-ret));
2098        return ret;
2099}
2100
2101static int del_trace_probe_event(int fd, const char *buf,
2102                                                  struct strlist *namelist)
2103{
2104        struct str_node *ent, *n;
2105        int ret = -1;
2106
2107        if (strpbrk(buf, "*?")) { /* Glob-exp */
2108                strlist__for_each_safe(ent, n, namelist)
2109                        if (strglobmatch(ent->s, buf)) {
2110                                ret = __del_trace_probe_event(fd, ent);
2111                                if (ret < 0)
2112                                        break;
2113                                strlist__remove(namelist, ent);
2114                        }
2115        } else {
2116                ent = strlist__find(namelist, buf);
2117                if (ent) {
2118                        ret = __del_trace_probe_event(fd, ent);
2119                        if (ret >= 0)
2120                                strlist__remove(namelist, ent);
2121                }
2122        }
2123
2124        return ret;
2125}
2126
2127int del_perf_probe_events(struct strlist *dellist)
2128{
2129        int ret = -1, ufd = -1, kfd = -1;
2130        char buf[128];
2131        const char *group, *event;
2132        char *p, *str;
2133        struct str_node *ent;
2134        struct strlist *namelist = NULL, *unamelist = NULL;
2135
2136        /* Get current event names */
2137        kfd = open_kprobe_events(true);
2138        if (kfd < 0)
2139                return kfd;
2140
2141        namelist = get_probe_trace_event_names(kfd, true);
2142        ufd = open_uprobe_events(true);
2143
2144        if (ufd >= 0)
2145                unamelist = get_probe_trace_event_names(ufd, true);
2146
2147        if (namelist == NULL && unamelist == NULL)
2148                goto error;
2149
2150        strlist__for_each(ent, dellist) {
2151                str = strdup(ent->s);
2152                if (str == NULL) {
2153                        ret = -ENOMEM;
2154                        goto error;
2155                }
2156                pr_debug("Parsing: %s\n", str);
2157                p = strchr(str, ':');
2158                if (p) {
2159                        group = str;
2160                        *p = '\0';
2161                        event = p + 1;
2162                } else {
2163                        group = "*";
2164                        event = str;
2165                }
2166
2167                ret = e_snprintf(buf, 128, "%s:%s", group, event);
2168                if (ret < 0) {
2169                        pr_err("Failed to copy event.");
2170                        free(str);
2171                        goto error;
2172                }
2173
2174                pr_debug("Group: %s, Event: %s\n", group, event);
2175
2176                if (namelist)
2177                        ret = del_trace_probe_event(kfd, buf, namelist);
2178
2179                if (unamelist && ret != 0)
2180                        ret = del_trace_probe_event(ufd, buf, unamelist);
2181
2182                if (ret != 0)
2183                        pr_info("Info: Event \"%s\" does not exist.\n", buf);
2184
2185                free(str);
2186        }
2187
2188error:
2189        if (kfd >= 0) {
2190                strlist__delete(namelist);
2191                close(kfd);
2192        }
2193
2194        if (ufd >= 0) {
2195                strlist__delete(unamelist);
2196                close(ufd);
2197        }
2198
2199        return ret;
2200}
2201
2202/* TODO: don't use a global variable for filter ... */
2203static struct strfilter *available_func_filter;
2204
2205/*
2206 * If a symbol corresponds to a function with global binding and
2207 * matches filter return 0. For all others return 1.
2208 */
2209static int filter_available_functions(struct map *map __maybe_unused,
2210                                      struct symbol *sym)
2211{
2212        if (sym->binding == STB_GLOBAL &&
2213            strfilter__compare(available_func_filter, sym->name))
2214                return 0;
2215        return 1;
2216}
2217
2218static int __show_available_funcs(struct map *map)
2219{
2220        if (map__load(map, filter_available_functions)) {
2221                pr_err("Failed to load map.\n");
2222                return -EINVAL;
2223        }
2224        if (!dso__sorted_by_name(map->dso, map->type))
2225                dso__sort_by_name(map->dso, map->type);
2226
2227        dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2228        return 0;
2229}
2230
2231static int available_kernel_funcs(const char *module)
2232{
2233        struct map *map;
2234        int ret;
2235
2236        ret = init_vmlinux();
2237        if (ret < 0)
2238                return ret;
2239
2240        map = kernel_get_module_map(module);
2241        if (!map) {
2242                pr_err("Failed to find %s map.\n", (module) ? : "kernel");
2243                return -EINVAL;
2244        }
2245        return __show_available_funcs(map);
2246}
2247
2248static int available_user_funcs(const char *target)
2249{
2250        struct map *map;
2251        int ret;
2252
2253        ret = init_user_exec();
2254        if (ret < 0)
2255                return ret;
2256
2257        map = dso__new_map(target);
2258        ret = __show_available_funcs(map);
2259        dso__delete(map->dso);
2260        map__delete(map);
2261        return ret;
2262}
2263
2264int show_available_funcs(const char *target, struct strfilter *_filter,
2265                                        bool user)
2266{
2267        setup_pager();
2268        available_func_filter = _filter;
2269
2270        if (!user)
2271                return available_kernel_funcs(target);
2272
2273        return available_user_funcs(target);
2274}
2275
2276/*
2277 * uprobe_events only accepts address:
2278 * Convert function and any offset to address
2279 */
2280static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2281{
2282        struct perf_probe_point *pp = &pev->point;
2283        struct symbol *sym;
2284        struct map *map = NULL;
2285        char *function = NULL, *name = NULL;
2286        int ret = -EINVAL;
2287        unsigned long long vaddr = 0;
2288
2289        if (!pp->function) {
2290                pr_warning("No function specified for uprobes");
2291                goto out;
2292        }
2293
2294        function = strdup(pp->function);
2295        if (!function) {
2296                pr_warning("Failed to allocate memory by strdup.\n");
2297                ret = -ENOMEM;
2298                goto out;
2299        }
2300
2301        name = realpath(exec, NULL);
2302        if (!name) {
2303                pr_warning("Cannot find realpath for %s.\n", exec);
2304                goto out;
2305        }
2306        map = dso__new_map(name);
2307        if (!map) {
2308                pr_warning("Cannot find appropriate DSO for %s.\n", exec);
2309                goto out;
2310        }
2311        available_func_filter = strfilter__new(function, NULL);
2312        if (map__load(map, filter_available_functions)) {
2313                pr_err("Failed to load map.\n");
2314                goto out;
2315        }
2316
2317        sym = map__find_symbol_by_name(map, function, NULL);
2318        if (!sym) {
2319                pr_warning("Cannot find %s in DSO %s\n", function, exec);
2320                goto out;
2321        }
2322
2323        if (map->start > sym->start)
2324                vaddr = map->start;
2325        vaddr += sym->start + pp->offset + map->pgoff;
2326        pp->offset = 0;
2327
2328        if (!pev->event) {
2329                pev->event = function;
2330                function = NULL;
2331        }
2332        if (!pev->group) {
2333                char *ptr1, *ptr2, *exec_copy;
2334
2335                pev->group = zalloc(sizeof(char *) * 64);
2336                exec_copy = strdup(exec);
2337                if (!exec_copy) {
2338                        ret = -ENOMEM;
2339                        pr_warning("Failed to copy exec string.\n");
2340                        goto out;
2341                }
2342
2343                ptr1 = strdup(basename(exec_copy));
2344                if (ptr1) {
2345                        ptr2 = strpbrk(ptr1, "-._");
2346                        if (ptr2)
2347                                *ptr2 = '\0';
2348                        e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP,
2349                                        ptr1);
2350                        free(ptr1);
2351                }
2352                free(exec_copy);
2353        }
2354        free(pp->function);
2355        pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS);
2356        if (!pp->function) {
2357                ret = -ENOMEM;
2358                pr_warning("Failed to allocate memory by zalloc.\n");
2359                goto out;
2360        }
2361        e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr);
2362        ret = 0;
2363
2364out:
2365        if (map) {
2366                dso__delete(map->dso);
2367                map__delete(map);
2368        }
2369        if (function)
2370                free(function);
2371        if (name)
2372                free(name);
2373        return ret;
2374}
2375