linux/tools/perf/util/probe-file.c
<<
>>
Prefs
   1/*
   2 * probe-file.c : operate ftrace k/uprobe events files
   3 *
   4 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.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 */
  17#include <errno.h>
  18#include <fcntl.h>
  19#include <sys/stat.h>
  20#include <sys/types.h>
  21#include <sys/uio.h>
  22#include <unistd.h>
  23#include "util.h"
  24#include "event.h"
  25#include "strlist.h"
  26#include "strfilter.h"
  27#include "debug.h"
  28#include "cache.h"
  29#include "color.h"
  30#include "symbol.h"
  31#include "thread.h"
  32#include <api/fs/tracing_path.h>
  33#include "probe-event.h"
  34#include "probe-file.h"
  35#include "session.h"
  36#include "perf_regs.h"
  37#include "string2.h"
  38
  39/* 4096 - 2 ('\n' + '\0') */
  40#define MAX_CMDLEN 4094
  41
  42static void print_open_warning(int err, bool uprobe)
  43{
  44        char sbuf[STRERR_BUFSIZE];
  45
  46        if (err == -ENOENT) {
  47                const char *config;
  48
  49                if (uprobe)
  50                        config = "CONFIG_UPROBE_EVENTS";
  51                else
  52                        config = "CONFIG_KPROBE_EVENTS";
  53
  54                pr_warning("%cprobe_events file does not exist"
  55                           " - please rebuild kernel with %s.\n",
  56                           uprobe ? 'u' : 'k', config);
  57        } else if (err == -ENOTSUP)
  58                pr_warning("Tracefs or debugfs is not mounted.\n");
  59        else
  60                pr_warning("Failed to open %cprobe_events: %s\n",
  61                           uprobe ? 'u' : 'k',
  62                           str_error_r(-err, sbuf, sizeof(sbuf)));
  63}
  64
  65static void print_both_open_warning(int kerr, int uerr)
  66{
  67        /* Both kprobes and uprobes are disabled, warn it. */
  68        if (kerr == -ENOTSUP && uerr == -ENOTSUP)
  69                pr_warning("Tracefs or debugfs is not mounted.\n");
  70        else if (kerr == -ENOENT && uerr == -ENOENT)
  71                pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
  72                           "or/and CONFIG_UPROBE_EVENTS.\n");
  73        else {
  74                char sbuf[STRERR_BUFSIZE];
  75                pr_warning("Failed to open kprobe events: %s.\n",
  76                           str_error_r(-kerr, sbuf, sizeof(sbuf)));
  77                pr_warning("Failed to open uprobe events: %s.\n",
  78                           str_error_r(-uerr, sbuf, sizeof(sbuf)));
  79        }
  80}
  81
  82int open_trace_file(const char *trace_file, bool readwrite)
  83{
  84        char buf[PATH_MAX];
  85        int ret;
  86
  87        ret = e_snprintf(buf, PATH_MAX, "%s/%s",
  88                         tracing_path, trace_file);
  89        if (ret >= 0) {
  90                pr_debug("Opening %s write=%d\n", buf, readwrite);
  91                if (readwrite && !probe_event_dry_run)
  92                        ret = open(buf, O_RDWR | O_APPEND, 0);
  93                else
  94                        ret = open(buf, O_RDONLY, 0);
  95
  96                if (ret < 0)
  97                        ret = -errno;
  98        }
  99        return ret;
 100}
 101
 102static int open_kprobe_events(bool readwrite)
 103{
 104        return open_trace_file("kprobe_events", readwrite);
 105}
 106
 107static int open_uprobe_events(bool readwrite)
 108{
 109        return open_trace_file("uprobe_events", readwrite);
 110}
 111
 112int probe_file__open(int flag)
 113{
 114        int fd;
 115
 116        if (flag & PF_FL_UPROBE)
 117                fd = open_uprobe_events(flag & PF_FL_RW);
 118        else
 119                fd = open_kprobe_events(flag & PF_FL_RW);
 120        if (fd < 0)
 121                print_open_warning(fd, flag & PF_FL_UPROBE);
 122
 123        return fd;
 124}
 125
 126int probe_file__open_both(int *kfd, int *ufd, int flag)
 127{
 128        if (!kfd || !ufd)
 129                return -EINVAL;
 130
 131        *kfd = open_kprobe_events(flag & PF_FL_RW);
 132        *ufd = open_uprobe_events(flag & PF_FL_RW);
 133        if (*kfd < 0 && *ufd < 0) {
 134                print_both_open_warning(*kfd, *ufd);
 135                return *kfd;
 136        }
 137
 138        return 0;
 139}
 140
 141/* Get raw string list of current kprobe_events  or uprobe_events */
 142struct strlist *probe_file__get_rawlist(int fd)
 143{
 144        int ret, idx, fddup;
 145        FILE *fp;
 146        char buf[MAX_CMDLEN];
 147        char *p;
 148        struct strlist *sl;
 149
 150        if (fd < 0)
 151                return NULL;
 152
 153        sl = strlist__new(NULL, NULL);
 154        if (sl == NULL)
 155                return NULL;
 156
 157        fddup = dup(fd);
 158        if (fddup < 0)
 159                goto out_free_sl;
 160
 161        fp = fdopen(fddup, "r");
 162        if (!fp)
 163                goto out_close_fddup;
 164
 165        while (!feof(fp)) {
 166                p = fgets(buf, MAX_CMDLEN, fp);
 167                if (!p)
 168                        break;
 169
 170                idx = strlen(p) - 1;
 171                if (p[idx] == '\n')
 172                        p[idx] = '\0';
 173                ret = strlist__add(sl, buf);
 174                if (ret < 0) {
 175                        pr_debug("strlist__add failed (%d)\n", ret);
 176                        goto out_close_fp;
 177                }
 178        }
 179        fclose(fp);
 180
 181        return sl;
 182
 183out_close_fp:
 184        fclose(fp);
 185        goto out_free_sl;
 186out_close_fddup:
 187        close(fddup);
 188out_free_sl:
 189        strlist__delete(sl);
 190        return NULL;
 191}
 192
 193static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
 194{
 195        char buf[128];
 196        struct strlist *sl, *rawlist;
 197        struct str_node *ent;
 198        struct probe_trace_event tev;
 199        int ret = 0;
 200
 201        memset(&tev, 0, sizeof(tev));
 202        rawlist = probe_file__get_rawlist(fd);
 203        if (!rawlist)
 204                return NULL;
 205        sl = strlist__new(NULL, NULL);
 206        strlist__for_each_entry(ent, rawlist) {
 207                ret = parse_probe_trace_command(ent->s, &tev);
 208                if (ret < 0)
 209                        break;
 210                if (include_group) {
 211                        ret = e_snprintf(buf, 128, "%s:%s", tev.group,
 212                                        tev.event);
 213                        if (ret >= 0)
 214                                ret = strlist__add(sl, buf);
 215                } else
 216                        ret = strlist__add(sl, tev.event);
 217                clear_probe_trace_event(&tev);
 218                if (ret < 0)
 219                        break;
 220        }
 221        strlist__delete(rawlist);
 222
 223        if (ret < 0) {
 224                strlist__delete(sl);
 225                return NULL;
 226        }
 227        return sl;
 228}
 229
 230/* Get current perf-probe event names */
 231struct strlist *probe_file__get_namelist(int fd)
 232{
 233        return __probe_file__get_namelist(fd, false);
 234}
 235
 236int probe_file__add_event(int fd, struct probe_trace_event *tev)
 237{
 238        int ret = 0;
 239        char *buf = synthesize_probe_trace_command(tev);
 240        char sbuf[STRERR_BUFSIZE];
 241
 242        if (!buf) {
 243                pr_debug("Failed to synthesize probe trace event.\n");
 244                return -EINVAL;
 245        }
 246
 247        pr_debug("Writing event: %s\n", buf);
 248        if (!probe_event_dry_run) {
 249                if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
 250                        ret = -errno;
 251                        pr_warning("Failed to write event: %s\n",
 252                                   str_error_r(errno, sbuf, sizeof(sbuf)));
 253                }
 254        }
 255        free(buf);
 256
 257        return ret;
 258}
 259
 260static int __del_trace_probe_event(int fd, struct str_node *ent)
 261{
 262        char *p;
 263        char buf[128];
 264        int ret;
 265
 266        /* Convert from perf-probe event to trace-probe event */
 267        ret = e_snprintf(buf, 128, "-:%s", ent->s);
 268        if (ret < 0)
 269                goto error;
 270
 271        p = strchr(buf + 2, ':');
 272        if (!p) {
 273                pr_debug("Internal error: %s should have ':' but not.\n",
 274                         ent->s);
 275                ret = -ENOTSUP;
 276                goto error;
 277        }
 278        *p = '/';
 279
 280        pr_debug("Writing event: %s\n", buf);
 281        ret = write(fd, buf, strlen(buf));
 282        if (ret < 0) {
 283                ret = -errno;
 284                goto error;
 285        }
 286
 287        return 0;
 288error:
 289        pr_warning("Failed to delete event: %s\n",
 290                   str_error_r(-ret, buf, sizeof(buf)));
 291        return ret;
 292}
 293
 294int probe_file__get_events(int fd, struct strfilter *filter,
 295                           struct strlist *plist)
 296{
 297        struct strlist *namelist;
 298        struct str_node *ent;
 299        const char *p;
 300        int ret = -ENOENT;
 301
 302        if (!plist)
 303                return -EINVAL;
 304
 305        namelist = __probe_file__get_namelist(fd, true);
 306        if (!namelist)
 307                return -ENOENT;
 308
 309        strlist__for_each_entry(ent, namelist) {
 310                p = strchr(ent->s, ':');
 311                if ((p && strfilter__compare(filter, p + 1)) ||
 312                    strfilter__compare(filter, ent->s)) {
 313                        strlist__add(plist, ent->s);
 314                        ret = 0;
 315                }
 316        }
 317        strlist__delete(namelist);
 318
 319        return ret;
 320}
 321
 322int probe_file__del_strlist(int fd, struct strlist *namelist)
 323{
 324        int ret = 0;
 325        struct str_node *ent;
 326
 327        strlist__for_each_entry(ent, namelist) {
 328                ret = __del_trace_probe_event(fd, ent);
 329                if (ret < 0)
 330                        break;
 331        }
 332        return ret;
 333}
 334
 335int probe_file__del_events(int fd, struct strfilter *filter)
 336{
 337        struct strlist *namelist;
 338        int ret;
 339
 340        namelist = strlist__new(NULL, NULL);
 341        if (!namelist)
 342                return -ENOMEM;
 343
 344        ret = probe_file__get_events(fd, filter, namelist);
 345        if (ret < 0)
 346                return ret;
 347
 348        ret = probe_file__del_strlist(fd, namelist);
 349        strlist__delete(namelist);
 350
 351        return ret;
 352}
 353
 354/* Caller must ensure to remove this entry from list */
 355static void probe_cache_entry__delete(struct probe_cache_entry *entry)
 356{
 357        if (entry) {
 358                BUG_ON(!list_empty(&entry->node));
 359
 360                strlist__delete(entry->tevlist);
 361                clear_perf_probe_event(&entry->pev);
 362                zfree(&entry->spev);
 363                free(entry);
 364        }
 365}
 366
 367static struct probe_cache_entry *
 368probe_cache_entry__new(struct perf_probe_event *pev)
 369{
 370        struct probe_cache_entry *entry = zalloc(sizeof(*entry));
 371
 372        if (entry) {
 373                INIT_LIST_HEAD(&entry->node);
 374                entry->tevlist = strlist__new(NULL, NULL);
 375                if (!entry->tevlist)
 376                        zfree(&entry);
 377                else if (pev) {
 378                        entry->spev = synthesize_perf_probe_command(pev);
 379                        if (!entry->spev ||
 380                            perf_probe_event__copy(&entry->pev, pev) < 0) {
 381                                probe_cache_entry__delete(entry);
 382                                return NULL;
 383                        }
 384                }
 385        }
 386
 387        return entry;
 388}
 389
 390int probe_cache_entry__get_event(struct probe_cache_entry *entry,
 391                                 struct probe_trace_event **tevs)
 392{
 393        struct probe_trace_event *tev;
 394        struct str_node *node;
 395        int ret, i;
 396
 397        ret = strlist__nr_entries(entry->tevlist);
 398        if (ret > probe_conf.max_probes)
 399                return -E2BIG;
 400
 401        *tevs = zalloc(ret * sizeof(*tev));
 402        if (!*tevs)
 403                return -ENOMEM;
 404
 405        i = 0;
 406        strlist__for_each_entry(node, entry->tevlist) {
 407                tev = &(*tevs)[i++];
 408                ret = parse_probe_trace_command(node->s, tev);
 409                if (ret < 0)
 410                        break;
 411        }
 412        return i;
 413}
 414
 415/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
 416static int probe_cache__open(struct probe_cache *pcache, const char *target,
 417                             struct nsinfo *nsi)
 418{
 419        char cpath[PATH_MAX];
 420        char sbuildid[SBUILD_ID_SIZE];
 421        char *dir_name = NULL;
 422        bool is_kallsyms = false;
 423        int ret, fd;
 424        struct nscookie nsc;
 425
 426        if (target && build_id_cache__cached(target)) {
 427                /* This is a cached buildid */
 428                strncpy(sbuildid, target, SBUILD_ID_SIZE);
 429                dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
 430                goto found;
 431        }
 432
 433        if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
 434                target = DSO__NAME_KALLSYMS;
 435                is_kallsyms = true;
 436                ret = sysfs__sprintf_build_id("/", sbuildid);
 437        } else {
 438                nsinfo__mountns_enter(nsi, &nsc);
 439                ret = filename__sprintf_build_id(target, sbuildid);
 440                nsinfo__mountns_exit(&nsc);
 441        }
 442
 443        if (ret < 0) {
 444                pr_debug("Failed to get build-id from %s.\n", target);
 445                return ret;
 446        }
 447
 448        /* If we have no buildid cache, make it */
 449        if (!build_id_cache__cached(sbuildid)) {
 450                ret = build_id_cache__add_s(sbuildid, target, nsi,
 451                                            is_kallsyms, NULL);
 452                if (ret < 0) {
 453                        pr_debug("Failed to add build-id cache: %s\n", target);
 454                        return ret;
 455                }
 456        }
 457
 458        dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
 459                                            false);
 460found:
 461        if (!dir_name) {
 462                pr_debug("Failed to get cache from %s\n", target);
 463                return -ENOMEM;
 464        }
 465
 466        snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
 467        fd = open(cpath, O_CREAT | O_RDWR, 0644);
 468        if (fd < 0)
 469                pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
 470        free(dir_name);
 471        pcache->fd = fd;
 472
 473        return fd;
 474}
 475
 476static int probe_cache__load(struct probe_cache *pcache)
 477{
 478        struct probe_cache_entry *entry = NULL;
 479        char buf[MAX_CMDLEN], *p;
 480        int ret = 0, fddup;
 481        FILE *fp;
 482
 483        fddup = dup(pcache->fd);
 484        if (fddup < 0)
 485                return -errno;
 486        fp = fdopen(fddup, "r");
 487        if (!fp) {
 488                close(fddup);
 489                return -EINVAL;
 490        }
 491
 492        while (!feof(fp)) {
 493                if (!fgets(buf, MAX_CMDLEN, fp))
 494                        break;
 495                p = strchr(buf, '\n');
 496                if (p)
 497                        *p = '\0';
 498                /* #perf_probe_event or %sdt_event */
 499                if (buf[0] == '#' || buf[0] == '%') {
 500                        entry = probe_cache_entry__new(NULL);
 501                        if (!entry) {
 502                                ret = -ENOMEM;
 503                                goto out;
 504                        }
 505                        if (buf[0] == '%')
 506                                entry->sdt = true;
 507                        entry->spev = strdup(buf + 1);
 508                        if (entry->spev)
 509                                ret = parse_perf_probe_command(buf + 1,
 510                                                                &entry->pev);
 511                        else
 512                                ret = -ENOMEM;
 513                        if (ret < 0) {
 514                                probe_cache_entry__delete(entry);
 515                                goto out;
 516                        }
 517                        list_add_tail(&entry->node, &pcache->entries);
 518                } else {        /* trace_probe_event */
 519                        if (!entry) {
 520                                ret = -EINVAL;
 521                                goto out;
 522                        }
 523                        strlist__add(entry->tevlist, buf);
 524                }
 525        }
 526out:
 527        fclose(fp);
 528        return ret;
 529}
 530
 531static struct probe_cache *probe_cache__alloc(void)
 532{
 533        struct probe_cache *pcache = zalloc(sizeof(*pcache));
 534
 535        if (pcache) {
 536                INIT_LIST_HEAD(&pcache->entries);
 537                pcache->fd = -EINVAL;
 538        }
 539        return pcache;
 540}
 541
 542void probe_cache__purge(struct probe_cache *pcache)
 543{
 544        struct probe_cache_entry *entry, *n;
 545
 546        list_for_each_entry_safe(entry, n, &pcache->entries, node) {
 547                list_del_init(&entry->node);
 548                probe_cache_entry__delete(entry);
 549        }
 550}
 551
 552void probe_cache__delete(struct probe_cache *pcache)
 553{
 554        if (!pcache)
 555                return;
 556
 557        probe_cache__purge(pcache);
 558        if (pcache->fd > 0)
 559                close(pcache->fd);
 560        free(pcache);
 561}
 562
 563struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
 564{
 565        struct probe_cache *pcache = probe_cache__alloc();
 566        int ret;
 567
 568        if (!pcache)
 569                return NULL;
 570
 571        ret = probe_cache__open(pcache, target, nsi);
 572        if (ret < 0) {
 573                pr_debug("Cache open error: %d\n", ret);
 574                goto out_err;
 575        }
 576
 577        ret = probe_cache__load(pcache);
 578        if (ret < 0) {
 579                pr_debug("Cache read error: %d\n", ret);
 580                goto out_err;
 581        }
 582
 583        return pcache;
 584
 585out_err:
 586        probe_cache__delete(pcache);
 587        return NULL;
 588}
 589
 590static bool streql(const char *a, const char *b)
 591{
 592        if (a == b)
 593                return true;
 594
 595        if (!a || !b)
 596                return false;
 597
 598        return !strcmp(a, b);
 599}
 600
 601struct probe_cache_entry *
 602probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 603{
 604        struct probe_cache_entry *entry = NULL;
 605        char *cmd = synthesize_perf_probe_command(pev);
 606
 607        if (!cmd)
 608                return NULL;
 609
 610        for_each_probe_cache_entry(entry, pcache) {
 611                if (pev->sdt) {
 612                        if (entry->pev.event &&
 613                            streql(entry->pev.event, pev->event) &&
 614                            (!pev->group ||
 615                             streql(entry->pev.group, pev->group)))
 616                                goto found;
 617
 618                        continue;
 619                }
 620                /* Hit if same event name or same command-string */
 621                if ((pev->event &&
 622                     (streql(entry->pev.group, pev->group) &&
 623                      streql(entry->pev.event, pev->event))) ||
 624                    (!strcmp(entry->spev, cmd)))
 625                        goto found;
 626        }
 627        entry = NULL;
 628
 629found:
 630        free(cmd);
 631        return entry;
 632}
 633
 634struct probe_cache_entry *
 635probe_cache__find_by_name(struct probe_cache *pcache,
 636                          const char *group, const char *event)
 637{
 638        struct probe_cache_entry *entry = NULL;
 639
 640        for_each_probe_cache_entry(entry, pcache) {
 641                /* Hit if same event name or same command-string */
 642                if (streql(entry->pev.group, group) &&
 643                    streql(entry->pev.event, event))
 644                        goto found;
 645        }
 646        entry = NULL;
 647
 648found:
 649        return entry;
 650}
 651
 652int probe_cache__add_entry(struct probe_cache *pcache,
 653                           struct perf_probe_event *pev,
 654                           struct probe_trace_event *tevs, int ntevs)
 655{
 656        struct probe_cache_entry *entry = NULL;
 657        char *command;
 658        int i, ret = 0;
 659
 660        if (!pcache || !pev || !tevs || ntevs <= 0) {
 661                ret = -EINVAL;
 662                goto out_err;
 663        }
 664
 665        /* Remove old cache entry */
 666        entry = probe_cache__find(pcache, pev);
 667        if (entry) {
 668                list_del_init(&entry->node);
 669                probe_cache_entry__delete(entry);
 670        }
 671
 672        ret = -ENOMEM;
 673        entry = probe_cache_entry__new(pev);
 674        if (!entry)
 675                goto out_err;
 676
 677        for (i = 0; i < ntevs; i++) {
 678                if (!tevs[i].point.symbol)
 679                        continue;
 680
 681                command = synthesize_probe_trace_command(&tevs[i]);
 682                if (!command)
 683                        goto out_err;
 684                strlist__add(entry->tevlist, command);
 685                free(command);
 686        }
 687        list_add_tail(&entry->node, &pcache->entries);
 688        pr_debug("Added probe cache: %d\n", ntevs);
 689        return 0;
 690
 691out_err:
 692        pr_debug("Failed to add probe caches\n");
 693        probe_cache_entry__delete(entry);
 694        return ret;
 695}
 696
 697#ifdef HAVE_GELF_GETNOTE_SUPPORT
 698static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 699{
 700        return note->bit32 ? (unsigned long long)note->addr.a32[0]
 701                 : (unsigned long long)note->addr.a64[0];
 702}
 703
 704static const char * const type_to_suffix[] = {
 705        ":s64", "", "", "", ":s32", "", ":s16", ":s8",
 706        "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
 707};
 708
 709/*
 710 * Isolate the string number and convert it into a decimal value;
 711 * this will be an index to get suffix of the uprobe name (defining
 712 * the type)
 713 */
 714static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
 715{
 716        long type_idx;
 717
 718        type_idx = strtol(n_ptr, NULL, 10);
 719        if (type_idx < -8 || type_idx > 8) {
 720                pr_debug4("Failed to get a valid sdt type\n");
 721                return -1;
 722        }
 723
 724        *suffix = type_to_suffix[type_idx + 8];
 725        return 0;
 726}
 727
 728static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
 729{
 730        char *op, *desc = strdup(arg), *new_op = NULL;
 731        const char *suffix = "";
 732        int ret = -1;
 733
 734        if (desc == NULL) {
 735                pr_debug4("Allocation error\n");
 736                return ret;
 737        }
 738
 739        /*
 740         * Argument is in N@OP format. N is size of the argument and OP is
 741         * the actual assembly operand. N can be omitted; in that case
 742         * argument is just OP(without @).
 743         */
 744        op = strchr(desc, '@');
 745        if (op) {
 746                op[0] = '\0';
 747                op++;
 748
 749                if (sdt_arg_parse_size(desc, &suffix))
 750                        goto error;
 751        } else {
 752                op = desc;
 753        }
 754
 755        ret = arch_sdt_arg_parse_op(op, &new_op);
 756
 757        if (ret < 0)
 758                goto error;
 759
 760        if (ret == SDT_ARG_VALID) {
 761                ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
 762                if (ret < 0)
 763                        goto error;
 764        }
 765
 766        ret = 0;
 767error:
 768        free(desc);
 769        free(new_op);
 770        return ret;
 771}
 772
 773static char *synthesize_sdt_probe_command(struct sdt_note *note,
 774                                        const char *pathname,
 775                                        const char *sdtgrp)
 776{
 777        struct strbuf buf;
 778        char *ret = NULL, **args;
 779        int i, args_count;
 780
 781        if (strbuf_init(&buf, 32) < 0)
 782                return NULL;
 783
 784        if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
 785                                sdtgrp, note->name, pathname,
 786                                sdt_note__get_addr(note)) < 0)
 787                goto error;
 788
 789        if (!note->args)
 790                goto out;
 791
 792        if (note->args) {
 793                args = argv_split(note->args, &args_count);
 794
 795                for (i = 0; i < args_count; ++i) {
 796                        if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
 797                                goto error;
 798                }
 799        }
 800
 801out:
 802        ret = strbuf_detach(&buf, NULL);
 803error:
 804        strbuf_release(&buf);
 805        return ret;
 806}
 807
 808int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 809{
 810        struct probe_cache_entry *entry = NULL;
 811        struct list_head sdtlist;
 812        struct sdt_note *note;
 813        char *buf;
 814        char sdtgrp[64];
 815        int ret;
 816
 817        INIT_LIST_HEAD(&sdtlist);
 818        ret = get_sdt_note_list(&sdtlist, pathname);
 819        if (ret < 0) {
 820                pr_debug4("Failed to get sdt note: %d\n", ret);
 821                return ret;
 822        }
 823        list_for_each_entry(note, &sdtlist, note_list) {
 824                ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
 825                if (ret < 0)
 826                        break;
 827                /* Try to find same-name entry */
 828                entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
 829                if (!entry) {
 830                        entry = probe_cache_entry__new(NULL);
 831                        if (!entry) {
 832                                ret = -ENOMEM;
 833                                break;
 834                        }
 835                        entry->sdt = true;
 836                        ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
 837                                        note->name, note->name);
 838                        if (ret < 0)
 839                                break;
 840                        entry->pev.event = strdup(note->name);
 841                        entry->pev.group = strdup(sdtgrp);
 842                        list_add_tail(&entry->node, &pcache->entries);
 843                }
 844                buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
 845                if (!buf) {
 846                        ret = -ENOMEM;
 847                        break;
 848                }
 849
 850                strlist__add(entry->tevlist, buf);
 851                free(buf);
 852                entry = NULL;
 853        }
 854        if (entry) {
 855                list_del_init(&entry->node);
 856                probe_cache_entry__delete(entry);
 857        }
 858        cleanup_sdt_note_list(&sdtlist);
 859        return ret;
 860}
 861#endif
 862
 863static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
 864{
 865        struct str_node *snode;
 866        struct stat st;
 867        struct iovec iov[3];
 868        const char *prefix = entry->sdt ? "%" : "#";
 869        int ret;
 870        /* Save stat for rollback */
 871        ret = fstat(fd, &st);
 872        if (ret < 0)
 873                return ret;
 874
 875        pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
 876        iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
 877        iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
 878        iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
 879        ret = writev(fd, iov, 3);
 880        if (ret < (int)iov[1].iov_len + 2)
 881                goto rollback;
 882
 883        strlist__for_each_entry(snode, entry->tevlist) {
 884                iov[0].iov_base = (void *)snode->s;
 885                iov[0].iov_len = strlen(snode->s);
 886                iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
 887                ret = writev(fd, iov, 2);
 888                if (ret < (int)iov[0].iov_len + 1)
 889                        goto rollback;
 890        }
 891        return 0;
 892
 893rollback:
 894        /* Rollback to avoid cache file corruption */
 895        if (ret > 0)
 896                ret = -1;
 897        if (ftruncate(fd, st.st_size) < 0)
 898                ret = -2;
 899
 900        return ret;
 901}
 902
 903int probe_cache__commit(struct probe_cache *pcache)
 904{
 905        struct probe_cache_entry *entry;
 906        int ret = 0;
 907
 908        /* TBD: if we do not update existing entries, skip it */
 909        ret = lseek(pcache->fd, 0, SEEK_SET);
 910        if (ret < 0)
 911                goto out;
 912
 913        ret = ftruncate(pcache->fd, 0);
 914        if (ret < 0)
 915                goto out;
 916
 917        for_each_probe_cache_entry(entry, pcache) {
 918                ret = probe_cache_entry__write(entry, pcache->fd);
 919                pr_debug("Cache committed: %d\n", ret);
 920                if (ret < 0)
 921                        break;
 922        }
 923out:
 924        return ret;
 925}
 926
 927static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
 928                                       struct strfilter *filter)
 929{
 930        char buf[128], *ptr = entry->spev;
 931
 932        if (entry->pev.event) {
 933                snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
 934                ptr = buf;
 935        }
 936        return strfilter__compare(filter, ptr);
 937}
 938
 939int probe_cache__filter_purge(struct probe_cache *pcache,
 940                              struct strfilter *filter)
 941{
 942        struct probe_cache_entry *entry, *tmp;
 943
 944        list_for_each_entry_safe(entry, tmp, &pcache->entries, node) {
 945                if (probe_cache_entry__compare(entry, filter)) {
 946                        pr_info("Removed cached event: %s\n", entry->spev);
 947                        list_del_init(&entry->node);
 948                        probe_cache_entry__delete(entry);
 949                }
 950        }
 951        return 0;
 952}
 953
 954static int probe_cache__show_entries(struct probe_cache *pcache,
 955                                     struct strfilter *filter)
 956{
 957        struct probe_cache_entry *entry;
 958
 959        for_each_probe_cache_entry(entry, pcache) {
 960                if (probe_cache_entry__compare(entry, filter))
 961                        printf("%s\n", entry->spev);
 962        }
 963        return 0;
 964}
 965
 966/* Show all cached probes */
 967int probe_cache__show_all_caches(struct strfilter *filter)
 968{
 969        struct probe_cache *pcache;
 970        struct strlist *bidlist;
 971        struct str_node *nd;
 972        char *buf = strfilter__string(filter);
 973
 974        pr_debug("list cache with filter: %s\n", buf);
 975        free(buf);
 976
 977        bidlist = build_id_cache__list_all(true);
 978        if (!bidlist) {
 979                pr_debug("Failed to get buildids: %d\n", errno);
 980                return -EINVAL;
 981        }
 982        strlist__for_each_entry(nd, bidlist) {
 983                pcache = probe_cache__new(nd->s, NULL);
 984                if (!pcache)
 985                        continue;
 986                if (!list_empty(&pcache->entries)) {
 987                        buf = build_id_cache__origname(nd->s);
 988                        printf("%s (%s):\n", buf, nd->s);
 989                        free(buf);
 990                        probe_cache__show_entries(pcache, filter);
 991                }
 992                probe_cache__delete(pcache);
 993        }
 994        strlist__delete(bidlist);
 995
 996        return 0;
 997}
 998
 999enum ftrace_readme {
1000        FTRACE_README_PROBE_TYPE_X = 0,
1001        FTRACE_README_KRETPROBE_OFFSET,
1002        FTRACE_README_END,
1003};
1004
1005static struct {
1006        const char *pattern;
1007        bool avail;
1008} ftrace_readme_table[] = {
1009#define DEFINE_TYPE(idx, pat)                   \
1010        [idx] = {.pattern = pat, .avail = false}
1011        DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
1012        DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
1013};
1014
1015static bool scan_ftrace_readme(enum ftrace_readme type)
1016{
1017        int fd;
1018        FILE *fp;
1019        char *buf = NULL;
1020        size_t len = 0;
1021        bool ret = false;
1022        static bool scanned = false;
1023
1024        if (scanned)
1025                goto result;
1026
1027        fd = open_trace_file("README", false);
1028        if (fd < 0)
1029                return ret;
1030
1031        fp = fdopen(fd, "r");
1032        if (!fp) {
1033                close(fd);
1034                return ret;
1035        }
1036
1037        while (getline(&buf, &len, fp) > 0)
1038                for (enum ftrace_readme i = 0; i < FTRACE_README_END; i++)
1039                        if (!ftrace_readme_table[i].avail)
1040                                ftrace_readme_table[i].avail =
1041                                        strglobmatch(buf, ftrace_readme_table[i].pattern);
1042        scanned = true;
1043
1044        fclose(fp);
1045        free(buf);
1046
1047result:
1048        if (type >= FTRACE_README_END)
1049                return false;
1050
1051        return ftrace_readme_table[type].avail;
1052}
1053
1054bool probe_type_is_available(enum probe_type type)
1055{
1056        if (type >= PROBE_TYPE_END)
1057                return false;
1058        else if (type == PROBE_TYPE_X)
1059                return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X);
1060
1061        return true;
1062}
1063
1064bool kretprobe_offset_is_supported(void)
1065{
1066        return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
1067}
1068