Skip to content

Commit d762ba0

Browse files
captain5050acmel
authored andcommitted
perf inject: Add new mmap2-buildid-all option
Add an option that allows all mmap or mmap2 events to be rewritten as mmap2 events with build IDs. This is similar to the existing -b/--build-ids and --buildid-all options except instead of adding a build_id event an existing mmap/mmap2 event is used as a template and a new mmap2 event synthesized from it. As mmap2 events are typical this avoids the insertion of build_id events. Add test coverage to the pipe test. Signed-off-by: Ian Rogers <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Anne Macedo <[email protected]> Cc: Casey Chen <[email protected]> Cc: Colin Ian King <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Sun Haiyong <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent ae39ba1 commit d762ba0

File tree

4 files changed

+154
-3
lines changed

4 files changed

+154
-3
lines changed

tools/perf/builtin-inject.c

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ enum build_id_rewrite_style {
107107
BID_RWS__NONE = 0,
108108
BID_RWS__INJECT_HEADER_LAZY,
109109
BID_RWS__INJECT_HEADER_ALL,
110+
BID_RWS__MMAP2_BUILDID_ALL,
110111
};
111112

112113
struct perf_inject {
@@ -146,6 +147,16 @@ static int tool__inject_build_id(const struct perf_tool *tool,
146147
__u16 misc,
147148
const char *filename,
148149
struct dso *dso, u32 flags);
150+
static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
151+
struct perf_sample *sample,
152+
struct machine *machine,
153+
const struct evsel *evsel,
154+
__u16 misc,
155+
__u32 pid, __u32 tid,
156+
__u64 start, __u64 len, __u64 pgoff,
157+
struct dso *dso,
158+
__u32 prot, __u32 flags,
159+
const char *filename);
149160

150161
static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
151162
{
@@ -161,6 +172,7 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
161172

162173
static int perf_event__repipe_synth(const struct perf_tool *tool,
163174
union perf_event *event)
175+
164176
{
165177
struct perf_inject *inject = container_of(tool, struct perf_inject,
166178
tool);
@@ -454,7 +466,9 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
454466
union perf_event *event,
455467
struct perf_sample *sample,
456468
struct machine *machine,
457-
__u32 pid, __u32 tid, __u32 flags,
469+
__u32 pid, __u32 tid,
470+
__u64 start, __u64 len, __u64 pgoff,
471+
__u32 flags, __u32 prot,
458472
const char *filename,
459473
const struct dso_id *dso_id,
460474
int (*perf_event_process)(const struct perf_tool *tool,
@@ -525,6 +539,26 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
525539
return err;
526540
}
527541
}
542+
if ((inject->build_id_style == BID_RWS__MMAP2_BUILDID_ALL) &&
543+
!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) {
544+
struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event);
545+
546+
if (evsel && !dso_sought) {
547+
dso = findnew_dso(pid, tid, filename, dso_id, machine);
548+
dso_sought = true;
549+
}
550+
if (evsel && dso &&
551+
!tool__inject_mmap2_build_id(tool, sample, machine, evsel,
552+
sample->cpumode | PERF_RECORD_MISC_MMAP_BUILD_ID,
553+
pid, tid, start, len, pgoff,
554+
dso,
555+
prot, flags,
556+
filename)) {
557+
/* Injected mmap2 so no need to repipe. */
558+
dso__put(dso);
559+
return 0;
560+
}
561+
}
528562
dso__put(dso);
529563
return perf_event__repipe(tool, event, sample, machine);
530564
}
@@ -536,7 +570,9 @@ static int perf_event__repipe_mmap(const struct perf_tool *tool,
536570
{
537571
return perf_event__repipe_common_mmap(
538572
tool, event, sample, machine,
539-
event->mmap.pid, event->mmap.tid, /*flags=*/0,
573+
event->mmap.pid, event->mmap.tid,
574+
event->mmap.start, event->mmap.len, event->mmap.pgoff,
575+
/*flags=*/0, PROT_EXEC,
540576
event->mmap.filename, /*dso_id=*/NULL,
541577
perf_event__process_mmap);
542578
}
@@ -559,7 +595,9 @@ static int perf_event__repipe_mmap2(const struct perf_tool *tool,
559595

560596
return perf_event__repipe_common_mmap(
561597
tool, event, sample, machine,
562-
event->mmap2.pid, event->mmap2.tid, event->mmap2.flags,
598+
event->mmap2.pid, event->mmap2.tid,
599+
event->mmap2.start, event->mmap2.len, event->mmap2.pgoff,
600+
event->mmap2.flags, event->mmap2.prot,
563601
event->mmap2.filename, dso_id,
564602
perf_event__process_mmap2);
565603
}
@@ -748,6 +786,45 @@ static int tool__inject_build_id(const struct perf_tool *tool,
748786
return 0;
749787
}
750788

789+
static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
790+
struct perf_sample *sample,
791+
struct machine *machine,
792+
const struct evsel *evsel,
793+
__u16 misc,
794+
__u32 pid, __u32 tid,
795+
__u64 start, __u64 len, __u64 pgoff,
796+
struct dso *dso,
797+
__u32 prot, __u32 flags,
798+
const char *filename)
799+
{
800+
int err;
801+
802+
/* Return to repipe anonymous maps. */
803+
if (is_anon_memory(filename) || flags & MAP_HUGETLB)
804+
return 1;
805+
if (is_no_dso_memory(filename))
806+
return 1;
807+
808+
if (dso__read_build_id(dso)) {
809+
pr_debug("no build_id found for %s\n", filename);
810+
return -1;
811+
}
812+
813+
err = perf_event__synthesize_mmap2_build_id(tool, sample, machine,
814+
perf_event__repipe,
815+
evsel,
816+
misc, pid, tid,
817+
start, len, pgoff,
818+
dso__bid(dso),
819+
prot, flags,
820+
filename);
821+
if (err) {
822+
pr_err("Can't synthesize build_id event for %s\n", filename);
823+
return -1;
824+
}
825+
return 0;
826+
}
827+
751828
static int mark_dso_hit(const struct perf_tool *tool,
752829
struct perf_sample *sample,
753830
struct machine *machine,
@@ -2261,12 +2338,15 @@ int cmd_inject(int argc, const char **argv)
22612338
const char *known_build_ids = NULL;
22622339
bool build_ids;
22632340
bool build_id_all;
2341+
bool mmap2_build_id_all;
22642342

22652343
struct option options[] = {
22662344
OPT_BOOLEAN('b', "build-ids", &build_ids,
22672345
"Inject build-ids into the output stream"),
22682346
OPT_BOOLEAN(0, "buildid-all", &build_id_all,
22692347
"Inject build-ids of all DSOs into the output stream"),
2348+
OPT_BOOLEAN(0, "mmap2-buildid-all", &mmap2_build_id_all,
2349+
"Rewrite all mmap events as mmap2 events with build IDs"),
22702350
OPT_STRING(0, "known-build-ids", &known_build_ids,
22712351
"buildid path [,buildid path...]",
22722352
"build-ids to use for given paths"),
@@ -2363,6 +2443,8 @@ int cmd_inject(int argc, const char **argv)
23632443
return -1;
23642444
}
23652445
}
2446+
if (mmap2_build_id_all)
2447+
inject.build_id_style = BID_RWS__MMAP2_BUILDID_ALL;
23662448
if (build_ids)
23672449
inject.build_id_style = BID_RWS__INJECT_HEADER_LAZY;
23682450
if (build_id_all)

tools/perf/tests/shell/pipe_test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ test_inject_bids() {
118118
test_record_report
119119
test_inject_bids -b
120120
test_inject_bids --buildid-all
121+
test_inject_bids --mmap2-buildid-all
121122

122123
cleanup
123124
exit $err

tools/perf/util/synthetic-events.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,63 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool,
22662266

22672267
ev.header.size += ret;
22682268
}
2269+
2270+
return process(tool, &ev, sample, machine);
2271+
}
2272+
2273+
int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,
2274+
struct perf_sample *sample,
2275+
struct machine *machine,
2276+
perf_event__handler_t process,
2277+
const struct evsel *evsel,
2278+
__u16 misc,
2279+
__u32 pid, __u32 tid,
2280+
__u64 start, __u64 len, __u64 pgoff,
2281+
const struct build_id *bid,
2282+
__u32 prot, __u32 flags,
2283+
const char *filename)
2284+
{
2285+
union perf_event ev;
2286+
size_t ev_len;
2287+
void *array;
2288+
int ret;
2289+
2290+
ev_len = sizeof(ev.mmap2) - sizeof(ev.mmap2.filename) + strlen(filename) + 1;
2291+
ev_len = PERF_ALIGN(ev_len, sizeof(u64));
2292+
2293+
memset(&ev, 0, ev_len);
2294+
2295+
ev.mmap2.header.type = PERF_RECORD_MMAP2;
2296+
ev.mmap2.header.misc = misc | PERF_RECORD_MISC_MMAP_BUILD_ID;
2297+
ev.mmap2.header.size = ev_len;
2298+
2299+
ev.mmap2.pid = pid;
2300+
ev.mmap2.tid = tid;
2301+
ev.mmap2.start = start;
2302+
ev.mmap2.len = len;
2303+
ev.mmap2.pgoff = pgoff;
2304+
2305+
ev.mmap2.build_id_size = min(bid->size, sizeof(ev.mmap2.build_id));
2306+
memcpy(ev.mmap2.build_id, bid->data, ev.mmap2.build_id_size);
2307+
2308+
ev.mmap2.prot = prot;
2309+
ev.mmap2.flags = flags;
2310+
2311+
memcpy(ev.mmap2.filename, filename, min(strlen(filename), sizeof(ev.mmap.filename)));
2312+
2313+
array = &ev;
2314+
array += ev.header.size;
2315+
ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample);
2316+
if (ret < 0)
2317+
return ret;
2318+
2319+
if (ret & 7) {
2320+
pr_err("Bad id sample size %d\n", ret);
2321+
return -EINVAL;
2322+
}
2323+
2324+
ev.header.size += ret;
2325+
22692326
return process(tool, &ev, sample, machine);
22702327
}
22712328

tools/perf/util/synthetic-events.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool,
5454
__u16 misc,
5555
const struct build_id *bid,
5656
const char *filename);
57+
int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,
58+
struct perf_sample *sample,
59+
struct machine *machine,
60+
perf_event__handler_t process,
61+
const struct evsel *evsel,
62+
__u16 misc,
63+
__u32 pid, __u32 tid,
64+
__u64 start, __u64 len, __u64 pgoff,
65+
const struct build_id *bid,
66+
__u32 prot, __u32 flags,
67+
const char *filename);
5768
int perf_event__synthesize_cpu_map(const struct perf_tool *tool, const struct perf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine);
5869
int perf_event__synthesize_event_update_cpus(const struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);
5970
int perf_event__synthesize_event_update_name(const struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);

0 commit comments

Comments
 (0)