| Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 | 
| Arnaldo Carvalho de Melo | fd20e81 | 2017-04-17 15:23:08 -0300 | [diff] [blame] | 2 | #include <inttypes.h> | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 3 | #include "perf.h" | 
|  | 4 | #include "util/debug.h" | 
|  | 5 | #include "util/symbol.h" | 
|  | 6 | #include "util/sort.h" | 
|  | 7 | #include "util/evsel.h" | 
|  | 8 | #include "util/evlist.h" | 
|  | 9 | #include "util/machine.h" | 
|  | 10 | #include "util/thread.h" | 
|  | 11 | #include "tests/hists_common.h" | 
| Arnaldo Carvalho de Melo | 877a7a1 | 2017-04-17 11:39:06 -0300 | [diff] [blame] | 12 | #include <linux/kernel.h> | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 13 |  | 
|  | 14 | static struct { | 
|  | 15 | u32 pid; | 
|  | 16 | const char *comm; | 
|  | 17 | } fake_threads[] = { | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 18 | { FAKE_PID_PERF1, "perf" }, | 
|  | 19 | { FAKE_PID_PERF2, "perf" }, | 
|  | 20 | { FAKE_PID_BASH,  "bash" }, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 21 | }; | 
|  | 22 |  | 
|  | 23 | static struct { | 
|  | 24 | u32 pid; | 
|  | 25 | u64 start; | 
|  | 26 | const char *filename; | 
|  | 27 | } fake_mmap_info[] = { | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 28 | { FAKE_PID_PERF1, FAKE_MAP_PERF,   "perf" }, | 
|  | 29 | { FAKE_PID_PERF1, FAKE_MAP_LIBC,   "libc" }, | 
|  | 30 | { FAKE_PID_PERF1, FAKE_MAP_KERNEL, "[kernel]" }, | 
|  | 31 | { FAKE_PID_PERF2, FAKE_MAP_PERF,   "perf" }, | 
|  | 32 | { FAKE_PID_PERF2, FAKE_MAP_LIBC,   "libc" }, | 
|  | 33 | { FAKE_PID_PERF2, FAKE_MAP_KERNEL, "[kernel]" }, | 
|  | 34 | { FAKE_PID_BASH,  FAKE_MAP_BASH,   "bash" }, | 
|  | 35 | { FAKE_PID_BASH,  FAKE_MAP_LIBC,   "libc" }, | 
|  | 36 | { FAKE_PID_BASH,  FAKE_MAP_KERNEL, "[kernel]" }, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 37 | }; | 
|  | 38 |  | 
|  | 39 | struct fake_sym { | 
|  | 40 | u64 start; | 
|  | 41 | u64 length; | 
|  | 42 | const char *name; | 
|  | 43 | }; | 
|  | 44 |  | 
|  | 45 | static struct fake_sym perf_syms[] = { | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 46 | { FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "main" }, | 
|  | 47 | { FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "run_command" }, | 
|  | 48 | { FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "cmd_record" }, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 49 | }; | 
|  | 50 |  | 
|  | 51 | static struct fake_sym bash_syms[] = { | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 52 | { FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "main" }, | 
|  | 53 | { FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "xmalloc" }, | 
|  | 54 | { FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "xfree" }, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 55 | }; | 
|  | 56 |  | 
|  | 57 | static struct fake_sym libc_syms[] = { | 
|  | 58 | { 700, 100, "malloc" }, | 
|  | 59 | { 800, 100, "free" }, | 
|  | 60 | { 900, 100, "realloc" }, | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 61 | { FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "malloc" }, | 
|  | 62 | { FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "free" }, | 
|  | 63 | { FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "realloc" }, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 64 | }; | 
|  | 65 |  | 
|  | 66 | static struct fake_sym kernel_syms[] = { | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 67 | { FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "schedule" }, | 
|  | 68 | { FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "page_fault" }, | 
|  | 69 | { FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "sys_perf_event_open" }, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 70 | }; | 
|  | 71 |  | 
|  | 72 | static struct { | 
|  | 73 | const char *dso_name; | 
|  | 74 | struct fake_sym *syms; | 
|  | 75 | size_t nr_syms; | 
|  | 76 | } fake_symbols[] = { | 
|  | 77 | { "perf", perf_syms, ARRAY_SIZE(perf_syms) }, | 
|  | 78 | { "bash", bash_syms, ARRAY_SIZE(bash_syms) }, | 
|  | 79 | { "libc", libc_syms, ARRAY_SIZE(libc_syms) }, | 
|  | 80 | { "[kernel]", kernel_syms, ARRAY_SIZE(kernel_syms) }, | 
|  | 81 | }; | 
|  | 82 |  | 
|  | 83 | struct machine *setup_fake_machine(struct machines *machines) | 
|  | 84 | { | 
|  | 85 | struct machine *machine = machines__find(machines, HOST_KERNEL_ID); | 
|  | 86 | size_t i; | 
|  | 87 |  | 
|  | 88 | if (machine == NULL) { | 
|  | 89 | pr_debug("Not enough memory for machine setup\n"); | 
|  | 90 | return NULL; | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { | 
|  | 94 | struct thread *thread; | 
|  | 95 |  | 
|  | 96 | thread = machine__findnew_thread(machine, fake_threads[i].pid, | 
|  | 97 | fake_threads[i].pid); | 
|  | 98 | if (thread == NULL) | 
|  | 99 | goto out; | 
|  | 100 |  | 
|  | 101 | thread__set_comm(thread, fake_threads[i].comm, 0); | 
| Arnaldo Carvalho de Melo | b91fc39 | 2015-04-06 20:43:22 -0300 | [diff] [blame] | 102 | thread__put(thread); | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 103 | } | 
|  | 104 |  | 
|  | 105 | for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { | 
| Arnaldo Carvalho de Melo | 473398a | 2016-03-22 18:23:43 -0300 | [diff] [blame] | 106 | struct perf_sample sample = { | 
|  | 107 | .cpumode = PERF_RECORD_MISC_USER, | 
|  | 108 | }; | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 109 | union perf_event fake_mmap_event = { | 
|  | 110 | .mmap = { | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 111 | .pid = fake_mmap_info[i].pid, | 
|  | 112 | .tid = fake_mmap_info[i].pid, | 
|  | 113 | .start = fake_mmap_info[i].start, | 
| Namhyung Kim | a1891aa | 2014-05-23 14:59:57 +0900 | [diff] [blame] | 114 | .len = FAKE_MAP_LENGTH, | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 115 | .pgoff = 0ULL, | 
|  | 116 | }, | 
|  | 117 | }; | 
|  | 118 |  | 
|  | 119 | strcpy(fake_mmap_event.mmap.filename, | 
|  | 120 | fake_mmap_info[i].filename); | 
|  | 121 |  | 
| Arnaldo Carvalho de Melo | 473398a | 2016-03-22 18:23:43 -0300 | [diff] [blame] | 122 | machine__process_mmap_event(machine, &fake_mmap_event, &sample); | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 123 | } | 
|  | 124 |  | 
|  | 125 | for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { | 
|  | 126 | size_t k; | 
|  | 127 | struct dso *dso; | 
|  | 128 |  | 
| Arnaldo Carvalho de Melo | aa7cc2a | 2015-05-29 11:31:12 -0300 | [diff] [blame] | 129 | dso = machine__findnew_dso(machine, fake_symbols[i].dso_name); | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 130 | if (dso == NULL) | 
|  | 131 | goto out; | 
|  | 132 |  | 
|  | 133 | /* emulate dso__load() */ | 
|  | 134 | dso__set_loaded(dso, MAP__FUNCTION); | 
|  | 135 |  | 
|  | 136 | for (k = 0; k < fake_symbols[i].nr_syms; k++) { | 
|  | 137 | struct symbol *sym; | 
|  | 138 | struct fake_sym *fsym = &fake_symbols[i].syms[k]; | 
|  | 139 |  | 
|  | 140 | sym = symbol__new(fsym->start, fsym->length, | 
|  | 141 | STB_GLOBAL, fsym->name); | 
| Arnaldo Carvalho de Melo | d3a7c48 | 2015-06-02 11:53:26 -0300 | [diff] [blame] | 142 | if (sym == NULL) { | 
|  | 143 | dso__put(dso); | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 144 | goto out; | 
| Arnaldo Carvalho de Melo | d3a7c48 | 2015-06-02 11:53:26 -0300 | [diff] [blame] | 145 | } | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 146 |  | 
|  | 147 | symbols__insert(&dso->symbols[MAP__FUNCTION], sym); | 
|  | 148 | } | 
| Arnaldo Carvalho de Melo | d3a7c48 | 2015-06-02 11:53:26 -0300 | [diff] [blame] | 149 |  | 
|  | 150 | dso__put(dso); | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 151 | } | 
|  | 152 |  | 
|  | 153 | return machine; | 
|  | 154 |  | 
|  | 155 | out: | 
|  | 156 | pr_debug("Not enough memory for machine setup\n"); | 
|  | 157 | machine__delete_threads(machine); | 
| Namhyung Kim | 6e344a9 | 2014-04-25 12:28:13 +0900 | [diff] [blame] | 158 | return NULL; | 
|  | 159 | } | 
| Namhyung Kim | 4e754e1 | 2014-05-12 10:06:18 +0900 | [diff] [blame] | 160 |  | 
|  | 161 | void print_hists_in(struct hists *hists) | 
|  | 162 | { | 
|  | 163 | int i = 0; | 
|  | 164 | struct rb_root *root; | 
|  | 165 | struct rb_node *node; | 
|  | 166 |  | 
| Jiri Olsa | 5222503 | 2016-05-03 13:54:42 +0200 | [diff] [blame] | 167 | if (hists__has(hists, need_collapse)) | 
| Namhyung Kim | 4e754e1 | 2014-05-12 10:06:18 +0900 | [diff] [blame] | 168 | root = &hists->entries_collapsed; | 
|  | 169 | else | 
|  | 170 | root = hists->entries_in; | 
|  | 171 |  | 
|  | 172 | pr_info("----- %s --------\n", __func__); | 
|  | 173 | node = rb_first(root); | 
|  | 174 | while (node) { | 
|  | 175 | struct hist_entry *he; | 
|  | 176 |  | 
|  | 177 | he = rb_entry(node, struct hist_entry, rb_node_in); | 
|  | 178 |  | 
|  | 179 | if (!he->filtered) { | 
|  | 180 | pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", | 
|  | 181 | i, thread__comm_str(he->thread), | 
|  | 182 | he->ms.map->dso->short_name, | 
|  | 183 | he->ms.sym->name, he->stat.period); | 
|  | 184 | } | 
|  | 185 |  | 
|  | 186 | i++; | 
|  | 187 | node = rb_next(node); | 
|  | 188 | } | 
|  | 189 | } | 
|  | 190 |  | 
|  | 191 | void print_hists_out(struct hists *hists) | 
|  | 192 | { | 
|  | 193 | int i = 0; | 
|  | 194 | struct rb_root *root; | 
|  | 195 | struct rb_node *node; | 
|  | 196 |  | 
|  | 197 | root = &hists->entries; | 
|  | 198 |  | 
|  | 199 | pr_info("----- %s --------\n", __func__); | 
|  | 200 | node = rb_first(root); | 
|  | 201 | while (node) { | 
|  | 202 | struct hist_entry *he; | 
|  | 203 |  | 
|  | 204 | he = rb_entry(node, struct hist_entry, rb_node); | 
|  | 205 |  | 
|  | 206 | if (!he->filtered) { | 
| Namhyung Kim | 0506aec | 2014-05-23 18:04:42 +0900 | [diff] [blame] | 207 | pr_info("%2d: entry: %8s:%5d [%-8s] %20s: period = %"PRIu64"/%"PRIu64"\n", | 
| Namhyung Kim | f21d181 | 2014-05-12 14:43:18 +0900 | [diff] [blame] | 208 | i, thread__comm_str(he->thread), he->thread->tid, | 
| Namhyung Kim | 4e754e1 | 2014-05-12 10:06:18 +0900 | [diff] [blame] | 209 | he->ms.map->dso->short_name, | 
| Namhyung Kim | 0506aec | 2014-05-23 18:04:42 +0900 | [diff] [blame] | 210 | he->ms.sym->name, he->stat.period, | 
|  | 211 | he->stat_acc ? he->stat_acc->period : 0); | 
| Namhyung Kim | 4e754e1 | 2014-05-12 10:06:18 +0900 | [diff] [blame] | 212 | } | 
|  | 213 |  | 
|  | 214 | i++; | 
|  | 215 | node = rb_next(node); | 
|  | 216 | } | 
|  | 217 | } |