builtin-inject.c 25 KB

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