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