diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-05-10 16:23:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-05-11 10:56:58 -0400 |
commit | 38f5d8b32f36bcac1f54d4511a81e02ed8771a29 (patch) | |
tree | 86df6a818bbbea9f2c585716ccf72e7332c872c4 /tools/perf | |
parent | d2950158d0d7bc376503393ca5f73f6f8d27c56b (diff) | |
parent | 452e84012595d681f254a3a0d733fb0b18ffaf42 (diff) |
Merge tag 'perf-core-for-mingo-20160510' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
- Recording 'dwarf' callchains do not need DWARF unwinding support (He Kuang)
- Print recently added perf_event_attr.write_backward bit flag in -vv
verbose mode (Arnaldo Carvalho de Melo)
- Fix incorrect python db-export error message in 'perf script' (Chris Phlipot)
- Fix handling of zero-length symbols (Chris Phlipot)
- perf stat: Scale values by unit before metrics (Andi Kleen)
Infrastructure changes:
- Rewrite strbuf not to die(), making tools using it to check its
return value instead (Masami Hiramatsu)
- Support reading from backward ring buffer, add a 'perf test' entry
for it (Wang Nan)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
27 files changed, 510 insertions, 245 deletions
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index bc1de9b8fd67..f9830c902b78 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c | |||
@@ -61,6 +61,7 @@ static int check_emacsclient_version(void) | |||
61 | struct child_process ec_process; | 61 | struct child_process ec_process; |
62 | const char *argv_ec[] = { "emacsclient", "--version", NULL }; | 62 | const char *argv_ec[] = { "emacsclient", "--version", NULL }; |
63 | int version; | 63 | int version; |
64 | int ret = -1; | ||
64 | 65 | ||
65 | /* emacsclient prints its version number on stderr */ | 66 | /* emacsclient prints its version number on stderr */ |
66 | memset(&ec_process, 0, sizeof(ec_process)); | 67 | memset(&ec_process, 0, sizeof(ec_process)); |
@@ -71,7 +72,10 @@ static int check_emacsclient_version(void) | |||
71 | fprintf(stderr, "Failed to start emacsclient.\n"); | 72 | fprintf(stderr, "Failed to start emacsclient.\n"); |
72 | return -1; | 73 | return -1; |
73 | } | 74 | } |
74 | strbuf_read(&buffer, ec_process.err, 20); | 75 | if (strbuf_read(&buffer, ec_process.err, 20) < 0) { |
76 | fprintf(stderr, "Failed to read emacsclient version\n"); | ||
77 | goto out; | ||
78 | } | ||
75 | close(ec_process.err); | 79 | close(ec_process.err); |
76 | 80 | ||
77 | /* | 81 | /* |
@@ -82,8 +86,7 @@ static int check_emacsclient_version(void) | |||
82 | 86 | ||
83 | if (prefixcmp(buffer.buf, "emacsclient")) { | 87 | if (prefixcmp(buffer.buf, "emacsclient")) { |
84 | fprintf(stderr, "Failed to parse emacsclient version.\n"); | 88 | fprintf(stderr, "Failed to parse emacsclient version.\n"); |
85 | strbuf_release(&buffer); | 89 | goto out; |
86 | return -1; | ||
87 | } | 90 | } |
88 | 91 | ||
89 | version = atoi(buffer.buf + strlen("emacsclient")); | 92 | version = atoi(buffer.buf + strlen("emacsclient")); |
@@ -92,12 +95,11 @@ static int check_emacsclient_version(void) | |||
92 | fprintf(stderr, | 95 | fprintf(stderr, |
93 | "emacsclient version '%d' too old (< 22).\n", | 96 | "emacsclient version '%d' too old (< 22).\n", |
94 | version); | 97 | version); |
95 | strbuf_release(&buffer); | 98 | } else |
96 | return -1; | 99 | ret = 0; |
97 | } | 100 | out: |
98 | |||
99 | strbuf_release(&buffer); | 101 | strbuf_release(&buffer); |
100 | return 0; | 102 | return ret; |
101 | } | 103 | } |
102 | 104 | ||
103 | static void exec_woman_emacs(const char *path, const char *page) | 105 | static void exec_woman_emacs(const char *path, const char *page) |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 83ffe7cd7330..797000842d40 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -309,9 +309,11 @@ static int handle_alias(int *argcp, const char ***argv) | |||
309 | if (*argcp > 1) { | 309 | if (*argcp > 1) { |
310 | struct strbuf buf; | 310 | struct strbuf buf; |
311 | 311 | ||
312 | strbuf_init(&buf, PATH_MAX); | 312 | if (strbuf_init(&buf, PATH_MAX) < 0 || |
313 | strbuf_addstr(&buf, alias_string); | 313 | strbuf_addstr(&buf, alias_string) < 0 || |
314 | sq_quote_argv(&buf, (*argv) + 1, PATH_MAX); | 314 | sq_quote_argv(&buf, (*argv) + 1, |
315 | PATH_MAX) < 0) | ||
316 | die("Failed to allocate memory."); | ||
315 | free(alias_string); | 317 | free(alias_string); |
316 | alias_string = buf.buf; | 318 | alias_string = buf.buf; |
317 | } | 319 | } |
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 449fe97a555f..66a28982547b 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
@@ -38,6 +38,7 @@ perf-y += cpumap.o | |||
38 | perf-y += stat.o | 38 | perf-y += stat.o |
39 | perf-y += event_update.o | 39 | perf-y += event_update.o |
40 | perf-y += event-times.o | 40 | perf-y += event-times.o |
41 | perf-y += backward-ring-buffer.o | ||
41 | 42 | ||
42 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build | 43 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build |
43 | $(call rule_mkdir) | 44 | $(call rule_mkdir) |
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c new file mode 100644 index 000000000000..d9ba991a9a30 --- /dev/null +++ b/tools/perf/tests/backward-ring-buffer.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * Test backward bit in event attribute, read ring buffer from end to | ||
3 | * beginning | ||
4 | */ | ||
5 | |||
6 | #include <perf.h> | ||
7 | #include <evlist.h> | ||
8 | #include <sys/prctl.h> | ||
9 | #include "tests.h" | ||
10 | #include "debug.h" | ||
11 | |||
12 | #define NR_ITERS 111 | ||
13 | |||
14 | static void testcase(void) | ||
15 | { | ||
16 | int i; | ||
17 | |||
18 | for (i = 0; i < NR_ITERS; i++) { | ||
19 | char proc_name[10]; | ||
20 | |||
21 | snprintf(proc_name, sizeof(proc_name), "p:%d\n", i); | ||
22 | prctl(PR_SET_NAME, proc_name); | ||
23 | } | ||
24 | } | ||
25 | |||
26 | static int count_samples(struct perf_evlist *evlist, int *sample_count, | ||
27 | int *comm_count) | ||
28 | { | ||
29 | int i; | ||
30 | |||
31 | for (i = 0; i < evlist->nr_mmaps; i++) { | ||
32 | union perf_event *event; | ||
33 | |||
34 | perf_evlist__mmap_read_catchup(evlist, i); | ||
35 | while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) { | ||
36 | const u32 type = event->header.type; | ||
37 | |||
38 | switch (type) { | ||
39 | case PERF_RECORD_SAMPLE: | ||
40 | (*sample_count)++; | ||
41 | break; | ||
42 | case PERF_RECORD_COMM: | ||
43 | (*comm_count)++; | ||
44 | break; | ||
45 | default: | ||
46 | pr_err("Unexpected record of type %d\n", type); | ||
47 | return TEST_FAIL; | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | return TEST_OK; | ||
52 | } | ||
53 | |||
54 | static int do_test(struct perf_evlist *evlist, int mmap_pages, | ||
55 | int *sample_count, int *comm_count) | ||
56 | { | ||
57 | int err; | ||
58 | char sbuf[STRERR_BUFSIZE]; | ||
59 | |||
60 | err = perf_evlist__mmap(evlist, mmap_pages, true); | ||
61 | if (err < 0) { | ||
62 | pr_debug("perf_evlist__mmap: %s\n", | ||
63 | strerror_r(errno, sbuf, sizeof(sbuf))); | ||
64 | return TEST_FAIL; | ||
65 | } | ||
66 | |||
67 | perf_evlist__enable(evlist); | ||
68 | testcase(); | ||
69 | perf_evlist__disable(evlist); | ||
70 | |||
71 | err = count_samples(evlist, sample_count, comm_count); | ||
72 | perf_evlist__munmap(evlist); | ||
73 | return err; | ||
74 | } | ||
75 | |||
76 | |||
77 | int test__backward_ring_buffer(int subtest __maybe_unused) | ||
78 | { | ||
79 | int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; | ||
80 | char pid[16], sbuf[STRERR_BUFSIZE]; | ||
81 | struct perf_evlist *evlist; | ||
82 | struct perf_evsel *evsel __maybe_unused; | ||
83 | struct parse_events_error parse_error; | ||
84 | struct record_opts opts = { | ||
85 | .target = { | ||
86 | .uid = UINT_MAX, | ||
87 | .uses_mmap = true, | ||
88 | }, | ||
89 | .freq = 0, | ||
90 | .mmap_pages = 256, | ||
91 | .default_interval = 1, | ||
92 | }; | ||
93 | |||
94 | snprintf(pid, sizeof(pid), "%d", getpid()); | ||
95 | pid[sizeof(pid) - 1] = '\0'; | ||
96 | opts.target.tid = opts.target.pid = pid; | ||
97 | |||
98 | evlist = perf_evlist__new(); | ||
99 | if (!evlist) { | ||
100 | pr_debug("No ehough memory to create evlist\n"); | ||
101 | return TEST_FAIL; | ||
102 | } | ||
103 | |||
104 | err = perf_evlist__create_maps(evlist, &opts.target); | ||
105 | if (err < 0) { | ||
106 | pr_debug("Not enough memory to create thread/cpu maps\n"); | ||
107 | goto out_delete_evlist; | ||
108 | } | ||
109 | |||
110 | bzero(&parse_error, sizeof(parse_error)); | ||
111 | err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error); | ||
112 | if (err) { | ||
113 | pr_debug("Failed to parse tracepoint event, try use root\n"); | ||
114 | ret = TEST_SKIP; | ||
115 | goto out_delete_evlist; | ||
116 | } | ||
117 | |||
118 | perf_evlist__config(evlist, &opts, NULL); | ||
119 | |||
120 | /* Set backward bit, ring buffer should be writing from end */ | ||
121 | evlist__for_each(evlist, evsel) | ||
122 | evsel->attr.write_backward = 1; | ||
123 | |||
124 | err = perf_evlist__open(evlist); | ||
125 | if (err < 0) { | ||
126 | pr_debug("perf_evlist__open: %s\n", | ||
127 | strerror_r(errno, sbuf, sizeof(sbuf))); | ||
128 | goto out_delete_evlist; | ||
129 | } | ||
130 | |||
131 | ret = TEST_FAIL; | ||
132 | err = do_test(evlist, opts.mmap_pages, &sample_count, | ||
133 | &comm_count); | ||
134 | if (err != TEST_OK) | ||
135 | goto out_delete_evlist; | ||
136 | |||
137 | if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) { | ||
138 | pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n", | ||
139 | sample_count, comm_count); | ||
140 | goto out_delete_evlist; | ||
141 | } | ||
142 | |||
143 | err = do_test(evlist, 1, &sample_count, &comm_count); | ||
144 | if (err != TEST_OK) | ||
145 | goto out_delete_evlist; | ||
146 | |||
147 | ret = TEST_OK; | ||
148 | out_delete_evlist: | ||
149 | perf_evlist__delete(evlist); | ||
150 | return ret; | ||
151 | } | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 93c467015e71..0e95c20ecf6e 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -208,6 +208,10 @@ static struct test generic_tests[] = { | |||
208 | .func = test__event_times, | 208 | .func = test__event_times, |
209 | }, | 209 | }, |
210 | { | 210 | { |
211 | .desc = "Test backward reading from ring buffer", | ||
212 | .func = test__backward_ring_buffer, | ||
213 | }, | ||
214 | { | ||
211 | .func = NULL, | 215 | .func = NULL, |
212 | }, | 216 | }, |
213 | }; | 217 | }; |
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 0fc946989cf0..c57e72c826d2 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -86,6 +86,7 @@ int test__synthesize_stat(int subtest); | |||
86 | int test__synthesize_stat_round(int subtest); | 86 | int test__synthesize_stat_round(int subtest); |
87 | int test__event_update(int subtest); | 87 | int test__event_update(int subtest); |
88 | int test__event_times(int subtest); | 88 | int test__event_times(int subtest); |
89 | int test__backward_ring_buffer(int subtest); | ||
89 | 90 | ||
90 | #if defined(__arm__) || defined(__aarch64__) | 91 | #if defined(__arm__) || defined(__aarch64__) |
91 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 92 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 027bb2b89d7f..8c6c8a0ca642 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -27,7 +27,6 @@ libperf-y += strlist.o | |||
27 | libperf-y += strfilter.o | 27 | libperf-y += strfilter.o |
28 | libperf-y += top.o | 28 | libperf-y += top.o |
29 | libperf-y += usage.o | 29 | libperf-y += usage.o |
30 | libperf-y += wrapper.o | ||
31 | libperf-y += dso.o | 30 | libperf-y += dso.o |
32 | libperf-y += symbol.o | 31 | libperf-y += symbol.o |
33 | libperf-y += symbol_fprintf.o | 32 | libperf-y += symbol_fprintf.o |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 1f5a93c2c9a2..0d814bb74661 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -40,25 +40,6 @@ int split_cmdline(char *cmdline, const char ***argv); | |||
40 | 40 | ||
41 | #define alloc_nr(x) (((x)+16)*3/2) | 41 | #define alloc_nr(x) (((x)+16)*3/2) |
42 | 42 | ||
43 | /* | ||
44 | * Realloc the buffer pointed at by variable 'x' so that it can hold | ||
45 | * at least 'nr' entries; the number of entries currently allocated | ||
46 | * is 'alloc', using the standard growing factor alloc_nr() macro. | ||
47 | * | ||
48 | * DO NOT USE any expression with side-effect for 'x' or 'alloc'. | ||
49 | */ | ||
50 | #define ALLOC_GROW(x, nr, alloc) \ | ||
51 | do { \ | ||
52 | if ((nr) > alloc) { \ | ||
53 | if (alloc_nr(alloc) < (nr)) \ | ||
54 | alloc = (nr); \ | ||
55 | else \ | ||
56 | alloc = alloc_nr(alloc); \ | ||
57 | x = xrealloc((x), alloc * sizeof(*(x))); \ | ||
58 | } \ | ||
59 | } while(0) | ||
60 | |||
61 | |||
62 | static inline int is_absolute_path(const char *path) | 43 | static inline int is_absolute_path(const char *path) |
63 | { | 44 | { |
64 | return path[0] == '/'; | 45 | return path[0] == '/'; |
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index aea189b41cc8..a347b19c961a 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c | |||
@@ -915,8 +915,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) | |||
915 | tmp = "*"; | 915 | tmp = "*"; |
916 | else if (tag == DW_TAG_subroutine_type) { | 916 | else if (tag == DW_TAG_subroutine_type) { |
917 | /* Function pointer */ | 917 | /* Function pointer */ |
918 | strbuf_add(buf, "(function_type)", 15); | 918 | return strbuf_add(buf, "(function_type)", 15); |
919 | return 0; | ||
920 | } else { | 919 | } else { |
921 | if (!dwarf_diename(&type)) | 920 | if (!dwarf_diename(&type)) |
922 | return -ENOENT; | 921 | return -ENOENT; |
@@ -927,14 +926,10 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) | |||
927 | else if (tag == DW_TAG_enumeration_type) | 926 | else if (tag == DW_TAG_enumeration_type) |
928 | tmp = "enum "; | 927 | tmp = "enum "; |
929 | /* Write a base name */ | 928 | /* Write a base name */ |
930 | strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type)); | 929 | return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type)); |
931 | return 0; | ||
932 | } | 930 | } |
933 | ret = die_get_typename(&type, buf); | 931 | ret = die_get_typename(&type, buf); |
934 | if (ret == 0) | 932 | return ret ? ret : strbuf_addstr(buf, tmp); |
935 | strbuf_addstr(buf, tmp); | ||
936 | |||
937 | return ret; | ||
938 | } | 933 | } |
939 | 934 | ||
940 | /** | 935 | /** |
@@ -951,12 +946,10 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) | |||
951 | ret = die_get_typename(vr_die, buf); | 946 | ret = die_get_typename(vr_die, buf); |
952 | if (ret < 0) { | 947 | if (ret < 0) { |
953 | pr_debug("Failed to get type, make it unknown.\n"); | 948 | pr_debug("Failed to get type, make it unknown.\n"); |
954 | strbuf_add(buf, " (unknown_type)", 14); | 949 | ret = strbuf_add(buf, " (unknown_type)", 14); |
955 | } | 950 | } |
956 | 951 | ||
957 | strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); | 952 | return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); |
958 | |||
959 | return 0; | ||
960 | } | 953 | } |
961 | 954 | ||
962 | #ifdef HAVE_DWARF_GETLOCATIONS | 955 | #ifdef HAVE_DWARF_GETLOCATIONS |
@@ -999,22 +992,24 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die, | |||
999 | } | 992 | } |
1000 | 993 | ||
1001 | while ((offset = dwarf_ranges(&scopes[1], offset, &base, | 994 | while ((offset = dwarf_ranges(&scopes[1], offset, &base, |
1002 | &start, &end)) > 0) { | 995 | &start, &end)) > 0) { |
1003 | start -= entry; | 996 | start -= entry; |
1004 | end -= entry; | 997 | end -= entry; |
1005 | 998 | ||
1006 | if (first) { | 999 | if (first) { |
1007 | strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, | 1000 | ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, |
1008 | name, start, end); | 1001 | name, start, end); |
1009 | first = false; | 1002 | first = false; |
1010 | } else { | 1003 | } else { |
1011 | strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, | 1004 | ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, |
1012 | start, end); | 1005 | start, end); |
1013 | } | 1006 | } |
1007 | if (ret < 0) | ||
1008 | goto out; | ||
1014 | } | 1009 | } |
1015 | 1010 | ||
1016 | if (!first) | 1011 | if (!first) |
1017 | strbuf_add(buf, "]>", 2); | 1012 | ret = strbuf_add(buf, "]>", 2); |
1018 | 1013 | ||
1019 | out: | 1014 | out: |
1020 | free(scopes); | 1015 | free(scopes); |
@@ -1054,31 +1049,32 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) | |||
1054 | if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) | 1049 | if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) |
1055 | return -EINVAL; | 1050 | return -EINVAL; |
1056 | 1051 | ||
1057 | while ((offset = dwarf_getlocations( | 1052 | while ((offset = dwarf_getlocations(&attr, offset, &base, |
1058 | &attr, offset, &base, | 1053 | &start, &end, &op, &nops)) > 0) { |
1059 | &start, &end, &op, &nops)) > 0) { | ||
1060 | if (start == 0) { | 1054 | if (start == 0) { |
1061 | /* Single Location Descriptions */ | 1055 | /* Single Location Descriptions */ |
1062 | ret = die_get_var_innermost_scope(sp_die, vr_die, buf); | 1056 | ret = die_get_var_innermost_scope(sp_die, vr_die, buf); |
1063 | return ret; | 1057 | goto out; |
1064 | } | 1058 | } |
1065 | 1059 | ||
1066 | /* Location Lists */ | 1060 | /* Location Lists */ |
1067 | start -= entry; | 1061 | start -= entry; |
1068 | end -= entry; | 1062 | end -= entry; |
1069 | if (first) { | 1063 | if (first) { |
1070 | strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, | 1064 | ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, |
1071 | name, start, end); | 1065 | name, start, end); |
1072 | first = false; | 1066 | first = false; |
1073 | } else { | 1067 | } else { |
1074 | strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, | 1068 | ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, |
1075 | start, end); | 1069 | start, end); |
1076 | } | 1070 | } |
1071 | if (ret < 0) | ||
1072 | goto out; | ||
1077 | } | 1073 | } |
1078 | 1074 | ||
1079 | if (!first) | 1075 | if (!first) |
1080 | strbuf_add(buf, "]>", 2); | 1076 | ret = strbuf_add(buf, "]>", 2); |
1081 | 1077 | out: | |
1082 | return ret; | 1078 | return ret; |
1083 | } | 1079 | } |
1084 | #else | 1080 | #else |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 17cd01421e7f..c4bfe11479a0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -766,6 +766,56 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | |||
766 | return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); | 766 | return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); |
767 | } | 767 | } |
768 | 768 | ||
769 | union perf_event * | ||
770 | perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | ||
771 | { | ||
772 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
773 | u64 head, end; | ||
774 | u64 start = md->prev; | ||
775 | |||
776 | /* | ||
777 | * Check if event was unmapped due to a POLLHUP/POLLERR. | ||
778 | */ | ||
779 | if (!atomic_read(&md->refcnt)) | ||
780 | return NULL; | ||
781 | |||
782 | head = perf_mmap__read_head(md); | ||
783 | if (!head) | ||
784 | return NULL; | ||
785 | |||
786 | /* | ||
787 | * 'head' pointer starts from 0. Kernel minus sizeof(record) form | ||
788 | * it each time when kernel writes to it, so in fact 'head' is | ||
789 | * negative. 'end' pointer is made manually by adding the size of | ||
790 | * the ring buffer to 'head' pointer, means the validate data can | ||
791 | * read is the whole ring buffer. If 'end' is positive, the ring | ||
792 | * buffer has not fully filled, so we must adjust 'end' to 0. | ||
793 | * | ||
794 | * However, since both 'head' and 'end' is unsigned, we can't | ||
795 | * simply compare 'end' against 0. Here we compare '-head' and | ||
796 | * the size of the ring buffer, where -head is the number of bytes | ||
797 | * kernel write to the ring buffer. | ||
798 | */ | ||
799 | if (-head < (u64)(md->mask + 1)) | ||
800 | end = 0; | ||
801 | else | ||
802 | end = head + md->mask + 1; | ||
803 | |||
804 | return perf_mmap__read(md, false, start, end, &md->prev); | ||
805 | } | ||
806 | |||
807 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | ||
808 | { | ||
809 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
810 | u64 head; | ||
811 | |||
812 | if (!atomic_read(&md->refcnt)) | ||
813 | return; | ||
814 | |||
815 | head = perf_mmap__read_head(md); | ||
816 | md->prev = head; | ||
817 | } | ||
818 | |||
769 | static bool perf_mmap__empty(struct perf_mmap *md) | 819 | static bool perf_mmap__empty(struct perf_mmap *md) |
770 | { | 820 | { |
771 | return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; | 821 | return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 208897a646ca..85d1b59802e8 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -129,6 +129,10 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); | |||
129 | 129 | ||
130 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); | 130 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); |
131 | 131 | ||
132 | union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, | ||
133 | int idx); | ||
134 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); | ||
135 | |||
132 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); | 136 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); |
133 | 137 | ||
134 | int perf_evlist__open(struct perf_evlist *evlist); | 138 | int perf_evlist__open(struct perf_evlist *evlist); |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3371721a05f2..a23f54793e51 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -1316,6 +1316,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | |||
1316 | PRINT_ATTRf(comm_exec, p_unsigned); | 1316 | PRINT_ATTRf(comm_exec, p_unsigned); |
1317 | PRINT_ATTRf(use_clockid, p_unsigned); | 1317 | PRINT_ATTRf(use_clockid, p_unsigned); |
1318 | PRINT_ATTRf(context_switch, p_unsigned); | 1318 | PRINT_ATTRf(context_switch, p_unsigned); |
1319 | PRINT_ATTRf(write_backward, p_unsigned); | ||
1319 | 1320 | ||
1320 | PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); | 1321 | PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); |
1321 | PRINT_ATTRf(bp_type, p_unsigned); | 1322 | PRINT_ATTRf(bp_type, p_unsigned); |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 90680ec9f8b8..c6000d44f98c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1819,7 +1819,8 @@ static int process_cpu_topology(struct perf_file_section *section, | |||
1819 | 1819 | ||
1820 | ph->env.nr_sibling_cores = nr; | 1820 | ph->env.nr_sibling_cores = nr; |
1821 | size += sizeof(u32); | 1821 | size += sizeof(u32); |
1822 | strbuf_init(&sb, 128); | 1822 | if (strbuf_init(&sb, 128) < 0) |
1823 | goto free_cpu; | ||
1823 | 1824 | ||
1824 | for (i = 0; i < nr; i++) { | 1825 | for (i = 0; i < nr; i++) { |
1825 | str = do_read_string(fd, ph); | 1826 | str = do_read_string(fd, ph); |
@@ -1827,7 +1828,8 @@ static int process_cpu_topology(struct perf_file_section *section, | |||
1827 | goto error; | 1828 | goto error; |
1828 | 1829 | ||
1829 | /* include a NULL character at the end */ | 1830 | /* include a NULL character at the end */ |
1830 | strbuf_add(&sb, str, strlen(str) + 1); | 1831 | if (strbuf_add(&sb, str, strlen(str) + 1) < 0) |
1832 | goto error; | ||
1831 | size += string_size(str); | 1833 | size += string_size(str); |
1832 | free(str); | 1834 | free(str); |
1833 | } | 1835 | } |
@@ -1849,7 +1851,8 @@ static int process_cpu_topology(struct perf_file_section *section, | |||
1849 | goto error; | 1851 | goto error; |
1850 | 1852 | ||
1851 | /* include a NULL character at the end */ | 1853 | /* include a NULL character at the end */ |
1852 | strbuf_add(&sb, str, strlen(str) + 1); | 1854 | if (strbuf_add(&sb, str, strlen(str) + 1) < 0) |
1855 | goto error; | ||
1853 | size += string_size(str); | 1856 | size += string_size(str); |
1854 | free(str); | 1857 | free(str); |
1855 | } | 1858 | } |
@@ -1912,13 +1915,14 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse | |||
1912 | /* nr nodes */ | 1915 | /* nr nodes */ |
1913 | ret = readn(fd, &nr, sizeof(nr)); | 1916 | ret = readn(fd, &nr, sizeof(nr)); |
1914 | if (ret != sizeof(nr)) | 1917 | if (ret != sizeof(nr)) |
1915 | goto error; | 1918 | return -1; |
1916 | 1919 | ||
1917 | if (ph->needs_swap) | 1920 | if (ph->needs_swap) |
1918 | nr = bswap_32(nr); | 1921 | nr = bswap_32(nr); |
1919 | 1922 | ||
1920 | ph->env.nr_numa_nodes = nr; | 1923 | ph->env.nr_numa_nodes = nr; |
1921 | strbuf_init(&sb, 256); | 1924 | if (strbuf_init(&sb, 256) < 0) |
1925 | return -1; | ||
1922 | 1926 | ||
1923 | for (i = 0; i < nr; i++) { | 1927 | for (i = 0; i < nr; i++) { |
1924 | /* node number */ | 1928 | /* node number */ |
@@ -1940,15 +1944,17 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse | |||
1940 | mem_free = bswap_64(mem_free); | 1944 | mem_free = bswap_64(mem_free); |
1941 | } | 1945 | } |
1942 | 1946 | ||
1943 | strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":", | 1947 | if (strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":", |
1944 | node, mem_total, mem_free); | 1948 | node, mem_total, mem_free) < 0) |
1949 | goto error; | ||
1945 | 1950 | ||
1946 | str = do_read_string(fd, ph); | 1951 | str = do_read_string(fd, ph); |
1947 | if (!str) | 1952 | if (!str) |
1948 | goto error; | 1953 | goto error; |
1949 | 1954 | ||
1950 | /* include a NULL character at the end */ | 1955 | /* include a NULL character at the end */ |
1951 | strbuf_add(&sb, str, strlen(str) + 1); | 1956 | if (strbuf_add(&sb, str, strlen(str) + 1) < 0) |
1957 | goto error; | ||
1952 | free(str); | 1958 | free(str); |
1953 | } | 1959 | } |
1954 | ph->env.numa_nodes = strbuf_detach(&sb, NULL); | 1960 | ph->env.numa_nodes = strbuf_detach(&sb, NULL); |
@@ -1982,7 +1988,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused | |||
1982 | } | 1988 | } |
1983 | 1989 | ||
1984 | ph->env.nr_pmu_mappings = pmu_num; | 1990 | ph->env.nr_pmu_mappings = pmu_num; |
1985 | strbuf_init(&sb, 128); | 1991 | if (strbuf_init(&sb, 128) < 0) |
1992 | return -1; | ||
1986 | 1993 | ||
1987 | while (pmu_num) { | 1994 | while (pmu_num) { |
1988 | if (readn(fd, &type, sizeof(type)) != sizeof(type)) | 1995 | if (readn(fd, &type, sizeof(type)) != sizeof(type)) |
@@ -1994,9 +2001,11 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused | |||
1994 | if (!name) | 2001 | if (!name) |
1995 | goto error; | 2002 | goto error; |
1996 | 2003 | ||
1997 | strbuf_addf(&sb, "%u:%s", type, name); | 2004 | if (strbuf_addf(&sb, "%u:%s", type, name) < 0) |
2005 | goto error; | ||
1998 | /* include a NULL character at the end */ | 2006 | /* include a NULL character at the end */ |
1999 | strbuf_add(&sb, "", 1); | 2007 | if (strbuf_add(&sb, "", 1) < 0) |
2008 | goto error; | ||
2000 | 2009 | ||
2001 | if (!strcmp(name, "msr")) | 2010 | if (!strcmp(name, "msr")) |
2002 | ph->env.msr_pmu_type = type; | 2011 | ph->env.msr_pmu_type = type; |
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c index 43a98a4dc1e1..d62ccaeeadd6 100644 --- a/tools/perf/util/help-unknown-cmd.c +++ b/tools/perf/util/help-unknown-cmd.c | |||
@@ -27,16 +27,27 @@ static int levenshtein_compare(const void *p1, const void *p2) | |||
27 | return l1 != l2 ? l1 - l2 : strcmp(s1, s2); | 27 | return l1 != l2 ? l1 - l2 : strcmp(s1, s2); |
28 | } | 28 | } |
29 | 29 | ||
30 | static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) | 30 | static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) |
31 | { | 31 | { |
32 | unsigned int i; | 32 | unsigned int i, nr = cmds->cnt + old->cnt; |
33 | 33 | void *tmp; | |
34 | ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); | 34 | |
35 | 35 | if (nr > cmds->alloc) { | |
36 | /* Choose bigger one to alloc */ | ||
37 | if (alloc_nr(cmds->alloc) < nr) | ||
38 | cmds->alloc = nr; | ||
39 | else | ||
40 | cmds->alloc = alloc_nr(cmds->alloc); | ||
41 | tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names)); | ||
42 | if (!tmp) | ||
43 | return -1; | ||
44 | cmds->names = tmp; | ||
45 | } | ||
36 | for (i = 0; i < old->cnt; i++) | 46 | for (i = 0; i < old->cnt; i++) |
37 | cmds->names[cmds->cnt++] = old->names[i]; | 47 | cmds->names[cmds->cnt++] = old->names[i]; |
38 | zfree(&old->names); | 48 | zfree(&old->names); |
39 | old->cnt = 0; | 49 | old->cnt = 0; |
50 | return 0; | ||
40 | } | 51 | } |
41 | 52 | ||
42 | const char *help_unknown_cmd(const char *cmd) | 53 | const char *help_unknown_cmd(const char *cmd) |
@@ -52,8 +63,11 @@ const char *help_unknown_cmd(const char *cmd) | |||
52 | 63 | ||
53 | load_command_list("perf-", &main_cmds, &other_cmds); | 64 | load_command_list("perf-", &main_cmds, &other_cmds); |
54 | 65 | ||
55 | add_cmd_list(&main_cmds, &aliases); | 66 | if (add_cmd_list(&main_cmds, &aliases) < 0 || |
56 | add_cmd_list(&main_cmds, &other_cmds); | 67 | add_cmd_list(&main_cmds, &other_cmds) < 0) { |
68 | fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n"); | ||
69 | goto end; | ||
70 | } | ||
57 | qsort(main_cmds.names, main_cmds.cnt, | 71 | qsort(main_cmds.names, main_cmds.cnt, |
58 | sizeof(main_cmds.names), cmdname_compare); | 72 | sizeof(main_cmds.names), cmdname_compare); |
59 | uniq(&main_cmds); | 73 | uniq(&main_cmds); |
@@ -99,6 +113,6 @@ const char *help_unknown_cmd(const char *cmd) | |||
99 | for (i = 0; i < n; i++) | 113 | for (i = 0; i < n; i++) |
100 | fprintf(stderr, "\t%s\n", main_cmds.names[i]->name); | 114 | fprintf(stderr, "\t%s\n", main_cmds.names[i]->name); |
101 | } | 115 | } |
102 | 116 | end: | |
103 | exit(1); | 117 | exit(1); |
104 | } | 118 | } |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index bf34468a99cb..ddb0261b2577 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -643,20 +643,20 @@ static int pmu_resolve_param_term(struct parse_events_term *term, | |||
643 | static char *pmu_formats_string(struct list_head *formats) | 643 | static char *pmu_formats_string(struct list_head *formats) |
644 | { | 644 | { |
645 | struct perf_pmu_format *format; | 645 | struct perf_pmu_format *format; |
646 | char *str; | 646 | char *str = NULL; |
647 | struct strbuf buf; | 647 | struct strbuf buf = STRBUF_INIT; |
648 | unsigned i = 0; | 648 | unsigned i = 0; |
649 | 649 | ||
650 | if (!formats) | 650 | if (!formats) |
651 | return NULL; | 651 | return NULL; |
652 | 652 | ||
653 | strbuf_init(&buf, 0); | ||
654 | /* sysfs exported terms */ | 653 | /* sysfs exported terms */ |
655 | list_for_each_entry(format, formats, list) | 654 | list_for_each_entry(format, formats, list) |
656 | strbuf_addf(&buf, i++ ? ",%s" : "%s", | 655 | if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) |
657 | format->name); | 656 | goto error; |
658 | 657 | ||
659 | str = strbuf_detach(&buf, NULL); | 658 | str = strbuf_detach(&buf, NULL); |
659 | error: | ||
660 | strbuf_release(&buf); | 660 | strbuf_release(&buf); |
661 | 661 | ||
662 | return str; | 662 | return str; |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index c82c625395ab..74401a20106d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -1677,28 +1677,37 @@ char *synthesize_perf_probe_arg(struct perf_probe_arg *pa) | |||
1677 | { | 1677 | { |
1678 | struct perf_probe_arg_field *field = pa->field; | 1678 | struct perf_probe_arg_field *field = pa->field; |
1679 | struct strbuf buf; | 1679 | struct strbuf buf; |
1680 | char *ret; | 1680 | char *ret = NULL; |
1681 | int err; | ||
1682 | |||
1683 | if (strbuf_init(&buf, 64) < 0) | ||
1684 | return NULL; | ||
1681 | 1685 | ||
1682 | strbuf_init(&buf, 64); | ||
1683 | if (pa->name && pa->var) | 1686 | if (pa->name && pa->var) |
1684 | strbuf_addf(&buf, "%s=%s", pa->name, pa->var); | 1687 | err = strbuf_addf(&buf, "%s=%s", pa->name, pa->var); |
1685 | else | 1688 | else |
1686 | strbuf_addstr(&buf, pa->name ?: pa->var); | 1689 | err = strbuf_addstr(&buf, pa->name ?: pa->var); |
1690 | if (err) | ||
1691 | goto out; | ||
1687 | 1692 | ||
1688 | while (field) { | 1693 | while (field) { |
1689 | if (field->name[0] == '[') | 1694 | if (field->name[0] == '[') |
1690 | strbuf_addstr(&buf, field->name); | 1695 | err = strbuf_addstr(&buf, field->name); |
1691 | else | 1696 | else |
1692 | strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".", | 1697 | err = strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".", |
1693 | field->name); | 1698 | field->name); |
1694 | field = field->next; | 1699 | field = field->next; |
1700 | if (err) | ||
1701 | goto out; | ||
1695 | } | 1702 | } |
1696 | 1703 | ||
1697 | if (pa->type) | 1704 | if (pa->type) |
1698 | strbuf_addf(&buf, ":%s", pa->type); | 1705 | if (strbuf_addf(&buf, ":%s", pa->type) < 0) |
1706 | goto out; | ||
1699 | 1707 | ||
1700 | ret = strbuf_detach(&buf, NULL); | 1708 | ret = strbuf_detach(&buf, NULL); |
1701 | 1709 | out: | |
1710 | strbuf_release(&buf); | ||
1702 | return ret; | 1711 | return ret; |
1703 | } | 1712 | } |
1704 | 1713 | ||
@@ -1706,18 +1715,23 @@ char *synthesize_perf_probe_arg(struct perf_probe_arg *pa) | |||
1706 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp) | 1715 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp) |
1707 | { | 1716 | { |
1708 | struct strbuf buf; | 1717 | struct strbuf buf; |
1709 | char *tmp; | 1718 | char *tmp, *ret = NULL; |
1710 | int len; | 1719 | int len, err = 0; |
1720 | |||
1721 | if (strbuf_init(&buf, 64) < 0) | ||
1722 | return NULL; | ||
1711 | 1723 | ||
1712 | strbuf_init(&buf, 64); | ||
1713 | if (pp->function) { | 1724 | if (pp->function) { |
1714 | strbuf_addstr(&buf, pp->function); | 1725 | if (strbuf_addstr(&buf, pp->function) < 0) |
1726 | goto out; | ||
1715 | if (pp->offset) | 1727 | if (pp->offset) |
1716 | strbuf_addf(&buf, "+%lu", pp->offset); | 1728 | err = strbuf_addf(&buf, "+%lu", pp->offset); |
1717 | else if (pp->line) | 1729 | else if (pp->line) |
1718 | strbuf_addf(&buf, ":%d", pp->line); | 1730 | err = strbuf_addf(&buf, ":%d", pp->line); |
1719 | else if (pp->retprobe) | 1731 | else if (pp->retprobe) |
1720 | strbuf_addstr(&buf, "%return"); | 1732 | err = strbuf_addstr(&buf, "%return"); |
1733 | if (err) | ||
1734 | goto out; | ||
1721 | } | 1735 | } |
1722 | if (pp->file) { | 1736 | if (pp->file) { |
1723 | tmp = pp->file; | 1737 | tmp = pp->file; |
@@ -1726,12 +1740,15 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) | |||
1726 | tmp = strchr(pp->file + len - 30, '/'); | 1740 | tmp = strchr(pp->file + len - 30, '/'); |
1727 | tmp = tmp ? tmp + 1 : pp->file + len - 30; | 1741 | tmp = tmp ? tmp + 1 : pp->file + len - 30; |
1728 | } | 1742 | } |
1729 | strbuf_addf(&buf, "@%s", tmp); | 1743 | err = strbuf_addf(&buf, "@%s", tmp); |
1730 | if (!pp->function && pp->line) | 1744 | if (!err && !pp->function && pp->line) |
1731 | strbuf_addf(&buf, ":%d", pp->line); | 1745 | err = strbuf_addf(&buf, ":%d", pp->line); |
1732 | } | 1746 | } |
1733 | 1747 | if (!err) | |
1734 | return strbuf_detach(&buf, NULL); | 1748 | ret = strbuf_detach(&buf, NULL); |
1749 | out: | ||
1750 | strbuf_release(&buf); | ||
1751 | return ret; | ||
1735 | } | 1752 | } |
1736 | 1753 | ||
1737 | #if 0 | 1754 | #if 0 |
@@ -1762,28 +1779,30 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev) | |||
1762 | static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, | 1779 | static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, |
1763 | struct strbuf *buf, int depth) | 1780 | struct strbuf *buf, int depth) |
1764 | { | 1781 | { |
1782 | int err; | ||
1765 | if (ref->next) { | 1783 | if (ref->next) { |
1766 | depth = __synthesize_probe_trace_arg_ref(ref->next, buf, | 1784 | depth = __synthesize_probe_trace_arg_ref(ref->next, buf, |
1767 | depth + 1); | 1785 | depth + 1); |
1768 | if (depth < 0) | 1786 | if (depth < 0) |
1769 | goto out; | 1787 | return depth; |
1770 | } | 1788 | } |
1771 | strbuf_addf(buf, "%+ld(", ref->offset); | 1789 | err = strbuf_addf(buf, "%+ld(", ref->offset); |
1772 | out: | 1790 | return (err < 0) ? err : depth; |
1773 | return depth; | ||
1774 | } | 1791 | } |
1775 | 1792 | ||
1776 | static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, | 1793 | static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, |
1777 | struct strbuf *buf) | 1794 | struct strbuf *buf) |
1778 | { | 1795 | { |
1779 | struct probe_trace_arg_ref *ref = arg->ref; | 1796 | struct probe_trace_arg_ref *ref = arg->ref; |
1780 | int depth = 0; | 1797 | int depth = 0, err; |
1781 | 1798 | ||
1782 | /* Argument name or separator */ | 1799 | /* Argument name or separator */ |
1783 | if (arg->name) | 1800 | if (arg->name) |
1784 | strbuf_addf(buf, " %s=", arg->name); | 1801 | err = strbuf_addf(buf, " %s=", arg->name); |
1785 | else | 1802 | else |
1786 | strbuf_addch(buf, ' '); | 1803 | err = strbuf_addch(buf, ' '); |
1804 | if (err) | ||
1805 | return err; | ||
1787 | 1806 | ||
1788 | /* Special case: @XXX */ | 1807 | /* Special case: @XXX */ |
1789 | if (arg->value[0] == '@' && arg->ref) | 1808 | if (arg->value[0] == '@' && arg->ref) |
@@ -1798,18 +1817,19 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, | |||
1798 | 1817 | ||
1799 | /* Print argument value */ | 1818 | /* Print argument value */ |
1800 | if (arg->value[0] == '@' && arg->ref) | 1819 | if (arg->value[0] == '@' && arg->ref) |
1801 | strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset); | 1820 | err = strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset); |
1802 | else | 1821 | else |
1803 | strbuf_addstr(buf, arg->value); | 1822 | err = strbuf_addstr(buf, arg->value); |
1804 | 1823 | ||
1805 | /* Closing */ | 1824 | /* Closing */ |
1806 | while (depth--) | 1825 | while (!err && depth--) |
1807 | strbuf_addch(buf, ')'); | 1826 | err = strbuf_addch(buf, ')'); |
1827 | |||
1808 | /* Print argument type */ | 1828 | /* Print argument type */ |
1809 | if (arg->type) | 1829 | if (!err && arg->type) |
1810 | strbuf_addf(buf, ":%s", arg->type); | 1830 | err = strbuf_addf(buf, ":%s", arg->type); |
1811 | 1831 | ||
1812 | return 0; | 1832 | return err; |
1813 | } | 1833 | } |
1814 | 1834 | ||
1815 | char *synthesize_probe_trace_command(struct probe_trace_event *tev) | 1835 | char *synthesize_probe_trace_command(struct probe_trace_event *tev) |
@@ -1817,15 +1837,18 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) | |||
1817 | struct probe_trace_point *tp = &tev->point; | 1837 | struct probe_trace_point *tp = &tev->point; |
1818 | struct strbuf buf; | 1838 | struct strbuf buf; |
1819 | char *ret = NULL; | 1839 | char *ret = NULL; |
1820 | int i; | 1840 | int i, err; |
1821 | 1841 | ||
1822 | /* Uprobes must have tp->module */ | 1842 | /* Uprobes must have tp->module */ |
1823 | if (tev->uprobes && !tp->module) | 1843 | if (tev->uprobes && !tp->module) |
1824 | return NULL; | 1844 | return NULL; |
1825 | 1845 | ||
1826 | strbuf_init(&buf, 32); | 1846 | if (strbuf_init(&buf, 32) < 0) |
1827 | strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', | 1847 | return NULL; |
1828 | tev->group, tev->event); | 1848 | |
1849 | if (strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', | ||
1850 | tev->group, tev->event) < 0) | ||
1851 | goto error; | ||
1829 | /* | 1852 | /* |
1830 | * If tp->address == 0, then this point must be a | 1853 | * If tp->address == 0, then this point must be a |
1831 | * absolute address uprobe. | 1854 | * absolute address uprobe. |
@@ -1839,14 +1862,16 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) | |||
1839 | 1862 | ||
1840 | /* Use the tp->address for uprobes */ | 1863 | /* Use the tp->address for uprobes */ |
1841 | if (tev->uprobes) | 1864 | if (tev->uprobes) |
1842 | strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address); | 1865 | err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address); |
1843 | else if (!strncmp(tp->symbol, "0x", 2)) | 1866 | else if (!strncmp(tp->symbol, "0x", 2)) |
1844 | /* Absolute address. See try_to_find_absolute_address() */ | 1867 | /* Absolute address. See try_to_find_absolute_address() */ |
1845 | strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "", | 1868 | err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "", |
1846 | tp->module ? ":" : "", tp->address); | 1869 | tp->module ? ":" : "", tp->address); |
1847 | else | 1870 | else |
1848 | strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "", | 1871 | err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "", |
1849 | tp->module ? ":" : "", tp->symbol, tp->offset); | 1872 | tp->module ? ":" : "", tp->symbol, tp->offset); |
1873 | if (err) | ||
1874 | goto error; | ||
1850 | 1875 | ||
1851 | for (i = 0; i < tev->nargs; i++) | 1876 | for (i = 0; i < tev->nargs; i++) |
1852 | if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0) | 1877 | if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0) |
@@ -1960,14 +1985,15 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev, | |||
1960 | if (tev->args[i].name) | 1985 | if (tev->args[i].name) |
1961 | pev->args[i].name = strdup(tev->args[i].name); | 1986 | pev->args[i].name = strdup(tev->args[i].name); |
1962 | else { | 1987 | else { |
1963 | strbuf_init(&buf, 32); | 1988 | if ((ret = strbuf_init(&buf, 32)) < 0) |
1989 | goto error; | ||
1964 | ret = synthesize_probe_trace_arg(&tev->args[i], &buf); | 1990 | ret = synthesize_probe_trace_arg(&tev->args[i], &buf); |
1965 | pev->args[i].name = strbuf_detach(&buf, NULL); | 1991 | pev->args[i].name = strbuf_detach(&buf, NULL); |
1966 | } | 1992 | } |
1967 | if (pev->args[i].name == NULL && ret >= 0) | 1993 | if (pev->args[i].name == NULL && ret >= 0) |
1968 | ret = -ENOMEM; | 1994 | ret = -ENOMEM; |
1969 | } | 1995 | } |
1970 | 1996 | error: | |
1971 | if (ret < 0) | 1997 | if (ret < 0) |
1972 | clear_perf_probe_event(pev); | 1998 | clear_perf_probe_event(pev); |
1973 | 1999 | ||
@@ -2140,37 +2166,40 @@ static int perf_probe_event__sprintf(const char *group, const char *event, | |||
2140 | const char *module, | 2166 | const char *module, |
2141 | struct strbuf *result) | 2167 | struct strbuf *result) |
2142 | { | 2168 | { |
2143 | int i; | 2169 | int i, ret; |
2144 | char *buf; | 2170 | char *buf; |
2145 | 2171 | ||
2146 | if (asprintf(&buf, "%s:%s", group, event) < 0) | 2172 | if (asprintf(&buf, "%s:%s", group, event) < 0) |
2147 | return -errno; | 2173 | return -errno; |
2148 | strbuf_addf(result, " %-20s (on ", buf); | 2174 | ret = strbuf_addf(result, " %-20s (on ", buf); |
2149 | free(buf); | 2175 | free(buf); |
2176 | if (ret) | ||
2177 | return ret; | ||
2150 | 2178 | ||
2151 | /* Synthesize only event probe point */ | 2179 | /* Synthesize only event probe point */ |
2152 | buf = synthesize_perf_probe_point(&pev->point); | 2180 | buf = synthesize_perf_probe_point(&pev->point); |
2153 | if (!buf) | 2181 | if (!buf) |
2154 | return -ENOMEM; | 2182 | return -ENOMEM; |
2155 | strbuf_addstr(result, buf); | 2183 | ret = strbuf_addstr(result, buf); |
2156 | free(buf); | 2184 | free(buf); |
2157 | 2185 | ||
2158 | if (module) | 2186 | if (!ret && module) |
2159 | strbuf_addf(result, " in %s", module); | 2187 | ret = strbuf_addf(result, " in %s", module); |
2160 | 2188 | ||
2161 | if (pev->nargs > 0) { | 2189 | if (!ret && pev->nargs > 0) { |
2162 | strbuf_add(result, " with", 5); | 2190 | ret = strbuf_add(result, " with", 5); |
2163 | for (i = 0; i < pev->nargs; i++) { | 2191 | for (i = 0; !ret && i < pev->nargs; i++) { |
2164 | buf = synthesize_perf_probe_arg(&pev->args[i]); | 2192 | buf = synthesize_perf_probe_arg(&pev->args[i]); |
2165 | if (!buf) | 2193 | if (!buf) |
2166 | return -ENOMEM; | 2194 | return -ENOMEM; |
2167 | strbuf_addf(result, " %s", buf); | 2195 | ret = strbuf_addf(result, " %s", buf); |
2168 | free(buf); | 2196 | free(buf); |
2169 | } | 2197 | } |
2170 | } | 2198 | } |
2171 | strbuf_addch(result, ')'); | 2199 | if (!ret) |
2200 | ret = strbuf_addch(result, ')'); | ||
2172 | 2201 | ||
2173 | return 0; | 2202 | return ret; |
2174 | } | 2203 | } |
2175 | 2204 | ||
2176 | /* Show an event */ | 2205 | /* Show an event */ |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 9f688758b000..1259839dbf6d 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -1294,6 +1294,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) | |||
1294 | { | 1294 | { |
1295 | struct available_var_finder *af = data; | 1295 | struct available_var_finder *af = data; |
1296 | struct variable_list *vl; | 1296 | struct variable_list *vl; |
1297 | struct strbuf buf = STRBUF_INIT; | ||
1297 | int tag, ret; | 1298 | int tag, ret; |
1298 | 1299 | ||
1299 | vl = &af->vls[af->nvls - 1]; | 1300 | vl = &af->vls[af->nvls - 1]; |
@@ -1307,25 +1308,26 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) | |||
1307 | if (ret == 0 || ret == -ERANGE) { | 1308 | if (ret == 0 || ret == -ERANGE) { |
1308 | int ret2; | 1309 | int ret2; |
1309 | bool externs = !af->child; | 1310 | bool externs = !af->child; |
1310 | struct strbuf buf; | ||
1311 | 1311 | ||
1312 | strbuf_init(&buf, 64); | 1312 | if (strbuf_init(&buf, 64) < 0) |
1313 | goto error; | ||
1313 | 1314 | ||
1314 | if (probe_conf.show_location_range) { | 1315 | if (probe_conf.show_location_range) { |
1315 | if (!externs) { | 1316 | if (!externs) |
1316 | if (ret) | 1317 | ret2 = strbuf_add(&buf, |
1317 | strbuf_add(&buf, "[INV]\t", 6); | 1318 | ret ? "[INV]\t" : "[VAL]\t", 6); |
1318 | else | 1319 | else |
1319 | strbuf_add(&buf, "[VAL]\t", 6); | 1320 | ret2 = strbuf_add(&buf, "[EXT]\t", 6); |
1320 | } else | 1321 | if (ret2) |
1321 | strbuf_add(&buf, "[EXT]\t", 6); | 1322 | goto error; |
1322 | } | 1323 | } |
1323 | 1324 | ||
1324 | ret2 = die_get_varname(die_mem, &buf); | 1325 | ret2 = die_get_varname(die_mem, &buf); |
1325 | 1326 | ||
1326 | if (!ret2 && probe_conf.show_location_range && | 1327 | if (!ret2 && probe_conf.show_location_range && |
1327 | !externs) { | 1328 | !externs) { |
1328 | strbuf_addch(&buf, '\t'); | 1329 | if (strbuf_addch(&buf, '\t') < 0) |
1330 | goto error; | ||
1329 | ret2 = die_get_var_range(&af->pf.sp_die, | 1331 | ret2 = die_get_var_range(&af->pf.sp_die, |
1330 | die_mem, &buf); | 1332 | die_mem, &buf); |
1331 | } | 1333 | } |
@@ -1334,8 +1336,8 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) | |||
1334 | if (ret2 == 0) { | 1336 | if (ret2 == 0) { |
1335 | strlist__add(vl->vars, | 1337 | strlist__add(vl->vars, |
1336 | strbuf_detach(&buf, NULL)); | 1338 | strbuf_detach(&buf, NULL)); |
1337 | } else | 1339 | } |
1338 | strbuf_release(&buf); | 1340 | strbuf_release(&buf); |
1339 | } | 1341 | } |
1340 | } | 1342 | } |
1341 | 1343 | ||
@@ -1343,6 +1345,10 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) | |||
1343 | return DIE_FIND_CB_CONTINUE; | 1345 | return DIE_FIND_CB_CONTINUE; |
1344 | else | 1346 | else |
1345 | return DIE_FIND_CB_SIBLING; | 1347 | return DIE_FIND_CB_SIBLING; |
1348 | error: | ||
1349 | strbuf_release(&buf); | ||
1350 | pr_debug("Error in strbuf\n"); | ||
1351 | return DIE_FIND_CB_END; | ||
1346 | } | 1352 | } |
1347 | 1353 | ||
1348 | /* Add a found vars into available variables list */ | 1354 | /* Add a found vars into available variables list */ |
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c index 01f03242b86a..c6d4ee2de752 100644 --- a/tools/perf/util/quote.c +++ b/tools/perf/util/quote.c | |||
@@ -17,38 +17,42 @@ static inline int need_bs_quote(char c) | |||
17 | return (c == '\'' || c == '!'); | 17 | return (c == '\'' || c == '!'); |
18 | } | 18 | } |
19 | 19 | ||
20 | static void sq_quote_buf(struct strbuf *dst, const char *src) | 20 | static int sq_quote_buf(struct strbuf *dst, const char *src) |
21 | { | 21 | { |
22 | char *to_free = NULL; | 22 | char *to_free = NULL; |
23 | int ret; | ||
23 | 24 | ||
24 | if (dst->buf == src) | 25 | if (dst->buf == src) |
25 | to_free = strbuf_detach(dst, NULL); | 26 | to_free = strbuf_detach(dst, NULL); |
26 | 27 | ||
27 | strbuf_addch(dst, '\''); | 28 | ret = strbuf_addch(dst, '\''); |
28 | while (*src) { | 29 | while (!ret && *src) { |
29 | size_t len = strcspn(src, "'!"); | 30 | size_t len = strcspn(src, "'!"); |
30 | strbuf_add(dst, src, len); | 31 | ret = strbuf_add(dst, src, len); |
31 | src += len; | 32 | src += len; |
32 | while (need_bs_quote(*src)) { | 33 | while (!ret && need_bs_quote(*src)) |
33 | strbuf_addstr(dst, "'\\"); | 34 | ret = strbuf_addf(dst, "'\\%c\'", *src++); |
34 | strbuf_addch(dst, *src++); | ||
35 | strbuf_addch(dst, '\''); | ||
36 | } | ||
37 | } | 35 | } |
38 | strbuf_addch(dst, '\''); | 36 | if (!ret) |
37 | ret = strbuf_addch(dst, '\''); | ||
39 | free(to_free); | 38 | free(to_free); |
39 | |||
40 | return ret; | ||
40 | } | 41 | } |
41 | 42 | ||
42 | void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) | 43 | int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) |
43 | { | 44 | { |
44 | int i; | 45 | int i, ret; |
45 | 46 | ||
46 | /* Copy into destination buffer. */ | 47 | /* Copy into destination buffer. */ |
47 | strbuf_grow(dst, 255); | 48 | ret = strbuf_grow(dst, 255); |
48 | for (i = 0; argv[i]; ++i) { | 49 | for (i = 0; !ret && argv[i]; ++i) { |
49 | strbuf_addch(dst, ' '); | 50 | ret = strbuf_addch(dst, ' '); |
50 | sq_quote_buf(dst, argv[i]); | 51 | if (ret) |
52 | break; | ||
53 | ret = sq_quote_buf(dst, argv[i]); | ||
51 | if (maxlen && dst->len > maxlen) | 54 | if (maxlen && dst->len > maxlen) |
52 | die("Too many or long arguments"); | 55 | die("Too many or long arguments"); |
53 | } | 56 | } |
57 | return ret; | ||
54 | } | 58 | } |
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h index 3340c9c4a6ca..e1ec19146fb0 100644 --- a/tools/perf/util/quote.h +++ b/tools/perf/util/quote.h | |||
@@ -24,6 +24,6 @@ | |||
24 | * sq_quote() in a real application. | 24 | * sq_quote() in a real application. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); | 27 | int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); |
28 | 28 | ||
29 | #endif /* __PERF_QUOTE_H */ | 29 | #endif /* __PERF_QUOTE_H */ |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 091bce67844c..1546b749a3a3 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -1062,7 +1062,7 @@ static void set_table_handlers(struct tables *tables) | |||
1062 | tables->dbe.cpr = call_path_root__new(); | 1062 | tables->dbe.cpr = call_path_root__new(); |
1063 | 1063 | ||
1064 | if (!tables->dbe.cpr) | 1064 | if (!tables->dbe.cpr) |
1065 | Py_FatalError("failed to create calls processor"); | 1065 | Py_FatalError("failed to create call path root"); |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | tables->db_export_mode = true; | 1068 | tables->db_export_mode = true; |
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 4d9b481cf3b6..ffa1d0653861 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c | |||
@@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, | |||
307 | struct perf_counts_values *aggr = &counter->counts->aggr; | 307 | struct perf_counts_values *aggr = &counter->counts->aggr; |
308 | struct perf_stat_evsel *ps = counter->priv; | 308 | struct perf_stat_evsel *ps = counter->priv; |
309 | u64 *count = counter->counts->aggr.values; | 309 | u64 *count = counter->counts->aggr.values; |
310 | u64 val; | ||
310 | int i, ret; | 311 | int i, ret; |
311 | 312 | ||
312 | aggr->val = aggr->ena = aggr->run = 0; | 313 | aggr->val = aggr->ena = aggr->run = 0; |
@@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, | |||
346 | /* | 347 | /* |
347 | * Save the full runtime - to allow normalization during printout: | 348 | * Save the full runtime - to allow normalization during printout: |
348 | */ | 349 | */ |
349 | perf_stat__update_shadow_stats(counter, count, 0); | 350 | val = counter->scale * *count; |
351 | perf_stat__update_shadow_stats(counter, &val, 0); | ||
350 | 352 | ||
351 | return 0; | 353 | return 0; |
352 | } | 354 | } |
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 8fb73295ec34..f95f682aa2b2 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include "debug.h" | ||
1 | #include "cache.h" | 2 | #include "cache.h" |
2 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
3 | 4 | ||
@@ -17,12 +18,13 @@ int prefixcmp(const char *str, const char *prefix) | |||
17 | */ | 18 | */ |
18 | char strbuf_slopbuf[1]; | 19 | char strbuf_slopbuf[1]; |
19 | 20 | ||
20 | void strbuf_init(struct strbuf *sb, ssize_t hint) | 21 | int strbuf_init(struct strbuf *sb, ssize_t hint) |
21 | { | 22 | { |
22 | sb->alloc = sb->len = 0; | 23 | sb->alloc = sb->len = 0; |
23 | sb->buf = strbuf_slopbuf; | 24 | sb->buf = strbuf_slopbuf; |
24 | if (hint) | 25 | if (hint) |
25 | strbuf_grow(sb, hint); | 26 | return strbuf_grow(sb, hint); |
27 | return 0; | ||
26 | } | 28 | } |
27 | 29 | ||
28 | void strbuf_release(struct strbuf *sb) | 30 | void strbuf_release(struct strbuf *sb) |
@@ -42,67 +44,104 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz) | |||
42 | return res; | 44 | return res; |
43 | } | 45 | } |
44 | 46 | ||
45 | void strbuf_grow(struct strbuf *sb, size_t extra) | 47 | int strbuf_grow(struct strbuf *sb, size_t extra) |
46 | { | 48 | { |
47 | if (sb->len + extra + 1 <= sb->len) | 49 | char *buf; |
48 | die("you want to use way too much memory"); | 50 | size_t nr = sb->len + extra + 1; |
49 | if (!sb->alloc) | 51 | |
50 | sb->buf = NULL; | 52 | if (nr < sb->alloc) |
51 | ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); | 53 | return 0; |
54 | |||
55 | if (nr <= sb->len) | ||
56 | return -E2BIG; | ||
57 | |||
58 | if (alloc_nr(sb->alloc) > nr) | ||
59 | nr = alloc_nr(sb->alloc); | ||
60 | |||
61 | /* | ||
62 | * Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is | ||
63 | * a static variable. Thus we have to avoid passing it to realloc. | ||
64 | */ | ||
65 | buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf)); | ||
66 | if (!buf) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | sb->buf = buf; | ||
70 | sb->alloc = nr; | ||
71 | return 0; | ||
52 | } | 72 | } |
53 | 73 | ||
54 | void strbuf_addch(struct strbuf *sb, int c) | 74 | int strbuf_addch(struct strbuf *sb, int c) |
55 | { | 75 | { |
56 | strbuf_grow(sb, 1); | 76 | int ret = strbuf_grow(sb, 1); |
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
57 | sb->buf[sb->len++] = c; | 80 | sb->buf[sb->len++] = c; |
58 | sb->buf[sb->len] = '\0'; | 81 | sb->buf[sb->len] = '\0'; |
82 | return 0; | ||
59 | } | 83 | } |
60 | 84 | ||
61 | void strbuf_add(struct strbuf *sb, const void *data, size_t len) | 85 | int strbuf_add(struct strbuf *sb, const void *data, size_t len) |
62 | { | 86 | { |
63 | strbuf_grow(sb, len); | 87 | int ret = strbuf_grow(sb, len); |
88 | if (ret) | ||
89 | return ret; | ||
90 | |||
64 | memcpy(sb->buf + sb->len, data, len); | 91 | memcpy(sb->buf + sb->len, data, len); |
65 | strbuf_setlen(sb, sb->len + len); | 92 | return strbuf_setlen(sb, sb->len + len); |
66 | } | 93 | } |
67 | 94 | ||
68 | static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) | 95 | static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) |
69 | { | 96 | { |
70 | int len; | 97 | int len, ret; |
71 | va_list ap_saved; | 98 | va_list ap_saved; |
72 | 99 | ||
73 | if (!strbuf_avail(sb)) | 100 | if (!strbuf_avail(sb)) { |
74 | strbuf_grow(sb, 64); | 101 | ret = strbuf_grow(sb, 64); |
102 | if (ret) | ||
103 | return ret; | ||
104 | } | ||
75 | 105 | ||
76 | va_copy(ap_saved, ap); | 106 | va_copy(ap_saved, ap); |
77 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); | 107 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); |
78 | if (len < 0) | 108 | if (len < 0) |
79 | die("your vsnprintf is broken"); | 109 | return len; |
80 | if (len > strbuf_avail(sb)) { | 110 | if (len > strbuf_avail(sb)) { |
81 | strbuf_grow(sb, len); | 111 | ret = strbuf_grow(sb, len); |
112 | if (ret) | ||
113 | return ret; | ||
82 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); | 114 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); |
83 | va_end(ap_saved); | 115 | va_end(ap_saved); |
84 | if (len > strbuf_avail(sb)) { | 116 | if (len > strbuf_avail(sb)) { |
85 | die("this should not happen, your vsnprintf is broken"); | 117 | pr_debug("this should not happen, your vsnprintf is broken"); |
118 | return -EINVAL; | ||
86 | } | 119 | } |
87 | } | 120 | } |
88 | strbuf_setlen(sb, sb->len + len); | 121 | return strbuf_setlen(sb, sb->len + len); |
89 | } | 122 | } |
90 | 123 | ||
91 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | 124 | int strbuf_addf(struct strbuf *sb, const char *fmt, ...) |
92 | { | 125 | { |
93 | va_list ap; | 126 | va_list ap; |
127 | int ret; | ||
94 | 128 | ||
95 | va_start(ap, fmt); | 129 | va_start(ap, fmt); |
96 | strbuf_addv(sb, fmt, ap); | 130 | ret = strbuf_addv(sb, fmt, ap); |
97 | va_end(ap); | 131 | va_end(ap); |
132 | return ret; | ||
98 | } | 133 | } |
99 | 134 | ||
100 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) | 135 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) |
101 | { | 136 | { |
102 | size_t oldlen = sb->len; | 137 | size_t oldlen = sb->len; |
103 | size_t oldalloc = sb->alloc; | 138 | size_t oldalloc = sb->alloc; |
139 | int ret; | ||
140 | |||
141 | ret = strbuf_grow(sb, hint ? hint : 8192); | ||
142 | if (ret) | ||
143 | return ret; | ||
104 | 144 | ||
105 | strbuf_grow(sb, hint ? hint : 8192); | ||
106 | for (;;) { | 145 | for (;;) { |
107 | ssize_t cnt; | 146 | ssize_t cnt; |
108 | 147 | ||
@@ -112,12 +151,14 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) | |||
112 | strbuf_release(sb); | 151 | strbuf_release(sb); |
113 | else | 152 | else |
114 | strbuf_setlen(sb, oldlen); | 153 | strbuf_setlen(sb, oldlen); |
115 | return -1; | 154 | return cnt; |
116 | } | 155 | } |
117 | if (!cnt) | 156 | if (!cnt) |
118 | break; | 157 | break; |
119 | sb->len += cnt; | 158 | sb->len += cnt; |
120 | strbuf_grow(sb, 8192); | 159 | ret = strbuf_grow(sb, 8192); |
160 | if (ret) | ||
161 | return ret; | ||
121 | } | 162 | } |
122 | 163 | ||
123 | sb->buf[sb->len] = '\0'; | 164 | sb->buf[sb->len] = '\0'; |
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index ab9be0fbbd40..54b409297d4a 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h | |||
@@ -51,7 +51,7 @@ struct strbuf { | |||
51 | #define STRBUF_INIT { 0, 0, strbuf_slopbuf } | 51 | #define STRBUF_INIT { 0, 0, strbuf_slopbuf } |
52 | 52 | ||
53 | /*----- strbuf life cycle -----*/ | 53 | /*----- strbuf life cycle -----*/ |
54 | void strbuf_init(struct strbuf *buf, ssize_t hint); | 54 | int strbuf_init(struct strbuf *buf, ssize_t hint); |
55 | void strbuf_release(struct strbuf *buf); | 55 | void strbuf_release(struct strbuf *buf); |
56 | char *strbuf_detach(struct strbuf *buf, size_t *); | 56 | char *strbuf_detach(struct strbuf *buf, size_t *); |
57 | 57 | ||
@@ -60,26 +60,31 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) { | |||
60 | return sb->alloc ? sb->alloc - sb->len - 1 : 0; | 60 | return sb->alloc ? sb->alloc - sb->len - 1 : 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | void strbuf_grow(struct strbuf *buf, size_t); | 63 | int strbuf_grow(struct strbuf *buf, size_t); |
64 | 64 | ||
65 | static inline void strbuf_setlen(struct strbuf *sb, size_t len) { | 65 | static inline int strbuf_setlen(struct strbuf *sb, size_t len) { |
66 | if (!sb->alloc) | 66 | int ret; |
67 | strbuf_grow(sb, 0); | 67 | if (!sb->alloc) { |
68 | ret = strbuf_grow(sb, 0); | ||
69 | if (ret) | ||
70 | return ret; | ||
71 | } | ||
68 | assert(len < sb->alloc); | 72 | assert(len < sb->alloc); |
69 | sb->len = len; | 73 | sb->len = len; |
70 | sb->buf[len] = '\0'; | 74 | sb->buf[len] = '\0'; |
75 | return 0; | ||
71 | } | 76 | } |
72 | 77 | ||
73 | /*----- add data in your buffer -----*/ | 78 | /*----- add data in your buffer -----*/ |
74 | void strbuf_addch(struct strbuf *sb, int c); | 79 | int strbuf_addch(struct strbuf *sb, int c); |
75 | 80 | ||
76 | void strbuf_add(struct strbuf *buf, const void *, size_t); | 81 | int strbuf_add(struct strbuf *buf, const void *, size_t); |
77 | static inline void strbuf_addstr(struct strbuf *sb, const char *s) { | 82 | static inline int strbuf_addstr(struct strbuf *sb, const char *s) { |
78 | strbuf_add(sb, s, strlen(s)); | 83 | return strbuf_add(sb, s, strlen(s)); |
79 | } | 84 | } |
80 | 85 | ||
81 | __attribute__((format(printf,2,3))) | 86 | __attribute__((format(printf,2,3))) |
82 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...); | 87 | int strbuf_addf(struct strbuf *sb, const char *fmt, ...); |
83 | 88 | ||
84 | /* XXX: if read fails, any partial read is undone */ | 89 | /* XXX: if read fails, any partial read is undone */ |
85 | ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); | 90 | ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 415c4f6d98fd..2946295ca502 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -301,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) | |||
301 | 301 | ||
302 | if (ip < s->start) | 302 | if (ip < s->start) |
303 | n = n->rb_left; | 303 | n = n->rb_left; |
304 | else if (ip >= s->end) | 304 | else if (ip > s->end || (ip == s->end && ip != s->start)) |
305 | n = n->rb_right; | 305 | n = n->rb_right; |
306 | else | 306 | else |
307 | return s; | 307 | return s; |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 619ba2061b62..01c9433de7ef 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -507,7 +507,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) | |||
507 | "needed for --call-graph fp\n"); | 507 | "needed for --call-graph fp\n"); |
508 | break; | 508 | break; |
509 | 509 | ||
510 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
511 | /* Dwarf style */ | 510 | /* Dwarf style */ |
512 | } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { | 511 | } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { |
513 | const unsigned long default_stack_dump_size = 8192; | 512 | const unsigned long default_stack_dump_size = 8192; |
@@ -523,7 +522,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) | |||
523 | ret = get_stack_size(tok, &size); | 522 | ret = get_stack_size(tok, &size); |
524 | param->dump_size = size; | 523 | param->dump_size = size; |
525 | } | 524 | } |
526 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | ||
527 | } else if (!strncmp(name, "lbr", sizeof("lbr"))) { | 525 | } else if (!strncmp(name, "lbr", sizeof("lbr"))) { |
528 | if (!strtok_r(NULL, ",", &saveptr)) { | 526 | if (!strtok_r(NULL, ",", &saveptr)) { |
529 | param->record_mode = CALLCHAIN_LBR; | 527 | param->record_mode = CALLCHAIN_LBR; |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 88f607af1f47..7651633a8dc7 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -160,12 +160,6 @@ static inline char *gitstrchrnul(const char *s, int c) | |||
160 | } | 160 | } |
161 | #endif | 161 | #endif |
162 | 162 | ||
163 | /* | ||
164 | * Wrappers: | ||
165 | */ | ||
166 | void *xrealloc(void *ptr, size_t size) __attribute__((weak)); | ||
167 | |||
168 | |||
169 | static inline void *zalloc(size_t size) | 163 | static inline void *zalloc(size_t size) |
170 | { | 164 | { |
171 | return calloc(1, size); | 165 | return calloc(1, size); |
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c deleted file mode 100644 index 5f1a07c4b87b..000000000000 --- a/tools/perf/util/wrapper.c +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Various trivial helper wrappers around standard functions | ||
3 | */ | ||
4 | #include "cache.h" | ||
5 | |||
6 | /* | ||
7 | * There's no pack memory to release - but stay close to the Git | ||
8 | * version so wrap this away: | ||
9 | */ | ||
10 | static inline void release_pack_memory(size_t size __maybe_unused, | ||
11 | int flag __maybe_unused) | ||
12 | { | ||
13 | } | ||
14 | |||
15 | void *xrealloc(void *ptr, size_t size) | ||
16 | { | ||
17 | void *ret = realloc(ptr, size); | ||
18 | if (!ret && !size) | ||
19 | ret = realloc(ptr, 1); | ||
20 | if (!ret) { | ||
21 | release_pack_memory(size, -1); | ||
22 | ret = realloc(ptr, size); | ||
23 | if (!ret && !size) | ||
24 | ret = realloc(ptr, 1); | ||
25 | if (!ret) | ||
26 | die("Out of memory, realloc failed"); | ||
27 | } | ||
28 | return ret; | ||
29 | } | ||