Linux Perf
hists_common.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <inttypes.h>
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"
12 #include <linux/kernel.h>
13 
14 static struct {
15  u32 pid;
16  const char *comm;
17 } fake_threads[] = {
18  { FAKE_PID_PERF1, "perf" },
19  { FAKE_PID_PERF2, "perf" },
20  { FAKE_PID_BASH, "bash" },
21 };
22 
23 static struct {
24  u32 pid;
25  u64 start;
26  const char *filename;
27 } fake_mmap_info[] = {
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]" },
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[] = {
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" },
49 };
50 
51 static struct fake_sym bash_syms[] = {
52  { FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "main" },
53  { FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "xmalloc" },
54  { FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "xfree" },
55 };
56 
57 static struct fake_sym libc_syms[] = {
58  { 700, 100, "malloc" },
59  { 800, 100, "free" },
60  { 900, 100, "realloc" },
61  { FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "malloc" },
62  { FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "free" },
63  { FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "realloc" },
64 };
65 
66 static struct fake_sym kernel_syms[] = {
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" },
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 
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);
102  thread__put(thread);
103  }
104 
105  for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
106  struct perf_sample sample = {
107  .cpumode = PERF_RECORD_MISC_USER,
108  };
109  union perf_event fake_mmap_event = {
110  .mmap = {
111  .pid = fake_mmap_info[i].pid,
112  .tid = fake_mmap_info[i].pid,
113  .start = fake_mmap_info[i].start,
114  .len = FAKE_MAP_LENGTH,
115  .pgoff = 0ULL,
116  },
117  };
118 
119  strcpy(fake_mmap_event.mmap.filename,
120  fake_mmap_info[i].filename);
121 
122  machine__process_mmap_event(machine, &fake_mmap_event, &sample);
123  }
124 
125  for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
126  size_t k;
127  struct dso *dso;
128 
129  dso = machine__findnew_dso(machine, fake_symbols[i].dso_name);
130  if (dso == NULL)
131  goto out;
132 
133  /* emulate dso__load() */
134  dso__set_loaded(dso);
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, STT_FUNC, fsym->name);
142  if (sym == NULL) {
143  dso__put(dso);
144  goto out;
145  }
146 
147  symbols__insert(&dso->symbols, sym);
148  }
149 
150  dso__put(dso);
151  }
152 
153  return machine;
154 
155 out:
156  pr_debug("Not enough memory for machine setup\n");
157  machine__delete_threads(machine);
158  return NULL;
159 }
160 
162 {
163  int i = 0;
164  struct rb_root *root;
165  struct rb_node *node;
166 
167  if (hists__has(hists, need_collapse))
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 
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) {
207  pr_info("%2d: entry: %8s:%5d [%-8s] %20s: period = %"PRIu64"/%"PRIu64"\n",
208  i, thread__comm_str(he->thread), he->thread->tid,
209  he->ms.map->dso->short_name,
210  he->ms.sym->name, he->stat.period,
211  he->stat_acc ? he->stat_acc->period : 0);
212  }
213 
214  i++;
215  node = rb_next(node);
216  }
217 }
struct rb_root * entries_in
Definition: hist.h:73
const char * comm
Definition: hists_common.c:16
Definition: mem2node.c:7
static void dso__set_loaded(struct dso *dso)
Definition: dso.h:209
struct map_symbol ms
Definition: sort.h:98
struct he_stat stat
Definition: sort.h:96
struct symbol * sym
Definition: symbol.h:181
const char * filename
Definition: hists_common.c:26
struct map * map
Definition: symbol.h:180
#define FAKE_SYM_LENGTH
Definition: hists_common.h:21
struct rb_root root
Definition: block-range.c:6
struct rb_node rb_node
Definition: sort.h:91
#define FAKE_MAP_LENGTH
Definition: hists_common.h:16
struct thread * thread
Definition: sort.h:99
void dso__put(struct dso *dso)
Definition: dso.c:1270
static struct fake_sym perf_syms[]
Definition: hists_common.c:45
void symbols__insert(struct rb_root *symbols, struct symbol *sym)
Definition: symbol.c:328
Definition: comm.h:11
const char * dso_name
Definition: hists_common.c:73
Definition: sort.h:89
struct dso * machine__findnew_dso(struct machine *machine, const char *filename)
Definition: machine.c:2496
u64 period
Definition: sort.h:50
struct machine * machines__find(struct machines *machines, pid_t pid)
Definition: machine.c:277
struct symbol * symbol__new(u64 start, u64 len, u8 binding, u8 type, const char *name)
Definition: symbol.c:251
Definition: thread.h:18
const char * thread__comm_str(const struct thread *thread)
Definition: thread.c:258
#define pr_debug(fmt,...)
Definition: json.h:27
#define FAKE_MAP_LIBC
Definition: hists_common.h:14
void print_hists_in(struct hists *hists)
Definition: hists_common.c:161
static struct @26 fake_mmap_info[]
struct dso * dso
Definition: map.h:45
#define FAKE_PID_PERF2
Definition: hists_common.h:9
#define FAKE_MAP_BASH
Definition: hists_common.h:13
pid_t tid
Definition: thread.h:25
char name[0]
Definition: symbol.h:66
static struct fake_sym libc_syms[]
Definition: hists_common.c:57
#define hists__has(__h, __f)
Definition: hist.h:94
Definition: dso.h:138
struct rb_node rb_node_in
Definition: sort.h:90
#define FAKE_SYM_OFFSET3
Definition: hists_common.h:20
u32 pid
Definition: hists_common.c:15
struct rb_root symbols
Definition: dso.h:143
static int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp)
Definition: thread.h:77
u64 start
Definition: hists_common.c:25
#define FAKE_PID_PERF1
Definition: hists_common.h:8
static struct fake_sym kernel_syms[]
Definition: hists_common.c:66
void thread__put(struct thread *thread)
Definition: thread.c:119
#define HOST_KERNEL_ID
Definition: machine.h:21
#define FAKE_MAP_PERF
Definition: hists_common.h:12
void print_hists_out(struct hists *hists)
Definition: hists_common.c:191
u8 filtered
Definition: sort.h:114
static int sym(yyscan_t scanner, int type, int config)
#define FAKE_SYM_OFFSET1
Definition: hists_common.h:18
static struct fake_sym bash_syms[]
Definition: hists_common.c:51
u32 pid
Definition: event.h:15
#define pr_info(fmt,...)
Definition: json.h:24
#define FAKE_MAP_KERNEL
Definition: hists_common.h:15
u64 length
Definition: hists_common.c:41
struct rb_root entries
Definition: hist.h:74
Definition: symbol.h:55
static struct @25 fake_threads[]
struct machine * setup_fake_machine(struct machines *machines)
Definition: hists_common.c:83
struct fake_sym * syms
Definition: hists_common.c:74
#define FAKE_PID_BASH
Definition: hists_common.h:10
Definition: hist.h:71
struct he_stat * stat_acc
Definition: sort.h:97
struct rb_root entries_collapsed
Definition: hist.h:75
char filename[PATH_MAX]
Definition: event.h:19
struct mmap_event mmap
Definition: event.h:625
void machine__delete_threads(struct machine *machine)
Definition: machine.c:174
size_t nr_syms
Definition: hists_common.c:75
#define FAKE_SYM_OFFSET2
Definition: hists_common.h:19
u8 cpumode
Definition: event.h:207
static struct @27 fake_symbols[]
const char * short_name
Definition: dso.h:172
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
Definition: machine.c:492
const char * name
Definition: hists_common.c:42
int machine__process_mmap_event(struct machine *machine, union perf_event *event, struct perf_sample *sample)
Definition: machine.c:1580