|
@@ -574,3 +574,82 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
|
|
+ const struct perf_sample *sample,
|
|
|
+ bool swapped)
|
|
|
+{
|
|
|
+ u64 *array;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * used for cross-endian analysis. See git commit 65014ab3
|
|
|
+ * for why this goofiness is needed.
|
|
|
+ */
|
|
|
+ union {
|
|
|
+ u64 val64;
|
|
|
+ u32 val32[2];
|
|
|
+ } u;
|
|
|
+
|
|
|
+ array = event->sample.array;
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_IP) {
|
|
|
+ event->ip.ip = sample->ip;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_TID) {
|
|
|
+ u.val32[0] = sample->pid;
|
|
|
+ u.val32[1] = sample->tid;
|
|
|
+ if (swapped) {
|
|
|
+ /*
|
|
|
+ * Inverse of what is done in perf_event__parse_sample
|
|
|
+ */
|
|
|
+ u.val32[0] = bswap_32(u.val32[0]);
|
|
|
+ u.val32[1] = bswap_32(u.val32[1]);
|
|
|
+ u.val64 = bswap_64(u.val64);
|
|
|
+ }
|
|
|
+
|
|
|
+ *array = u.val64;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_TIME) {
|
|
|
+ *array = sample->time;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_ADDR) {
|
|
|
+ *array = sample->addr;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_ID) {
|
|
|
+ *array = sample->id;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_STREAM_ID) {
|
|
|
+ *array = sample->stream_id;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_CPU) {
|
|
|
+ u.val32[0] = sample->cpu;
|
|
|
+ if (swapped) {
|
|
|
+ /*
|
|
|
+ * Inverse of what is done in perf_event__parse_sample
|
|
|
+ */
|
|
|
+ u.val32[0] = bswap_32(u.val32[0]);
|
|
|
+ u.val64 = bswap_64(u.val64);
|
|
|
+ }
|
|
|
+ *array = u.val64;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type & PERF_SAMPLE_PERIOD) {
|
|
|
+ *array = sample->period;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|