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 <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Anne Macedo <retpolanne@posteo.net> Cc: Casey Chen <cachen@purestorage.com> Cc: Colin Ian King <colin.i.king@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sun Haiyong <sunhaiyong@loongson.cn> Link: https://lore.kernel.org/r/20240909203740.143492-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
ae39ba1655
commit
d762ba020d
@ -107,6 +107,7 @@ enum build_id_rewrite_style {
|
||||
BID_RWS__NONE = 0,
|
||||
BID_RWS__INJECT_HEADER_LAZY,
|
||||
BID_RWS__INJECT_HEADER_ALL,
|
||||
BID_RWS__MMAP2_BUILDID_ALL,
|
||||
};
|
||||
|
||||
struct perf_inject {
|
||||
@ -146,6 +147,16 @@ static int tool__inject_build_id(const struct perf_tool *tool,
|
||||
__u16 misc,
|
||||
const char *filename,
|
||||
struct dso *dso, u32 flags);
|
||||
static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
const struct evsel *evsel,
|
||||
__u16 misc,
|
||||
__u32 pid, __u32 tid,
|
||||
__u64 start, __u64 len, __u64 pgoff,
|
||||
struct dso *dso,
|
||||
__u32 prot, __u32 flags,
|
||||
const char *filename);
|
||||
|
||||
static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
|
||||
{
|
||||
@ -161,6 +172,7 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
|
||||
|
||||
static int perf_event__repipe_synth(const struct perf_tool *tool,
|
||||
union perf_event *event)
|
||||
|
||||
{
|
||||
struct perf_inject *inject = container_of(tool, struct perf_inject,
|
||||
tool);
|
||||
@ -454,7 +466,9 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
__u32 pid, __u32 tid, __u32 flags,
|
||||
__u32 pid, __u32 tid,
|
||||
__u64 start, __u64 len, __u64 pgoff,
|
||||
__u32 flags, __u32 prot,
|
||||
const char *filename,
|
||||
const struct dso_id *dso_id,
|
||||
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,
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if ((inject->build_id_style == BID_RWS__MMAP2_BUILDID_ALL) &&
|
||||
!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) {
|
||||
struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event);
|
||||
|
||||
if (evsel && !dso_sought) {
|
||||
dso = findnew_dso(pid, tid, filename, dso_id, machine);
|
||||
dso_sought = true;
|
||||
}
|
||||
if (evsel && dso &&
|
||||
!tool__inject_mmap2_build_id(tool, sample, machine, evsel,
|
||||
sample->cpumode | PERF_RECORD_MISC_MMAP_BUILD_ID,
|
||||
pid, tid, start, len, pgoff,
|
||||
dso,
|
||||
prot, flags,
|
||||
filename)) {
|
||||
/* Injected mmap2 so no need to repipe. */
|
||||
dso__put(dso);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dso__put(dso);
|
||||
return perf_event__repipe(tool, event, sample, machine);
|
||||
}
|
||||
@ -536,7 +570,9 @@ static int perf_event__repipe_mmap(const struct perf_tool *tool,
|
||||
{
|
||||
return perf_event__repipe_common_mmap(
|
||||
tool, event, sample, machine,
|
||||
event->mmap.pid, event->mmap.tid, /*flags=*/0,
|
||||
event->mmap.pid, event->mmap.tid,
|
||||
event->mmap.start, event->mmap.len, event->mmap.pgoff,
|
||||
/*flags=*/0, PROT_EXEC,
|
||||
event->mmap.filename, /*dso_id=*/NULL,
|
||||
perf_event__process_mmap);
|
||||
}
|
||||
@ -559,7 +595,9 @@ static int perf_event__repipe_mmap2(const struct perf_tool *tool,
|
||||
|
||||
return perf_event__repipe_common_mmap(
|
||||
tool, event, sample, machine,
|
||||
event->mmap2.pid, event->mmap2.tid, event->mmap2.flags,
|
||||
event->mmap2.pid, event->mmap2.tid,
|
||||
event->mmap2.start, event->mmap2.len, event->mmap2.pgoff,
|
||||
event->mmap2.flags, event->mmap2.prot,
|
||||
event->mmap2.filename, dso_id,
|
||||
perf_event__process_mmap2);
|
||||
}
|
||||
@ -748,6 +786,45 @@ static int tool__inject_build_id(const struct perf_tool *tool,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
const struct evsel *evsel,
|
||||
__u16 misc,
|
||||
__u32 pid, __u32 tid,
|
||||
__u64 start, __u64 len, __u64 pgoff,
|
||||
struct dso *dso,
|
||||
__u32 prot, __u32 flags,
|
||||
const char *filename)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Return to repipe anonymous maps. */
|
||||
if (is_anon_memory(filename) || flags & MAP_HUGETLB)
|
||||
return 1;
|
||||
if (is_no_dso_memory(filename))
|
||||
return 1;
|
||||
|
||||
if (dso__read_build_id(dso)) {
|
||||
pr_debug("no build_id found for %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = perf_event__synthesize_mmap2_build_id(tool, sample, machine,
|
||||
perf_event__repipe,
|
||||
evsel,
|
||||
misc, pid, tid,
|
||||
start, len, pgoff,
|
||||
dso__bid(dso),
|
||||
prot, flags,
|
||||
filename);
|
||||
if (err) {
|
||||
pr_err("Can't synthesize build_id event for %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mark_dso_hit(const struct perf_tool *tool,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
@ -2261,12 +2338,15 @@ int cmd_inject(int argc, const char **argv)
|
||||
const char *known_build_ids = NULL;
|
||||
bool build_ids;
|
||||
bool build_id_all;
|
||||
bool mmap2_build_id_all;
|
||||
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN('b', "build-ids", &build_ids,
|
||||
"Inject build-ids into the output stream"),
|
||||
OPT_BOOLEAN(0, "buildid-all", &build_id_all,
|
||||
"Inject build-ids of all DSOs into the output stream"),
|
||||
OPT_BOOLEAN(0, "mmap2-buildid-all", &mmap2_build_id_all,
|
||||
"Rewrite all mmap events as mmap2 events with build IDs"),
|
||||
OPT_STRING(0, "known-build-ids", &known_build_ids,
|
||||
"buildid path [,buildid path...]",
|
||||
"build-ids to use for given paths"),
|
||||
@ -2363,6 +2443,8 @@ int cmd_inject(int argc, const char **argv)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (mmap2_build_id_all)
|
||||
inject.build_id_style = BID_RWS__MMAP2_BUILDID_ALL;
|
||||
if (build_ids)
|
||||
inject.build_id_style = BID_RWS__INJECT_HEADER_LAZY;
|
||||
if (build_id_all)
|
||||
|
@ -118,6 +118,7 @@ test_inject_bids() {
|
||||
test_record_report
|
||||
test_inject_bids -b
|
||||
test_inject_bids --buildid-all
|
||||
test_inject_bids --mmap2-buildid-all
|
||||
|
||||
cleanup
|
||||
exit $err
|
||||
|
@ -2266,6 +2266,63 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool,
|
||||
|
||||
ev.header.size += ret;
|
||||
}
|
||||
|
||||
return process(tool, &ev, sample, machine);
|
||||
}
|
||||
|
||||
int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
perf_event__handler_t process,
|
||||
const struct evsel *evsel,
|
||||
__u16 misc,
|
||||
__u32 pid, __u32 tid,
|
||||
__u64 start, __u64 len, __u64 pgoff,
|
||||
const struct build_id *bid,
|
||||
__u32 prot, __u32 flags,
|
||||
const char *filename)
|
||||
{
|
||||
union perf_event ev;
|
||||
size_t ev_len;
|
||||
void *array;
|
||||
int ret;
|
||||
|
||||
ev_len = sizeof(ev.mmap2) - sizeof(ev.mmap2.filename) + strlen(filename) + 1;
|
||||
ev_len = PERF_ALIGN(ev_len, sizeof(u64));
|
||||
|
||||
memset(&ev, 0, ev_len);
|
||||
|
||||
ev.mmap2.header.type = PERF_RECORD_MMAP2;
|
||||
ev.mmap2.header.misc = misc | PERF_RECORD_MISC_MMAP_BUILD_ID;
|
||||
ev.mmap2.header.size = ev_len;
|
||||
|
||||
ev.mmap2.pid = pid;
|
||||
ev.mmap2.tid = tid;
|
||||
ev.mmap2.start = start;
|
||||
ev.mmap2.len = len;
|
||||
ev.mmap2.pgoff = pgoff;
|
||||
|
||||
ev.mmap2.build_id_size = min(bid->size, sizeof(ev.mmap2.build_id));
|
||||
memcpy(ev.mmap2.build_id, bid->data, ev.mmap2.build_id_size);
|
||||
|
||||
ev.mmap2.prot = prot;
|
||||
ev.mmap2.flags = flags;
|
||||
|
||||
memcpy(ev.mmap2.filename, filename, min(strlen(filename), sizeof(ev.mmap.filename)));
|
||||
|
||||
array = &ev;
|
||||
array += ev.header.size;
|
||||
ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & 7) {
|
||||
pr_err("Bad id sample size %d\n", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ev.header.size += ret;
|
||||
|
||||
return process(tool, &ev, sample, machine);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,17 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool,
|
||||
__u16 misc,
|
||||
const struct build_id *bid,
|
||||
const char *filename);
|
||||
int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
perf_event__handler_t process,
|
||||
const struct evsel *evsel,
|
||||
__u16 misc,
|
||||
__u32 pid, __u32 tid,
|
||||
__u64 start, __u64 len, __u64 pgoff,
|
||||
const struct build_id *bid,
|
||||
__u32 prot, __u32 flags,
|
||||
const char *filename);
|
||||
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);
|
||||
int perf_event__synthesize_event_update_cpus(const struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);
|
||||
int perf_event__synthesize_event_update_name(const struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);
|
||||
|
Loading…
Reference in New Issue
Block a user