Skip to content

Commit 88a16a1

Browse files
olsajiriAlexei Starovoitov
authored andcommitted
perf: Add build id data in mmap2 event
Adding support to carry build id data in mmap2 event. The build id data replaces maj/min/ino/ino_generation fields, which are also used to identify map's binary, so it's ok to replace them with build id data: union { struct { u32 maj; u32 min; u64 ino; u64 ino_generation; }; struct { u8 build_id_size; u8 __reserved_1; u16 __reserved_2; u8 build_id[20]; }; }; Replaced maj/min/ino/ino_generation fields give us size of 24 bytes. We use 20 bytes for build id data, 1 byte for size and rest is unused. There's new misc bit for mmap2 to signal there's build id data in it: #define PERF_RECORD_MISC_MMAP_BUILD_ID (1 << 14) Signed-off-by: Jiri Olsa <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 921f88f commit 88a16a1

File tree

2 files changed

+65
-9
lines changed

2 files changed

+65
-9
lines changed

include/uapi/linux/perf_event.h

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,8 @@ struct perf_event_attr {
386386
aux_output : 1, /* generate AUX records instead of events */
387387
cgroup : 1, /* include cgroup events */
388388
text_poke : 1, /* include text poke events */
389-
__reserved_1 : 30;
389+
build_id : 1, /* use build id in mmap2 events */
390+
__reserved_1 : 29;
390391

391392
union {
392393
__u32 wakeup_events; /* wakeup every n events */
@@ -659,6 +660,22 @@ struct perf_event_mmap_page {
659660
__u64 aux_size;
660661
};
661662

663+
/*
664+
* The current state of perf_event_header::misc bits usage:
665+
* ('|' used bit, '-' unused bit)
666+
*
667+
* 012 CDEF
668+
* |||---------||||
669+
*
670+
* Where:
671+
* 0-2 CPUMODE_MASK
672+
*
673+
* C PROC_MAP_PARSE_TIMEOUT
674+
* D MMAP_DATA / COMM_EXEC / FORK_EXEC / SWITCH_OUT
675+
* E MMAP_BUILD_ID / EXACT_IP / SCHED_OUT_PREEMPT
676+
* F (reserved)
677+
*/
678+
662679
#define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0)
663680
#define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0)
664681
#define PERF_RECORD_MISC_KERNEL (1 << 0)
@@ -690,6 +707,7 @@ struct perf_event_mmap_page {
690707
*
691708
* PERF_RECORD_MISC_EXACT_IP - PERF_RECORD_SAMPLE of precise events
692709
* PERF_RECORD_MISC_SWITCH_OUT_PREEMPT - PERF_RECORD_SWITCH* events
710+
* PERF_RECORD_MISC_MMAP_BUILD_ID - PERF_RECORD_MMAP2 event
693711
*
694712
*
695713
* PERF_RECORD_MISC_EXACT_IP:
@@ -699,9 +717,13 @@ struct perf_event_mmap_page {
699717
*
700718
* PERF_RECORD_MISC_SWITCH_OUT_PREEMPT:
701719
* Indicates that thread was preempted in TASK_RUNNING state.
720+
*
721+
* PERF_RECORD_MISC_MMAP_BUILD_ID:
722+
* Indicates that mmap2 event carries build id data.
702723
*/
703724
#define PERF_RECORD_MISC_EXACT_IP (1 << 14)
704725
#define PERF_RECORD_MISC_SWITCH_OUT_PREEMPT (1 << 14)
726+
#define PERF_RECORD_MISC_MMAP_BUILD_ID (1 << 14)
705727
/*
706728
* Reserve the last bit to indicate some extended misc field
707729
*/
@@ -915,10 +937,20 @@ enum perf_event_type {
915937
* u64 addr;
916938
* u64 len;
917939
* u64 pgoff;
918-
* u32 maj;
919-
* u32 min;
920-
* u64 ino;
921-
* u64 ino_generation;
940+
* union {
941+
* struct {
942+
* u32 maj;
943+
* u32 min;
944+
* u64 ino;
945+
* u64 ino_generation;
946+
* };
947+
* struct {
948+
* u8 build_id_size;
949+
* u8 __reserved_1;
950+
* u16 __reserved_2;
951+
* u8 build_id[20];
952+
* };
953+
* };
922954
* u32 prot, flags;
923955
* char filename[];
924956
* struct sample_id sample_id;

kernel/events/core.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <linux/min_heap.h>
5454
#include <linux/highmem.h>
5555
#include <linux/pgtable.h>
56+
#include <linux/buildid.h>
5657

5758
#include "internal.h"
5859

@@ -397,6 +398,7 @@ static atomic_t nr_ksymbol_events __read_mostly;
397398
static atomic_t nr_bpf_events __read_mostly;
398399
static atomic_t nr_cgroup_events __read_mostly;
399400
static atomic_t nr_text_poke_events __read_mostly;
401+
static atomic_t nr_build_id_events __read_mostly;
400402

401403
static LIST_HEAD(pmus);
402404
static DEFINE_MUTEX(pmus_lock);
@@ -4673,6 +4675,8 @@ static void unaccount_event(struct perf_event *event)
46734675
dec = true;
46744676
if (event->attr.mmap || event->attr.mmap_data)
46754677
atomic_dec(&nr_mmap_events);
4678+
if (event->attr.build_id)
4679+
atomic_dec(&nr_build_id_events);
46764680
if (event->attr.comm)
46774681
atomic_dec(&nr_comm_events);
46784682
if (event->attr.namespaces)
@@ -8046,6 +8050,8 @@ struct perf_mmap_event {
80468050
u64 ino;
80478051
u64 ino_generation;
80488052
u32 prot, flags;
8053+
u8 build_id[BUILD_ID_SIZE_MAX];
8054+
u32 build_id_size;
80498055

80508056
struct {
80518057
struct perf_event_header header;
@@ -8077,6 +8083,7 @@ static void perf_event_mmap_output(struct perf_event *event,
80778083
struct perf_sample_data sample;
80788084
int size = mmap_event->event_id.header.size;
80798085
u32 type = mmap_event->event_id.header.type;
8086+
bool use_build_id;
80808087
int ret;
80818088

80828089
if (!perf_event_mmap_match(event, data))
@@ -8101,13 +8108,25 @@ static void perf_event_mmap_output(struct perf_event *event,
81018108
mmap_event->event_id.pid = perf_event_pid(event, current);
81028109
mmap_event->event_id.tid = perf_event_tid(event, current);
81038110

8111+
use_build_id = event->attr.build_id && mmap_event->build_id_size;
8112+
8113+
if (event->attr.mmap2 && use_build_id)
8114+
mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_BUILD_ID;
8115+
81048116
perf_output_put(&handle, mmap_event->event_id);
81058117

81068118
if (event->attr.mmap2) {
8107-
perf_output_put(&handle, mmap_event->maj);
8108-
perf_output_put(&handle, mmap_event->min);
8109-
perf_output_put(&handle, mmap_event->ino);
8110-
perf_output_put(&handle, mmap_event->ino_generation);
8119+
if (use_build_id) {
8120+
u8 size[4] = { (u8) mmap_event->build_id_size, 0, 0, 0 };
8121+
8122+
__output_copy(&handle, size, 4);
8123+
__output_copy(&handle, mmap_event->build_id, BUILD_ID_SIZE_MAX);
8124+
} else {
8125+
perf_output_put(&handle, mmap_event->maj);
8126+
perf_output_put(&handle, mmap_event->min);
8127+
perf_output_put(&handle, mmap_event->ino);
8128+
perf_output_put(&handle, mmap_event->ino_generation);
8129+
}
81118130
perf_output_put(&handle, mmap_event->prot);
81128131
perf_output_put(&handle, mmap_event->flags);
81138132
}
@@ -8236,6 +8255,9 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
82368255

82378256
mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
82388257

8258+
if (atomic_read(&nr_build_id_events))
8259+
build_id_parse(vma, mmap_event->build_id, &mmap_event->build_id_size);
8260+
82398261
perf_iterate_sb(perf_event_mmap_output,
82408262
mmap_event,
82418263
NULL);
@@ -11172,6 +11194,8 @@ static void account_event(struct perf_event *event)
1117211194
inc = true;
1117311195
if (event->attr.mmap || event->attr.mmap_data)
1117411196
atomic_inc(&nr_mmap_events);
11197+
if (event->attr.build_id)
11198+
atomic_inc(&nr_build_id_events);
1117511199
if (event->attr.comm)
1117611200
atomic_inc(&nr_comm_events);
1117711201
if (event->attr.namespaces)

0 commit comments

Comments
 (0)