xref: /OK3568_Linux_fs/kernel/tools/perf/builtin-inject.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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