perf tools: Pass tool context in the the perf_event_ops functions
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / tools / perf / builtin-inject.c
CommitLineData
454c407e
TZ
1/*
2 * builtin-inject.c
3 *
4 * Builtin inject command: Examine the live mode (stdin) event stream
5 * and repipe it to stdout while optionally injecting additional
6 * events into it.
7 */
8#include "builtin.h"
9
10#include "perf.h"
11#include "util/session.h"
12#include "util/debug.h"
13
14#include "util/parse-options.h"
15
16static char const *input_name = "-";
17static bool inject_build_ids;
18
d20deb64
ACM
19static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
20 union perf_event *event,
8115d60c 21 struct perf_session *session __used)
454c407e
TZ
22{
23 uint32_t size;
24 void *buf = event;
25
26 size = event->header.size;
27
28 while (size) {
29 int ret = write(STDOUT_FILENO, buf, size);
30 if (ret < 0)
31 return -errno;
32
33 size -= ret;
34 buf += ret;
35 }
36
37 return 0;
38}
39
d20deb64
ACM
40static int perf_event__repipe_tracing_data_synth(union perf_event *event,
41 struct perf_session *session)
42{
43 return perf_event__repipe_synth(NULL, event, session);
44}
45
10d0f086
ACM
46static int perf_event__repipe_attr(union perf_event *event,
47 struct perf_evlist **pevlist __used)
48{
d20deb64 49 return perf_event__repipe_synth(NULL, event, NULL);
10d0f086
ACM
50}
51
d20deb64
ACM
52static int perf_event__repipe(struct perf_event_ops *ops,
53 union perf_event *event,
8115d60c
ACM
54 struct perf_sample *sample __used,
55 struct perf_session *session)
640c03ce 56{
d20deb64 57 return perf_event__repipe_synth(ops, event, session);
640c03ce
ACM
58}
59
d20deb64
ACM
60static int perf_event__repipe_sample(struct perf_event_ops *ops,
61 union perf_event *event,
9e69c210
ACM
62 struct perf_sample *sample __used,
63 struct perf_evsel *evsel __used,
64 struct perf_session *session)
65{
d20deb64 66 return perf_event__repipe_synth(ops, event, session);
9e69c210
ACM
67}
68
d20deb64
ACM
69static int perf_event__repipe_mmap(struct perf_event_ops *ops,
70 union perf_event *event,
8115d60c
ACM
71 struct perf_sample *sample,
72 struct perf_session *session)
454c407e
TZ
73{
74 int err;
75
d20deb64
ACM
76 err = perf_event__process_mmap(ops, event, sample, session);
77 perf_event__repipe(ops, event, sample, session);
454c407e
TZ
78
79 return err;
80}
81
d20deb64
ACM
82static int perf_event__repipe_task(struct perf_event_ops *ops,
83 union perf_event *event,
8115d60c
ACM
84 struct perf_sample *sample,
85 struct perf_session *session)
454c407e
TZ
86{
87 int err;
88
d20deb64
ACM
89 err = perf_event__process_task(ops, event, sample, session);
90 perf_event__repipe(ops, event, sample, session);
454c407e
TZ
91
92 return err;
93}
94
8115d60c
ACM
95static int perf_event__repipe_tracing_data(union perf_event *event,
96 struct perf_session *session)
454c407e
TZ
97{
98 int err;
99
d20deb64 100 perf_event__repipe_synth(NULL, event, session);
8115d60c 101 err = perf_event__process_tracing_data(event, session);
454c407e
TZ
102
103 return err;
104}
105
090f7204 106static int dso__read_build_id(struct dso *self)
454c407e 107{
090f7204
ACM
108 if (self->has_build_id)
109 return 0;
454c407e 110
090f7204
ACM
111 if (filename__read_build_id(self->long_name, self->build_id,
112 sizeof(self->build_id)) > 0) {
113 self->has_build_id = true;
114 return 0;
115 }
454c407e 116
090f7204
ACM
117 return -1;
118}
454c407e 119
d20deb64
ACM
120static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
121 struct perf_session *session)
090f7204
ACM
122{
123 u16 misc = PERF_RECORD_MISC_USER;
124 struct machine *machine;
125 int err;
454c407e 126
090f7204
ACM
127 if (dso__read_build_id(self) < 0) {
128 pr_debug("no build_id found for %s\n", self->long_name);
129 return -1;
130 }
454c407e 131
090f7204
ACM
132 machine = perf_session__find_host_machine(session);
133 if (machine == NULL) {
134 pr_err("Can't find machine for session\n");
135 return -1;
136 }
454c407e 137
090f7204
ACM
138 if (self->kernel)
139 misc = PERF_RECORD_MISC_KERNEL;
454c407e 140
d20deb64 141 err = perf_event__synthesize_build_id(ops, self, misc, perf_event__repipe,
8115d60c 142 machine, session);
090f7204
ACM
143 if (err) {
144 pr_err("Can't synthesize build_id event for %s\n", self->long_name);
454c407e
TZ
145 return -1;
146 }
147
148 return 0;
149}
150
d20deb64
ACM
151static int perf_event__inject_buildid(struct perf_event_ops *ops,
152 union perf_event *event,
8115d60c 153 struct perf_sample *sample,
9e69c210 154 struct perf_evsel *evsel __used,
8115d60c 155 struct perf_session *session)
454c407e
TZ
156{
157 struct addr_location al;
158 struct thread *thread;
159 u8 cpumode;
454c407e
TZ
160
161 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
162
163 thread = perf_session__findnew(session, event->ip.pid);
164 if (thread == NULL) {
165 pr_err("problem processing %d event, skipping it.\n",
166 event->header.type);
454c407e
TZ
167 goto repipe;
168 }
169
170 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
171 event->ip.pid, event->ip.ip, &al);
172
173 if (al.map != NULL) {
174 if (!al.map->dso->hit) {
175 al.map->dso->hit = 1;
090f7204 176 if (map__load(al.map, NULL) >= 0) {
d20deb64 177 dso__inject_build_id(al.map->dso, ops, session);
090f7204
ACM
178 /*
179 * If this fails, too bad, let the other side
180 * account this as unresolved.
181 */
182 } else
454c407e
TZ
183 pr_warning("no symbols found in %s, maybe "
184 "install a debug package?\n",
185 al.map->dso->long_name);
186 }
187 }
188
189repipe:
d20deb64 190 perf_event__repipe(ops, event, sample, session);
090f7204 191 return 0;
454c407e
TZ
192}
193
194struct perf_event_ops inject_ops = {
9e69c210 195 .sample = perf_event__repipe_sample,
8115d60c
ACM
196 .mmap = perf_event__repipe,
197 .comm = perf_event__repipe,
198 .fork = perf_event__repipe,
199 .exit = perf_event__repipe,
200 .lost = perf_event__repipe,
201 .read = perf_event__repipe,
202 .throttle = perf_event__repipe,
203 .unthrottle = perf_event__repipe,
10d0f086 204 .attr = perf_event__repipe_attr,
d20deb64
ACM
205 .event_type = perf_event__repipe_synth,
206 .tracing_data = perf_event__repipe_tracing_data_synth,
207 .build_id = perf_event__repipe_synth,
454c407e
TZ
208};
209
210extern volatile int session_done;
211
212static void sig_handler(int sig __attribute__((__unused__)))
213{
214 session_done = 1;
215}
216
217static int __cmd_inject(void)
218{
219 struct perf_session *session;
220 int ret = -EINVAL;
221
222 signal(SIGINT, sig_handler);
223
224 if (inject_build_ids) {
8115d60c
ACM
225 inject_ops.sample = perf_event__inject_buildid;
226 inject_ops.mmap = perf_event__repipe_mmap;
227 inject_ops.fork = perf_event__repipe_task;
228 inject_ops.tracing_data = perf_event__repipe_tracing_data;
454c407e
TZ
229 }
230
21ef97f0 231 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
454c407e
TZ
232 if (session == NULL)
233 return -ENOMEM;
234
235 ret = perf_session__process_events(session, &inject_ops);
236
237 perf_session__delete(session);
238
239 return ret;
240}
241
242static const char * const report_usage[] = {
243 "perf inject [<options>]",
244 NULL
245};
246
247static const struct option options[] = {
11d232ec 248 OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
454c407e
TZ
249 "Inject build-ids into the output stream"),
250 OPT_INCR('v', "verbose", &verbose,
251 "be more verbose (show build ids, etc)"),
252 OPT_END()
253};
254
255int cmd_inject(int argc, const char **argv, const char *prefix __used)
256{
257 argc = parse_options(argc, argv, options, report_usage, 0);
258
259 /*
260 * Any (unrecognized) arguments left?
261 */
262 if (argc)
263 usage_with_options(report_usage, options);
264
265 if (symbol__init() < 0)
266 return -1;
267
268 return __cmd_inject();
269}