Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'perf-core-for-mingo-20160803' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

New features:

- Add --sample-cpu to 'perf record', to explicitely ask for sampling
the CPU (Jiri Olsa)

Fixes:

- Fix processing of multi byte chunks in objdump output, fixing
disassemble processing for annotation on at least ARM64 (Jan Stancek)

- Use SyS_epoll_wait in a BPF 'perf test' entry instead of sys_epoll_wait, that
is not present in the DWARF info in vmlinux files (Arnaldo Carvalho de Melo)

- Add -wno-shadow when processing files using perl headers, fixing
the build on Fedora Rawhide and Arch Linux (Namhyung Kim)

Infrastructure changes:

- Annotate prep work to better catch and report errors related to
using objdump to disassemble DSOs (Arnaldo Carvalho de Melo)

- Add 'alloc', 'scnprintf' and 'and' methods for bitmap processing (Jiri Olsa)

- Add nested output resorting callback in hists processing (Jiri Olsa)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+394 -106
+37
tools/include/linux/bitmap.h
··· 3 3 4 4 #include <string.h> 5 5 #include <linux/bitops.h> 6 + #include <stdlib.h> 6 7 7 8 #define DECLARE_BITMAP(name,bits) \ 8 9 unsigned long name[BITS_TO_LONGS(bits)] ··· 11 10 int __bitmap_weight(const unsigned long *bitmap, int bits); 12 11 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 13 12 const unsigned long *bitmap2, int bits); 13 + int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, 14 + const unsigned long *bitmap2, unsigned int bits); 14 15 15 16 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) 16 17 ··· 66 63 *p = old | mask; 67 64 68 65 return (old & mask) != 0; 66 + } 67 + 68 + /** 69 + * bitmap_alloc - Allocate bitmap 70 + * @nr: Bit to set 71 + */ 72 + static inline unsigned long *bitmap_alloc(int nbits) 73 + { 74 + return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long)); 75 + } 76 + 77 + /* 78 + * bitmap_scnprintf - print bitmap list into buffer 79 + * @bitmap: bitmap 80 + * @nbits: size of bitmap 81 + * @buf: buffer to store output 82 + * @size: size of @buf 83 + */ 84 + size_t bitmap_scnprintf(unsigned long *bitmap, int nbits, 85 + char *buf, size_t size); 86 + 87 + /** 88 + * bitmap_and - Do logical and on bitmaps 89 + * @dst: resulting bitmap 90 + * @src1: operand 1 91 + * @src2: operand 2 92 + * @nbits: size of bitmap 93 + */ 94 + static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, 95 + const unsigned long *src2, unsigned int nbits) 96 + { 97 + if (small_const_nbits(nbits)) 98 + return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0; 99 + return __bitmap_and(dst, src1, src2, nbits); 69 100 } 70 101 71 102 #endif /* _PERF_BITOPS_H */
+44
tools/lib/bitmap.c
··· 29 29 for (k = 0; k < nr; k++) 30 30 dst[k] = bitmap1[k] | bitmap2[k]; 31 31 } 32 + 33 + size_t bitmap_scnprintf(unsigned long *bitmap, int nbits, 34 + char *buf, size_t size) 35 + { 36 + /* current bit is 'cur', most recently seen range is [rbot, rtop] */ 37 + int cur, rbot, rtop; 38 + bool first = true; 39 + size_t ret = 0; 40 + 41 + rbot = cur = find_first_bit(bitmap, nbits); 42 + while (cur < nbits) { 43 + rtop = cur; 44 + cur = find_next_bit(bitmap, nbits, cur + 1); 45 + if (cur < nbits && cur <= rtop + 1) 46 + continue; 47 + 48 + if (!first) 49 + ret += scnprintf(buf + ret, size - ret, ","); 50 + 51 + first = false; 52 + 53 + ret += scnprintf(buf + ret, size - ret, "%d", rbot); 54 + if (rbot < rtop) 55 + ret += scnprintf(buf + ret, size - ret, "-%d", rtop); 56 + 57 + rbot = cur; 58 + } 59 + return ret; 60 + } 61 + 62 + int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, 63 + const unsigned long *bitmap2, unsigned int bits) 64 + { 65 + unsigned int k; 66 + unsigned int lim = bits/BITS_PER_LONG; 67 + unsigned long result = 0; 68 + 69 + for (k = 0; k < lim; k++) 70 + result |= (dst[k] = bitmap1[k] & bitmap2[k]); 71 + if (bits % BITS_PER_LONG) 72 + result |= (dst[k] = bitmap1[k] & bitmap2[k] & 73 + BITMAP_LAST_WORD_MASK(bits)); 74 + return result != 0; 75 + }
+1
tools/lib/traceevent/.gitignore
··· 1 1 TRACEEVENT-CFLAGS 2 2 libtraceevent-dynamic-list 3 + libtraceevent.so.*
+3
tools/perf/Documentation/perf-record.txt
··· 192 192 --period:: 193 193 Record the sample period. 194 194 195 + --sample-cpu:: 196 + Record the sample cpu. 197 + 195 198 -n:: 196 199 --no-samples:: 197 200 Don't sample.
+3 -3
tools/perf/Makefile.perf
··· 161 161 BPF_DIR = $(srctree)/tools/lib/bpf/ 162 162 SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ 163 163 164 - # include config/Makefile by default and rule out 164 + # include Makefile.config by default and rule out 165 165 # non-config cases 166 166 config := 1 167 167 ··· 183 183 FEATURE_TESTS := all 184 184 endif 185 185 endif 186 - include config/Makefile 186 + include Makefile.config 187 187 endif 188 188 189 189 ifeq ($(config),0) ··· 706 706 ### Cleaning rules 707 707 708 708 # 709 - # This is here, not in config/Makefile, because config/Makefile does 709 + # This is here, not in Makefile.config, because Makefile.config does 710 710 # not get included for the clean target: 711 711 # 712 712 config-clean:
+1
tools/perf/builtin-record.c
··· 1434 1434 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1435 1435 "per thread counts"), 1436 1436 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1437 + OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 1437 1438 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1438 1439 &record.opts.sample_time_set, 1439 1440 "Record the sample timestamps"),
+5 -1
tools/perf/builtin-top.c
··· 128 128 return err; 129 129 } 130 130 131 - err = symbol__annotate(sym, map, 0); 131 + err = symbol__disassemble(sym, map, 0); 132 132 if (err == 0) { 133 133 out_assign: 134 134 top->sym_filter_entry = he; 135 + } else { 136 + char msg[BUFSIZ]; 137 + symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 138 + pr_err("Couldn't annotate %s: %s\n", sym->name, msg); 135 139 } 136 140 137 141 pthread_mutex_unlock(&notes->lock);
tools/perf/config/Makefile tools/perf/Makefile.config
+1
tools/perf/perf.h
··· 52 52 bool sample_weight; 53 53 bool sample_time; 54 54 bool sample_time_set; 55 + bool sample_cpu; 55 56 bool period; 56 57 bool running_time; 57 58 bool full_auxtrace;
+3 -1
tools/perf/scripts/perl/Perf-Trace-Util/Build
··· 1 1 libperf-y += Context.o 2 2 3 - CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default 3 + CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes 4 + CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef 5 + CFLAGS_Context.o += -Wno-switch-default -Wno-shadow
+1
tools/perf/tests/Build
··· 41 41 perf-y += backward-ring-buffer.o 42 42 perf-y += sdt.o 43 43 perf-y += is_printable_array.o 44 + perf-y += bitmap.o 44 45 45 46 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 46 47 $(call rule_mkdir)
+53
tools/perf/tests/bitmap.c
··· 1 + #include <linux/compiler.h> 2 + #include <linux/bitmap.h> 3 + #include "tests.h" 4 + #include "cpumap.h" 5 + #include "debug.h" 6 + 7 + #define NBITS 100 8 + 9 + static unsigned long *get_bitmap(const char *str, int nbits) 10 + { 11 + struct cpu_map *map = cpu_map__new(str); 12 + unsigned long *bm = NULL; 13 + int i; 14 + 15 + bm = bitmap_alloc(nbits); 16 + 17 + if (map && bm) { 18 + bitmap_zero(bm, nbits); 19 + 20 + for (i = 0; i < map->nr; i++) 21 + set_bit(map->map[i], bm); 22 + } 23 + 24 + if (map) 25 + cpu_map__put(map); 26 + return bm; 27 + } 28 + 29 + static int test_bitmap(const char *str) 30 + { 31 + unsigned long *bm = get_bitmap(str, NBITS); 32 + char buf[100]; 33 + int ret; 34 + 35 + bitmap_scnprintf(bm, NBITS, buf, sizeof(buf)); 36 + pr_debug("bitmap: %s\n", buf); 37 + 38 + ret = !strcmp(buf, str); 39 + free(bm); 40 + return ret; 41 + } 42 + 43 + int test__bitmap_print(int subtest __maybe_unused) 44 + { 45 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("1")); 46 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5")); 47 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3,5,7,9,11,13,15,17,19,21-40")); 48 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("2-5")); 49 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37")); 50 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37")); 51 + TEST_ASSERT_VAL("failed to convert map", test_bitmap("1-10,12-20,22-30,32-40")); 52 + return 0; 53 + }
+2 -2
tools/perf/tests/bpf-script-example.c
··· 31 31 .max_entries = 1, 32 32 }; 33 33 34 - SEC("func=sys_epoll_wait") 35 - int bpf_func__sys_epoll_wait(void *ctx) 34 + SEC("func=SyS_epoll_wait") 35 + int bpf_func__SyS_epoll_wait(void *ctx) 36 36 { 37 37 int ind =0; 38 38 int *flag = bpf_map_lookup_elem(&flip_table, &ind);
+4
tools/perf/tests/builtin-test.c
··· 226 226 .func = test__is_printable_array, 227 227 }, 228 228 { 229 + .desc = "Test bitmap print", 230 + .func = test__bitmap_print, 231 + }, 232 + { 229 233 .func = NULL, 230 234 }, 231 235 };
+71 -29
tools/perf/tests/code-reading.c
··· 33 33 return c - 'A' + 10; 34 34 } 35 35 36 - static size_t read_objdump_line(const char *line, size_t line_len, void *buf, 37 - size_t len) 36 + static size_t read_objdump_chunk(const char **line, unsigned char **buf, 37 + size_t *buf_len) 38 + { 39 + size_t bytes_read = 0; 40 + unsigned char *chunk_start = *buf; 41 + 42 + /* Read bytes */ 43 + while (*buf_len > 0) { 44 + char c1, c2; 45 + 46 + /* Get 2 hex digits */ 47 + c1 = *(*line)++; 48 + if (!isxdigit(c1)) 49 + break; 50 + c2 = *(*line)++; 51 + if (!isxdigit(c2)) 52 + break; 53 + 54 + /* Store byte and advance buf */ 55 + **buf = (hex(c1) << 4) | hex(c2); 56 + (*buf)++; 57 + (*buf_len)--; 58 + bytes_read++; 59 + 60 + /* End of chunk? */ 61 + if (isspace(**line)) 62 + break; 63 + } 64 + 65 + /* 66 + * objdump will display raw insn as LE if code endian 67 + * is LE and bytes_per_chunk > 1. In that case reverse 68 + * the chunk we just read. 69 + * 70 + * see disassemble_bytes() at binutils/objdump.c for details 71 + * how objdump chooses display endian) 72 + */ 73 + if (bytes_read > 1 && !bigendian()) { 74 + unsigned char *chunk_end = chunk_start + bytes_read - 1; 75 + unsigned char tmp; 76 + 77 + while (chunk_start < chunk_end) { 78 + tmp = *chunk_start; 79 + *chunk_start = *chunk_end; 80 + *chunk_end = tmp; 81 + chunk_start++; 82 + chunk_end--; 83 + } 84 + } 85 + 86 + return bytes_read; 87 + } 88 + 89 + static size_t read_objdump_line(const char *line, unsigned char *buf, 90 + size_t buf_len) 38 91 { 39 92 const char *p; 40 - size_t i, j = 0; 93 + size_t ret, bytes_read = 0; 41 94 42 95 /* Skip to a colon */ 43 96 p = strchr(line, ':'); 44 97 if (!p) 45 98 return 0; 46 - i = p + 1 - line; 99 + p++; 47 100 48 - /* Read bytes */ 49 - while (j < len) { 50 - char c1, c2; 51 - 52 - /* Skip spaces */ 53 - for (; i < line_len; i++) { 54 - if (!isspace(line[i])) 55 - break; 56 - } 57 - /* Get 2 hex digits */ 58 - if (i >= line_len || !isxdigit(line[i])) 101 + /* Skip initial spaces */ 102 + while (*p) { 103 + if (!isspace(*p)) 59 104 break; 60 - c1 = line[i++]; 61 - if (i >= line_len || !isxdigit(line[i])) 62 - break; 63 - c2 = line[i++]; 64 - /* Followed by a space */ 65 - if (i < line_len && line[i] && !isspace(line[i])) 66 - break; 67 - /* Store byte */ 68 - *(unsigned char *)buf = (hex(c1) << 4) | hex(c2); 69 - buf += 1; 70 - j++; 105 + p++; 71 106 } 107 + 108 + do { 109 + ret = read_objdump_chunk(&p, &buf, &buf_len); 110 + bytes_read += ret; 111 + p++; 112 + } while (ret > 0); 113 + 72 114 /* return number of successfully read bytes */ 73 - return j; 115 + return bytes_read; 74 116 } 75 117 76 118 static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) ··· 137 95 } 138 96 139 97 /* read objdump data into temporary buffer */ 140 - read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp)); 98 + read_bytes = read_objdump_line(line, tmp, sizeof(tmp)); 141 99 if (!read_bytes) 142 100 continue; 143 101 ··· 194 152 195 153 ret = read_objdump_output(f, buf, &len, addr); 196 154 if (len) { 197 - pr_debug("objdump read too few bytes\n"); 155 + pr_debug("objdump read too few bytes: %zd\n", len); 198 156 if (!ret) 199 157 ret = len; 200 158 }
+1
tools/perf/tests/tests.h
··· 90 90 int test__cpu_map_print(int subtest); 91 91 int test__sdt_event(int subtest); 92 92 int test__is_printable_array(int subtest); 93 + int test__bitmap_print(int subtest); 93 94 94 95 #if defined(__arm__) || defined(__aarch64__) 95 96 #ifdef HAVE_DWARF_UNWIND_SUPPORT
+6 -3
tools/perf/ui/browsers/annotate.c
··· 1026 1026 .use_navkeypressed = true, 1027 1027 }, 1028 1028 }; 1029 - int ret = -1; 1029 + int ret = -1, err; 1030 1030 int nr_pcnt = 1; 1031 1031 size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1032 1032 ··· 1050 1050 (nr_pcnt - 1); 1051 1051 } 1052 1052 1053 - if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 1054 - ui__error("%s", ui_helpline__last_msg); 1053 + err = symbol__disassemble(sym, map, sizeof_bdl); 1054 + if (err) { 1055 + char msg[BUFSIZ]; 1056 + symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1057 + ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 1055 1058 goto out_free_offsets; 1056 1059 } 1057 1060
+6 -2
tools/perf/ui/gtk/annotate.c
··· 162 162 GtkWidget *notebook; 163 163 GtkWidget *scrolled_window; 164 164 GtkWidget *tab_label; 165 + int err; 165 166 166 167 if (map->dso->annotate_warned) 167 168 return -1; 168 169 169 - if (symbol__annotate(sym, map, 0) < 0) { 170 - ui__error("%s", ui_helpline__current); 170 + err = symbol__disassemble(sym, map, 0); 171 + if (err) { 172 + char msg[BUFSIZ]; 173 + symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 174 + ui__error("Couldn't annotate %s: %s\n", sym->name, msg); 171 175 return -1; 172 176 } 173 177
+81 -35
tools/perf/util/annotate.c
··· 1123 1123 } 1124 1124 } 1125 1125 1126 - int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 1126 + int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map, 1127 + int errnum, char *buf, size_t buflen) 1128 + { 1129 + struct dso *dso = map->dso; 1130 + 1131 + BUG_ON(buflen == 0); 1132 + 1133 + if (errnum >= 0) { 1134 + str_error_r(errnum, buf, buflen); 1135 + return 0; 1136 + } 1137 + 1138 + switch (errnum) { 1139 + case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: { 1140 + char bf[SBUILD_ID_SIZE + 15] = " with build id "; 1141 + char *build_id_msg = NULL; 1142 + 1143 + if (dso->has_build_id) { 1144 + build_id__sprintf(dso->build_id, 1145 + sizeof(dso->build_id), bf + 15); 1146 + build_id_msg = bf; 1147 + } 1148 + scnprintf(buf, buflen, 1149 + "No vmlinux file%s\nwas found in the path.\n\n" 1150 + "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" 1151 + "Please use:\n\n" 1152 + " perf buildid-cache -vu vmlinux\n\n" 1153 + "or:\n\n" 1154 + " --vmlinux vmlinux\n", build_id_msg ?: ""); 1155 + } 1156 + break; 1157 + default: 1158 + scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); 1159 + break; 1160 + } 1161 + 1162 + return 0; 1163 + } 1164 + 1165 + int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) 1127 1166 { 1128 1167 struct dso *dso = map->dso; 1129 1168 char *filename = dso__build_id_filename(dso, NULL, 0); ··· 1173 1134 char symfs_filename[PATH_MAX]; 1174 1135 struct kcore_extract kce; 1175 1136 bool delete_extract = false; 1137 + int stdout_fd[2]; 1176 1138 int lineno = 0; 1177 1139 int nline; 1140 + pid_t pid; 1178 1141 1179 1142 if (filename) 1180 1143 symbol__join_symfs(symfs_filename, filename); 1181 1144 1182 1145 if (filename == NULL) { 1183 - if (dso->has_build_id) { 1184 - pr_err("Can't annotate %s: not enough memory\n", 1185 - sym->name); 1186 - return -ENOMEM; 1187 - } 1146 + if (dso->has_build_id) 1147 + return ENOMEM; 1188 1148 goto fallback; 1189 - } else if (dso__is_kcore(dso)) { 1190 - goto fallback; 1191 - } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 1149 + } else if (dso__is_kcore(dso) || 1150 + readlink(symfs_filename, command, sizeof(command)) < 0 || 1192 1151 strstr(command, DSO__NAME_KALLSYMS) || 1193 1152 access(symfs_filename, R_OK)) { 1194 1153 free(filename); ··· 1203 1166 1204 1167 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1205 1168 !dso__is_kcore(dso)) { 1206 - char bf[SBUILD_ID_SIZE + 15] = " with build id "; 1207 - char *build_id_msg = NULL; 1208 - 1209 - if (dso->annotate_warned) 1210 - goto out_free_filename; 1211 - 1212 - if (dso->has_build_id) { 1213 - build_id__sprintf(dso->build_id, 1214 - sizeof(dso->build_id), bf + 15); 1215 - build_id_msg = bf; 1216 - } 1217 - err = -ENOENT; 1218 - dso->annotate_warned = 1; 1219 - pr_err("Can't annotate %s:\n\n" 1220 - "No vmlinux file%s\nwas found in the path.\n\n" 1221 - "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" 1222 - "Please use:\n\n" 1223 - " perf buildid-cache -vu vmlinux\n\n" 1224 - "or:\n\n" 1225 - " --vmlinux vmlinux\n", 1226 - sym->name, build_id_msg ?: ""); 1169 + err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1227 1170 goto out_free_filename; 1228 1171 } 1229 1172 ··· 1275 1258 1276 1259 pr_debug("Executing: %s\n", command); 1277 1260 1278 - file = popen(command, "r"); 1261 + err = -1; 1262 + if (pipe(stdout_fd) < 0) { 1263 + pr_err("Failure creating the pipe to run %s\n", command); 1264 + goto out_remove_tmp; 1265 + } 1266 + 1267 + pid = fork(); 1268 + if (pid < 0) { 1269 + pr_err("Failure forking to run %s\n", command); 1270 + goto out_close_stdout; 1271 + } 1272 + 1273 + if (pid == 0) { 1274 + close(stdout_fd[0]); 1275 + dup2(stdout_fd[1], 1); 1276 + close(stdout_fd[1]); 1277 + execl("/bin/sh", "sh", "-c", command, NULL); 1278 + perror(command); 1279 + exit(-1); 1280 + } 1281 + 1282 + close(stdout_fd[1]); 1283 + 1284 + file = fdopen(stdout_fd[0], "r"); 1279 1285 if (!file) { 1280 - pr_err("Failure running %s\n", command); 1286 + pr_err("Failure creating FILE stream for %s\n", command); 1281 1287 /* 1282 1288 * If we were using debug info should retry with 1283 1289 * original binary. ··· 1326 1286 if (dso__is_kcore(dso)) 1327 1287 delete_last_nop(sym); 1328 1288 1329 - pclose(file); 1330 - 1289 + fclose(file); 1290 + err = 0; 1331 1291 out_remove_tmp: 1292 + close(stdout_fd[0]); 1293 + 1332 1294 if (dso__needs_decompress(dso)) 1333 1295 unlink(symfs_filename); 1334 1296 out_free_filename: ··· 1339 1297 if (free_filename) 1340 1298 free(filename); 1341 1299 return err; 1300 + 1301 + out_close_stdout: 1302 + close(stdout_fd[1]); 1303 + goto out_remove_tmp; 1342 1304 } 1343 1305 1344 1306 static void insert_source_line(struct rb_root *root, struct source_line *src_line) ··· 1709 1663 struct rb_root source_line = RB_ROOT; 1710 1664 u64 len; 1711 1665 1712 - if (symbol__annotate(sym, map, 0) < 0) 1666 + if (symbol__disassemble(sym, map, 0) < 0) 1713 1667 return -1; 1714 1668 1715 1669 len = symbol__size(sym);
+21 -1
tools/perf/util/annotate.h
··· 155 155 int symbol__alloc_hist(struct symbol *sym); 156 156 void symbol__annotate_zero_histograms(struct symbol *sym); 157 157 158 - int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 158 + int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize); 159 + 160 + enum symbol_disassemble_errno { 161 + SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 162 + 163 + /* 164 + * Choose an arbitrary negative big number not to clash with standard 165 + * errno since SUS requires the errno has distinct positive values. 166 + * See 'Issue 6' in the link below. 167 + * 168 + * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html 169 + */ 170 + __SYMBOL_ANNOTATE_ERRNO__START = -10000, 171 + 172 + SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, 173 + 174 + __SYMBOL_ANNOTATE_ERRNO__END, 175 + }; 176 + 177 + int symbol__strerror_disassemble(struct symbol *sym, struct map *map, 178 + int errnum, char *buf, size_t buflen); 159 179 160 180 int symbol__annotate_init(struct map *map, struct symbol *sym); 161 181 int symbol__annotate_printf(struct symbol *sym, struct map *map,
+2 -20
tools/perf/util/evlist.c
··· 239 239 240 240 int perf_evlist__add_default(struct perf_evlist *evlist) 241 241 { 242 - struct perf_event_attr attr = { 243 - .type = PERF_TYPE_HARDWARE, 244 - .config = PERF_COUNT_HW_CPU_CYCLES, 245 - }; 246 - struct perf_evsel *evsel; 242 + struct perf_evsel *evsel = perf_evsel__new_cycles(); 247 243 248 - event_attr_init(&attr); 249 - 250 - perf_event_attr__set_max_precise_ip(&attr); 251 - 252 - evsel = perf_evsel__new(&attr); 253 244 if (evsel == NULL) 254 - goto error; 255 - 256 - /* use asprintf() because free(evsel) assumes name is allocated */ 257 - if (asprintf(&evsel->name, "cycles%.*s", 258 - attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) 259 - goto error_free; 245 + return -ENOMEM; 260 246 261 247 perf_evlist__add(evlist, evsel); 262 248 return 0; 263 - error_free: 264 - perf_evsel__delete(evsel); 265 - error: 266 - return -ENOMEM; 267 249 } 268 250 269 251 int perf_evlist__add_dummy(struct perf_evlist *evlist)
+29 -1
tools/perf/util/evsel.c
··· 253 253 return evsel; 254 254 } 255 255 256 + struct perf_evsel *perf_evsel__new_cycles(void) 257 + { 258 + struct perf_event_attr attr = { 259 + .type = PERF_TYPE_HARDWARE, 260 + .config = PERF_COUNT_HW_CPU_CYCLES, 261 + }; 262 + struct perf_evsel *evsel; 263 + 264 + event_attr_init(&attr); 265 + 266 + perf_event_attr__set_max_precise_ip(&attr); 267 + 268 + evsel = perf_evsel__new(&attr); 269 + if (evsel == NULL) 270 + goto out; 271 + 272 + /* use asprintf() because free(evsel) assumes name is allocated */ 273 + if (asprintf(&evsel->name, "cycles%.*s", 274 + attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) 275 + goto error_free; 276 + out: 277 + return evsel; 278 + error_free: 279 + perf_evsel__delete(evsel); 280 + evsel = NULL; 281 + goto out; 282 + } 283 + 256 284 /* 257 285 * Returns pointer with encoded error via <linux/err.h> interface. 258 286 */ ··· 882 854 perf_evsel__set_sample_bit(evsel, REGS_INTR); 883 855 } 884 856 885 - if (target__has_cpu(&opts->target)) 857 + if (target__has_cpu(&opts->target) || opts->sample_cpu) 886 858 perf_evsel__set_sample_bit(evsel, CPU); 887 859 888 860 if (opts->period)
+2
tools/perf/util/evsel.h
··· 175 175 return perf_evsel__newtp_idx(sys, name, 0); 176 176 } 177 177 178 + struct perf_evsel *perf_evsel__new_cycles(void); 179 + 178 180 struct event_format *event_format__new(const char *sys, const char *name); 179 181 180 182 void perf_evsel__init(struct perf_evsel *evsel,
+12 -3
tools/perf/util/hist.c
··· 1672 1672 } 1673 1673 1674 1674 static void output_resort(struct hists *hists, struct ui_progress *prog, 1675 - bool use_callchain) 1675 + bool use_callchain, hists__resort_cb_t cb) 1676 1676 { 1677 1677 struct rb_root *root; 1678 1678 struct rb_node *next; ··· 1711 1711 n = rb_entry(next, struct hist_entry, rb_node_in); 1712 1712 next = rb_next(&n->rb_node_in); 1713 1713 1714 + if (cb && cb(n)) 1715 + continue; 1716 + 1714 1717 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); 1715 1718 hists__inc_stats(hists, n); 1716 1719 ··· 1734 1731 else 1735 1732 use_callchain = symbol_conf.use_callchain; 1736 1733 1737 - output_resort(evsel__hists(evsel), prog, use_callchain); 1734 + output_resort(evsel__hists(evsel), prog, use_callchain, NULL); 1738 1735 } 1739 1736 1740 1737 void hists__output_resort(struct hists *hists, struct ui_progress *prog) 1741 1738 { 1742 - output_resort(hists, prog, symbol_conf.use_callchain); 1739 + output_resort(hists, prog, symbol_conf.use_callchain, NULL); 1740 + } 1741 + 1742 + void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, 1743 + hists__resort_cb_t cb) 1744 + { 1745 + output_resort(hists, prog, symbol_conf.use_callchain, cb); 1743 1746 } 1744 1747 1745 1748 static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd)
+4
tools/perf/util/hist.h
··· 153 153 struct perf_hpp_fmt *fmt, int printed); 154 154 void hist_entry__delete(struct hist_entry *he); 155 155 156 + typedef int (*hists__resort_cb_t)(struct hist_entry *he); 157 + 156 158 void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); 157 159 void hists__output_resort(struct hists *hists, struct ui_progress *prog); 160 + void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, 161 + hists__resort_cb_t cb); 158 162 int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 159 163 160 164 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
+1 -5
tools/perf/util/target.c
··· 122 122 BUG_ON(buflen == 0); 123 123 124 124 if (errnum >= 0) { 125 - const char *err = str_error_r(errnum, buf, buflen); 126 - 127 - if (err != buf) 128 - scnprintf(buf, buflen, "%s", err); 129 - 125 + str_error_r(errnum, buf, buflen); 130 126 return 0; 131 127 } 132 128