1 #include "perf.h" 2 #include "util/debug.h" 3 #include "util/symbol.h" 4 #include "util/sort.h" 5 #include "util/evsel.h" 6 #include "util/evlist.h" 7 #include "util/machine.h" 8 #include "util/thread.h" 9 #include "tests/hists_common.h" 10 11 static struct { 12 u32 pid; 13 const char *comm; 14 } fake_threads[] = { 15 { 100, "perf" }, 16 { 200, "perf" }, 17 { 300, "bash" }, 18 }; 19 20 static struct { 21 u32 pid; 22 u64 start; 23 const char *filename; 24 } fake_mmap_info[] = { 25 { 100, 0x40000, "perf" }, 26 { 100, 0x50000, "libc" }, 27 { 100, 0xf0000, "[kernel]" }, 28 { 200, 0x40000, "perf" }, 29 { 200, 0x50000, "libc" }, 30 { 200, 0xf0000, "[kernel]" }, 31 { 300, 0x40000, "bash" }, 32 { 300, 0x50000, "libc" }, 33 { 300, 0xf0000, "[kernel]" }, 34 }; 35 36 struct fake_sym { 37 u64 start; 38 u64 length; 39 const char *name; 40 }; 41 42 static struct fake_sym perf_syms[] = { 43 { 700, 100, "main" }, 44 { 800, 100, "run_command" }, 45 { 900, 100, "cmd_record" }, 46 }; 47 48 static struct fake_sym bash_syms[] = { 49 { 700, 100, "main" }, 50 { 800, 100, "xmalloc" }, 51 { 900, 100, "xfree" }, 52 }; 53 54 static struct fake_sym libc_syms[] = { 55 { 700, 100, "malloc" }, 56 { 800, 100, "free" }, 57 { 900, 100, "realloc" }, 58 }; 59 60 static struct fake_sym kernel_syms[] = { 61 { 700, 100, "schedule" }, 62 { 800, 100, "page_fault" }, 63 { 900, 100, "sys_perf_event_open" }, 64 }; 65 66 static struct { 67 const char *dso_name; 68 struct fake_sym *syms; 69 size_t nr_syms; 70 } fake_symbols[] = { 71 { "perf", perf_syms, ARRAY_SIZE(perf_syms) }, 72 { "bash", bash_syms, ARRAY_SIZE(bash_syms) }, 73 { "libc", libc_syms, ARRAY_SIZE(libc_syms) }, 74 { "[kernel]", kernel_syms, ARRAY_SIZE(kernel_syms) }, 75 }; 76 77 struct machine *setup_fake_machine(struct machines *machines) 78 { 79 struct machine *machine = machines__find(machines, HOST_KERNEL_ID); 80 size_t i; 81 82 if (machine == NULL) { 83 pr_debug("Not enough memory for machine setup\n"); 84 return NULL; 85 } 86 87 for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { 88 struct thread *thread; 89 90 thread = machine__findnew_thread(machine, fake_threads[i].pid, 91 fake_threads[i].pid); 92 if (thread == NULL) 93 goto out; 94 95 thread__set_comm(thread, fake_threads[i].comm, 0); 96 } 97 98 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { 99 union perf_event fake_mmap_event = { 100 .mmap = { 101 .header = { .misc = PERF_RECORD_MISC_USER, }, 102 .pid = fake_mmap_info[i].pid, 103 .tid = fake_mmap_info[i].pid, 104 .start = fake_mmap_info[i].start, 105 .len = 0x1000ULL, 106 .pgoff = 0ULL, 107 }, 108 }; 109 110 strcpy(fake_mmap_event.mmap.filename, 111 fake_mmap_info[i].filename); 112 113 machine__process_mmap_event(machine, &fake_mmap_event, NULL); 114 } 115 116 for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { 117 size_t k; 118 struct dso *dso; 119 120 dso = __dsos__findnew(&machine->user_dsos, 121 fake_symbols[i].dso_name); 122 if (dso == NULL) 123 goto out; 124 125 /* emulate dso__load() */ 126 dso__set_loaded(dso, MAP__FUNCTION); 127 128 for (k = 0; k < fake_symbols[i].nr_syms; k++) { 129 struct symbol *sym; 130 struct fake_sym *fsym = &fake_symbols[i].syms[k]; 131 132 sym = symbol__new(fsym->start, fsym->length, 133 STB_GLOBAL, fsym->name); 134 if (sym == NULL) 135 goto out; 136 137 symbols__insert(&dso->symbols[MAP__FUNCTION], sym); 138 } 139 } 140 141 return machine; 142 143 out: 144 pr_debug("Not enough memory for machine setup\n"); 145 machine__delete_threads(machine); 146 machine__delete(machine); 147 return NULL; 148 } 149