.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * probe-file.c : operate ftrace k/uprobe events files |
---|
3 | 4 | * |
---|
4 | 5 | * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | 6 | */ |
---|
17 | 7 | #include <errno.h> |
---|
18 | 8 | #include <fcntl.h> |
---|
.. | .. |
---|
20 | 10 | #include <sys/types.h> |
---|
21 | 11 | #include <sys/uio.h> |
---|
22 | 12 | #include <unistd.h> |
---|
23 | | -#include "util.h" |
---|
| 13 | +#include <linux/zalloc.h> |
---|
| 14 | +#include "namespaces.h" |
---|
24 | 15 | #include "event.h" |
---|
25 | 16 | #include "strlist.h" |
---|
26 | 17 | #include "strfilter.h" |
---|
27 | 18 | #include "debug.h" |
---|
28 | | -#include "cache.h" |
---|
| 19 | +#include "build-id.h" |
---|
| 20 | +#include "dso.h" |
---|
29 | 21 | #include "color.h" |
---|
30 | 22 | #include "symbol.h" |
---|
31 | | -#include "thread.h" |
---|
| 23 | +#include "strbuf.h" |
---|
32 | 24 | #include <api/fs/tracing_path.h> |
---|
33 | 25 | #include "probe-event.h" |
---|
34 | 26 | #include "probe-file.h" |
---|
.. | .. |
---|
214 | 206 | } else |
---|
215 | 207 | ret = strlist__add(sl, tev.event); |
---|
216 | 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; |
---|
217 | 212 | if (ret < 0) |
---|
218 | 213 | break; |
---|
219 | 214 | } |
---|
.. | .. |
---|
309 | 304 | p = strchr(ent->s, ':'); |
---|
310 | 305 | if ((p && strfilter__compare(filter, p + 1)) || |
---|
311 | 306 | strfilter__compare(filter, ent->s)) { |
---|
312 | | - strlist__add(plist, ent->s); |
---|
| 307 | + ret = strlist__add(plist, ent->s); |
---|
| 308 | + if (ret == -ENOMEM) { |
---|
| 309 | + pr_err("strlist__add failed with -ENOMEM\n"); |
---|
| 310 | + goto out; |
---|
| 311 | + } |
---|
313 | 312 | ret = 0; |
---|
314 | 313 | } |
---|
315 | 314 | } |
---|
| 315 | +out: |
---|
316 | 316 | strlist__delete(namelist); |
---|
317 | 317 | |
---|
318 | 318 | return ret; |
---|
.. | .. |
---|
519 | 519 | ret = -EINVAL; |
---|
520 | 520 | goto out; |
---|
521 | 521 | } |
---|
522 | | - strlist__add(entry->tevlist, buf); |
---|
| 522 | + ret = strlist__add(entry->tevlist, buf); |
---|
| 523 | + if (ret == -ENOMEM) { |
---|
| 524 | + pr_err("strlist__add failed with -ENOMEM\n"); |
---|
| 525 | + goto out; |
---|
| 526 | + } |
---|
523 | 527 | } |
---|
524 | 528 | } |
---|
525 | 529 | out: |
---|
.. | .. |
---|
680 | 684 | command = synthesize_probe_trace_command(&tevs[i]); |
---|
681 | 685 | if (!command) |
---|
682 | 686 | goto out_err; |
---|
683 | | - strlist__add(entry->tevlist, command); |
---|
| 687 | + ret = strlist__add(entry->tevlist, command); |
---|
| 688 | + if (ret == -ENOMEM) { |
---|
| 689 | + pr_err("strlist__add failed with -ENOMEM\n"); |
---|
| 690 | + goto out_err; |
---|
| 691 | + } |
---|
| 692 | + |
---|
684 | 693 | free(command); |
---|
685 | 694 | } |
---|
686 | 695 | list_add_tail(&entry->node, &pcache->entries); |
---|
.. | .. |
---|
696 | 705 | #ifdef HAVE_GELF_GETNOTE_SUPPORT |
---|
697 | 706 | static unsigned long long sdt_note__get_addr(struct sdt_note *note) |
---|
698 | 707 | { |
---|
699 | | - return note->bit32 ? (unsigned long long)note->addr.a32[0] |
---|
700 | | - : (unsigned long long)note->addr.a64[0]; |
---|
| 708 | + return note->bit32 ? |
---|
| 709 | + (unsigned long long)note->addr.a32[SDT_NOTE_IDX_LOC] : |
---|
| 710 | + (unsigned long long)note->addr.a64[SDT_NOTE_IDX_LOC]; |
---|
| 711 | +} |
---|
| 712 | + |
---|
| 713 | +static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note *note) |
---|
| 714 | +{ |
---|
| 715 | + return note->bit32 ? |
---|
| 716 | + (unsigned long long)note->addr.a32[SDT_NOTE_IDX_REFCTR] : |
---|
| 717 | + (unsigned long long)note->addr.a64[SDT_NOTE_IDX_REFCTR]; |
---|
701 | 718 | } |
---|
702 | 719 | |
---|
703 | 720 | static const char * const type_to_suffix[] = { |
---|
.. | .. |
---|
774 | 791 | const char *sdtgrp) |
---|
775 | 792 | { |
---|
776 | 793 | struct strbuf buf; |
---|
777 | | - char *ret = NULL, **args; |
---|
778 | | - int i, args_count; |
---|
| 794 | + char *ret = NULL; |
---|
| 795 | + int i, args_count, err; |
---|
| 796 | + unsigned long long ref_ctr_offset; |
---|
779 | 797 | |
---|
780 | 798 | if (strbuf_init(&buf, 32) < 0) |
---|
781 | 799 | return NULL; |
---|
782 | 800 | |
---|
783 | | - if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx", |
---|
784 | | - sdtgrp, note->name, pathname, |
---|
785 | | - sdt_note__get_addr(note)) < 0) |
---|
| 801 | + err = strbuf_addf(&buf, "p:%s/%s %s:0x%llx", |
---|
| 802 | + sdtgrp, note->name, pathname, |
---|
| 803 | + sdt_note__get_addr(note)); |
---|
| 804 | + |
---|
| 805 | + ref_ctr_offset = sdt_note__get_ref_ctr_offset(note); |
---|
| 806 | + if (ref_ctr_offset && err >= 0) |
---|
| 807 | + err = strbuf_addf(&buf, "(0x%llx)", ref_ctr_offset); |
---|
| 808 | + |
---|
| 809 | + if (err < 0) |
---|
786 | 810 | goto error; |
---|
787 | 811 | |
---|
788 | 812 | if (!note->args) |
---|
789 | 813 | goto out; |
---|
790 | 814 | |
---|
791 | 815 | if (note->args) { |
---|
792 | | - args = argv_split(note->args, &args_count); |
---|
| 816 | + char **args = argv_split(note->args, &args_count); |
---|
| 817 | + |
---|
| 818 | + if (args == NULL) |
---|
| 819 | + goto error; |
---|
793 | 820 | |
---|
794 | 821 | for (i = 0; i < args_count; ++i) { |
---|
795 | | - if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0) |
---|
| 822 | + if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0) { |
---|
| 823 | + argv_free(args); |
---|
796 | 824 | goto error; |
---|
| 825 | + } |
---|
797 | 826 | } |
---|
| 827 | + |
---|
| 828 | + argv_free(args); |
---|
798 | 829 | } |
---|
799 | 830 | |
---|
800 | 831 | out: |
---|
.. | .. |
---|
846 | 877 | break; |
---|
847 | 878 | } |
---|
848 | 879 | |
---|
849 | | - strlist__add(entry->tevlist, buf); |
---|
| 880 | + ret = strlist__add(entry->tevlist, buf); |
---|
| 881 | + |
---|
850 | 882 | free(buf); |
---|
851 | 883 | entry = NULL; |
---|
| 884 | + |
---|
| 885 | + if (ret == -ENOMEM) { |
---|
| 886 | + pr_err("strlist__add failed with -ENOMEM\n"); |
---|
| 887 | + break; |
---|
| 888 | + } |
---|
852 | 889 | } |
---|
853 | 890 | if (entry) { |
---|
854 | 891 | list_del_init(&entry->node); |
---|
.. | .. |
---|
998 | 1035 | enum ftrace_readme { |
---|
999 | 1036 | FTRACE_README_PROBE_TYPE_X = 0, |
---|
1000 | 1037 | FTRACE_README_KRETPROBE_OFFSET, |
---|
| 1038 | + FTRACE_README_UPROBE_REF_CTR, |
---|
| 1039 | + FTRACE_README_USER_ACCESS, |
---|
| 1040 | + FTRACE_README_MULTIPROBE_EVENT, |
---|
| 1041 | + FTRACE_README_IMMEDIATE_VALUE, |
---|
1001 | 1042 | FTRACE_README_END, |
---|
1002 | 1043 | }; |
---|
1003 | 1044 | |
---|
.. | .. |
---|
1009 | 1050 | [idx] = {.pattern = pat, .avail = false} |
---|
1010 | 1051 | DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"), |
---|
1011 | 1052 | DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"), |
---|
| 1053 | + DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"), |
---|
| 1054 | + DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*u]<offset>*"), |
---|
| 1055 | + DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT, "*Create/append/*"), |
---|
| 1056 | + DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE, "*\\imm-value,*"), |
---|
1012 | 1057 | }; |
---|
1013 | 1058 | |
---|
1014 | 1059 | static bool scan_ftrace_readme(enum ftrace_readme type) |
---|
.. | .. |
---|
1064 | 1109 | { |
---|
1065 | 1110 | return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET); |
---|
1066 | 1111 | } |
---|
| 1112 | + |
---|
| 1113 | +bool uprobe_ref_ctr_is_supported(void) |
---|
| 1114 | +{ |
---|
| 1115 | + return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR); |
---|
| 1116 | +} |
---|
| 1117 | + |
---|
| 1118 | +bool user_access_is_supported(void) |
---|
| 1119 | +{ |
---|
| 1120 | + return scan_ftrace_readme(FTRACE_README_USER_ACCESS); |
---|
| 1121 | +} |
---|
| 1122 | + |
---|
| 1123 | +bool multiprobe_event_is_supported(void) |
---|
| 1124 | +{ |
---|
| 1125 | + return scan_ftrace_readme(FTRACE_README_MULTIPROBE_EVENT); |
---|
| 1126 | +} |
---|
| 1127 | + |
---|
| 1128 | +bool immediate_value_is_supported(void) |
---|
| 1129 | +{ |
---|
| 1130 | + return scan_ftrace_readme(FTRACE_README_IMMEDIATE_VALUE); |
---|
| 1131 | +} |
---|