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