root/tools/perf/util/probe-file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. print_open_warning
  2. print_both_open_warning
  3. open_trace_file
  4. open_kprobe_events
  5. open_uprobe_events
  6. probe_file__open
  7. probe_file__open_both
  8. probe_file__get_rawlist
  9. __probe_file__get_namelist
  10. probe_file__get_namelist
  11. probe_file__add_event
  12. __del_trace_probe_event
  13. probe_file__get_events
  14. probe_file__del_strlist
  15. probe_file__del_events
  16. probe_cache_entry__delete
  17. probe_cache_entry__new
  18. probe_cache_entry__get_event
  19. probe_cache__open
  20. probe_cache__load
  21. probe_cache__alloc
  22. probe_cache__purge
  23. probe_cache__delete
  24. probe_cache__new
  25. streql
  26. probe_cache__find
  27. probe_cache__find_by_name
  28. probe_cache__add_entry
  29. sdt_note__get_addr
  30. sdt_note__get_ref_ctr_offset
  31. sdt_arg_parse_size
  32. synthesize_sdt_probe_arg
  33. synthesize_sdt_probe_command
  34. probe_cache__scan_sdt
  35. probe_cache_entry__write
  36. probe_cache__commit
  37. probe_cache_entry__compare
  38. probe_cache__filter_purge
  39. probe_cache__show_entries
  40. probe_cache__show_all_caches
  41. scan_ftrace_readme
  42. probe_type_is_available
  43. kretprobe_offset_is_supported
  44. uprobe_ref_ctr_is_supported
  45. user_access_is_supported

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

/* [<][>][^][v][top][bottom][index][help] */