xref: /linux/tools/perf/tests/hists_common.c (revision 21a8b756b84ecaa0b7f29199669c151e2ce5e723)
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