Blame view

tools/perf/builtin-inject.c 6.37 KB
454c407ec   Tom Zanussi   perf: add perf-in...
1
2
3
4
5
6
7
8
9
10
11
  /*
   * builtin-inject.c
   *
   * Builtin inject command: Examine the live mode (stdin) event stream
   * and repipe it to stdout while optionally injecting additional
   * events into it.
   */
  #include "builtin.h"
  
  #include "perf.h"
  #include "util/session.h"
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
12
  #include "util/tool.h"
454c407ec   Tom Zanussi   perf: add perf-in...
13
14
15
16
17
18
  #include "util/debug.h"
  
  #include "util/parse-options.h"
  
  static char		const *input_name = "-";
  static bool		inject_build_ids;
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
19
  static int perf_event__repipe_synth(struct perf_tool *tool __used,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
20
  				    union perf_event *event,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
21
  				    struct machine *machine __used)
454c407ec   Tom Zanussi   perf: add perf-in...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  {
  	uint32_t size;
  	void *buf = event;
  
  	size = event->header.size;
  
  	while (size) {
  		int ret = write(STDOUT_FILENO, buf, size);
  		if (ret < 0)
  			return -errno;
  
  		size -= ret;
  		buf += ret;
  	}
  
  	return 0;
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
39
  static int perf_event__repipe_op2_synth(struct perf_tool *tool,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
40
41
42
  					union perf_event *event,
  					struct perf_session *session __used)
  {
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
43
  	return perf_event__repipe_synth(tool, event, NULL);
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
44
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
45
  static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
46
47
  					       union perf_event *event)
  {
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
48
  	return perf_event__repipe_synth(tool, event, NULL);
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
49
  }
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
50
  static int perf_event__repipe_tracing_data_synth(union perf_event *event,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
51
  						 struct perf_session *session __used)
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
52
  {
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
53
  	return perf_event__repipe_synth(NULL, event, NULL);
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
54
  }
10d0f086d   Arnaldo Carvalho de Melo   perf event: perf_...
55
56
57
  static int perf_event__repipe_attr(union perf_event *event,
  				   struct perf_evlist **pevlist __used)
  {
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
58
  	return perf_event__repipe_synth(NULL, event, NULL);
10d0f086d   Arnaldo Carvalho de Melo   perf event: perf_...
59
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
60
  static int perf_event__repipe(struct perf_tool *tool,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
61
  			      union perf_event *event,
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
62
  			      struct perf_sample *sample __used,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
63
  			      struct machine *machine)
640c03ce8   Arnaldo Carvalho de Melo   perf session: Par...
64
  {
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
65
  	return perf_event__repipe_synth(tool, event, machine);
640c03ce8   Arnaldo Carvalho de Melo   perf session: Par...
66
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
67
  static int perf_event__repipe_sample(struct perf_tool *tool,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
68
  				     union perf_event *event,
9e69c2108   Arnaldo Carvalho de Melo   perf session: Pas...
69
70
  			      struct perf_sample *sample __used,
  			      struct perf_evsel *evsel __used,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
71
  			      struct machine *machine)
9e69c2108   Arnaldo Carvalho de Melo   perf session: Pas...
72
  {
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
73
  	return perf_event__repipe_synth(tool, event, machine);
9e69c2108   Arnaldo Carvalho de Melo   perf session: Pas...
74
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
75
  static int perf_event__repipe_mmap(struct perf_tool *tool,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
76
  				   union perf_event *event,
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
77
  				   struct perf_sample *sample,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
78
  				   struct machine *machine)
454c407ec   Tom Zanussi   perf: add perf-in...
79
80
  {
  	int err;
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
81
82
  	err = perf_event__process_mmap(tool, event, sample, machine);
  	perf_event__repipe(tool, event, sample, machine);
454c407ec   Tom Zanussi   perf: add perf-in...
83
84
85
  
  	return err;
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
86
  static int perf_event__repipe_task(struct perf_tool *tool,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
87
  				   union perf_event *event,
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
88
  				   struct perf_sample *sample,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
89
  				   struct machine *machine)
454c407ec   Tom Zanussi   perf: add perf-in...
90
91
  {
  	int err;
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
92
93
  	err = perf_event__process_task(tool, event, sample, machine);
  	perf_event__repipe(tool, event, sample, machine);
454c407ec   Tom Zanussi   perf: add perf-in...
94
95
96
  
  	return err;
  }
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
97
98
  static int perf_event__repipe_tracing_data(union perf_event *event,
  					   struct perf_session *session)
454c407ec   Tom Zanussi   perf: add perf-in...
99
100
  {
  	int err;
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
101
  	perf_event__repipe_synth(NULL, event, NULL);
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
102
  	err = perf_event__process_tracing_data(event, session);
454c407ec   Tom Zanussi   perf: add perf-in...
103
104
105
  
  	return err;
  }
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
106
  static int dso__read_build_id(struct dso *self)
454c407ec   Tom Zanussi   perf: add perf-in...
107
  {
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
108
109
  	if (self->has_build_id)
  		return 0;
454c407ec   Tom Zanussi   perf: add perf-in...
110

090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
111
112
113
114
115
  	if (filename__read_build_id(self->long_name, self->build_id,
  				    sizeof(self->build_id)) > 0) {
  		self->has_build_id = true;
  		return 0;
  	}
454c407ec   Tom Zanussi   perf: add perf-in...
116

090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
117
118
  	return -1;
  }
454c407ec   Tom Zanussi   perf: add perf-in...
119

45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
120
  static int dso__inject_build_id(struct dso *self, struct perf_tool *tool,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
121
  				struct machine *machine)
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
122
123
  {
  	u16 misc = PERF_RECORD_MISC_USER;
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
124
  	int err;
454c407ec   Tom Zanussi   perf: add perf-in...
125

090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
126
127
128
129
130
  	if (dso__read_build_id(self) < 0) {
  		pr_debug("no build_id found for %s
  ", self->long_name);
  		return -1;
  	}
454c407ec   Tom Zanussi   perf: add perf-in...
131

090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
132
133
  	if (self->kernel)
  		misc = PERF_RECORD_MISC_KERNEL;
454c407ec   Tom Zanussi   perf: add perf-in...
134

45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
135
  	err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
136
  					      machine);
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
137
138
139
  	if (err) {
  		pr_err("Can't synthesize build_id event for %s
  ", self->long_name);
454c407ec   Tom Zanussi   perf: add perf-in...
140
141
142
143
144
  		return -1;
  	}
  
  	return 0;
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
145
  static int perf_event__inject_buildid(struct perf_tool *tool,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
146
  				      union perf_event *event,
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
147
  				      struct perf_sample *sample,
9e69c2108   Arnaldo Carvalho de Melo   perf session: Pas...
148
  				      struct perf_evsel *evsel __used,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
149
  				      struct machine *machine)
454c407ec   Tom Zanussi   perf: add perf-in...
150
151
152
153
  {
  	struct addr_location al;
  	struct thread *thread;
  	u8 cpumode;
454c407ec   Tom Zanussi   perf: add perf-in...
154
155
  
  	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
156
  	thread = machine__findnew_thread(machine, event->ip.pid);
454c407ec   Tom Zanussi   perf: add perf-in...
157
158
159
160
  	if (thread == NULL) {
  		pr_err("problem processing %d event, skipping it.
  ",
  		       event->header.type);
454c407ec   Tom Zanussi   perf: add perf-in...
161
162
  		goto repipe;
  	}
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
163
164
  	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
  			      event->ip.ip, &al);
454c407ec   Tom Zanussi   perf: add perf-in...
165
166
167
168
  
  	if (al.map != NULL) {
  		if (!al.map->dso->hit) {
  			al.map->dso->hit = 1;
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
169
  			if (map__load(al.map, NULL) >= 0) {
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
170
  				dso__inject_build_id(al.map->dso, tool, machine);
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
171
172
173
174
175
  				/*
  				 * If this fails, too bad, let the other side
  				 * account this as unresolved.
  				 */
  			} else
454c407ec   Tom Zanussi   perf: add perf-in...
176
177
178
179
180
181
182
183
  				pr_warning("no symbols found in %s, maybe "
  					   "install a debug package?
  ",
  					   al.map->dso->long_name);
  		}
  	}
  
  repipe:
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
184
  	perf_event__repipe(tool, event, sample, machine);
090f7204d   Arnaldo Carvalho de Melo   perf inject: Refa...
185
  	return 0;
454c407ec   Tom Zanussi   perf: add perf-in...
186
  }
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
187
  struct perf_tool perf_inject = {
9e69c2108   Arnaldo Carvalho de Melo   perf session: Pas...
188
  	.sample		= perf_event__repipe_sample,
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
189
190
191
192
193
  	.mmap		= perf_event__repipe,
  	.comm		= perf_event__repipe,
  	.fork		= perf_event__repipe,
  	.exit		= perf_event__repipe,
  	.lost		= perf_event__repipe,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
194
  	.read		= perf_event__repipe_sample,
8115d60c3   Arnaldo Carvalho de Melo   perf tools: Kill ...
195
196
  	.throttle	= perf_event__repipe,
  	.unthrottle	= perf_event__repipe,
10d0f086d   Arnaldo Carvalho de Melo   perf event: perf_...
197
  	.attr		= perf_event__repipe_attr,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
198
  	.event_type	= perf_event__repipe_event_type_synth,
d20deb64e   Arnaldo Carvalho de Melo   perf tools: Pass ...
199
  	.tracing_data	= perf_event__repipe_tracing_data_synth,
743eb8686   Arnaldo Carvalho de Melo   perf tools: Resol...
200
  	.build_id	= perf_event__repipe_op2_synth,
454c407ec   Tom Zanussi   perf: add perf-in...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  };
  
  extern volatile int session_done;
  
  static void sig_handler(int sig __attribute__((__unused__)))
  {
  	session_done = 1;
  }
  
  static int __cmd_inject(void)
  {
  	struct perf_session *session;
  	int ret = -EINVAL;
  
  	signal(SIGINT, sig_handler);
  
  	if (inject_build_ids) {
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
218
219
220
221
  		perf_inject.sample	 = perf_event__inject_buildid;
  		perf_inject.mmap	 = perf_event__repipe_mmap;
  		perf_inject.fork	 = perf_event__repipe_task;
  		perf_inject.tracing_data = perf_event__repipe_tracing_data;
454c407ec   Tom Zanussi   perf: add perf-in...
222
  	}
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
223
  	session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
454c407ec   Tom Zanussi   perf: add perf-in...
224
225
  	if (session == NULL)
  		return -ENOMEM;
45694aa77   Arnaldo Carvalho de Melo   perf tools: Renam...
226
  	ret = perf_session__process_events(session, &perf_inject);
454c407ec   Tom Zanussi   perf: add perf-in...
227
228
229
230
231
232
233
234
235
236
237
238
  
  	perf_session__delete(session);
  
  	return ret;
  }
  
  static const char * const report_usage[] = {
  	"perf inject [<options>]",
  	NULL
  };
  
  static const struct option options[] = {
11d232ec2   Arnaldo Carvalho de Melo   perf inject: Add ...
239
  	OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
454c407ec   Tom Zanussi   perf: add perf-in...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  		    "Inject build-ids into the output stream"),
  	OPT_INCR('v', "verbose", &verbose,
  		 "be more verbose (show build ids, etc)"),
  	OPT_END()
  };
  
  int cmd_inject(int argc, const char **argv, const char *prefix __used)
  {
  	argc = parse_options(argc, argv, options, report_usage, 0);
  
  	/*
  	 * Any (unrecognized) arguments left?
  	 */
  	if (argc)
  		usage_with_options(report_usage, options);
  
  	if (symbol__init() < 0)
  		return -1;
  
  	return __cmd_inject();
  }