0001
0002
0003
0004
0005
0006
0007 #include <errno.h>
0008 #include <fcntl.h>
0009 #include <sys/stat.h>
0010 #include <sys/types.h>
0011 #include <sys/uio.h>
0012 #include <unistd.h>
0013 #include <linux/zalloc.h>
0014 #include "namespaces.h"
0015 #include "event.h"
0016 #include "strlist.h"
0017 #include "strfilter.h"
0018 #include "debug.h"
0019 #include "build-id.h"
0020 #include "dso.h"
0021 #include "color.h"
0022 #include "symbol.h"
0023 #include "strbuf.h"
0024 #include <api/fs/tracing_path.h>
0025 #include <api/fs/fs.h>
0026 #include "probe-event.h"
0027 #include "probe-file.h"
0028 #include "session.h"
0029 #include "perf_regs.h"
0030 #include "string2.h"
0031
0032
0033 #define MAX_CMDLEN 4094
0034
0035 static bool print_common_warning(int err, bool readwrite)
0036 {
0037 if (err == -EACCES)
0038 pr_warning("No permission to %s tracefs.\nPlease %s\n",
0039 readwrite ? "write" : "read",
0040 readwrite ? "run this command again with sudo." :
0041 "try 'sudo mount -o remount,mode=755 /sys/kernel/tracing/'");
0042 else
0043 return false;
0044
0045 return true;
0046 }
0047
0048 static bool print_configure_probe_event(int kerr, int uerr)
0049 {
0050 const char *config, *file;
0051
0052 if (kerr == -ENOENT && uerr == -ENOENT) {
0053 file = "{k,u}probe_events";
0054 config = "CONFIG_KPROBE_EVENTS=y and CONFIG_UPROBE_EVENTS=y";
0055 } else if (kerr == -ENOENT) {
0056 file = "kprobe_events";
0057 config = "CONFIG_KPROBE_EVENTS=y";
0058 } else if (uerr == -ENOENT) {
0059 file = "uprobe_events";
0060 config = "CONFIG_UPROBE_EVENTS=y";
0061 } else
0062 return false;
0063
0064 if (!debugfs__configured() && !tracefs__configured())
0065 pr_warning("Debugfs or tracefs is not mounted\n"
0066 "Please try 'sudo mount -t tracefs nodev /sys/kernel/tracing/'\n");
0067 else
0068 pr_warning("%s/%s does not exist.\nPlease rebuild kernel with %s.\n",
0069 tracing_path_mount(), file, config);
0070
0071 return true;
0072 }
0073
0074 static void print_open_warning(int err, bool uprobe, bool readwrite)
0075 {
0076 char sbuf[STRERR_BUFSIZE];
0077
0078 if (print_common_warning(err, readwrite))
0079 return;
0080
0081 if (print_configure_probe_event(uprobe ? 0 : err, uprobe ? err : 0))
0082 return;
0083
0084 pr_warning("Failed to open %s/%cprobe_events: %s\n",
0085 tracing_path_mount(), uprobe ? 'u' : 'k',
0086 str_error_r(-err, sbuf, sizeof(sbuf)));
0087 }
0088
0089 static void print_both_open_warning(int kerr, int uerr, bool readwrite)
0090 {
0091 char sbuf[STRERR_BUFSIZE];
0092
0093 if (kerr == uerr && print_common_warning(kerr, readwrite))
0094 return;
0095
0096 if (print_configure_probe_event(kerr, uerr))
0097 return;
0098
0099 if (kerr < 0)
0100 pr_warning("Failed to open %s/kprobe_events: %s.\n",
0101 tracing_path_mount(),
0102 str_error_r(-kerr, sbuf, sizeof(sbuf)));
0103 if (uerr < 0)
0104 pr_warning("Failed to open %s/uprobe_events: %s.\n",
0105 tracing_path_mount(),
0106 str_error_r(-uerr, sbuf, sizeof(sbuf)));
0107 }
0108
0109 int open_trace_file(const char *trace_file, bool readwrite)
0110 {
0111 char buf[PATH_MAX];
0112 int ret;
0113
0114 ret = e_snprintf(buf, PATH_MAX, "%s/%s", tracing_path_mount(), trace_file);
0115 if (ret >= 0) {
0116 pr_debug("Opening %s write=%d\n", buf, readwrite);
0117 if (readwrite && !probe_event_dry_run)
0118 ret = open(buf, O_RDWR | O_APPEND, 0);
0119 else
0120 ret = open(buf, O_RDONLY, 0);
0121
0122 if (ret < 0)
0123 ret = -errno;
0124 }
0125 return ret;
0126 }
0127
0128 static int open_kprobe_events(bool readwrite)
0129 {
0130 return open_trace_file("kprobe_events", readwrite);
0131 }
0132
0133 static int open_uprobe_events(bool readwrite)
0134 {
0135 return open_trace_file("uprobe_events", readwrite);
0136 }
0137
0138 int probe_file__open(int flag)
0139 {
0140 int fd;
0141
0142 if (flag & PF_FL_UPROBE)
0143 fd = open_uprobe_events(flag & PF_FL_RW);
0144 else
0145 fd = open_kprobe_events(flag & PF_FL_RW);
0146 if (fd < 0)
0147 print_open_warning(fd, flag & PF_FL_UPROBE, flag & PF_FL_RW);
0148
0149 return fd;
0150 }
0151
0152 int probe_file__open_both(int *kfd, int *ufd, int flag)
0153 {
0154 if (!kfd || !ufd)
0155 return -EINVAL;
0156
0157 *kfd = open_kprobe_events(flag & PF_FL_RW);
0158 *ufd = open_uprobe_events(flag & PF_FL_RW);
0159 if (*kfd < 0 && *ufd < 0) {
0160 print_both_open_warning(*kfd, *ufd, flag & PF_FL_RW);
0161 return *kfd;
0162 }
0163
0164 return 0;
0165 }
0166
0167
0168 struct strlist *probe_file__get_rawlist(int fd)
0169 {
0170 int ret, idx, fddup;
0171 FILE *fp;
0172 char buf[MAX_CMDLEN];
0173 char *p;
0174 struct strlist *sl;
0175
0176 if (fd < 0)
0177 return NULL;
0178
0179 sl = strlist__new(NULL, NULL);
0180 if (sl == NULL)
0181 return NULL;
0182
0183 fddup = dup(fd);
0184 if (fddup < 0)
0185 goto out_free_sl;
0186
0187 fp = fdopen(fddup, "r");
0188 if (!fp)
0189 goto out_close_fddup;
0190
0191 while (!feof(fp)) {
0192 p = fgets(buf, MAX_CMDLEN, fp);
0193 if (!p)
0194 break;
0195
0196 idx = strlen(p) - 1;
0197 if (p[idx] == '\n')
0198 p[idx] = '\0';
0199 ret = strlist__add(sl, buf);
0200 if (ret < 0) {
0201 pr_debug("strlist__add failed (%d)\n", ret);
0202 goto out_close_fp;
0203 }
0204 }
0205 fclose(fp);
0206
0207 return sl;
0208
0209 out_close_fp:
0210 fclose(fp);
0211 goto out_free_sl;
0212 out_close_fddup:
0213 close(fddup);
0214 out_free_sl:
0215 strlist__delete(sl);
0216 return NULL;
0217 }
0218
0219 static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
0220 {
0221 char buf[128];
0222 struct strlist *sl, *rawlist;
0223 struct str_node *ent;
0224 struct probe_trace_event tev;
0225 int ret = 0;
0226
0227 memset(&tev, 0, sizeof(tev));
0228 rawlist = probe_file__get_rawlist(fd);
0229 if (!rawlist)
0230 return NULL;
0231 sl = strlist__new(NULL, NULL);
0232 strlist__for_each_entry(ent, rawlist) {
0233 ret = parse_probe_trace_command(ent->s, &tev);
0234 if (ret < 0)
0235 break;
0236 if (include_group) {
0237 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
0238 tev.event);
0239 if (ret >= 0)
0240 ret = strlist__add(sl, buf);
0241 } else
0242 ret = strlist__add(sl, tev.event);
0243 clear_probe_trace_event(&tev);
0244
0245 if (ret == -EEXIST)
0246 ret = 0;
0247 if (ret < 0)
0248 break;
0249 }
0250 strlist__delete(rawlist);
0251
0252 if (ret < 0) {
0253 strlist__delete(sl);
0254 return NULL;
0255 }
0256 return sl;
0257 }
0258
0259
0260 struct strlist *probe_file__get_namelist(int fd)
0261 {
0262 return __probe_file__get_namelist(fd, false);
0263 }
0264
0265 int probe_file__add_event(int fd, struct probe_trace_event *tev)
0266 {
0267 int ret = 0;
0268 char *buf = synthesize_probe_trace_command(tev);
0269 char sbuf[STRERR_BUFSIZE];
0270
0271 if (!buf) {
0272 pr_debug("Failed to synthesize probe trace event.\n");
0273 return -EINVAL;
0274 }
0275
0276 pr_debug("Writing event: %s\n", buf);
0277 if (!probe_event_dry_run) {
0278 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
0279 ret = -errno;
0280 pr_warning("Failed to write event: %s\n",
0281 str_error_r(errno, sbuf, sizeof(sbuf)));
0282 }
0283 }
0284 free(buf);
0285
0286 return ret;
0287 }
0288
0289 static int __del_trace_probe_event(int fd, struct str_node *ent)
0290 {
0291 char *p;
0292 char buf[128];
0293 int ret;
0294
0295
0296 ret = e_snprintf(buf, 128, "-:%s", ent->s);
0297 if (ret < 0)
0298 goto error;
0299
0300 p = strchr(buf + 2, ':');
0301 if (!p) {
0302 pr_debug("Internal error: %s should have ':' but not.\n",
0303 ent->s);
0304 ret = -ENOTSUP;
0305 goto error;
0306 }
0307 *p = '/';
0308
0309 pr_debug("Writing event: %s\n", buf);
0310 ret = write(fd, buf, strlen(buf));
0311 if (ret < 0) {
0312 ret = -errno;
0313 goto error;
0314 }
0315
0316 return 0;
0317 error:
0318 pr_warning("Failed to delete event: %s\n",
0319 str_error_r(-ret, buf, sizeof(buf)));
0320 return ret;
0321 }
0322
0323 int probe_file__get_events(int fd, struct strfilter *filter,
0324 struct strlist *plist)
0325 {
0326 struct strlist *namelist;
0327 struct str_node *ent;
0328 const char *p;
0329 int ret = -ENOENT;
0330
0331 if (!plist)
0332 return -EINVAL;
0333
0334 namelist = __probe_file__get_namelist(fd, true);
0335 if (!namelist)
0336 return -ENOENT;
0337
0338 strlist__for_each_entry(ent, namelist) {
0339 p = strchr(ent->s, ':');
0340 if ((p && strfilter__compare(filter, p + 1)) ||
0341 strfilter__compare(filter, ent->s)) {
0342 ret = strlist__add(plist, ent->s);
0343 if (ret == -ENOMEM) {
0344 pr_err("strlist__add failed with -ENOMEM\n");
0345 goto out;
0346 }
0347 ret = 0;
0348 }
0349 }
0350 out:
0351 strlist__delete(namelist);
0352
0353 return ret;
0354 }
0355
0356 int probe_file__del_strlist(int fd, struct strlist *namelist)
0357 {
0358 int ret = 0;
0359 struct str_node *ent;
0360
0361 strlist__for_each_entry(ent, namelist) {
0362 ret = __del_trace_probe_event(fd, ent);
0363 if (ret < 0)
0364 break;
0365 }
0366 return ret;
0367 }
0368
0369 int probe_file__del_events(int fd, struct strfilter *filter)
0370 {
0371 struct strlist *namelist;
0372 int ret;
0373
0374 namelist = strlist__new(NULL, NULL);
0375 if (!namelist)
0376 return -ENOMEM;
0377
0378 ret = probe_file__get_events(fd, filter, namelist);
0379 if (ret < 0)
0380 goto out;
0381
0382 ret = probe_file__del_strlist(fd, namelist);
0383 out:
0384 strlist__delete(namelist);
0385 return ret;
0386 }
0387
0388
0389 static void probe_cache_entry__delete(struct probe_cache_entry *entry)
0390 {
0391 if (entry) {
0392 BUG_ON(!list_empty(&entry->node));
0393
0394 strlist__delete(entry->tevlist);
0395 clear_perf_probe_event(&entry->pev);
0396 zfree(&entry->spev);
0397 free(entry);
0398 }
0399 }
0400
0401 static struct probe_cache_entry *
0402 probe_cache_entry__new(struct perf_probe_event *pev)
0403 {
0404 struct probe_cache_entry *entry = zalloc(sizeof(*entry));
0405
0406 if (entry) {
0407 INIT_LIST_HEAD(&entry->node);
0408 entry->tevlist = strlist__new(NULL, NULL);
0409 if (!entry->tevlist)
0410 zfree(&entry);
0411 else if (pev) {
0412 entry->spev = synthesize_perf_probe_command(pev);
0413 if (!entry->spev ||
0414 perf_probe_event__copy(&entry->pev, pev) < 0) {
0415 probe_cache_entry__delete(entry);
0416 return NULL;
0417 }
0418 }
0419 }
0420
0421 return entry;
0422 }
0423
0424 int probe_cache_entry__get_event(struct probe_cache_entry *entry,
0425 struct probe_trace_event **tevs)
0426 {
0427 struct probe_trace_event *tev;
0428 struct str_node *node;
0429 int ret, i;
0430
0431 ret = strlist__nr_entries(entry->tevlist);
0432 if (ret > probe_conf.max_probes)
0433 return -E2BIG;
0434
0435 *tevs = zalloc(ret * sizeof(*tev));
0436 if (!*tevs)
0437 return -ENOMEM;
0438
0439 i = 0;
0440 strlist__for_each_entry(node, entry->tevlist) {
0441 tev = &(*tevs)[i++];
0442 ret = parse_probe_trace_command(node->s, tev);
0443 if (ret < 0)
0444 break;
0445 }
0446 return i;
0447 }
0448
0449
0450 static int probe_cache__open(struct probe_cache *pcache, const char *target,
0451 struct nsinfo *nsi)
0452 {
0453 char cpath[PATH_MAX];
0454 char sbuildid[SBUILD_ID_SIZE];
0455 char *dir_name = NULL;
0456 bool is_kallsyms = false;
0457 int ret, fd;
0458 struct nscookie nsc;
0459
0460 if (target && build_id_cache__cached(target)) {
0461
0462 strlcpy(sbuildid, target, SBUILD_ID_SIZE);
0463 dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
0464 goto found;
0465 }
0466
0467 if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
0468 target = DSO__NAME_KALLSYMS;
0469 is_kallsyms = true;
0470 ret = sysfs__sprintf_build_id("/", sbuildid);
0471 } else {
0472 nsinfo__mountns_enter(nsi, &nsc);
0473 ret = filename__sprintf_build_id(target, sbuildid);
0474 nsinfo__mountns_exit(&nsc);
0475 }
0476
0477 if (ret < 0) {
0478 pr_debug("Failed to get build-id from %s.\n", target);
0479 return ret;
0480 }
0481
0482
0483 if (!build_id_cache__cached(sbuildid)) {
0484 ret = build_id_cache__add_s(sbuildid, target, nsi,
0485 is_kallsyms, NULL);
0486 if (ret < 0) {
0487 pr_debug("Failed to add build-id cache: %s\n", target);
0488 return ret;
0489 }
0490 }
0491
0492 dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
0493 false);
0494 found:
0495 if (!dir_name) {
0496 pr_debug("Failed to get cache from %s\n", target);
0497 return -ENOMEM;
0498 }
0499
0500 snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
0501 fd = open(cpath, O_CREAT | O_RDWR, 0644);
0502 if (fd < 0)
0503 pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
0504 free(dir_name);
0505 pcache->fd = fd;
0506
0507 return fd;
0508 }
0509
0510 static int probe_cache__load(struct probe_cache *pcache)
0511 {
0512 struct probe_cache_entry *entry = NULL;
0513 char buf[MAX_CMDLEN], *p;
0514 int ret = 0, fddup;
0515 FILE *fp;
0516
0517 fddup = dup(pcache->fd);
0518 if (fddup < 0)
0519 return -errno;
0520 fp = fdopen(fddup, "r");
0521 if (!fp) {
0522 close(fddup);
0523 return -EINVAL;
0524 }
0525
0526 while (!feof(fp)) {
0527 if (!fgets(buf, MAX_CMDLEN, fp))
0528 break;
0529 p = strchr(buf, '\n');
0530 if (p)
0531 *p = '\0';
0532
0533 if (buf[0] == '#' || buf[0] == '%') {
0534 entry = probe_cache_entry__new(NULL);
0535 if (!entry) {
0536 ret = -ENOMEM;
0537 goto out;
0538 }
0539 if (buf[0] == '%')
0540 entry->sdt = true;
0541 entry->spev = strdup(buf + 1);
0542 if (entry->spev)
0543 ret = parse_perf_probe_command(buf + 1,
0544 &entry->pev);
0545 else
0546 ret = -ENOMEM;
0547 if (ret < 0) {
0548 probe_cache_entry__delete(entry);
0549 goto out;
0550 }
0551 list_add_tail(&entry->node, &pcache->entries);
0552 } else {
0553 if (!entry) {
0554 ret = -EINVAL;
0555 goto out;
0556 }
0557 ret = strlist__add(entry->tevlist, buf);
0558 if (ret == -ENOMEM) {
0559 pr_err("strlist__add failed with -ENOMEM\n");
0560 goto out;
0561 }
0562 }
0563 }
0564 out:
0565 fclose(fp);
0566 return ret;
0567 }
0568
0569 static struct probe_cache *probe_cache__alloc(void)
0570 {
0571 struct probe_cache *pcache = zalloc(sizeof(*pcache));
0572
0573 if (pcache) {
0574 INIT_LIST_HEAD(&pcache->entries);
0575 pcache->fd = -EINVAL;
0576 }
0577 return pcache;
0578 }
0579
0580 void probe_cache__purge(struct probe_cache *pcache)
0581 {
0582 struct probe_cache_entry *entry, *n;
0583
0584 list_for_each_entry_safe(entry, n, &pcache->entries, node) {
0585 list_del_init(&entry->node);
0586 probe_cache_entry__delete(entry);
0587 }
0588 }
0589
0590 void probe_cache__delete(struct probe_cache *pcache)
0591 {
0592 if (!pcache)
0593 return;
0594
0595 probe_cache__purge(pcache);
0596 if (pcache->fd > 0)
0597 close(pcache->fd);
0598 free(pcache);
0599 }
0600
0601 struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
0602 {
0603 struct probe_cache *pcache = probe_cache__alloc();
0604 int ret;
0605
0606 if (!pcache)
0607 return NULL;
0608
0609 ret = probe_cache__open(pcache, target, nsi);
0610 if (ret < 0) {
0611 pr_debug("Cache open error: %d\n", ret);
0612 goto out_err;
0613 }
0614
0615 ret = probe_cache__load(pcache);
0616 if (ret < 0) {
0617 pr_debug("Cache read error: %d\n", ret);
0618 goto out_err;
0619 }
0620
0621 return pcache;
0622
0623 out_err:
0624 probe_cache__delete(pcache);
0625 return NULL;
0626 }
0627
0628 static bool streql(const char *a, const char *b)
0629 {
0630 if (a == b)
0631 return true;
0632
0633 if (!a || !b)
0634 return false;
0635
0636 return !strcmp(a, b);
0637 }
0638
0639 struct probe_cache_entry *
0640 probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
0641 {
0642 struct probe_cache_entry *entry = NULL;
0643 char *cmd = synthesize_perf_probe_command(pev);
0644
0645 if (!cmd)
0646 return NULL;
0647
0648 for_each_probe_cache_entry(entry, pcache) {
0649 if (pev->sdt) {
0650 if (entry->pev.event &&
0651 streql(entry->pev.event, pev->event) &&
0652 (!pev->group ||
0653 streql(entry->pev.group, pev->group)))
0654 goto found;
0655
0656 continue;
0657 }
0658
0659 if ((pev->event &&
0660 (streql(entry->pev.group, pev->group) &&
0661 streql(entry->pev.event, pev->event))) ||
0662 (!strcmp(entry->spev, cmd)))
0663 goto found;
0664 }
0665 entry = NULL;
0666
0667 found:
0668 free(cmd);
0669 return entry;
0670 }
0671
0672 struct probe_cache_entry *
0673 probe_cache__find_by_name(struct probe_cache *pcache,
0674 const char *group, const char *event)
0675 {
0676 struct probe_cache_entry *entry = NULL;
0677
0678 for_each_probe_cache_entry(entry, pcache) {
0679
0680 if (streql(entry->pev.group, group) &&
0681 streql(entry->pev.event, event))
0682 goto found;
0683 }
0684 entry = NULL;
0685
0686 found:
0687 return entry;
0688 }
0689
0690 int probe_cache__add_entry(struct probe_cache *pcache,
0691 struct perf_probe_event *pev,
0692 struct probe_trace_event *tevs, int ntevs)
0693 {
0694 struct probe_cache_entry *entry = NULL;
0695 char *command;
0696 int i, ret = 0;
0697
0698 if (!pcache || !pev || !tevs || ntevs <= 0) {
0699 ret = -EINVAL;
0700 goto out_err;
0701 }
0702
0703
0704 entry = probe_cache__find(pcache, pev);
0705 if (entry) {
0706 list_del_init(&entry->node);
0707 probe_cache_entry__delete(entry);
0708 }
0709
0710 ret = -ENOMEM;
0711 entry = probe_cache_entry__new(pev);
0712 if (!entry)
0713 goto out_err;
0714
0715 for (i = 0; i < ntevs; i++) {
0716 if (!tevs[i].point.symbol)
0717 continue;
0718
0719 command = synthesize_probe_trace_command(&tevs[i]);
0720 if (!command)
0721 goto out_err;
0722 ret = strlist__add(entry->tevlist, command);
0723 if (ret == -ENOMEM) {
0724 pr_err("strlist__add failed with -ENOMEM\n");
0725 goto out_err;
0726 }
0727
0728 free(command);
0729 }
0730 list_add_tail(&entry->node, &pcache->entries);
0731 pr_debug("Added probe cache: %d\n", ntevs);
0732 return 0;
0733
0734 out_err:
0735 pr_debug("Failed to add probe caches\n");
0736 probe_cache_entry__delete(entry);
0737 return ret;
0738 }
0739
0740 #ifdef HAVE_GELF_GETNOTE_SUPPORT
0741 static unsigned long long sdt_note__get_addr(struct sdt_note *note)
0742 {
0743 return note->bit32 ?
0744 (unsigned long long)note->addr.a32[SDT_NOTE_IDX_LOC] :
0745 (unsigned long long)note->addr.a64[SDT_NOTE_IDX_LOC];
0746 }
0747
0748 static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note *note)
0749 {
0750 return note->bit32 ?
0751 (unsigned long long)note->addr.a32[SDT_NOTE_IDX_REFCTR] :
0752 (unsigned long long)note->addr.a64[SDT_NOTE_IDX_REFCTR];
0753 }
0754
0755 static const char * const type_to_suffix[] = {
0756 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
0757 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
0758 };
0759
0760
0761
0762
0763
0764
0765 static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
0766 {
0767 long type_idx;
0768
0769 type_idx = strtol(n_ptr, NULL, 10);
0770 if (type_idx < -8 || type_idx > 8) {
0771 pr_debug4("Failed to get a valid sdt type\n");
0772 return -1;
0773 }
0774
0775 *suffix = type_to_suffix[type_idx + 8];
0776 return 0;
0777 }
0778
0779 static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
0780 {
0781 char *op, *desc = strdup(arg), *new_op = NULL;
0782 const char *suffix = "";
0783 int ret = -1;
0784
0785 if (desc == NULL) {
0786 pr_debug4("Allocation error\n");
0787 return ret;
0788 }
0789
0790
0791
0792
0793
0794
0795 op = strchr(desc, '@');
0796 if (op) {
0797 op[0] = '\0';
0798 op++;
0799
0800 if (sdt_arg_parse_size(desc, &suffix))
0801 goto error;
0802 } else {
0803 op = desc;
0804 }
0805
0806 ret = arch_sdt_arg_parse_op(op, &new_op);
0807
0808 if (ret < 0)
0809 goto error;
0810
0811 if (ret == SDT_ARG_VALID) {
0812 ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
0813 if (ret < 0)
0814 goto error;
0815 }
0816
0817 ret = 0;
0818 error:
0819 free(desc);
0820 free(new_op);
0821 return ret;
0822 }
0823
0824 static char *synthesize_sdt_probe_command(struct sdt_note *note,
0825 const char *pathname,
0826 const char *sdtgrp)
0827 {
0828 struct strbuf buf;
0829 char *ret = NULL;
0830 int i, args_count, err;
0831 unsigned long long ref_ctr_offset;
0832 char *arg;
0833 int arg_idx = 0;
0834
0835 if (strbuf_init(&buf, 32) < 0)
0836 return NULL;
0837
0838 err = strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
0839 sdtgrp, note->name, pathname,
0840 sdt_note__get_addr(note));
0841
0842 ref_ctr_offset = sdt_note__get_ref_ctr_offset(note);
0843 if (ref_ctr_offset && err >= 0)
0844 err = strbuf_addf(&buf, "(0x%llx)", ref_ctr_offset);
0845
0846 if (err < 0)
0847 goto error;
0848
0849 if (!note->args)
0850 goto out;
0851
0852 if (note->args) {
0853 char **args = argv_split(note->args, &args_count);
0854
0855 if (args == NULL)
0856 goto error;
0857
0858 for (i = 0; i < args_count; ) {
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873 if (strstr(args[i], "[sp,") && (i+1) < args_count) {
0874 err = asprintf(&arg, "%s %s", args[i], args[i+1]);
0875 i += 2;
0876 } else {
0877 err = asprintf(&arg, "%s", args[i]);
0878 i += 1;
0879 }
0880
0881
0882 if (err < 0) {
0883 argv_free(args);
0884 goto error;
0885 }
0886
0887 if (synthesize_sdt_probe_arg(&buf, arg_idx, arg) < 0) {
0888 free(arg);
0889 argv_free(args);
0890 goto error;
0891 }
0892
0893 free(arg);
0894 arg_idx++;
0895 }
0896
0897 argv_free(args);
0898 }
0899
0900 out:
0901 ret = strbuf_detach(&buf, NULL);
0902 error:
0903 strbuf_release(&buf);
0904 return ret;
0905 }
0906
0907 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
0908 {
0909 struct probe_cache_entry *entry = NULL;
0910 struct list_head sdtlist;
0911 struct sdt_note *note;
0912 char *buf;
0913 char sdtgrp[64];
0914 int ret;
0915
0916 INIT_LIST_HEAD(&sdtlist);
0917 ret = get_sdt_note_list(&sdtlist, pathname);
0918 if (ret < 0) {
0919 pr_debug4("Failed to get sdt note: %d\n", ret);
0920 return ret;
0921 }
0922 list_for_each_entry(note, &sdtlist, note_list) {
0923 ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
0924 if (ret < 0)
0925 break;
0926
0927 entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
0928 if (!entry) {
0929 entry = probe_cache_entry__new(NULL);
0930 if (!entry) {
0931 ret = -ENOMEM;
0932 break;
0933 }
0934 entry->sdt = true;
0935 ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
0936 note->name, note->name);
0937 if (ret < 0)
0938 break;
0939 entry->pev.event = strdup(note->name);
0940 entry->pev.group = strdup(sdtgrp);
0941 list_add_tail(&entry->node, &pcache->entries);
0942 }
0943 buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
0944 if (!buf) {
0945 ret = -ENOMEM;
0946 break;
0947 }
0948
0949 ret = strlist__add(entry->tevlist, buf);
0950
0951 free(buf);
0952 entry = NULL;
0953
0954 if (ret == -ENOMEM) {
0955 pr_err("strlist__add failed with -ENOMEM\n");
0956 break;
0957 }
0958 }
0959 if (entry) {
0960 list_del_init(&entry->node);
0961 probe_cache_entry__delete(entry);
0962 }
0963 cleanup_sdt_note_list(&sdtlist);
0964 return ret;
0965 }
0966 #endif
0967
0968 static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
0969 {
0970 struct str_node *snode;
0971 struct stat st;
0972 struct iovec iov[3];
0973 const char *prefix = entry->sdt ? "%" : "#";
0974 int ret;
0975
0976 ret = fstat(fd, &st);
0977 if (ret < 0)
0978 return ret;
0979
0980 pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
0981 iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
0982 iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
0983 iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
0984 ret = writev(fd, iov, 3);
0985 if (ret < (int)iov[1].iov_len + 2)
0986 goto rollback;
0987
0988 strlist__for_each_entry(snode, entry->tevlist) {
0989 iov[0].iov_base = (void *)snode->s;
0990 iov[0].iov_len = strlen(snode->s);
0991 iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
0992 ret = writev(fd, iov, 2);
0993 if (ret < (int)iov[0].iov_len + 1)
0994 goto rollback;
0995 }
0996 return 0;
0997
0998 rollback:
0999
1000 if (ret > 0)
1001 ret = -1;
1002 if (ftruncate(fd, st.st_size) < 0)
1003 ret = -2;
1004
1005 return ret;
1006 }
1007
1008 int probe_cache__commit(struct probe_cache *pcache)
1009 {
1010 struct probe_cache_entry *entry;
1011 int ret = 0;
1012
1013
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 }
1028 out:
1029 return ret;
1030 }
1031
1032 static 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
1044 int 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
1059 static 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
1072 int 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
1104 enum 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
1114 static 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
1128 static 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
1160 result:
1161 if (type >= FTRACE_README_END)
1162 return false;
1163
1164 return ftrace_readme_table[type].avail;
1165 }
1166
1167 bool 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
1177 bool kretprobe_offset_is_supported(void)
1178 {
1179 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
1180 }
1181
1182 bool uprobe_ref_ctr_is_supported(void)
1183 {
1184 return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR);
1185 }
1186
1187 bool user_access_is_supported(void)
1188 {
1189 return scan_ftrace_readme(FTRACE_README_USER_ACCESS);
1190 }
1191
1192 bool multiprobe_event_is_supported(void)
1193 {
1194 return scan_ftrace_readme(FTRACE_README_MULTIPROBE_EVENT);
1195 }
1196
1197 bool immediate_value_is_supported(void)
1198 {
1199 return scan_ftrace_readme(FTRACE_README_IMMEDIATE_VALUE);
1200 }