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

perf symbols: Simplify symbol machinery setup

And also express its configuration toggles via a struct.

Now all one has to do is to call symbol__init(NULL) if the
defaults are OK, or pass a struct symbol_conf pointer with the
desired configuration.

If a tool uses kernel_maps__find_symbol() to look at the kernel
and modules mappings for a symbol but didn't call symbol__init()
first, that will generate a one time warning too, alerting the
subcommand developer that symbol__init() must be called.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259071517-3242-2-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Arnaldo Carvalho de Melo and committed by
Ingo Molnar
b32d133a 7cc017ed

+85 -60
+10 -10
tools/perf/builtin-annotate.c
··· 34 34 static int full_paths; 35 35 36 36 static int print_line; 37 - static bool use_modules; 38 37 39 38 static unsigned long page_size; 40 39 static unsigned long mmap_window = 32; 41 - const char *vmlinux_name; 42 40 43 41 struct sym_hist { 44 42 u64 sum; ··· 52 54 struct sym_priv { 53 55 struct sym_hist *hist; 54 56 struct sym_ext *ext; 57 + }; 58 + 59 + static struct symbol_conf symbol_conf = { 60 + .priv_size = sizeof(struct sym_priv), 61 + .try_vmlinux_path = true, 55 62 }; 56 63 57 64 static const char *sym_hist_filter; ··· 589 586 exit(0); 590 587 } 591 588 592 - if (kernel_maps__init(vmlinux_name, true, use_modules) < 0) { 593 - pr_err("failed to create kernel maps for symbol resolution\b"); 594 - return -1; 595 - } 596 - 597 589 remap: 598 590 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 599 591 MAP_SHARED, input, offset); ··· 689 691 "be more verbose (show symbol address, etc)"), 690 692 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 691 693 "dump raw trace in ASCII"), 692 - OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 693 - OPT_BOOLEAN('m', "modules", &use_modules, 694 + OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 695 + "file", "vmlinux pathname"), 696 + OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 694 697 "load module symbols - WARNING: use only with -k and LIVE kernel"), 695 698 OPT_BOOLEAN('l', "print-line", &print_line, 696 699 "print matching source lines (may be slow)"), ··· 717 718 718 719 int cmd_annotate(int argc, const char **argv, const char *prefix __used) 719 720 { 720 - symbol__init(sizeof(struct sym_priv)); 721 + if (symbol__init(&symbol_conf) < 0) 722 + return -1; 721 723 722 724 page_size = getpagesize(); 723 725
+1 -1
tools/perf/builtin-kmem.c
··· 412 412 register_idle_thread(); 413 413 register_perf_file_handler(&file_handler); 414 414 415 - return mmap_dispatch_perf_file(&header, input_name, NULL, false, 0, 0, 415 + return mmap_dispatch_perf_file(&header, input_name, 0, 0, 416 416 &cwdlen, &cwd); 417 417 } 418 418
+8 -7
tools/perf/builtin-report.c
··· 39 39 static struct strlist *dso_list, *comm_list, *sym_list; 40 40 41 41 static int force; 42 - static bool use_modules; 43 42 44 43 static int full_paths; 45 44 static int show_nr_samples; ··· 52 53 static int exclude_other = 1; 53 54 54 55 static char callchain_default_opt[] = "fractal,0.5"; 55 - const char *vmlinux_name; 56 56 57 57 static struct perf_header *header; 58 58 59 59 static u64 sample_type; 60 + 61 + struct symbol_conf symbol_conf; 60 62 61 63 62 64 static size_t ··· 865 865 866 866 register_perf_file_handler(&file_handler); 867 867 868 - ret = mmap_dispatch_perf_file(&header, input_name, vmlinux_name, 869 - !vmlinux_name, force, 868 + ret = mmap_dispatch_perf_file(&header, input_name, force, 870 869 full_paths, &cwdlen, &cwd); 871 870 if (ret) 872 871 return ret; ··· 962 963 "be more verbose (show symbol address, etc)"), 963 964 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 964 965 "dump raw trace in ASCII"), 965 - OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 966 + OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 967 + "file", "vmlinux pathname"), 966 968 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 967 - OPT_BOOLEAN('m', "modules", &use_modules, 969 + OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 968 970 "load module symbols - WARNING: use only with -k and LIVE kernel"), 969 971 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, 970 972 "Show a column with the number of samples"), ··· 1035 1035 1036 1036 int cmd_report(int argc, const char **argv, const char *prefix __used) 1037 1037 { 1038 - symbol__init(0); 1038 + if (symbol__init(&symbol_conf) < 0) 1039 + return -1; 1039 1040 1040 1041 argc = parse_options(argc, argv, options, report_usage, 0); 1041 1042
+1 -1
tools/perf/builtin-sched.c
··· 1718 1718 register_idle_thread(); 1719 1719 register_perf_file_handler(&file_handler); 1720 1720 1721 - return mmap_dispatch_perf_file(&header, input_name, NULL, false, 0, 0, 1721 + return mmap_dispatch_perf_file(&header, input_name, 0, 0, 1722 1722 &cwdlen, &cwd); 1723 1723 } 1724 1724
+13 -11
tools/perf/builtin-top.c
··· 79 79 static bool hide_kernel_symbols = false; 80 80 static bool hide_user_symbols = false; 81 81 static struct winsize winsize; 82 - const char *vmlinux_name; 82 + struct symbol_conf symbol_conf; 83 83 84 84 /* 85 85 * Source ··· 128 128 129 129 static inline struct symbol *sym_entry__symbol(struct sym_entry *self) 130 130 { 131 - return ((void *)self) + symbol__priv_size; 131 + return ((void *)self) + symbol_conf.priv_size; 132 132 } 133 133 134 134 static void get_term_dimensions(struct winsize *ws) ··· 695 695 696 696 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 697 697 698 - if (vmlinux_name) { 698 + if (symbol_conf.vmlinux_name) { 699 699 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 700 700 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 701 701 fprintf(stdout, "\t[S] stop annotation.\n"); ··· 732 732 case 'F': 733 733 case 's': 734 734 case 'S': 735 - return vmlinux_name ? 1 : 0; 735 + return symbol_conf.vmlinux_name ? 1 : 0; 736 736 default: 737 737 break; 738 738 } ··· 1261 1261 "system-wide collection from all CPUs"), 1262 1262 OPT_INTEGER('C', "CPU", &profile_cpu, 1263 1263 "CPU to profile on"), 1264 - OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 1264 + OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1265 + "file", "vmlinux pathname"), 1265 1266 OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, 1266 1267 "hide kernel symbols"), 1267 1268 OPT_INTEGER('m', "mmap-pages", &mmap_pages, ··· 1296 1295 1297 1296 int cmd_top(int argc, const char **argv, const char *prefix __used) 1298 1297 { 1299 - int counter, err; 1298 + int counter; 1300 1299 1301 1300 page_size = sysconf(_SC_PAGE_SIZE); 1302 1301 ··· 1314 1313 if (!nr_counters) 1315 1314 nr_counters = 1; 1316 1315 1317 - symbol__init(sizeof(struct sym_entry) + 1318 - (nr_counters + 1) * sizeof(unsigned long)); 1316 + symbol_conf.priv_size = (sizeof(struct sym_entry) + 1317 + (nr_counters + 1) * sizeof(unsigned long)); 1318 + if (symbol_conf.vmlinux_name == NULL) 1319 + symbol_conf.try_vmlinux_path = true; 1320 + if (symbol__init(&symbol_conf) < 0) 1321 + return -1; 1319 1322 1320 1323 if (delay_secs < 1) 1321 1324 delay_secs = 1; 1322 1325 1323 - err = kernel_maps__init(vmlinux_name, !vmlinux_name, true); 1324 - if (err < 0) 1325 - return err; 1326 1326 parse_source(sym_filter_entry); 1327 1327 1328 1328 /*
+1 -1
tools/perf/builtin-trace.c
··· 131 131 register_idle_thread(); 132 132 register_perf_file_handler(&file_handler); 133 133 134 - return mmap_dispatch_perf_file(&header, input_name, NULL, false, 134 + return mmap_dispatch_perf_file(&header, input_name, 135 135 0, 0, &cwdlen, &cwd); 136 136 } 137 137
-8
tools/perf/util/data_map.c
··· 101 101 102 102 int mmap_dispatch_perf_file(struct perf_header **pheader, 103 103 const char *input_name, 104 - const char *vmlinux_name, 105 - bool try_vmlinux_path, 106 104 int force, 107 105 int full_paths, 108 106 int *cwdlen, ··· 169 171 if (curr_handler->sample_type_check && 170 172 curr_handler->sample_type_check(sample_type) < 0) 171 173 goto out_delete; 172 - 173 - err = -ENOMEM; 174 - if (kernel_maps__init(vmlinux_name, try_vmlinux_path, true) < 0) { 175 - pr_err("failed to setup the kernel maps to resolve symbols\n"); 176 - goto out_delete; 177 - } 178 174 179 175 if (!full_paths) { 180 176 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
-2
tools/perf/util/data_map.h
··· 23 23 void register_perf_file_handler(struct perf_file_handler *handler); 24 24 int mmap_dispatch_perf_file(struct perf_header **pheader, 25 25 const char *input_name, 26 - const char *vmlinux_name, 27 - bool try_vmlinux_path, 28 26 int force, 29 27 int full_paths, 30 28 int *cwdlen,
-6
tools/perf/util/header.c
··· 253 253 254 254 buildid_sec = &feat_sec[idx++]; 255 255 256 - /* 257 - * Read the kernel buildid nad the list of loaded modules with 258 - * its build_ids: 259 - */ 260 - kernel_maps__init(NULL, false, true); 261 - 262 256 /* Write build-ids */ 263 257 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 264 258 err = dsos__write_buildid_table(fd);
+22
tools/perf/util/include/asm/bug.h
··· 1 + #ifndef _PERF_ASM_GENERIC_BUG_H 2 + #define _PERF_ASM_GENERIC_BUG_H 3 + 4 + #define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0) 5 + 6 + #define WARN(condition, format...) ({ \ 7 + int __ret_warn_on = !!(condition); \ 8 + if (unlikely(__ret_warn_on)) \ 9 + __WARN_printf(format); \ 10 + unlikely(__ret_warn_on); \ 11 + }) 12 + 13 + #define WARN_ONCE(condition, format...) ({ \ 14 + static int __warned; \ 15 + int __ret_warn_once = !!(condition); \ 16 + \ 17 + if (unlikely(__ret_warn_once)) \ 18 + if (WARN(!__warned, format)) \ 19 + __warned = 1; \ 20 + unlikely(__ret_warn_once); \ 21 + }) 22 + #endif
+21 -10
tools/perf/util/symbol.c
··· 6 6 7 7 #include "debug.h" 8 8 9 + #include <asm/bug.h> 9 10 #include <libelf.h> 10 11 #include <gelf.h> 11 12 #include <elf.h> ··· 37 36 unsigned int symbol__priv_size; 38 37 static int vmlinux_path__nr_entries; 39 38 static char **vmlinux_path; 39 + 40 + static struct symbol_conf symbol_conf__defaults = { 41 + .use_modules = true, 42 + .try_vmlinux_path = true, 43 + }; 40 44 41 45 static struct rb_root kernel_maps; 42 46 ··· 1172 1166 if (map) { 1173 1167 ip = map->map_ip(map, ip); 1174 1168 return map__find_symbol(map, ip, filter); 1175 - } 1169 + } else 1170 + WARN_ONCE(RB_EMPTY_ROOT(&kernel_maps), 1171 + "Empty kernel_maps, was symbol__init() called?\n"); 1176 1172 1177 1173 return NULL; 1178 1174 } ··· 1493 1485 return ret; 1494 1486 } 1495 1487 1496 - static int kernel_maps__create_kernel_map(const char *vmlinux_name) 1488 + static int kernel_maps__create_kernel_map(const struct symbol_conf *conf) 1497 1489 { 1498 - struct dso *kernel = dso__new(vmlinux_name ?: "[kernel.kallsyms]"); 1490 + struct dso *kernel = dso__new(conf->vmlinux_name ?: "[kernel.kallsyms]"); 1499 1491 1500 1492 if (kernel == NULL) 1501 1493 return -1; ··· 1585 1577 return -1; 1586 1578 } 1587 1579 1588 - int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path, 1589 - bool use_modules) 1580 + static int kernel_maps__init(const struct symbol_conf *conf) 1590 1581 { 1591 - if (try_vmlinux_path && vmlinux_path__init() < 0) 1582 + const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults; 1583 + 1584 + symbol__priv_size = pconf->priv_size; 1585 + 1586 + if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) 1592 1587 return -1; 1593 1588 1594 - if (kernel_maps__create_kernel_map(vmlinux_name) < 0) { 1589 + if (kernel_maps__create_kernel_map(pconf) < 0) { 1595 1590 vmlinux_path__exit(); 1596 1591 return -1; 1597 1592 } 1598 1593 1599 - if (use_modules && kernel_maps__create_module_maps() < 0) 1594 + if (pconf->use_modules && kernel_maps__create_module_maps() < 0) 1600 1595 pr_debug("Failed to load list of modules in use, " 1601 1596 "continuing...\n"); 1602 1597 /* ··· 1609 1598 return 0; 1610 1599 } 1611 1600 1612 - void symbol__init(unsigned int priv_size) 1601 + int symbol__init(struct symbol_conf *conf) 1613 1602 { 1614 1603 elf_version(EV_CURRENT); 1615 - symbol__priv_size = priv_size; 1604 + return kernel_maps__init(conf); 1616 1605 }
+8 -3
tools/perf/util/symbol.h
··· 49 49 char name[0]; 50 50 }; 51 51 52 + struct symbol_conf { 53 + unsigned short priv_size; 54 + bool try_vmlinux_path, 55 + use_modules; 56 + const char *vmlinux_name; 57 + }; 58 + 52 59 extern unsigned int symbol__priv_size; 53 60 54 61 static inline void *symbol__priv(struct symbol *self) ··· 100 93 bool dsos__read_build_ids(void); 101 94 int build_id__sprintf(u8 *self, int len, char *bf); 102 95 103 - int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path, 104 - bool use_modules); 105 96 size_t kernel_maps__fprintf(FILE *fp); 106 97 107 - void symbol__init(unsigned int priv_size); 98 + int symbol__init(struct symbol_conf *conf); 108 99 109 100 extern struct list_head dsos; 110 101 extern struct map *kernel_map;