···11+perf-test(1)22+============33+44+NAME55+----66+perf-test - Runs sanity tests.77+88+SYNOPSIS99+--------1010+[verse]1111+'perf test <options>'1212+1313+DESCRIPTION1414+-----------1515+This command does assorted sanity tests, initially thru linked routines but1616+also will look for a directory with more tests in the form of scripts.1717+1818+OPTIONS1919+-------2020+-v::2121+--verbose::2222+ Be more verbose.
+3
tools/perf/Makefile
···187187 ARCH := x86188188endif189189190190+$(shell sh -c 'mkdir -p $(OUTPUT)arch/$(ARCH)/util/' 2> /dev/null)191191+190192# CFLAGS and LDFLAGS are for the users to override from the command line.191193192194#···490488BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o491489BUILTIN_OBJS += $(OUTPUT)builtin-lock.o492490BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o491491+BUILTIN_OBJS += $(OUTPUT)builtin-test.o493492494493PERFLIBS = $(LIB_FILE)495494
···313313 perf_session__fprintf(session, stdout);314314315315 if (verbose > 2)316316- dsos__fprintf(&session->kerninfo_root, stdout);316316+ perf_session__fprintf_dsos(session, stdout);317317318318 next = rb_first(&session->stats_by_id);319319 while (next) {
+281
tools/perf/builtin-test.c
···11+/*22+ * builtin-test.c33+ *44+ * Builtin regression testing command: ever growing number of sanity tests55+ */66+#include "builtin.h"77+88+#include "util/cache.h"99+#include "util/debug.h"1010+#include "util/parse-options.h"1111+#include "util/session.h"1212+#include "util/symbol.h"1313+#include "util/thread.h"1414+1515+static long page_size;1616+1717+static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)1818+{1919+ bool *visited = symbol__priv(sym);2020+ *visited = true;2121+ return 0;2222+}2323+2424+static int test__vmlinux_matches_kallsyms(void)2525+{2626+ int err = -1;2727+ struct rb_node *nd;2828+ struct symbol *sym;2929+ struct map *kallsyms_map, *vmlinux_map;3030+ struct machine kallsyms, vmlinux;3131+ enum map_type type = MAP__FUNCTION;3232+ struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };3333+3434+ /*3535+ * Step 1:3636+ *3737+ * Init the machines that will hold kernel, modules obtained from3838+ * both vmlinux + .ko files and from /proc/kallsyms split by modules.3939+ */4040+ machine__init(&kallsyms, "", HOST_KERNEL_ID);4141+ machine__init(&vmlinux, "", HOST_KERNEL_ID);4242+4343+ /*4444+ * Step 2:4545+ *4646+ * Create the kernel maps for kallsyms and the DSO where we will then4747+ * load /proc/kallsyms. Also create the modules maps from /proc/modules4848+ * and find the .ko files that match them in /lib/modules/`uname -r`/.4949+ */5050+ if (machine__create_kernel_maps(&kallsyms) < 0) {5151+ pr_debug("machine__create_kernel_maps ");5252+ return -1;5353+ }5454+5555+ /*5656+ * Step 3:5757+ *5858+ * Load and split /proc/kallsyms into multiple maps, one per module.5959+ */6060+ if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {6161+ pr_debug("dso__load_kallsyms ");6262+ goto out;6363+ }6464+6565+ /*6666+ * Step 4:6767+ *6868+ * kallsyms will be internally on demand sorted by name so that we can6969+ * find the reference relocation * symbol, i.e. the symbol we will use7070+ * to see if the running kernel was relocated by checking if it has the7171+ * same value in the vmlinux file we load.7272+ */7373+ kallsyms_map = machine__kernel_map(&kallsyms, type);7474+7575+ sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);7676+ if (sym == NULL) {7777+ pr_debug("dso__find_symbol_by_name ");7878+ goto out;7979+ }8080+8181+ ref_reloc_sym.addr = sym->start;8282+8383+ /*8484+ * Step 5:8585+ *8686+ * Now repeat step 2, this time for the vmlinux file we'll auto-locate.8787+ */8888+ if (machine__create_kernel_maps(&vmlinux) < 0) {8989+ pr_debug("machine__create_kernel_maps ");9090+ goto out;9191+ }9292+9393+ vmlinux_map = machine__kernel_map(&vmlinux, type);9494+ map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;9595+9696+ /*9797+ * Step 6:9898+ *9999+ * Locate a vmlinux file in the vmlinux path that has a buildid that100100+ * matches the one of the running kernel.101101+ *102102+ * While doing that look if we find the ref reloc symbol, if we find it103103+ * we'll have its ref_reloc_symbol.unrelocated_addr and then104104+ * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines105105+ * to fixup the symbols.106106+ */107107+ if (machine__load_vmlinux_path(&vmlinux, type,108108+ vmlinux_matches_kallsyms_filter) <= 0) {109109+ pr_debug("machine__load_vmlinux_path ");110110+ goto out;111111+ }112112+113113+ err = 0;114114+ /*115115+ * Step 7:116116+ *117117+ * Now look at the symbols in the vmlinux DSO and check if we find all of them118118+ * in the kallsyms dso. For the ones that are in both, check its names and119119+ * end addresses too.120120+ */121121+ for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {122122+ struct symbol *pair;123123+124124+ sym = rb_entry(nd, struct symbol, rb_node);125125+ pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);126126+127127+ if (pair && pair->start == sym->start) {128128+next_pair:129129+ if (strcmp(sym->name, pair->name) == 0) {130130+ /*131131+ * kallsyms don't have the symbol end, so we132132+ * set that by using the next symbol start - 1,133133+ * in some cases we get this up to a page134134+ * wrong, trace_kmalloc when I was developing135135+ * this code was one such example, 2106 bytes136136+ * off the real size. More than that and we137137+ * _really_ have a problem.138138+ */139139+ s64 skew = sym->end - pair->end;140140+ if (llabs(skew) < page_size)141141+ continue;142142+143143+ pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n",144144+ sym->start, sym->name, sym->end, pair->end);145145+ } else {146146+ struct rb_node *nnd = rb_prev(&pair->rb_node);147147+148148+ if (nnd) {149149+ struct symbol *next = rb_entry(nnd, struct symbol, rb_node);150150+151151+ if (next->start == sym->start) {152152+ pair = next;153153+ goto next_pair;154154+ }155155+ }156156+ pr_debug("%#Lx: diff name v: %s k: %s\n",157157+ sym->start, sym->name, pair->name);158158+ }159159+ } else160160+ pr_debug("%#Lx: %s not on kallsyms\n", sym->start, sym->name);161161+162162+ err = -1;163163+ }164164+165165+ if (!verbose)166166+ goto out;167167+168168+ pr_info("Maps only in vmlinux:\n");169169+170170+ for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {171171+ struct map *pos = rb_entry(nd, struct map, rb_node), *pair;172172+ /*173173+ * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while174174+ * the kernel will have the path for the vmlinux file being used,175175+ * so use the short name, less descriptive but the same ("[kernel]" in176176+ * both cases.177177+ */178178+ pair = map_groups__find_by_name(&kallsyms.kmaps, type,179179+ (pos->dso->kernel ?180180+ pos->dso->short_name :181181+ pos->dso->name));182182+ if (pair)183183+ pair->priv = 1;184184+ else185185+ map__fprintf(pos, stderr);186186+ }187187+188188+ pr_info("Maps in vmlinux with a different name in kallsyms:\n");189189+190190+ for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {191191+ struct map *pos = rb_entry(nd, struct map, rb_node), *pair;192192+193193+ pair = map_groups__find(&kallsyms.kmaps, type, pos->start);194194+ if (pair == NULL || pair->priv)195195+ continue;196196+197197+ if (pair->start == pos->start) {198198+ pair->priv = 1;199199+ pr_info(" %Lx-%Lx %Lx %s in kallsyms as",200200+ pos->start, pos->end, pos->pgoff, pos->dso->name);201201+ if (pos->pgoff != pair->pgoff || pos->end != pair->end)202202+ pr_info(": \n*%Lx-%Lx %Lx",203203+ pair->start, pair->end, pair->pgoff);204204+ pr_info(" %s\n", pair->dso->name);205205+ pair->priv = 1;206206+ }207207+ }208208+209209+ pr_info("Maps only in kallsyms:\n");210210+211211+ for (nd = rb_first(&kallsyms.kmaps.maps[type]);212212+ nd; nd = rb_next(nd)) {213213+ struct map *pos = rb_entry(nd, struct map, rb_node);214214+215215+ if (!pos->priv)216216+ map__fprintf(pos, stderr);217217+ }218218+out:219219+ return err;220220+}221221+222222+static struct test {223223+ const char *desc;224224+ int (*func)(void);225225+} tests[] = {226226+ {227227+ .desc = "vmlinux symtab matches kallsyms",228228+ .func = test__vmlinux_matches_kallsyms,229229+ },230230+ {231231+ .func = NULL,232232+ },233233+};234234+235235+static int __cmd_test(void)236236+{237237+ int i = 0;238238+239239+ page_size = sysconf(_SC_PAGE_SIZE);240240+241241+ while (tests[i].func) {242242+ int err;243243+ pr_info("%2d: %s:", i + 1, tests[i].desc);244244+ pr_debug("\n--- start ---\n");245245+ err = tests[i].func();246246+ pr_debug("---- end ----\n%s:", tests[i].desc);247247+ pr_info(" %s\n", err ? "FAILED!\n" : "Ok");248248+ ++i;249249+ }250250+251251+ return 0;252252+}253253+254254+static const char * const test_usage[] = {255255+ "perf test [<options>]",256256+ NULL,257257+};258258+259259+static const struct option test_options[] = {260260+ OPT_BOOLEAN('v', "verbose", &verbose,261261+ "be more verbose (show symbol address, etc)"),262262+ OPT_END()263263+};264264+265265+int cmd_test(int argc, const char **argv, const char *prefix __used)266266+{267267+ argc = parse_options(argc, argv, test_options, test_usage, 0);268268+ if (argc)269269+ usage_with_options(test_usage, test_options);270270+271271+ symbol_conf.priv_size = sizeof(int);272272+ symbol_conf.sort_by_name = true;273273+ symbol_conf.try_vmlinux_path = true;274274+275275+ if (symbol__init() < 0)276276+ return -1;277277+278278+ setup_pager();279279+280280+ return __cmd_test();281281+}
+7-8
tools/perf/builtin-top.c
···854854 case 'Q':855855 printf("exiting.\n");856856 if (dump_symtab)857857- dsos__fprintf(&session->kerninfo_root, stderr);857857+ perf_session__fprintf_dsos(session, stderr);858858 exit(0);859859 case 's':860860 prompt_symbol(&sym_filter_entry, "Enter details symbol");···982982 u64 ip = self->ip.ip;983983 struct sym_entry *syme;984984 struct addr_location al;985985- struct kernel_info *kerninfo;985985+ struct machine *machine;986986 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;987987988988 ++samples;···992992 ++us_samples;993993 if (hide_user_symbols)994994 return;995995- kerninfo = kerninfo__findhost(&session->kerninfo_root);995995+ machine = perf_session__find_host_machine(session);996996 break;997997 case PERF_RECORD_MISC_KERNEL:998998 ++kernel_samples;999999 if (hide_kernel_symbols)10001000 return;10011001- kerninfo = kerninfo__findhost(&session->kerninfo_root);10011001+ machine = perf_session__find_host_machine(session);10021002 break;10031003 case PERF_RECORD_MISC_GUEST_KERNEL:10041004 ++guest_kernel_samples;10051005- kerninfo = kerninfo__find(&session->kerninfo_root,10061006- self->ip.pid);10051005+ machine = perf_session__find_machine(session, self->ip.pid);10071006 break;10081007 case PERF_RECORD_MISC_GUEST_USER:10091008 ++guest_us_samples;···10151016 return;10161017 }1017101810181018- if (!kerninfo && perf_guest) {10191019+ if (!machine && perf_guest) {10191020 pr_err("Can't find guest [%d]'s kernel information\n",10201021 self->ip.pid);10211022 return;···10401041 * --hide-kernel-symbols, even if the user specifies an10411042 * invalid --vmlinux ;-)10421043 */10431043- if (al.map == kerninfo->vmlinux_maps[MAP__FUNCTION] &&10441044+ if (al.map == machine->vmlinux_maps[MAP__FUNCTION] &&10441045 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {10451046 pr_err("The %s file can't be used\n",10461047 symbol_conf.vmlinux_name);
+1
tools/perf/builtin.h
···3333extern int cmd_kmem(int argc, const char **argv, const char *prefix);3434extern int cmd_lock(int argc, const char **argv, const char *prefix);3535extern int cmd_kvm(int argc, const char **argv, const char *prefix);3636+extern int cmd_test(int argc, const char **argv, const char *prefix);36373738#endif
+1
tools/perf/command-list.txt
···2020perf-kmem mainporcelain common2121perf-lock mainporcelain common2222perf-kvm mainporcelain common2323+perf-test mainporcelain common
···7272}73737474static char *synthesize_perf_probe_point(struct perf_probe_point *pp);7575-static struct map_groups kmap_groups;7676-static struct map *kmaps[MAP__NR_TYPES];7575+static struct machine machine;77767877/* Initialize symbol maps and path of vmlinux */7978static int init_vmlinux(void)···9192 goto out;9293 }93949595+ ret = machine__init(&machine, "/", 0);9696+ if (ret < 0)9797+ goto out;9898+9499 kernel = dso__new_kernel(symbol_conf.vmlinux_name);95100 if (kernel == NULL)96101 die("Failed to create kernel dso.");971029898- map_groups__init(&kmap_groups);9999- ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel);103103+ ret = __machine__create_kernel_maps(&machine, kernel);100104 if (ret < 0)101105 pr_debug("Failed to create kernel maps.\n");102106···112110#ifdef DWARF_SUPPORT113111static int open_vmlinux(void)114112{115115- if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) {113113+ if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {116114 pr_debug("Failed to load kernel map.\n");117115 return -EINVAL;118116 }119119- pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name);120120- return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY);117117+ pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name);118118+ return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY);121119}122120123121/* Convert trace point to probe point with debuginfo */···127125 struct symbol *sym;128126 int fd, ret = -ENOENT;129127130130- sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],128128+ sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],131129 tp->symbol, NULL);132130 if (sym) {133131 fd = open_vmlinux();···14681466 }1469146714701468 /* Currently just checking function name from symbol map */14711471- sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],14691469+ sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],14721470 tev->point.symbol, NULL);14731471 if (!sym) {14741472 pr_warning("Kernel symbol \'%s\' not found.\n",
+4-5
tools/perf/util/session.c
···69697070int perf_session__create_kernel_maps(struct perf_session *self)7171{7272- int ret;7373- struct rb_root *root = &self->kerninfo_root;7272+ struct rb_root *machines = &self->machines;7373+ int ret = machines__create_kernel_maps(machines, HOST_KERNEL_ID);74747575- ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID);7675 if (ret >= 0)7777- ret = map_groups__create_guest_kernel_maps(root);7676+ ret = machines__create_guest_kernel_maps(machines);7877 return ret;7978}8079···9697 self->cwd = NULL;9798 self->cwdlen = 0;9899 self->unknown_events = 0;9999- self->kerninfo_root = RB_ROOT;100100+ self->machines = RB_ROOT;100101 self->ordered_samples.flush_limit = ULLONG_MAX;101102 INIT_LIST_HEAD(&self->ordered_samples.samples_head);102103