hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/tools/perf/util/event.c
....@@ -1,16 +1,17 @@
1
-// SPDX-License-Identifier: GPL-2.0
2
-#include <dirent.h>
31 #include <errno.h>
42 #include <fcntl.h>
53 #include <inttypes.h>
64 #include <linux/kernel.h>
75 #include <linux/types.h>
6
+#include <perf/cpumap.h>
87 #include <sys/types.h>
98 #include <sys/stat.h>
109 #include <unistd.h>
1110 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
12
-#include <api/fs/fs.h>
1311 #include <linux/perf_event.h>
12
+#include <linux/zalloc.h>
13
+#include "cpumap.h"
14
+#include "dso.h"
1415 #include "event.h"
1516 #include "debug.h"
1617 #include "hist.h"
....@@ -20,10 +21,19 @@
2021 #include "strlist.h"
2122 #include "thread.h"
2223 #include "thread_map.h"
23
-#include "sane_ctype.h"
24
+#include "time-utils.h"
25
+#include <linux/ctype.h>
26
+#include "map.h"
27
+#include "util/namespaces.h"
28
+#include "symbol.h"
2429 #include "symbol/kallsyms.h"
2530 #include "asm/bug.h"
2631 #include "stat.h"
32
+#include "session.h"
33
+#include "bpf-event.h"
34
+#include "print_binary.h"
35
+#include "tool.h"
36
+#include "../perf.h"
2737
2838 static const char *perf_event__names[] = {
2939 [0] = "TOTAL",
....@@ -43,6 +53,10 @@
4353 [PERF_RECORD_SWITCH] = "SWITCH",
4454 [PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE",
4555 [PERF_RECORD_NAMESPACES] = "NAMESPACES",
56
+ [PERF_RECORD_KSYMBOL] = "KSYMBOL",
57
+ [PERF_RECORD_BPF_EVENT] = "BPF_EVENT",
58
+ [PERF_RECORD_CGROUP] = "CGROUP",
59
+ [PERF_RECORD_TEXT_POKE] = "TEXT_POKE",
4660 [PERF_RECORD_HEADER_ATTR] = "ATTR",
4761 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
4862 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
....@@ -60,16 +74,7 @@
6074 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
6175 [PERF_RECORD_TIME_CONV] = "TIME_CONV",
6276 [PERF_RECORD_HEADER_FEATURE] = "FEATURE",
63
-};
64
-
65
-static const char *perf_ns__names[] = {
66
- [NET_NS_INDEX] = "net",
67
- [UTS_NS_INDEX] = "uts",
68
- [IPC_NS_INDEX] = "ipc",
69
- [PID_NS_INDEX] = "pid",
70
- [USER_NS_INDEX] = "user",
71
- [MNT_NS_INDEX] = "mnt",
72
- [CGROUP_NS_INDEX] = "cgroup",
77
+ [PERF_RECORD_COMPRESSED] = "COMPRESSED",
7378 };
7479
7580 const char *perf_event__name(unsigned int id)
....@@ -79,786 +84,6 @@
7984 if (!perf_event__names[id])
8085 return "UNKNOWN";
8186 return perf_event__names[id];
82
-}
83
-
84
-static const char *perf_ns__name(unsigned int id)
85
-{
86
- if (id >= ARRAY_SIZE(perf_ns__names))
87
- return "UNKNOWN";
88
- return perf_ns__names[id];
89
-}
90
-
91
-int perf_tool__process_synth_event(struct perf_tool *tool,
92
- union perf_event *event,
93
- struct machine *machine,
94
- perf_event__handler_t process)
95
-{
96
- struct perf_sample synth_sample = {
97
- .pid = -1,
98
- .tid = -1,
99
- .time = -1,
100
- .stream_id = -1,
101
- .cpu = -1,
102
- .period = 1,
103
- .cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK,
104
- };
105
-
106
- return process(tool, event, &synth_sample, machine);
107
-};
108
-
109
-/*
110
- * Assumes that the first 4095 bytes of /proc/pid/stat contains
111
- * the comm, tgid and ppid.
112
- */
113
-static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
114
- pid_t *tgid, pid_t *ppid)
115
-{
116
- char filename[PATH_MAX];
117
- char bf[4096];
118
- int fd;
119
- size_t size = 0;
120
- ssize_t n;
121
- char *name, *tgids, *ppids;
122
-
123
- *tgid = -1;
124
- *ppid = -1;
125
-
126
- snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
127
-
128
- fd = open(filename, O_RDONLY);
129
- if (fd < 0) {
130
- pr_debug("couldn't open %s\n", filename);
131
- return -1;
132
- }
133
-
134
- n = read(fd, bf, sizeof(bf) - 1);
135
- close(fd);
136
- if (n <= 0) {
137
- pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
138
- pid);
139
- return -1;
140
- }
141
- bf[n] = '\0';
142
-
143
- name = strstr(bf, "Name:");
144
- tgids = strstr(bf, "Tgid:");
145
- ppids = strstr(bf, "PPid:");
146
-
147
- if (name) {
148
- char *nl;
149
-
150
- name += 5; /* strlen("Name:") */
151
- name = ltrim(name);
152
-
153
- nl = strchr(name, '\n');
154
- if (nl)
155
- *nl = '\0';
156
-
157
- size = strlen(name);
158
- if (size >= len)
159
- size = len - 1;
160
- memcpy(comm, name, size);
161
- comm[size] = '\0';
162
- } else {
163
- pr_debug("Name: string not found for pid %d\n", pid);
164
- }
165
-
166
- if (tgids) {
167
- tgids += 5; /* strlen("Tgid:") */
168
- *tgid = atoi(tgids);
169
- } else {
170
- pr_debug("Tgid: string not found for pid %d\n", pid);
171
- }
172
-
173
- if (ppids) {
174
- ppids += 5; /* strlen("PPid:") */
175
- *ppid = atoi(ppids);
176
- } else {
177
- pr_debug("PPid: string not found for pid %d\n", pid);
178
- }
179
-
180
- return 0;
181
-}
182
-
183
-static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
184
- struct machine *machine,
185
- pid_t *tgid, pid_t *ppid)
186
-{
187
- size_t size;
188
-
189
- *ppid = -1;
190
-
191
- memset(&event->comm, 0, sizeof(event->comm));
192
-
193
- if (machine__is_host(machine)) {
194
- if (perf_event__get_comm_ids(pid, event->comm.comm,
195
- sizeof(event->comm.comm),
196
- tgid, ppid) != 0) {
197
- return -1;
198
- }
199
- } else {
200
- *tgid = machine->pid;
201
- }
202
-
203
- if (*tgid < 0)
204
- return -1;
205
-
206
- event->comm.pid = *tgid;
207
- event->comm.header.type = PERF_RECORD_COMM;
208
-
209
- size = strlen(event->comm.comm) + 1;
210
- size = PERF_ALIGN(size, sizeof(u64));
211
- memset(event->comm.comm + size, 0, machine->id_hdr_size);
212
- event->comm.header.size = (sizeof(event->comm) -
213
- (sizeof(event->comm.comm) - size) +
214
- machine->id_hdr_size);
215
- event->comm.tid = pid;
216
-
217
- return 0;
218
-}
219
-
220
-pid_t perf_event__synthesize_comm(struct perf_tool *tool,
221
- union perf_event *event, pid_t pid,
222
- perf_event__handler_t process,
223
- struct machine *machine)
224
-{
225
- pid_t tgid, ppid;
226
-
227
- if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
228
- return -1;
229
-
230
- if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
231
- return -1;
232
-
233
- return tgid;
234
-}
235
-
236
-static void perf_event__get_ns_link_info(pid_t pid, const char *ns,
237
- struct perf_ns_link_info *ns_link_info)
238
-{
239
- struct stat64 st;
240
- char proc_ns[128];
241
-
242
- sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns);
243
- if (stat64(proc_ns, &st) == 0) {
244
- ns_link_info->dev = st.st_dev;
245
- ns_link_info->ino = st.st_ino;
246
- }
247
-}
248
-
249
-int perf_event__synthesize_namespaces(struct perf_tool *tool,
250
- union perf_event *event,
251
- pid_t pid, pid_t tgid,
252
- perf_event__handler_t process,
253
- struct machine *machine)
254
-{
255
- u32 idx;
256
- struct perf_ns_link_info *ns_link_info;
257
-
258
- if (!tool || !tool->namespace_events)
259
- return 0;
260
-
261
- memset(&event->namespaces, 0, (sizeof(event->namespaces) +
262
- (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
263
- machine->id_hdr_size));
264
-
265
- event->namespaces.pid = tgid;
266
- event->namespaces.tid = pid;
267
-
268
- event->namespaces.nr_namespaces = NR_NAMESPACES;
269
-
270
- ns_link_info = event->namespaces.link_info;
271
-
272
- for (idx = 0; idx < event->namespaces.nr_namespaces; idx++)
273
- perf_event__get_ns_link_info(pid, perf_ns__name(idx),
274
- &ns_link_info[idx]);
275
-
276
- event->namespaces.header.type = PERF_RECORD_NAMESPACES;
277
-
278
- event->namespaces.header.size = (sizeof(event->namespaces) +
279
- (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
280
- machine->id_hdr_size);
281
-
282
- if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
283
- return -1;
284
-
285
- return 0;
286
-}
287
-
288
-static int perf_event__synthesize_fork(struct perf_tool *tool,
289
- union perf_event *event,
290
- pid_t pid, pid_t tgid, pid_t ppid,
291
- perf_event__handler_t process,
292
- struct machine *machine)
293
-{
294
- memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
295
-
296
- /*
297
- * for main thread set parent to ppid from status file. For other
298
- * threads set parent pid to main thread. ie., assume main thread
299
- * spawns all threads in a process
300
- */
301
- if (tgid == pid) {
302
- event->fork.ppid = ppid;
303
- event->fork.ptid = ppid;
304
- } else {
305
- event->fork.ppid = tgid;
306
- event->fork.ptid = tgid;
307
- }
308
- event->fork.pid = tgid;
309
- event->fork.tid = pid;
310
- event->fork.header.type = PERF_RECORD_FORK;
311
-
312
- event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
313
-
314
- if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
315
- return -1;
316
-
317
- return 0;
318
-}
319
-
320
-int perf_event__synthesize_mmap_events(struct perf_tool *tool,
321
- union perf_event *event,
322
- pid_t pid, pid_t tgid,
323
- perf_event__handler_t process,
324
- struct machine *machine,
325
- bool mmap_data,
326
- unsigned int proc_map_timeout)
327
-{
328
- char filename[PATH_MAX];
329
- FILE *fp;
330
- unsigned long long t;
331
- bool truncation = false;
332
- unsigned long long timeout = proc_map_timeout * 1000000ULL;
333
- int rc = 0;
334
- const char *hugetlbfs_mnt = hugetlbfs__mountpoint();
335
- int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0;
336
-
337
- if (machine__is_default_guest(machine))
338
- return 0;
339
-
340
- snprintf(filename, sizeof(filename), "%s/proc/%d/task/%d/maps",
341
- machine->root_dir, pid, pid);
342
-
343
- fp = fopen(filename, "r");
344
- if (fp == NULL) {
345
- /*
346
- * We raced with a task exiting - just return:
347
- */
348
- pr_debug("couldn't open %s\n", filename);
349
- return -1;
350
- }
351
-
352
- event->header.type = PERF_RECORD_MMAP2;
353
- t = rdclock();
354
-
355
- while (1) {
356
- char bf[BUFSIZ];
357
- char prot[5];
358
- char execname[PATH_MAX];
359
- char anonstr[] = "//anon";
360
- unsigned int ino;
361
- size_t size;
362
- ssize_t n;
363
-
364
- if (fgets(bf, sizeof(bf), fp) == NULL)
365
- break;
366
-
367
- if ((rdclock() - t) > timeout) {
368
- pr_warning("Reading %s time out. "
369
- "You may want to increase "
370
- "the time limit by --proc-map-timeout\n",
371
- filename);
372
- truncation = true;
373
- goto out;
374
- }
375
-
376
- /* ensure null termination since stack will be reused. */
377
- strcpy(execname, "");
378
-
379
- /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
380
- n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %[^\n]\n",
381
- &event->mmap2.start, &event->mmap2.len, prot,
382
- &event->mmap2.pgoff, &event->mmap2.maj,
383
- &event->mmap2.min,
384
- &ino, execname);
385
-
386
- /*
387
- * Anon maps don't have the execname.
388
- */
389
- if (n < 7)
390
- continue;
391
-
392
- event->mmap2.ino = (u64)ino;
393
-
394
- /*
395
- * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
396
- */
397
- if (machine__is_host(machine))
398
- event->header.misc = PERF_RECORD_MISC_USER;
399
- else
400
- event->header.misc = PERF_RECORD_MISC_GUEST_USER;
401
-
402
- /* map protection and flags bits */
403
- event->mmap2.prot = 0;
404
- event->mmap2.flags = 0;
405
- if (prot[0] == 'r')
406
- event->mmap2.prot |= PROT_READ;
407
- if (prot[1] == 'w')
408
- event->mmap2.prot |= PROT_WRITE;
409
- if (prot[2] == 'x')
410
- event->mmap2.prot |= PROT_EXEC;
411
-
412
- if (prot[3] == 's')
413
- event->mmap2.flags |= MAP_SHARED;
414
- else
415
- event->mmap2.flags |= MAP_PRIVATE;
416
-
417
- if (prot[2] != 'x') {
418
- if (!mmap_data || prot[0] != 'r')
419
- continue;
420
-
421
- event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
422
- }
423
-
424
-out:
425
- if (truncation)
426
- event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
427
-
428
- if (!strcmp(execname, ""))
429
- strcpy(execname, anonstr);
430
-
431
- if (hugetlbfs_mnt_len &&
432
- !strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
433
- strcpy(execname, anonstr);
434
- event->mmap2.flags |= MAP_HUGETLB;
435
- }
436
-
437
- size = strlen(execname) + 1;
438
- memcpy(event->mmap2.filename, execname, size);
439
- size = PERF_ALIGN(size, sizeof(u64));
440
- event->mmap2.len -= event->mmap.start;
441
- event->mmap2.header.size = (sizeof(event->mmap2) -
442
- (sizeof(event->mmap2.filename) - size));
443
- memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
444
- event->mmap2.header.size += machine->id_hdr_size;
445
- event->mmap2.pid = tgid;
446
- event->mmap2.tid = pid;
447
-
448
- if (perf_tool__process_synth_event(tool, event, machine, process) != 0) {
449
- rc = -1;
450
- break;
451
- }
452
-
453
- if (truncation)
454
- break;
455
- }
456
-
457
- fclose(fp);
458
- return rc;
459
-}
460
-
461
-int perf_event__synthesize_modules(struct perf_tool *tool,
462
- perf_event__handler_t process,
463
- struct machine *machine)
464
-{
465
- int rc = 0;
466
- struct map *pos;
467
- struct maps *maps = machine__kernel_maps(machine);
468
- union perf_event *event = zalloc((sizeof(event->mmap) +
469
- machine->id_hdr_size));
470
- if (event == NULL) {
471
- pr_debug("Not enough memory synthesizing mmap event "
472
- "for kernel modules\n");
473
- return -1;
474
- }
475
-
476
- event->header.type = PERF_RECORD_MMAP;
477
-
478
- /*
479
- * kernel uses 0 for user space maps, see kernel/perf_event.c
480
- * __perf_event_mmap
481
- */
482
- if (machine__is_host(machine))
483
- event->header.misc = PERF_RECORD_MISC_KERNEL;
484
- else
485
- event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
486
-
487
- for (pos = maps__first(maps); pos; pos = map__next(pos)) {
488
- size_t size;
489
-
490
- if (!__map__is_kmodule(pos))
491
- continue;
492
-
493
- size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
494
- event->mmap.header.type = PERF_RECORD_MMAP;
495
- event->mmap.header.size = (sizeof(event->mmap) -
496
- (sizeof(event->mmap.filename) - size));
497
- memset(event->mmap.filename + size, 0, machine->id_hdr_size);
498
- event->mmap.header.size += machine->id_hdr_size;
499
- event->mmap.start = pos->start;
500
- event->mmap.len = pos->end - pos->start;
501
- event->mmap.pid = machine->pid;
502
-
503
- memcpy(event->mmap.filename, pos->dso->long_name,
504
- pos->dso->long_name_len + 1);
505
- if (perf_tool__process_synth_event(tool, event, machine, process) != 0) {
506
- rc = -1;
507
- break;
508
- }
509
- }
510
-
511
- free(event);
512
- return rc;
513
-}
514
-
515
-static int __event__synthesize_thread(union perf_event *comm_event,
516
- union perf_event *mmap_event,
517
- union perf_event *fork_event,
518
- union perf_event *namespaces_event,
519
- pid_t pid, int full,
520
- perf_event__handler_t process,
521
- struct perf_tool *tool,
522
- struct machine *machine,
523
- bool mmap_data,
524
- unsigned int proc_map_timeout)
525
-{
526
- char filename[PATH_MAX];
527
- DIR *tasks;
528
- struct dirent *dirent;
529
- pid_t tgid, ppid;
530
- int rc = 0;
531
-
532
- /* special case: only send one comm event using passed in pid */
533
- if (!full) {
534
- tgid = perf_event__synthesize_comm(tool, comm_event, pid,
535
- process, machine);
536
-
537
- if (tgid == -1)
538
- return -1;
539
-
540
- if (perf_event__synthesize_namespaces(tool, namespaces_event, pid,
541
- tgid, process, machine) < 0)
542
- return -1;
543
-
544
- /*
545
- * send mmap only for thread group leader
546
- * see thread__init_map_groups
547
- */
548
- if (pid == tgid &&
549
- perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
550
- process, machine, mmap_data,
551
- proc_map_timeout))
552
- return -1;
553
-
554
- return 0;
555
- }
556
-
557
- if (machine__is_default_guest(machine))
558
- return 0;
559
-
560
- snprintf(filename, sizeof(filename), "%s/proc/%d/task",
561
- machine->root_dir, pid);
562
-
563
- tasks = opendir(filename);
564
- if (tasks == NULL) {
565
- pr_debug("couldn't open %s\n", filename);
566
- return 0;
567
- }
568
-
569
- while ((dirent = readdir(tasks)) != NULL) {
570
- char *end;
571
- pid_t _pid;
572
-
573
- _pid = strtol(dirent->d_name, &end, 10);
574
- if (*end)
575
- continue;
576
-
577
- rc = -1;
578
- if (perf_event__prepare_comm(comm_event, _pid, machine,
579
- &tgid, &ppid) != 0)
580
- break;
581
-
582
- if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
583
- ppid, process, machine) < 0)
584
- break;
585
-
586
- if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid,
587
- tgid, process, machine) < 0)
588
- break;
589
-
590
- /*
591
- * Send the prepared comm event
592
- */
593
- if (perf_tool__process_synth_event(tool, comm_event, machine, process) != 0)
594
- break;
595
-
596
- rc = 0;
597
- if (_pid == pid) {
598
- /* process the parent's maps too */
599
- rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
600
- process, machine, mmap_data, proc_map_timeout);
601
- if (rc)
602
- break;
603
- }
604
- }
605
-
606
- closedir(tasks);
607
- return rc;
608
-}
609
-
610
-int perf_event__synthesize_thread_map(struct perf_tool *tool,
611
- struct thread_map *threads,
612
- perf_event__handler_t process,
613
- struct machine *machine,
614
- bool mmap_data,
615
- unsigned int proc_map_timeout)
616
-{
617
- union perf_event *comm_event, *mmap_event, *fork_event;
618
- union perf_event *namespaces_event;
619
- int err = -1, thread, j;
620
-
621
- comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
622
- if (comm_event == NULL)
623
- goto out;
624
-
625
- mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
626
- if (mmap_event == NULL)
627
- goto out_free_comm;
628
-
629
- fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
630
- if (fork_event == NULL)
631
- goto out_free_mmap;
632
-
633
- namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
634
- (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
635
- machine->id_hdr_size);
636
- if (namespaces_event == NULL)
637
- goto out_free_fork;
638
-
639
- err = 0;
640
- for (thread = 0; thread < threads->nr; ++thread) {
641
- if (__event__synthesize_thread(comm_event, mmap_event,
642
- fork_event, namespaces_event,
643
- thread_map__pid(threads, thread), 0,
644
- process, tool, machine,
645
- mmap_data, proc_map_timeout)) {
646
- err = -1;
647
- break;
648
- }
649
-
650
- /*
651
- * comm.pid is set to thread group id by
652
- * perf_event__synthesize_comm
653
- */
654
- if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) {
655
- bool need_leader = true;
656
-
657
- /* is thread group leader in thread_map? */
658
- for (j = 0; j < threads->nr; ++j) {
659
- if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) {
660
- need_leader = false;
661
- break;
662
- }
663
- }
664
-
665
- /* if not, generate events for it */
666
- if (need_leader &&
667
- __event__synthesize_thread(comm_event, mmap_event,
668
- fork_event, namespaces_event,
669
- comm_event->comm.pid, 0,
670
- process, tool, machine,
671
- mmap_data, proc_map_timeout)) {
672
- err = -1;
673
- break;
674
- }
675
- }
676
- }
677
- free(namespaces_event);
678
-out_free_fork:
679
- free(fork_event);
680
-out_free_mmap:
681
- free(mmap_event);
682
-out_free_comm:
683
- free(comm_event);
684
-out:
685
- return err;
686
-}
687
-
688
-static int __perf_event__synthesize_threads(struct perf_tool *tool,
689
- perf_event__handler_t process,
690
- struct machine *machine,
691
- bool mmap_data,
692
- unsigned int proc_map_timeout,
693
- struct dirent **dirent,
694
- int start,
695
- int num)
696
-{
697
- union perf_event *comm_event, *mmap_event, *fork_event;
698
- union perf_event *namespaces_event;
699
- int err = -1;
700
- char *end;
701
- pid_t pid;
702
- int i;
703
-
704
- comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
705
- if (comm_event == NULL)
706
- goto out;
707
-
708
- mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
709
- if (mmap_event == NULL)
710
- goto out_free_comm;
711
-
712
- fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
713
- if (fork_event == NULL)
714
- goto out_free_mmap;
715
-
716
- namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
717
- (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
718
- machine->id_hdr_size);
719
- if (namespaces_event == NULL)
720
- goto out_free_fork;
721
-
722
- for (i = start; i < start + num; i++) {
723
- if (!isdigit(dirent[i]->d_name[0]))
724
- continue;
725
-
726
- pid = (pid_t)strtol(dirent[i]->d_name, &end, 10);
727
- /* only interested in proper numerical dirents */
728
- if (*end)
729
- continue;
730
- /*
731
- * We may race with exiting thread, so don't stop just because
732
- * one thread couldn't be synthesized.
733
- */
734
- __event__synthesize_thread(comm_event, mmap_event, fork_event,
735
- namespaces_event, pid, 1, process,
736
- tool, machine, mmap_data,
737
- proc_map_timeout);
738
- }
739
- err = 0;
740
-
741
- free(namespaces_event);
742
-out_free_fork:
743
- free(fork_event);
744
-out_free_mmap:
745
- free(mmap_event);
746
-out_free_comm:
747
- free(comm_event);
748
-out:
749
- return err;
750
-}
751
-
752
-struct synthesize_threads_arg {
753
- struct perf_tool *tool;
754
- perf_event__handler_t process;
755
- struct machine *machine;
756
- bool mmap_data;
757
- unsigned int proc_map_timeout;
758
- struct dirent **dirent;
759
- int num;
760
- int start;
761
-};
762
-
763
-static void *synthesize_threads_worker(void *arg)
764
-{
765
- struct synthesize_threads_arg *args = arg;
766
-
767
- __perf_event__synthesize_threads(args->tool, args->process,
768
- args->machine, args->mmap_data,
769
- args->proc_map_timeout, args->dirent,
770
- args->start, args->num);
771
- return NULL;
772
-}
773
-
774
-int perf_event__synthesize_threads(struct perf_tool *tool,
775
- perf_event__handler_t process,
776
- struct machine *machine,
777
- bool mmap_data,
778
- unsigned int proc_map_timeout,
779
- unsigned int nr_threads_synthesize)
780
-{
781
- struct synthesize_threads_arg *args = NULL;
782
- pthread_t *synthesize_threads = NULL;
783
- char proc_path[PATH_MAX];
784
- struct dirent **dirent;
785
- int num_per_thread;
786
- int m, n, i, j;
787
- int thread_nr;
788
- int base = 0;
789
- int err = -1;
790
-
791
-
792
- if (machine__is_default_guest(machine))
793
- return 0;
794
-
795
- snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
796
- n = scandir(proc_path, &dirent, 0, alphasort);
797
- if (n < 0)
798
- return err;
799
-
800
- if (nr_threads_synthesize == UINT_MAX)
801
- thread_nr = sysconf(_SC_NPROCESSORS_ONLN);
802
- else
803
- thread_nr = nr_threads_synthesize;
804
-
805
- if (thread_nr <= 1) {
806
- err = __perf_event__synthesize_threads(tool, process,
807
- machine, mmap_data,
808
- proc_map_timeout,
809
- dirent, base, n);
810
- goto free_dirent;
811
- }
812
- if (thread_nr > n)
813
- thread_nr = n;
814
-
815
- synthesize_threads = calloc(sizeof(pthread_t), thread_nr);
816
- if (synthesize_threads == NULL)
817
- goto free_dirent;
818
-
819
- args = calloc(sizeof(*args), thread_nr);
820
- if (args == NULL)
821
- goto free_threads;
822
-
823
- num_per_thread = n / thread_nr;
824
- m = n % thread_nr;
825
- for (i = 0; i < thread_nr; i++) {
826
- args[i].tool = tool;
827
- args[i].process = process;
828
- args[i].machine = machine;
829
- args[i].mmap_data = mmap_data;
830
- args[i].proc_map_timeout = proc_map_timeout;
831
- args[i].dirent = dirent;
832
- }
833
- for (i = 0; i < m; i++) {
834
- args[i].num = num_per_thread + 1;
835
- args[i].start = i * args[i].num;
836
- }
837
- if (i != 0)
838
- base = args[i-1].start + args[i-1].num;
839
- for (j = i; j < thread_nr; j++) {
840
- args[j].num = num_per_thread;
841
- args[j].start = base + (j - i) * args[i].num;
842
- }
843
-
844
- for (i = 0; i < thread_nr; i++) {
845
- if (pthread_create(&synthesize_threads[i], NULL,
846
- synthesize_threads_worker, &args[i]))
847
- goto out_join;
848
- }
849
- err = 0;
850
-out_join:
851
- for (i = 0; i < thread_nr; i++)
852
- pthread_join(synthesize_threads[i], NULL);
853
- free(args);
854
-free_threads:
855
- free(synthesize_threads);
856
-free_dirent:
857
- for (i = 0; i < n; i++)
858
- free(dirent[i]);
859
- free(dirent);
860
-
861
- return err;
86287 }
86388
86489 struct process_symbol_args {
....@@ -895,329 +120,8 @@
895120 return 0;
896121 }
897122
898
-int __weak perf_event__synthesize_extra_kmaps(struct perf_tool *tool __maybe_unused,
899
- perf_event__handler_t process __maybe_unused,
900
- struct machine *machine __maybe_unused)
901
-{
902
- return 0;
903
-}
904
-
905
-static int __perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
906
- perf_event__handler_t process,
907
- struct machine *machine)
908
-{
909
- size_t size;
910
- struct map *map = machine__kernel_map(machine);
911
- struct kmap *kmap;
912
- int err;
913
- union perf_event *event;
914
-
915
- if (map == NULL)
916
- return -1;
917
-
918
- kmap = map__kmap(map);
919
- if (!kmap->ref_reloc_sym)
920
- return -1;
921
-
922
- /*
923
- * We should get this from /sys/kernel/sections/.text, but till that is
924
- * available use this, and after it is use this as a fallback for older
925
- * kernels.
926
- */
927
- event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
928
- if (event == NULL) {
929
- pr_debug("Not enough memory synthesizing mmap event "
930
- "for kernel modules\n");
931
- return -1;
932
- }
933
-
934
- if (machine__is_host(machine)) {
935
- /*
936
- * kernel uses PERF_RECORD_MISC_USER for user space maps,
937
- * see kernel/perf_event.c __perf_event_mmap
938
- */
939
- event->header.misc = PERF_RECORD_MISC_KERNEL;
940
- } else {
941
- event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
942
- }
943
-
944
- size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
945
- "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
946
- size = PERF_ALIGN(size, sizeof(u64));
947
- event->mmap.header.type = PERF_RECORD_MMAP;
948
- event->mmap.header.size = (sizeof(event->mmap) -
949
- (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
950
- event->mmap.pgoff = kmap->ref_reloc_sym->addr;
951
- event->mmap.start = map->start;
952
- event->mmap.len = map->end - event->mmap.start;
953
- event->mmap.pid = machine->pid;
954
-
955
- err = perf_tool__process_synth_event(tool, event, machine, process);
956
- free(event);
957
-
958
- return err;
959
-}
960
-
961
-int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
962
- perf_event__handler_t process,
963
- struct machine *machine)
964
-{
965
- int err;
966
-
967
- err = __perf_event__synthesize_kernel_mmap(tool, process, machine);
968
- if (err < 0)
969
- return err;
970
-
971
- return perf_event__synthesize_extra_kmaps(tool, process, machine);
972
-}
973
-
974
-int perf_event__synthesize_thread_map2(struct perf_tool *tool,
975
- struct thread_map *threads,
976
- perf_event__handler_t process,
977
- struct machine *machine)
978
-{
979
- union perf_event *event;
980
- int i, err, size;
981
-
982
- size = sizeof(event->thread_map);
983
- size += threads->nr * sizeof(event->thread_map.entries[0]);
984
-
985
- event = zalloc(size);
986
- if (!event)
987
- return -ENOMEM;
988
-
989
- event->header.type = PERF_RECORD_THREAD_MAP;
990
- event->header.size = size;
991
- event->thread_map.nr = threads->nr;
992
-
993
- for (i = 0; i < threads->nr; i++) {
994
- struct thread_map_event_entry *entry = &event->thread_map.entries[i];
995
- char *comm = thread_map__comm(threads, i);
996
-
997
- if (!comm)
998
- comm = (char *) "";
999
-
1000
- entry->pid = thread_map__pid(threads, i);
1001
- strncpy((char *) &entry->comm, comm, sizeof(entry->comm));
1002
- }
1003
-
1004
- err = process(tool, event, NULL, machine);
1005
-
1006
- free(event);
1007
- return err;
1008
-}
1009
-
1010
-static void synthesize_cpus(struct cpu_map_entries *cpus,
1011
- struct cpu_map *map)
1012
-{
1013
- int i;
1014
-
1015
- cpus->nr = map->nr;
1016
-
1017
- for (i = 0; i < map->nr; i++)
1018
- cpus->cpu[i] = map->map[i];
1019
-}
1020
-
1021
-static void synthesize_mask(struct cpu_map_mask *mask,
1022
- struct cpu_map *map, int max)
1023
-{
1024
- int i;
1025
-
1026
- mask->nr = BITS_TO_LONGS(max);
1027
- mask->long_size = sizeof(long);
1028
-
1029
- for (i = 0; i < map->nr; i++)
1030
- set_bit(map->map[i], mask->mask);
1031
-}
1032
-
1033
-static size_t cpus_size(struct cpu_map *map)
1034
-{
1035
- return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
1036
-}
1037
-
1038
-static size_t mask_size(struct cpu_map *map, int *max)
1039
-{
1040
- int i;
1041
-
1042
- *max = 0;
1043
-
1044
- for (i = 0; i < map->nr; i++) {
1045
- /* bit possition of the cpu is + 1 */
1046
- int bit = map->map[i] + 1;
1047
-
1048
- if (bit > *max)
1049
- *max = bit;
1050
- }
1051
-
1052
- return sizeof(struct cpu_map_mask) + BITS_TO_LONGS(*max) * sizeof(long);
1053
-}
1054
-
1055
-void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max)
1056
-{
1057
- size_t size_cpus, size_mask;
1058
- bool is_dummy = cpu_map__empty(map);
1059
-
1060
- /*
1061
- * Both array and mask data have variable size based
1062
- * on the number of cpus and their actual values.
1063
- * The size of the 'struct cpu_map_data' is:
1064
- *
1065
- * array = size of 'struct cpu_map_entries' +
1066
- * number of cpus * sizeof(u64)
1067
- *
1068
- * mask = size of 'struct cpu_map_mask' +
1069
- * maximum cpu bit converted to size of longs
1070
- *
1071
- * and finaly + the size of 'struct cpu_map_data'.
1072
- */
1073
- size_cpus = cpus_size(map);
1074
- size_mask = mask_size(map, max);
1075
-
1076
- if (is_dummy || (size_cpus < size_mask)) {
1077
- *size += size_cpus;
1078
- *type = PERF_CPU_MAP__CPUS;
1079
- } else {
1080
- *size += size_mask;
1081
- *type = PERF_CPU_MAP__MASK;
1082
- }
1083
-
1084
- *size += sizeof(struct cpu_map_data);
1085
- *size = PERF_ALIGN(*size, sizeof(u64));
1086
- return zalloc(*size);
1087
-}
1088
-
1089
-void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
1090
- u16 type, int max)
1091
-{
1092
- data->type = type;
1093
-
1094
- switch (type) {
1095
- case PERF_CPU_MAP__CPUS:
1096
- synthesize_cpus((struct cpu_map_entries *) data->data, map);
1097
- break;
1098
- case PERF_CPU_MAP__MASK:
1099
- synthesize_mask((struct cpu_map_mask *) data->data, map, max);
1100
- default:
1101
- break;
1102
- };
1103
-}
1104
-
1105
-static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map)
1106
-{
1107
- size_t size = sizeof(struct cpu_map_event);
1108
- struct cpu_map_event *event;
1109
- int max;
1110
- u16 type;
1111
-
1112
- event = cpu_map_data__alloc(map, &size, &type, &max);
1113
- if (!event)
1114
- return NULL;
1115
-
1116
- event->header.type = PERF_RECORD_CPU_MAP;
1117
- event->header.size = size;
1118
- event->data.type = type;
1119
-
1120
- cpu_map_data__synthesize(&event->data, map, type, max);
1121
- return event;
1122
-}
1123
-
1124
-int perf_event__synthesize_cpu_map(struct perf_tool *tool,
1125
- struct cpu_map *map,
1126
- perf_event__handler_t process,
1127
- struct machine *machine)
1128
-{
1129
- struct cpu_map_event *event;
1130
- int err;
1131
-
1132
- event = cpu_map_event__new(map);
1133
- if (!event)
1134
- return -ENOMEM;
1135
-
1136
- err = process(tool, (union perf_event *) event, NULL, machine);
1137
-
1138
- free(event);
1139
- return err;
1140
-}
1141
-
1142
-int perf_event__synthesize_stat_config(struct perf_tool *tool,
1143
- struct perf_stat_config *config,
1144
- perf_event__handler_t process,
1145
- struct machine *machine)
1146
-{
1147
- struct stat_config_event *event;
1148
- int size, i = 0, err;
1149
-
1150
- size = sizeof(*event);
1151
- size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0]));
1152
-
1153
- event = zalloc(size);
1154
- if (!event)
1155
- return -ENOMEM;
1156
-
1157
- event->header.type = PERF_RECORD_STAT_CONFIG;
1158
- event->header.size = size;
1159
- event->nr = PERF_STAT_CONFIG_TERM__MAX;
1160
-
1161
-#define ADD(__term, __val) \
1162
- event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term; \
1163
- event->data[i].val = __val; \
1164
- i++;
1165
-
1166
- ADD(AGGR_MODE, config->aggr_mode)
1167
- ADD(INTERVAL, config->interval)
1168
- ADD(SCALE, config->scale)
1169
-
1170
- WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX,
1171
- "stat config terms unbalanced\n");
1172
-#undef ADD
1173
-
1174
- err = process(tool, (union perf_event *) event, NULL, machine);
1175
-
1176
- free(event);
1177
- return err;
1178
-}
1179
-
1180
-int perf_event__synthesize_stat(struct perf_tool *tool,
1181
- u32 cpu, u32 thread, u64 id,
1182
- struct perf_counts_values *count,
1183
- perf_event__handler_t process,
1184
- struct machine *machine)
1185
-{
1186
- struct stat_event event;
1187
-
1188
- event.header.type = PERF_RECORD_STAT;
1189
- event.header.size = sizeof(event);
1190
- event.header.misc = 0;
1191
-
1192
- event.id = id;
1193
- event.cpu = cpu;
1194
- event.thread = thread;
1195
- event.val = count->val;
1196
- event.ena = count->ena;
1197
- event.run = count->run;
1198
-
1199
- return process(tool, (union perf_event *) &event, NULL, machine);
1200
-}
1201
-
1202
-int perf_event__synthesize_stat_round(struct perf_tool *tool,
1203
- u64 evtime, u64 type,
1204
- perf_event__handler_t process,
1205
- struct machine *machine)
1206
-{
1207
- struct stat_round_event event;
1208
-
1209
- event.header.type = PERF_RECORD_STAT_ROUND;
1210
- event.header.size = sizeof(event);
1211
- event.header.misc = 0;
1212
-
1213
- event.time = evtime;
1214
- event.type = type;
1215
-
1216
- return process(tool, (union perf_event *) &event, NULL, machine);
1217
-}
1218
-
1219123 void perf_event__read_stat_config(struct perf_stat_config *config,
1220
- struct stat_config_event *event)
124
+ struct perf_record_stat_config *event)
1221125 {
1222126 unsigned i;
1223127
....@@ -1234,7 +138,7 @@
1234138 CASE(INTERVAL, interval)
1235139 #undef CASE
1236140 default:
1237
- pr_warning("unknown stat config term %" PRIu64 "\n",
141
+ pr_warning("unknown stat config term %" PRI_lu64 "\n",
1238142 event->data[i].tag);
1239143 }
1240144 }
....@@ -1279,6 +183,12 @@
1279183 return ret;
1280184 }
1281185
186
+size_t perf_event__fprintf_cgroup(union perf_event *event, FILE *fp)
187
+{
188
+ return fprintf(fp, " cgroup: %" PRI_lu64 " %s\n",
189
+ event->cgroup.id, event->cgroup.path);
190
+}
191
+
1282192 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
1283193 union perf_event *event,
1284194 struct perf_sample *sample,
....@@ -1293,6 +203,14 @@
1293203 struct machine *machine)
1294204 {
1295205 return machine__process_namespaces_event(machine, event, sample);
206
+}
207
+
208
+int perf_event__process_cgroup(struct perf_tool *tool __maybe_unused,
209
+ union perf_event *event,
210
+ struct perf_sample *sample,
211
+ struct machine *machine)
212
+{
213
+ return machine__process_cgroup_event(machine, event, sample);
1296214 }
1297215
1298216 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
....@@ -1335,9 +253,33 @@
1335253 return machine__process_switch_event(machine, event);
1336254 }
1337255
256
+int perf_event__process_ksymbol(struct perf_tool *tool __maybe_unused,
257
+ union perf_event *event,
258
+ struct perf_sample *sample __maybe_unused,
259
+ struct machine *machine)
260
+{
261
+ return machine__process_ksymbol(machine, event, sample);
262
+}
263
+
264
+int perf_event__process_bpf(struct perf_tool *tool __maybe_unused,
265
+ union perf_event *event,
266
+ struct perf_sample *sample,
267
+ struct machine *machine)
268
+{
269
+ return machine__process_bpf(machine, event, sample);
270
+}
271
+
272
+int perf_event__process_text_poke(struct perf_tool *tool __maybe_unused,
273
+ union perf_event *event,
274
+ struct perf_sample *sample,
275
+ struct machine *machine)
276
+{
277
+ return machine__process_text_poke(machine, event, sample);
278
+}
279
+
1338280 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
1339281 {
1340
- return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
282
+ return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64 "]: %c %s\n",
1341283 event->mmap.pid, event->mmap.tid, event->mmap.start,
1342284 event->mmap.len, event->mmap.pgoff,
1343285 (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
....@@ -1346,8 +288,8 @@
1346288
1347289 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
1348290 {
1349
- return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
1350
- " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n",
291
+ return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
292
+ " %02x:%02x %"PRI_lu64" %"PRI_lu64"]: %c%c%c%c %s\n",
1351293 event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
1352294 event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
1353295 event->mmap2.min, event->mmap2.ino,
....@@ -1361,7 +303,7 @@
1361303
1362304 size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
1363305 {
1364
- struct thread_map *threads = thread_map__new_event(&event->thread_map);
306
+ struct perf_thread_map *threads = thread_map__new_event(&event->thread_map);
1365307 size_t ret;
1366308
1367309 ret = fprintf(fp, " nr: ");
....@@ -1371,13 +313,13 @@
1371313 else
1372314 ret += fprintf(fp, "failed to get threads from event\n");
1373315
1374
- thread_map__put(threads);
316
+ perf_thread_map__put(threads);
1375317 return ret;
1376318 }
1377319
1378320 size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
1379321 {
1380
- struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
322
+ struct perf_cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
1381323 size_t ret;
1382324
1383325 ret = fprintf(fp, ": ");
....@@ -1387,7 +329,7 @@
1387329 else
1388330 ret += fprintf(fp, "failed to get cpumap from event\n");
1389331
1390
- cpu_map__put(cpus);
332
+ perf_cpu_map__put(cpus);
1391333 return ret;
1392334 }
1393335
....@@ -1432,7 +374,7 @@
1432374
1433375 size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
1434376 {
1435
- return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s%s]\n",
377
+ return fprintf(fp, " offset: %#"PRI_lx64" size: %#"PRI_lx64" flags: %#"PRI_lx64" [%s%s%s]\n",
1436378 event->aux.aux_offset, event->aux.aux_size,
1437379 event->aux.flags,
1438380 event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
....@@ -1456,7 +398,7 @@
1456398 if (event->header.type == PERF_RECORD_SWITCH)
1457399 return fprintf(fp, " %s\n", in_out);
1458400
1459
- return fprintf(fp, " %s %s pid/tid: %5u/%-5u\n",
401
+ return fprintf(fp, " %s %s pid/tid: %5d/%-5d\n",
1460402 in_out, out ? "next" : "prev",
1461403 event->context_switch.next_prev_pid,
1462404 event->context_switch.next_prev_tid);
....@@ -1464,10 +406,69 @@
1464406
1465407 static size_t perf_event__fprintf_lost(union perf_event *event, FILE *fp)
1466408 {
1467
- return fprintf(fp, " lost %" PRIu64 "\n", event->lost.lost);
409
+ return fprintf(fp, " lost %" PRI_lu64 "\n", event->lost.lost);
1468410 }
1469411
1470
-size_t perf_event__fprintf(union perf_event *event, FILE *fp)
412
+size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp)
413
+{
414
+ return fprintf(fp, " addr %" PRI_lx64 " len %u type %u flags 0x%x name %s\n",
415
+ event->ksymbol.addr, event->ksymbol.len,
416
+ event->ksymbol.ksym_type,
417
+ event->ksymbol.flags, event->ksymbol.name);
418
+}
419
+
420
+size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp)
421
+{
422
+ return fprintf(fp, " type %u, flags %u, id %u\n",
423
+ event->bpf.type, event->bpf.flags, event->bpf.id);
424
+}
425
+
426
+static int text_poke_printer(enum binary_printer_ops op, unsigned int val,
427
+ void *extra, FILE *fp)
428
+{
429
+ bool old = *(bool *)extra;
430
+
431
+ switch ((int)op) {
432
+ case BINARY_PRINT_LINE_BEGIN:
433
+ return fprintf(fp, " %s bytes:", old ? "Old" : "New");
434
+ case BINARY_PRINT_NUM_DATA:
435
+ return fprintf(fp, " %02x", val);
436
+ case BINARY_PRINT_LINE_END:
437
+ return fprintf(fp, "\n");
438
+ default:
439
+ return 0;
440
+ }
441
+}
442
+
443
+size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *machine, FILE *fp)
444
+{
445
+ struct perf_record_text_poke_event *tp = &event->text_poke;
446
+ size_t ret;
447
+ bool old;
448
+
449
+ ret = fprintf(fp, " %" PRI_lx64 " ", tp->addr);
450
+ if (machine) {
451
+ struct addr_location al;
452
+
453
+ al.map = maps__find(&machine->kmaps, tp->addr);
454
+ if (al.map && map__load(al.map) >= 0) {
455
+ al.addr = al.map->map_ip(al.map, tp->addr);
456
+ al.sym = map__find_symbol(al.map, al.addr);
457
+ if (al.sym)
458
+ ret += symbol__fprintf_symname_offs(al.sym, &al, fp);
459
+ }
460
+ }
461
+ ret += fprintf(fp, " old len %u new len %u\n", tp->old_len, tp->new_len);
462
+ old = true;
463
+ ret += binary__fprintf(tp->bytes, tp->old_len, 16, text_poke_printer,
464
+ &old, fp);
465
+ old = false;
466
+ ret += binary__fprintf(tp->bytes + tp->old_len, tp->new_len, 16,
467
+ text_poke_printer, &old, fp);
468
+ return ret;
469
+}
470
+
471
+size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FILE *fp)
1471472 {
1472473 size_t ret = fprintf(fp, "PERF_RECORD_%s",
1473474 perf_event__name(event->header.type));
....@@ -1486,6 +487,9 @@
1486487 case PERF_RECORD_NAMESPACES:
1487488 ret += perf_event__fprintf_namespaces(event, fp);
1488489 break;
490
+ case PERF_RECORD_CGROUP:
491
+ ret += perf_event__fprintf_cgroup(event, fp);
492
+ break;
1489493 case PERF_RECORD_MMAP2:
1490494 ret += perf_event__fprintf_mmap2(event, fp);
1491495 break;
....@@ -1501,6 +505,15 @@
1501505 break;
1502506 case PERF_RECORD_LOST:
1503507 ret += perf_event__fprintf_lost(event, fp);
508
+ break;
509
+ case PERF_RECORD_KSYMBOL:
510
+ ret += perf_event__fprintf_ksymbol(event, fp);
511
+ break;
512
+ case PERF_RECORD_BPF_EVENT:
513
+ ret += perf_event__fprintf_bpf(event, fp);
514
+ break;
515
+ case PERF_RECORD_TEXT_POKE:
516
+ ret += perf_event__fprintf_text_poke(event, machine, fp);
1504517 break;
1505518 default:
1506519 ret += fprintf(fp, "\n");
....@@ -1520,11 +533,11 @@
1520533 struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
1521534 struct addr_location *al)
1522535 {
1523
- struct map_groups *mg = thread->mg;
1524
- struct machine *machine = mg->machine;
536
+ struct maps *maps = thread->maps;
537
+ struct machine *machine = maps->machine;
1525538 bool load_map = false;
1526539
1527
- al->machine = machine;
540
+ al->maps = maps;
1528541 al->thread = thread;
1529542 al->addr = addr;
1530543 al->cpumode = cpumode;
....@@ -1537,13 +550,13 @@
1537550
1538551 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
1539552 al->level = 'k';
1540
- mg = &machine->kmaps;
553
+ al->maps = maps = &machine->kmaps;
1541554 load_map = true;
1542555 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
1543556 al->level = '.';
1544557 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
1545558 al->level = 'g';
1546
- mg = &machine->kmaps;
559
+ al->maps = maps = &machine->kmaps;
1547560 load_map = true;
1548561 } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
1549562 al->level = 'u';
....@@ -1563,7 +576,7 @@
1563576 return NULL;
1564577 }
1565578
1566
- al->map = map_groups__find(mg, al->addr);
579
+ al->map = maps__find(maps, al->addr);
1567580 if (al->map != NULL) {
1568581 /*
1569582 * Kernel maps might be changed when loading symbols so loading
....@@ -1586,7 +599,7 @@
1586599 struct addr_location *al)
1587600 {
1588601 struct map *map = thread__find_map(thread, cpumode, addr, al);
1589
- struct machine *machine = thread->mg->machine;
602
+ struct machine *machine = thread->maps->machine;
1590603 u8 addr_cpumode = machine__addr_cpumode(machine, cpumode, addr);
1591604
1592605 if (map || addr_cpumode == cpumode)
....@@ -1664,10 +677,23 @@
1664677 al->filtered |= (1 << HIST_FILTER__DSO);
1665678 }
1666679
1667
- if (symbol_conf.sym_list &&
1668
- (!al->sym || !strlist__has_entry(symbol_conf.sym_list,
1669
- al->sym->name))) {
1670
- al->filtered |= (1 << HIST_FILTER__SYMBOL);
680
+ if (symbol_conf.sym_list) {
681
+ int ret = 0;
682
+ char al_addr_str[32];
683
+ size_t sz = sizeof(al_addr_str);
684
+
685
+ if (al->sym) {
686
+ ret = strlist__has_entry(symbol_conf.sym_list,
687
+ al->sym->name);
688
+ }
689
+ if (!ret && al->sym) {
690
+ snprintf(al_addr_str, sz, "0x%"PRIx64,
691
+ al->map->unmap_ip(al->map, al->sym->start));
692
+ ret = strlist__has_entry(symbol_conf.sym_list,
693
+ al_addr_str);
694
+ }
695
+ if (!ret)
696
+ al->filtered |= (1 << HIST_FILTER__SYMBOL);
1671697 }
1672698
1673699 return 0;