Blame view
tools/perf/builtin-inject.c
25.1 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
454c407ec perf: add perf-in... |
2 3 4 5 6 7 8 9 |
/* * builtin-inject.c * * Builtin inject command: Examine the live mode (stdin) event stream * and repipe it to stdout while optionally injecting additional * events into it. */ #include "builtin.h" |
26a031e13 perf inject: Merg... |
10 |
#include "util/color.h" |
4a3cec849 perf dsos: Move t... |
11 |
#include "util/dso.h" |
27c9c3424 perf inject: Add ... |
12 |
#include "util/vdso.h" |
26a031e13 perf inject: Merg... |
13 14 |
#include "util/evlist.h" #include "util/evsel.h" |
1101f69af pref tools: Add m... |
15 |
#include "util/map.h" |
454c407ec perf: add perf-in... |
16 |
#include "util/session.h" |
45694aa77 perf tools: Renam... |
17 |
#include "util/tool.h" |
454c407ec perf: add perf-in... |
18 |
#include "util/debug.h" |
54a3cf59b perf inject: Mark... |
19 |
#include "util/build-id.h" |
f5fc14124 perf tools: Add d... |
20 |
#include "util/data.h" |
0f0aa5e06 perf inject: Add ... |
21 |
#include "util/auxtrace.h" |
9b07e27f8 perf inject: Add ... |
22 |
#include "util/jit.h" |
daecf9e0f perf tools: Add m... |
23 |
#include "util/symbol.h" |
ea49e01cf perf tools: Move ... |
24 |
#include "util/synthetic-events.h" |
e7ff8920e perf tools: Use j... |
25 |
#include "util/thread.h" |
336c95b29 perf inject: Ente... |
26 |
#include "util/namespaces.h" |
454c407ec perf: add perf-in... |
27 |
|
e7b60c5a0 perf inject: Do n... |
28 |
#include <linux/err.h> |
4b6ab94ea perf subcmd: Crea... |
29 |
#include <subcmd/parse-options.h> |
e7b60c5a0 perf inject: Do n... |
30 |
#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ |
454c407ec perf: add perf-in... |
31 |
|
26a031e13 perf inject: Merg... |
32 |
#include <linux/list.h> |
a43783aee perf tools: Inclu... |
33 |
#include <errno.h> |
9607ad3a6 perf tools: Add s... |
34 |
#include <signal.h> |
26a031e13 perf inject: Merg... |
35 |
|
5ded57ac1 perf inject: Remo... |
36 |
struct perf_inject { |
3406912cc perf inject: Hand... |
37 |
struct perf_tool tool; |
1cb8bdcca perf inject: Move... |
38 |
struct perf_session *session; |
3406912cc perf inject: Hand... |
39 |
bool build_ids; |
27c9c3424 perf inject: Add ... |
40 |
bool build_id_all; |
3406912cc perf inject: Hand... |
41 |
bool sched_stat; |
cd10b2895 perf tools: Hit a... |
42 |
bool have_auxtrace; |
f56fb9864 perf inject: Add ... |
43 |
bool strip; |
9b07e27f8 perf inject: Add ... |
44 |
bool jit_mode; |
3406912cc perf inject: Hand... |
45 |
const char *input_name; |
8ceb41d7e perf tools: Renam... |
46 |
struct perf_data output; |
3406912cc perf inject: Hand... |
47 |
u64 bytes_written; |
73117308f perf inject: Remo... |
48 |
u64 aux_id; |
3406912cc perf inject: Hand... |
49 |
struct list_head samples; |
0f0aa5e06 perf inject: Add ... |
50 |
struct itrace_synth_opts itrace_synth_opts; |
ba2675bf1 perf inject: Cut ... |
51 |
char event_copy[PERF_SAMPLE_MAX_SIZE]; |
26a031e13 perf inject: Merg... |
52 53 54 55 56 |
}; struct event_entry { struct list_head node; u32 tid; |
6549a8c0c perf tools: Repla... |
57 |
union perf_event event[]; |
5ded57ac1 perf inject: Remo... |
58 |
}; |
454c407ec perf: add perf-in... |
59 |
|
27c9c3424 perf inject: Add ... |
60 61 |
static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool, struct machine *machine, u8 cpumode, u32 flags); |
cd17a9b54 perf inject: Re-p... |
62 |
static int output_bytes(struct perf_inject *inject, void *buf, size_t sz) |
454c407ec perf: add perf-in... |
63 |
{ |
3406912cc perf inject: Hand... |
64 |
ssize_t size; |
454c407ec perf: add perf-in... |
65 |
|
8ceb41d7e perf tools: Renam... |
66 |
size = perf_data__write(&inject->output, buf, sz); |
3406912cc perf inject: Hand... |
67 68 |
if (size < 0) return -errno; |
454c407ec perf: add perf-in... |
69 |
|
3406912cc perf inject: Hand... |
70 |
inject->bytes_written += size; |
454c407ec perf: add perf-in... |
71 72 |
return 0; } |
cd17a9b54 perf inject: Re-p... |
73 74 75 76 77 78 79 80 |
static int perf_event__repipe_synth(struct perf_tool *tool, union perf_event *event) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); return output_bytes(inject, event, event->header.size); } |
d704ebdae perf tools: tool-... |
81 82 83 84 85 86 |
static int perf_event__repipe_oe_synth(struct perf_tool *tool, union perf_event *event, struct ordered_events *oe __maybe_unused) { return perf_event__repipe_synth(tool, event); } |
e12b202f8 perf jitdump: Bui... |
87 |
#ifdef HAVE_JITDUMP |
9b07e27f8 perf inject: Add ... |
88 89 90 91 92 93 94 |
static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct ordered_events *oe __maybe_unused) { return 0; } #endif |
89f1688a5 perf tools: Remov... |
95 96 |
static int perf_event__repipe_op2_synth(struct perf_session *session, union perf_event *event) |
743eb8686 perf tools: Resol... |
97 |
{ |
89f1688a5 perf tools: Remov... |
98 |
return perf_event__repipe_synth(session->tool, event); |
743eb8686 perf tools: Resol... |
99 |
} |
2946ecedd perf inject: Add ... |
100 101 102 103 104 105 |
static int perf_event__repipe_op4_synth(struct perf_session *session, union perf_event *event, u64 data __maybe_unused) { return perf_event__repipe_synth(session->tool, event); } |
47c3d1091 perf tools: Fix m... |
106 107 |
static int perf_event__repipe_attr(struct perf_tool *tool, union perf_event *event, |
63503dba8 perf evlist: Rena... |
108 |
struct evlist **pevlist) |
10d0f086d perf event: perf_... |
109 |
{ |
89c97d936 perf inject: Do n... |
110 111 |
struct perf_inject *inject = container_of(tool, struct perf_inject, tool); |
1a1ed1ba6 perf inject: Fix ... |
112 |
int ret; |
47c3d1091 perf tools: Fix m... |
113 114 |
ret = perf_event__process_attr(tool, event, pevlist); |
1a1ed1ba6 perf inject: Fix ... |
115 116 |
if (ret) return ret; |
a261e4a09 perf tools: Fix p... |
117 |
if (!inject->output.is_pipe) |
89c97d936 perf inject: Do n... |
118 |
return 0; |
47c3d1091 perf tools: Fix m... |
119 |
return perf_event__repipe_synth(tool, event); |
10d0f086d perf event: perf_... |
120 |
} |
2946ecedd perf inject: Add ... |
121 122 123 124 125 126 |
static int perf_event__repipe_event_update(struct perf_tool *tool, union perf_event *event, struct evlist **pevlist __maybe_unused) { return perf_event__repipe_synth(tool, event); } |
e31f0d017 perf tools: Add b... |
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
#ifdef HAVE_AUXTRACE_SUPPORT static int copy_bytes(struct perf_inject *inject, int fd, off_t size) { char buf[4096]; ssize_t ssz; int ret; while (size > 0) { ssz = read(fd, buf, min(size, (off_t)sizeof(buf))); if (ssz < 0) return -errno; ret = output_bytes(inject, buf, ssz); if (ret) return ret; size -= ssz; } return 0; } |
7336555a6 perf tools: Remov... |
147 148 |
static s64 perf_event__repipe_auxtrace(struct perf_session *session, union perf_event *event) |
cd17a9b54 perf inject: Re-p... |
149 |
{ |
7336555a6 perf tools: Remov... |
150 |
struct perf_tool *tool = session->tool; |
cd17a9b54 perf inject: Re-p... |
151 152 153 |
struct perf_inject *inject = container_of(tool, struct perf_inject, tool); int ret; |
cd10b2895 perf tools: Hit a... |
154 |
inject->have_auxtrace = true; |
99fa29845 perf tools: Add A... |
155 156 |
if (!inject->output.is_pipe) { off_t offset; |
eae8ad804 perf tools: Add s... |
157 |
offset = lseek(inject->output.file.fd, 0, SEEK_CUR); |
99fa29845 perf tools: Add A... |
158 159 160 161 162 163 164 |
if (offset == -1) return -errno; ret = auxtrace_index__auxtrace_event(&session->auxtrace_index, event, offset); if (ret < 0) return ret; } |
8ceb41d7e perf tools: Renam... |
165 |
if (perf_data__is_pipe(session->data) || !session->one_mmap) { |
cd17a9b54 perf inject: Re-p... |
166 167 168 |
ret = output_bytes(inject, event, event->header.size); if (ret < 0) return ret; |
8ceb41d7e perf tools: Renam... |
169 |
ret = copy_bytes(inject, perf_data__fd(session->data), |
cd17a9b54 perf inject: Re-p... |
170 171 172 173 174 175 176 177 178 179 |
event->auxtrace.size); } else { ret = output_bytes(inject, event, event->header.size + event->auxtrace.size); } if (ret < 0) return ret; return event->auxtrace.size; } |
e31f0d017 perf tools: Add b... |
180 181 182 |
#else static s64 |
7336555a6 perf tools: Remov... |
183 184 |
perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused) |
e31f0d017 perf tools: Add b... |
185 186 187 188 189 190 191 |
{ pr_err("AUX area tracing not supported "); return -EINVAL; } #endif |
45694aa77 perf tools: Renam... |
192 |
static int perf_event__repipe(struct perf_tool *tool, |
d20deb64e perf tools: Pass ... |
193 |
union perf_event *event, |
1d037ca16 perf tools: Use _... |
194 |
struct perf_sample *sample __maybe_unused, |
63c2c9f8f perf inject: Remo... |
195 |
struct machine *machine __maybe_unused) |
640c03ce8 perf session: Par... |
196 |
{ |
63c2c9f8f perf inject: Remo... |
197 |
return perf_event__repipe_synth(tool, event); |
640c03ce8 perf session: Par... |
198 |
} |
f56fb9864 perf inject: Add ... |
199 200 201 202 203 204 205 |
static int perf_event__drop(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { return 0; } |
73117308f perf inject: Remo... |
206 207 208 209 210 211 212 213 214 215 216 217 |
static int perf_event__drop_aux(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, struct machine *machine __maybe_unused) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); if (!inject->aux_id) inject->aux_id = sample->id; return 0; } |
ba2675bf1 perf inject: Cut ... |
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
static union perf_event * perf_inject__cut_auxtrace_sample(struct perf_inject *inject, union perf_event *event, struct perf_sample *sample) { size_t sz1 = sample->aux_sample.data - (void *)event; size_t sz2 = event->header.size - sample->aux_sample.size - sz1; union perf_event *ev = (union perf_event *)inject->event_copy; if (sz1 > event->header.size || sz2 > event->header.size || sz1 + sz2 > event->header.size || sz1 < sizeof(struct perf_event_header) + sizeof(u64)) return event; memcpy(ev, event, sz1); memcpy((void *)ev + sz1, (void *)event + event->header.size - sz2, sz2); ev->header.size = sz1 + sz2; ((u64 *)((void *)ev + sz1))[-1] = 0; return ev; } |
26a031e13 perf inject: Merg... |
239 240 241 |
typedef int (*inject_handler)(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, |
32dcd021d perf evsel: Renam... |
242 |
struct evsel *evsel, |
26a031e13 perf inject: Merg... |
243 |
struct machine *machine); |
45694aa77 perf tools: Renam... |
244 |
static int perf_event__repipe_sample(struct perf_tool *tool, |
d20deb64e perf tools: Pass ... |
245 |
union perf_event *event, |
26a031e13 perf inject: Merg... |
246 |
struct perf_sample *sample, |
32dcd021d perf evsel: Renam... |
247 |
struct evsel *evsel, |
26a031e13 perf inject: Merg... |
248 |
struct machine *machine) |
9e69c2108 perf session: Pas... |
249 |
{ |
ba2675bf1 perf inject: Cut ... |
250 251 |
struct perf_inject *inject = container_of(tool, struct perf_inject, tool); |
40978e9bf perf inject: The ... |
252 |
if (evsel && evsel->handler) { |
744a97194 perf evsel: Ditch... |
253 |
inject_handler f = evsel->handler; |
26a031e13 perf inject: Merg... |
254 255 |
return f(tool, event, sample, evsel, machine); } |
54a3cf59b perf inject: Mark... |
256 |
build_id__mark_dso_hit(tool, event, sample, evsel, machine); |
ba2675bf1 perf inject: Cut ... |
257 258 |
if (inject->itrace_synth_opts.set && sample->aux_sample.size) event = perf_inject__cut_auxtrace_sample(inject, event, sample); |
63c2c9f8f perf inject: Remo... |
259 |
return perf_event__repipe_synth(tool, event); |
9e69c2108 perf session: Pas... |
260 |
} |
45694aa77 perf tools: Renam... |
261 |
static int perf_event__repipe_mmap(struct perf_tool *tool, |
d20deb64e perf tools: Pass ... |
262 |
union perf_event *event, |
8115d60c3 perf tools: Kill ... |
263 |
struct perf_sample *sample, |
743eb8686 perf tools: Resol... |
264 |
struct machine *machine) |
454c407ec perf: add perf-in... |
265 266 |
{ int err; |
45694aa77 perf tools: Renam... |
267 268 |
err = perf_event__process_mmap(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine); |
454c407ec perf: add perf-in... |
269 270 271 |
return err; } |
e12b202f8 perf jitdump: Bui... |
272 |
#ifdef HAVE_JITDUMP |
9b07e27f8 perf inject: Add ... |
273 274 275 276 277 278 279 |
static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); u64 n = 0; |
570735b33 perf jit: Let jit... |
280 |
int ret; |
9b07e27f8 perf inject: Add ... |
281 282 283 284 |
/* * if jit marker, then inject jit mmaps and generate ELF images */ |
570735b33 perf jit: Let jit... |
285 |
ret = jit_process(inject->session, &inject->output, machine, |
c8f6ae1fb perf inject jit: ... |
286 |
event->mmap.filename, event->mmap.pid, &n); |
570735b33 perf jit: Let jit... |
287 288 289 |
if (ret < 0) return ret; if (ret) { |
9b07e27f8 perf inject: Add ... |
290 291 292 293 294 295 |
inject->bytes_written += n; return 0; } return perf_event__repipe_mmap(tool, event, sample, machine); } #endif |
27c9c3424 perf inject: Add ... |
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
static struct dso *findnew_dso(int pid, int tid, const char *filename, struct dso_id *id, struct machine *machine) { struct thread *thread; struct nsinfo *nsi = NULL; struct nsinfo *nnsi; struct dso *dso; bool vdso; thread = machine__findnew_thread(machine, pid, tid); if (thread == NULL) { pr_err("cannot find or create a task %d/%d. ", tid, pid); return NULL; } vdso = is_vdso_map(filename); nsi = nsinfo__get(thread->nsinfo); if (vdso) { /* The vdso maps are always on the host and not the * container. Ensure that we don't use setns to look * them up. */ nnsi = nsinfo__copy(nsi); if (nnsi) { nsinfo__put(nsi); nnsi->need_setns = false; nsi = nnsi; } dso = machine__findnew_vdso(machine, thread); } else { dso = machine__findnew_dso_id(machine, filename, id); } if (dso) dso->nsinfo = nsi; else nsinfo__put(nsi); thread__put(thread); return dso; } static int perf_event__repipe_buildid_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { struct dso *dso; dso = findnew_dso(event->mmap.pid, event->mmap.tid, event->mmap.filename, NULL, machine); if (dso && !dso->hit) { dso->hit = 1; dso__inject_build_id(dso, tool, machine, sample->cpumode, 0); dso__put(dso); } return perf_event__repipe(tool, event, sample, machine); } |
5c5e854bc perf tools: Add a... |
358 359 360 361 362 363 364 365 366 367 368 369 |
static int perf_event__repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { int err; err = perf_event__process_mmap2(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine); return err; } |
e12b202f8 perf jitdump: Bui... |
370 |
#ifdef HAVE_JITDUMP |
9b07e27f8 perf inject: Add ... |
371 372 373 374 375 376 377 |
static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); u64 n = 0; |
570735b33 perf jit: Let jit... |
378 |
int ret; |
9b07e27f8 perf inject: Add ... |
379 380 381 382 |
/* * if jit marker, then inject jit mmaps and generate ELF images */ |
570735b33 perf jit: Let jit... |
383 |
ret = jit_process(inject->session, &inject->output, machine, |
c8f6ae1fb perf inject jit: ... |
384 |
event->mmap2.filename, event->mmap2.pid, &n); |
570735b33 perf jit: Let jit... |
385 386 387 |
if (ret < 0) return ret; if (ret) { |
9b07e27f8 perf inject: Add ... |
388 389 390 391 392 393 |
inject->bytes_written += n; return 0; } return perf_event__repipe_mmap2(tool, event, sample, machine); } #endif |
27c9c3424 perf inject: Add ... |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
static int perf_event__repipe_buildid_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { struct dso_id dso_id = { .maj = event->mmap2.maj, .min = event->mmap2.min, .ino = event->mmap2.ino, .ino_generation = event->mmap2.ino_generation, }; struct dso *dso; dso = findnew_dso(event->mmap2.pid, event->mmap2.tid, event->mmap2.filename, &dso_id, machine); if (dso && !dso->hit) { dso->hit = 1; dso__inject_build_id(dso, tool, machine, sample->cpumode, event->mmap2.flags); dso__put(dso); } perf_event__repipe(tool, event, sample, machine); return 0; } |
f62d3f0f4 perf event: No ne... |
421 |
static int perf_event__repipe_fork(struct perf_tool *tool, |
d20deb64e perf tools: Pass ... |
422 |
union perf_event *event, |
8115d60c3 perf tools: Kill ... |
423 |
struct perf_sample *sample, |
743eb8686 perf tools: Resol... |
424 |
struct machine *machine) |
454c407ec perf: add perf-in... |
425 426 |
{ int err; |
f62d3f0f4 perf event: No ne... |
427 |
err = perf_event__process_fork(tool, event, sample, machine); |
45694aa77 perf tools: Renam... |
428 |
perf_event__repipe(tool, event, sample, machine); |
454c407ec perf: add perf-in... |
429 430 431 |
return err; } |
0f0aa5e06 perf inject: Add ... |
432 433 434 435 436 437 438 439 440 441 442 443 |
static int perf_event__repipe_comm(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { int err; err = perf_event__process_comm(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine); return err; } |
f3b3614a2 perf tools: Add P... |
444 445 446 447 448 449 450 451 452 453 454 |
static int perf_event__repipe_namespaces(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { int err = perf_event__process_namespaces(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine); return err; } |
0f0aa5e06 perf inject: Add ... |
455 456 457 458 459 460 461 462 463 464 465 466 |
static int perf_event__repipe_exit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine) { int err; err = perf_event__process_exit(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine); return err; } |
89f1688a5 perf tools: Remov... |
467 468 |
static int perf_event__repipe_tracing_data(struct perf_session *session, union perf_event *event) |
454c407ec perf: add perf-in... |
469 470 |
{ int err; |
89f1688a5 perf tools: Remov... |
471 472 |
perf_event__repipe_synth(session->tool, event); err = perf_event__process_tracing_data(session, event); |
454c407ec perf: add perf-in... |
473 474 475 |
return err; } |
c824c4338 perf tools: Stop ... |
476 |
static int dso__read_build_id(struct dso *dso) |
454c407ec perf: add perf-in... |
477 |
{ |
336c95b29 perf inject: Ente... |
478 |
struct nscookie nsc; |
c824c4338 perf tools: Stop ... |
479 |
if (dso->has_build_id) |
090f7204d perf inject: Refa... |
480 |
return 0; |
454c407ec perf: add perf-in... |
481 |
|
336c95b29 perf inject: Ente... |
482 |
nsinfo__mountns_enter(dso->nsinfo, &nsc); |
f766819cd perf tools: Pass ... |
483 |
if (filename__read_build_id(dso->long_name, &dso->bid) > 0) |
c824c4338 perf tools: Stop ... |
484 |
dso->has_build_id = true; |
336c95b29 perf inject: Ente... |
485 |
nsinfo__mountns_exit(&nsc); |
454c407ec perf: add perf-in... |
486 |
|
336c95b29 perf inject: Ente... |
487 |
return dso->has_build_id ? 0 : -1; |
090f7204d perf inject: Refa... |
488 |
} |
454c407ec perf: add perf-in... |
489 |
|
c824c4338 perf tools: Stop ... |
490 |
static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool, |
e7b60c5a0 perf inject: Do n... |
491 |
struct machine *machine, u8 cpumode, u32 flags) |
090f7204d perf inject: Refa... |
492 |
{ |
090f7204d perf inject: Refa... |
493 |
int err; |
454c407ec perf: add perf-in... |
494 |
|
e7b60c5a0 perf inject: Do n... |
495 496 497 498 |
if (is_anon_memory(dso->long_name) || flags & MAP_HUGETLB) return 0; if (is_no_dso_memory(dso->long_name)) return 0; |
c824c4338 perf tools: Stop ... |
499 500 501 |
if (dso__read_build_id(dso) < 0) { pr_debug("no build_id found for %s ", dso->long_name); |
090f7204d perf inject: Refa... |
502 503 |
return -1; } |
454c407ec perf: add perf-in... |
504 |
|
e7b60c5a0 perf inject: Do n... |
505 506 |
err = perf_event__synthesize_build_id(tool, dso, cpumode, perf_event__repipe, machine); |
090f7204d perf inject: Refa... |
507 |
if (err) { |
c824c4338 perf tools: Stop ... |
508 509 |
pr_err("Can't synthesize build_id event for %s ", dso->long_name); |
454c407ec perf: add perf-in... |
510 511 512 513 514 |
return -1; } return 0; } |
0bf02a0d8 perf bench: Add b... |
515 516 517 518 |
int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct evsel *evsel __maybe_unused, struct machine *machine) |
454c407ec perf: add perf-in... |
519 520 521 |
{ struct addr_location al; struct thread *thread; |
454c407ec perf: add perf-in... |
522 |
|
13ce34df1 perf tools: Use t... |
523 |
thread = machine__findnew_thread(machine, sample->pid, sample->tid); |
454c407ec perf: add perf-in... |
524 525 526 527 |
if (thread == NULL) { pr_err("problem processing %d event, skipping it. ", event->header.type); |
454c407ec perf: add perf-in... |
528 529 |
goto repipe; } |
71a84b5ae perf thread: Make... |
530 |
if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) { |
454c407ec perf: add perf-in... |
531 532 |
if (!al.map->dso->hit) { al.map->dso->hit = 1; |
e7b60c5a0 perf inject: Do n... |
533 534 |
dso__inject_build_id(al.map->dso, tool, machine, sample->cpumode, al.map->flags); |
454c407ec perf: add perf-in... |
535 536 |
} } |
b91fc39f4 perf machine: Pro... |
537 |
thread__put(thread); |
454c407ec perf: add perf-in... |
538 |
repipe: |
45694aa77 perf tools: Renam... |
539 |
perf_event__repipe(tool, event, sample, machine); |
090f7204d perf inject: Refa... |
540 |
return 0; |
454c407ec perf: add perf-in... |
541 |
} |
26a031e13 perf inject: Merg... |
542 543 544 |
static int perf_inject__sched_process_exit(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, |
32dcd021d perf evsel: Renam... |
545 |
struct evsel *evsel __maybe_unused, |
26a031e13 perf inject: Merg... |
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
struct machine *machine __maybe_unused) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); struct event_entry *ent; list_for_each_entry(ent, &inject->samples, node) { if (sample->tid == ent->tid) { list_del_init(&ent->node); free(ent); break; } } return 0; } static int perf_inject__sched_switch(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, |
32dcd021d perf evsel: Renam... |
565 |
struct evsel *evsel, |
26a031e13 perf inject: Merg... |
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
struct machine *machine) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); struct event_entry *ent; perf_inject__sched_process_exit(tool, event, sample, evsel, machine); ent = malloc(event->header.size + sizeof(struct event_entry)); if (ent == NULL) { color_fprintf(stderr, PERF_COLOR_RED, "Not enough memory to process sched switch event!"); return -1; } ent->tid = sample->tid; memcpy(&ent->event, event, event->header.size); list_add(&ent->node, &inject->samples); return 0; } static int perf_inject__sched_stat(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, |
32dcd021d perf evsel: Renam... |
589 |
struct evsel *evsel, |
26a031e13 perf inject: Merg... |
590 591 592 593 594 595 |
struct machine *machine) { struct event_entry *ent; union perf_event *event_sw; struct perf_sample sample_sw; struct perf_inject *inject = container_of(tool, struct perf_inject, tool); |
efc0cdc9e perf evsel: Renam... |
596 |
u32 pid = evsel__intval(evsel, sample, "pid"); |
26a031e13 perf inject: Merg... |
597 598 599 600 601 602 603 604 605 |
list_for_each_entry(ent, &inject->samples, node) { if (pid == ent->tid) goto found; } return 0; found: event_sw = &ent->event[0]; |
6b6017a20 perf evsel: Renam... |
606 |
evsel__parse_sample(evsel, event_sw, &sample_sw); |
26a031e13 perf inject: Merg... |
607 608 609 |
sample_sw.period = sample->period; sample_sw.time = sample->time; |
1fc632cef libperf: Move per... |
610 611 |
perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type, evsel->core.attr.read_format, &sample_sw); |
54a3cf59b perf inject: Mark... |
612 |
build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); |
26a031e13 perf inject: Merg... |
613 614 |
return perf_event__repipe(tool, event_sw, &sample_sw, machine); } |
1d037ca16 perf tools: Use _... |
615 |
static void sig_handler(int sig __maybe_unused) |
454c407ec perf: add perf-in... |
616 617 618 |
{ session_done = 1; } |
b14b36d02 perf inject: Rena... |
619 |
static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg) |
26a031e13 perf inject: Merg... |
620 |
{ |
1fc632cef libperf: Move per... |
621 |
struct perf_event_attr *attr = &evsel->core.attr; |
8ab2e96d8 perf evsel: Renam... |
622 |
const char *name = evsel__name(evsel); |
26a031e13 perf inject: Merg... |
623 624 625 626 627 628 629 630 631 |
if (!(attr->sample_type & sample_type)) { pr_err("Samples for %s event do not have %s attribute set.", name, sample_msg); return -EINVAL; } return 0; } |
f56fb9864 perf inject: Add ... |
632 633 634 |
static int drop_sample(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, |
32dcd021d perf evsel: Renam... |
635 |
struct evsel *evsel __maybe_unused, |
f56fb9864 perf inject: Add ... |
636 637 638 639 640 641 642 |
struct machine *machine __maybe_unused) { return 0; } static void strip_init(struct perf_inject *inject) { |
63503dba8 perf evlist: Rena... |
643 |
struct evlist *evlist = inject->session->evlist; |
32dcd021d perf evsel: Renam... |
644 |
struct evsel *evsel; |
f56fb9864 perf inject: Add ... |
645 646 |
inject->tool.context_switch = perf_event__drop; |
e5cadb93d perf evlist: Rena... |
647 |
evlist__for_each_entry(evlist, evsel) |
f56fb9864 perf inject: Add ... |
648 649 |
evsel->handler = drop_sample; } |
5ded57ac1 perf inject: Remo... |
650 |
static int __cmd_inject(struct perf_inject *inject) |
454c407ec perf: add perf-in... |
651 |
{ |
454c407ec perf: add perf-in... |
652 |
int ret = -EINVAL; |
1cb8bdcca perf inject: Move... |
653 |
struct perf_session *session = inject->session; |
8ceb41d7e perf tools: Renam... |
654 655 |
struct perf_data *data_out = &inject->output; int fd = perf_data__fd(data_out); |
0f0aa5e06 perf inject: Add ... |
656 |
u64 output_data_offset; |
454c407ec perf: add perf-in... |
657 658 |
signal(SIGINT, sig_handler); |
0f0aa5e06 perf inject: Add ... |
659 |
if (inject->build_ids || inject->sched_stat || |
27c9c3424 perf inject: Add ... |
660 |
inject->itrace_synth_opts.set || inject->build_id_all) { |
5ded57ac1 perf inject: Remo... |
661 |
inject->tool.mmap = perf_event__repipe_mmap; |
5c5e854bc perf tools: Add a... |
662 |
inject->tool.mmap2 = perf_event__repipe_mmap2; |
f62d3f0f4 perf event: No ne... |
663 |
inject->tool.fork = perf_event__repipe_fork; |
5ded57ac1 perf inject: Remo... |
664 |
inject->tool.tracing_data = perf_event__repipe_tracing_data; |
454c407ec perf: add perf-in... |
665 |
} |
0f0aa5e06 perf inject: Add ... |
666 |
output_data_offset = session->header.data_offset; |
27c9c3424 perf inject: Add ... |
667 668 669 670 |
if (inject->build_id_all) { inject->tool.mmap = perf_event__repipe_buildid_mmap; inject->tool.mmap2 = perf_event__repipe_buildid_mmap2; } else if (inject->build_ids) { |
54a3cf59b perf inject: Mark... |
671 672 |
inject->tool.sample = perf_event__inject_buildid; } else if (inject->sched_stat) { |
32dcd021d perf evsel: Renam... |
673 |
struct evsel *evsel; |
26a031e13 perf inject: Merg... |
674 |
|
e5cadb93d perf evlist: Rena... |
675 |
evlist__for_each_entry(session->evlist, evsel) { |
8ab2e96d8 perf evsel: Renam... |
676 |
const char *name = evsel__name(evsel); |
26a031e13 perf inject: Merg... |
677 678 |
if (!strcmp(name, "sched:sched_switch")) { |
b14b36d02 perf inject: Rena... |
679 |
if (evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID")) |
26a031e13 perf inject: Merg... |
680 |
return -EINVAL; |
744a97194 perf evsel: Ditch... |
681 |
evsel->handler = perf_inject__sched_switch; |
26a031e13 perf inject: Merg... |
682 |
} else if (!strcmp(name, "sched:sched_process_exit")) |
744a97194 perf evsel: Ditch... |
683 |
evsel->handler = perf_inject__sched_process_exit; |
26a031e13 perf inject: Merg... |
684 |
else if (!strncmp(name, "sched:sched_stat_", 17)) |
744a97194 perf evsel: Ditch... |
685 |
evsel->handler = perf_inject__sched_stat; |
26a031e13 perf inject: Merg... |
686 |
} |
0f0aa5e06 perf inject: Add ... |
687 688 689 690 |
} else if (inject->itrace_synth_opts.set) { session->itrace_synth_opts = &inject->itrace_synth_opts; inject->itrace_synth_opts.inject = true; inject->tool.comm = perf_event__repipe_comm; |
f3b3614a2 perf tools: Add P... |
691 |
inject->tool.namespaces = perf_event__repipe_namespaces; |
0f0aa5e06 perf inject: Add ... |
692 |
inject->tool.exit = perf_event__repipe_exit; |
29f6eeca0 perf inject: Fix ... |
693 |
inject->tool.id_index = perf_event__process_id_index; |
0f0aa5e06 perf inject: Add ... |
694 695 |
inject->tool.auxtrace_info = perf_event__process_auxtrace_info; inject->tool.auxtrace = perf_event__process_auxtrace; |
73117308f perf inject: Remo... |
696 697 |
inject->tool.aux = perf_event__drop_aux; inject->tool.itrace_start = perf_event__drop_aux, |
0f0aa5e06 perf inject: Add ... |
698 699 700 701 |
inject->tool.ordered_events = true; inject->tool.ordering_requires_timestamps = true; /* Allow space in the header for new attributes */ output_data_offset = 4096; |
f56fb9864 perf inject: Add ... |
702 703 |
if (inject->strip) strip_init(inject); |
26a031e13 perf inject: Merg... |
704 |
} |
99fa29845 perf tools: Add A... |
705 706 |
if (!inject->itrace_synth_opts.set) auxtrace_index__free(&session->auxtrace_index); |
8ceb41d7e perf tools: Renam... |
707 |
if (!data_out->is_pipe) |
0f0aa5e06 perf inject: Add ... |
708 |
lseek(fd, output_data_offset, SEEK_SET); |
e558a5bd8 perf inject: Work... |
709 |
|
b7b61cbeb perf ordered_even... |
710 |
ret = perf_session__process_events(session); |
bb8d521f7 perf inject: Don'... |
711 712 |
if (ret) return ret; |
454c407ec perf: add perf-in... |
713 |
|
8ceb41d7e perf tools: Renam... |
714 |
if (!data_out->is_pipe) { |
640dad479 perf inject: Hit ... |
715 |
if (inject->build_ids) |
e38b43c3f perf inject: Fix ... |
716 717 |
perf_header__set_feat(&session->header, HEADER_BUILD_ID); |
640dad479 perf inject: Hit ... |
718 719 720 721 722 723 724 |
/* * Keep all buildids when there is unprocessed AUX data because * it is not known which ones the AUX trace hits. */ if (perf_header__has_feat(&session->header, HEADER_BUILD_ID) && inject->have_auxtrace && !inject->itrace_synth_opts.set) dsos__hit_all(session); |
0f0aa5e06 perf inject: Add ... |
725 726 |
/* * The AUX areas have been removed and replaced with |
1c756cd42 perf inject: Fix ... |
727 |
* synthesized hardware events, so clear the feature flag. |
0f0aa5e06 perf inject: Add ... |
728 |
*/ |
051a01b9a perf inject: Set ... |
729 |
if (inject->itrace_synth_opts.set) { |
0f0aa5e06 perf inject: Add ... |
730 731 |
perf_header__clear_feat(&session->header, HEADER_AUXTRACE); |
ec90e42ce perf auxtrace: Ad... |
732 733 |
if (inject->itrace_synth_opts.last_branch || inject->itrace_synth_opts.add_last_branch) |
051a01b9a perf inject: Set ... |
734 735 736 |
perf_header__set_feat(&session->header, HEADER_BRANCH_STACK); } |
0f0aa5e06 perf inject: Add ... |
737 |
session->header.data_offset = output_data_offset; |
e558a5bd8 perf inject: Work... |
738 |
session->header.data_size = inject->bytes_written; |
42aa276f4 perf tools: Use p... |
739 |
perf_session__write_header(session, session->evlist, fd, true); |
e558a5bd8 perf inject: Work... |
740 |
} |
454c407ec perf: add perf-in... |
741 742 |
return ret; } |
b0ad8ea66 perf tools: Remov... |
743 |
int cmd_inject(int argc, const char **argv) |
454c407ec perf: add perf-in... |
744 |
{ |
5ded57ac1 perf inject: Remo... |
745 746 747 |
struct perf_inject inject = { .tool = { .sample = perf_event__repipe_sample, |
2946ecedd perf inject: Add ... |
748 |
.read = perf_event__repipe_sample, |
5ded57ac1 perf inject: Remo... |
749 |
.mmap = perf_event__repipe, |
5c5e854bc perf tools: Add a... |
750 |
.mmap2 = perf_event__repipe, |
5ded57ac1 perf inject: Remo... |
751 |
.comm = perf_event__repipe, |
2946ecedd perf inject: Add ... |
752 753 |
.namespaces = perf_event__repipe, .cgroup = perf_event__repipe, |
5ded57ac1 perf inject: Remo... |
754 755 756 |
.fork = perf_event__repipe, .exit = perf_event__repipe, .lost = perf_event__repipe, |
d8145b3e3 perf inject: Also... |
757 |
.lost_samples = perf_event__repipe, |
4a96f7a02 perf tools: Add s... |
758 |
.aux = perf_event__repipe, |
0ad21f686 perf tools: Add s... |
759 |
.itrace_start = perf_event__repipe, |
0286039f7 perf tools: Add n... |
760 |
.context_switch = perf_event__repipe, |
5ded57ac1 perf inject: Remo... |
761 762 |
.throttle = perf_event__repipe, .unthrottle = perf_event__repipe, |
2946ecedd perf inject: Add ... |
763 764 765 |
.ksymbol = perf_event__repipe, .bpf = perf_event__repipe, .text_poke = perf_event__repipe, |
5ded57ac1 perf inject: Remo... |
766 |
.attr = perf_event__repipe_attr, |
2946ecedd perf inject: Add ... |
767 |
.event_update = perf_event__repipe_event_update, |
47c3d1091 perf tools: Fix m... |
768 |
.tracing_data = perf_event__repipe_op2_synth, |
d704ebdae perf tools: tool-... |
769 |
.finished_round = perf_event__repipe_oe_synth, |
5ded57ac1 perf inject: Remo... |
770 |
.build_id = perf_event__repipe_op2_synth, |
3c659eeda perf tools: Add i... |
771 |
.id_index = perf_event__repipe_op2_synth, |
2946ecedd perf inject: Add ... |
772 773 774 775 776 777 778 779 |
.auxtrace_info = perf_event__repipe_op2_synth, .auxtrace_error = perf_event__repipe_op2_synth, .time_conv = perf_event__repipe_op2_synth, .thread_map = perf_event__repipe_op2_synth, .cpu_map = perf_event__repipe_op2_synth, .stat_config = perf_event__repipe_op2_synth, .stat = perf_event__repipe_op2_synth, .stat_round = perf_event__repipe_op2_synth, |
e9def1b2e perf tools: Add f... |
780 |
.feature = perf_event__repipe_op2_synth, |
2946ecedd perf inject: Add ... |
781 782 |
.compressed = perf_event__repipe_op4_synth, .auxtrace = perf_event__repipe_auxtrace, |
5ded57ac1 perf inject: Remo... |
783 |
}, |
e558a5bd8 perf inject: Work... |
784 |
.input_name = "-", |
26a031e13 perf inject: Merg... |
785 |
.samples = LIST_HEAD_INIT(inject.samples), |
3406912cc perf inject: Hand... |
786 |
.output = { |
2d4f27999 perf data: Add gl... |
787 788 |
.path = "-", .mode = PERF_DATA_MODE_WRITE, |
3406912cc perf inject: Hand... |
789 |
}, |
5ded57ac1 perf inject: Remo... |
790 |
}; |
8ceb41d7e perf tools: Renam... |
791 |
struct perf_data data = { |
1cb8bdcca perf inject: Move... |
792 793 794 |
.mode = PERF_DATA_MODE_READ, }; int ret; |
9b07e27f8 perf inject: Add ... |
795 |
struct option options[] = { |
5ded57ac1 perf inject: Remo... |
796 797 |
OPT_BOOLEAN('b', "build-ids", &inject.build_ids, "Inject build-ids into the output stream"), |
27c9c3424 perf inject: Add ... |
798 799 |
OPT_BOOLEAN(0, "buildid-all", &inject.build_id_all, "Inject build-ids of all DSOs into the output stream"), |
e558a5bd8 perf inject: Work... |
800 801 |
OPT_STRING('i', "input", &inject.input_name, "file", "input file name"), |
2d4f27999 perf data: Add gl... |
802 |
OPT_STRING('o', "output", &inject.output.path, "file", |
e558a5bd8 perf inject: Work... |
803 |
"output file name"), |
26a031e13 perf inject: Merg... |
804 805 806 |
OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), |
e12b202f8 perf jitdump: Bui... |
807 |
#ifdef HAVE_JITDUMP |
9b07e27f8 perf inject: Add ... |
808 |
OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"), |
e12b202f8 perf jitdump: Bui... |
809 |
#endif |
5ded57ac1 perf inject: Remo... |
810 811 |
OPT_INCR('v', "verbose", &verbose, "be more verbose (show build ids, etc)"), |
a7a2b8b4c perf inject: Add ... |
812 813 |
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", "kallsyms pathname"), |
8ceb41d7e perf tools: Renam... |
814 |
OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), |
0f0aa5e06 perf inject: Add ... |
815 |
OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, |
c12e039d1 perf tools: Repor... |
816 817 818 |
NULL, "opts", "Instruction Tracing options " ITRACE_HELP, |
0f0aa5e06 perf inject: Add ... |
819 |
itrace_parse_synth_opts), |
f56fb9864 perf inject: Add ... |
820 821 |
OPT_BOOLEAN(0, "strip", &inject.strip, "strip non-synthesized events (use with --itrace)"), |
5ded57ac1 perf inject: Remo... |
822 823 |
OPT_END() }; |
002439e84 perf inject: Don'... |
824 825 826 827 |
const char * const inject_usage[] = { "perf inject [<options>]", NULL }; |
e12b202f8 perf jitdump: Bui... |
828 |
#ifndef HAVE_JITDUMP |
9b07e27f8 perf inject: Add ... |
829 830 |
set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true); #endif |
002439e84 perf inject: Don'... |
831 |
argc = parse_options(argc, argv, options, inject_usage, 0); |
454c407ec perf: add perf-in... |
832 833 834 835 836 |
/* * Any (unrecognized) arguments left? */ if (argc) |
002439e84 perf inject: Don'... |
837 |
usage_with_options(inject_usage, options); |
454c407ec perf: add perf-in... |
838 |
|
f56fb9864 perf inject: Add ... |
839 840 841 842 843 |
if (inject.strip && !inject.itrace_synth_opts.set) { pr_err("--strip option requires --itrace option "); return -1; } |
8ceb41d7e perf tools: Renam... |
844 |
if (perf_data__open(&inject.output)) { |
3406912cc perf inject: Hand... |
845 846 |
perror("failed to create output file"); return -1; |
e558a5bd8 perf inject: Work... |
847 |
} |
2d4f27999 perf data: Add gl... |
848 |
data.path = inject.input_name; |
8ceb41d7e perf tools: Renam... |
849 |
inject.session = perf_session__new(&data, true, &inject.tool); |
6ef81c55a perf session: Ret... |
850 851 |
if (IS_ERR(inject.session)) return PTR_ERR(inject.session); |
1cb8bdcca perf inject: Move... |
852 |
|
371a3378d perf inject: Enab... |
853 854 855 |
if (zstd_init(&(inject.session->zstd_data), 0) < 0) pr_warning("Decompression initialization failed. "); |
27c9c3424 perf inject: Add ... |
856 |
if (inject.build_ids && !inject.build_id_all) { |
921f3fadb perf inject: Make... |
857 858 859 860 861 862 863 864 865 |
/* * to make sure the mmap records are ordered correctly * and so that the correct especially due to jitted code * mmaps. We cannot generate the buildid hit list and * inject the jit mmaps at the same time for now. */ inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } |
27c9c3424 perf inject: Add ... |
866 867 868 869 |
if (inject.sched_stat) { inject.tool.ordered_events = true; } |
e12b202f8 perf jitdump: Bui... |
870 |
#ifdef HAVE_JITDUMP |
9b07e27f8 perf inject: Add ... |
871 |
if (inject.jit_mode) { |
9b07e27f8 perf inject: Add ... |
872 873 874 875 876 877 878 879 880 881 882 |
inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap; inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; /* * JIT MMAP injection injects all MMAP events in one go, so it * does not obey finished_round semantics. */ inject.tool.finished_round = perf_event__drop_oe; } #endif |
9fedfb0c5 perf inject: Fill... |
883 884 885 |
ret = symbol__init(&inject.session->header.env); if (ret < 0) goto out_delete; |
454c407ec perf: add perf-in... |
886 |
|
1cb8bdcca perf inject: Move... |
887 |
ret = __cmd_inject(&inject); |
9fedfb0c5 perf inject: Fill... |
888 |
out_delete: |
371a3378d perf inject: Enab... |
889 |
zstd_fini(&(inject.session->zstd_data)); |
1cb8bdcca perf inject: Move... |
890 |
perf_session__delete(inject.session); |
1cb8bdcca perf inject: Move... |
891 |
return ret; |
454c407ec perf: add perf-in... |
892 |
} |