#define _FILE_OFFSET_BITS 64 #include <linux/kernel.h> #include <byteswap.h>#include <unistd.h>#include <sys/types.h>#include <sys/mman.h> #include "evlist.h"#include "evsel.h"#include "session.h"#include "tool.h"#include "sort.h"#include "util.h"#include "cpumap.h" static int perf_session__open(struct perf_session *self, bool force){ struct stat input_stat; if (!strcmp(self->filename, "-")) { self->fd_pipe = true; self->fd = STDIN_FILENO; if (perf_session__read_header(self, self->fd) < 0) pr_err("incompatible file format (rerun with -v to learn more)"); return 0; } self->fd = open(self->filename, O_RDONLY); if (self->fd < 0) { int err = errno; pr_err("failed to open %s: %s", self->filename, strerror(err)); if (err == ENOENT && !strcmp(self->filename, "perf.data")) pr_err(" (try 'perf record' first)"); pr_err("\n"); return -errno; } if (fstat(self->fd, &input_stat) < 0) goto out_close; if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { pr_err("file %s not owned by current user or root\n", self->filename); goto out_close; } if (!input_stat.st_size) { pr_info("zero-sized file (%s), nothing to do!\n", self->filename); goto out_close; } if (perf_session__read_header(self, self->fd) < 0) { pr_err("incompatible file format (rerun with -v to learn more)"); goto out_close; } if (!perf_evlist__valid_sample_type(self->evlist)) { pr_err("non matching sample_type"); goto out_close; } if (!perf_evlist__valid_sample_id_all(self->evlist)) { pr_err("non matching sample_id_all"); goto out_close; } self->size = input_stat.st_size; return 0; out_close: close(self->fd); self->fd = -1; return -1;} void perf_session__update_sample_type(struct perf_session *self){ self->sample_type = perf_evlist__sample_type(self->evlist); self->sample_size = __perf_evsel__sample_size(self->sample_type); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); self->host_machine.id_hdr_size = self->id_hdr_size;} int perf_session__create_kernel_maps(struct perf_session *self){ int ret = machine__create_kernel_maps(&self->host_machine); if (ret >= 0) ret = machines__create_guest_kernel_maps(&self->machines); return ret;} static void perf_session__destroy_kernel_maps(struct perf_session *self){ machine__destroy_kernel_maps(&self->host_machine); machines__destroy_guest_kernel_maps(&self->machines);} struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe, struct perf_tool *tool){ struct perf_session *self; struct stat st; size_t len; if (!filename || !strlen(filename)) { if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) filename = "-"; else filename = "perf.data"; } len = strlen(filename); self = zalloc(sizeof(*self) + len); if (self == NULL) goto out; memcpy(self->filename, filename, len); /* * On 64bit we can mmap the data file in one go. No need for tiny mmap * slices. On 32bit we use 32MB. */#if BITS_PER_LONG == 64 self->mmap_window = ULLONG_MAX;#else self->mmap_window = 32 * 1024 * 1024ULL;#endif self->machines = RB_ROOT; self->repipe = repipe; INIT_LIST_HEAD(&self->ordered_samples.samples); INIT_LIST_HEAD(&self->ordered_samples.sample_cache); INIT_LIST_HEAD(&self->ordered_samples.to_free); machine__init(&self->host_machine, "", HOST_KERNEL_ID); hists__init(&self->hists); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) goto out_delete; perf_session__update_sample_type(self); } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the * kernel MMAP event, in perf_event__process_mmap(). */ if (perf_session__create_kernel_maps(self) < 0) goto out_delete; } if (tool && tool->ordering_requires_timestamps && tool->ordered_samples && !self->sample_id_all) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } out: return self;out_delete: perf_session__delete(self); return NULL;} static void machine__delete_dead_threads(struct machine *machine){ struct thread *n, *t; list_for_each_entry_safe(t, n, &machine->dead_threads, node) { list_del(&t->node); thread__delete(t); }} static void perf_session__delete_dead_threads(struct perf_session *session){ machine__delete_dead_threads(&session->host_machine);} static void machine__delete_threads(struct machine *self){ struct rb_node *nd = rb_first(&self->threads); while (nd) { struct thread *t = rb_entry(nd, struct thread, rb_node); rb_erase(&t->rb_node, &self->threads); nd = rb_next(nd); thread__delete(t); }} static void perf_session__delete_threads(struct perf_session *session){ machine__delete_threads(&session->host_machine);} void perf_session__delete(struct perf_session *self){ perf_session__destroy_kernel_maps(self); perf_session__delete_dead_threads(self); perf_session__delete_threads(self); machine__exit(&self->host_machine); close(self->fd); free(self);} void machine__remove_thread(struct machine *self, struct thread *th){ self->last_match = NULL; rb_erase(&th->rb_node, &self->threads); /* * We may have references to this thread, for instance in some hist_entry * instances, so just move them to a separate list. */ list_add_tail(&th->node, &self->dead_threads);} static bool symbol__match_parent_regex(struct symbol *sym){ if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) return 1; return 0;} static const u8 cpumodes[] = { PERF_RECORD_MISC_USER, PERF_RECORD_MISC_KERNEL, PERF_RECORD_MISC_GUEST_USER, PERF_RECORD_MISC_GUEST_KERNEL};#define NCPUMODES (sizeof(cpumodes)/sizeof(u8)) static void ip__resolve_ams(struct machine *self, struct thread *thread, struct addr_map_symbol *ams, u64 ip){ struct addr_location al; size_t i; u8 m; memset(&al, 0, sizeof(al)); for (i = 0; i < NCPUMODES; i++) { m = cpumodes[i]; /* * We cannot use the header.misc hint to determine whether a * branch stack address is user, kernel, guest, hypervisor. * Branches may straddle the kernel/user/hypervisor boundaries. * Thus, we have to try consecutively until we find a match * or else, the symbol is unknown */ thread__find_addr_location(thread, self, m, MAP__FUNCTION, ip, &al, NULL); if (al.sym) goto found; }found: ams->addr = ip; ams->al_addr = al.addr; ams->sym = al.sym; ams->map = al.map;} struct branch_info *machine__resolve_bstack(struct machine *self, struct thread *thr, struct branch_stack *bs){ struct branch_info *bi; unsigned int i; bi = calloc(bs->nr, sizeof(struct branch_info)); if (!bi) return NULL; for (i = 0; i < bs->nr; i++) { ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to); ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from); bi[i].flags = bs->entries[i].flags; } return bi;} int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel __used, struct thread *thread, struct ip_callchain *chain, struct symbol **parent){ u8 cpumode = PERF_RECORD_MISC_USER; unsigned int i; int err; callchain_cursor_reset(&callchain_cursor); if (chain->nr > PERF_MAX_STACK_DEPTH) { pr_warning("corrupted callchain. skipping...\n"); return 0; } for (i = 0; i < chain->nr; i++) { u64 ip; struct addr_location al; if (callchain_param.order == ORDER_CALLEE) ip = chain->ips[i]; else ip = chain->ips[chain->nr - i - 1]; if (ip >= PERF_CONTEXT_MAX) { switch (ip) { case PERF_CONTEXT_HV: cpumode = PERF_RECORD_MISC_HYPERVISOR; break; case PERF_CONTEXT_KERNEL: cpumode = PERF_RECORD_MISC_KERNEL; break; case PERF_CONTEXT_USER: cpumode = PERF_RECORD_MISC_USER; break; default: pr_debug("invalid callchain context: " "%"PRId64"\n", (s64) ip); /* * It seems the callchain is corrupted. * Discard all. */ callchain_cursor_reset(&callchain_cursor); return 0; } continue; } al.filtered = false; thread__find_addr_location(thread, self, cpumode, MAP__FUNCTION, ip, &al, NULL); if (al.sym != NULL) { if (sort__has_parent && !*parent && symbol__match_parent_regex(al.sym)) *parent = al.sym; if (!symbol_conf.use_callchain) break; } err = callchain_cursor_append(&callchain_cursor, ip, al.map, al.sym); if (err) return err; } return 0;} static int process_event_synth_tracing_data_stub(union perf_event *event __used, struct perf_session *session __used){ dump_printf(": unhandled!\n"); return 0;} static int process_event_synth_attr_stub(union perf_event *event __used, struct perf_evlist **pevlist __used){ dump_printf(": unhandled!\n"); return 0;} static int process_event_sample_stub(struct perf_tool *tool __used, union perf_event *event __used, struct perf_sample *sample __used, struct perf_evsel *evsel __used, struct machine *machine __used){ dump_printf(": unhandled!\n"); return 0;} static int process_event_stub(struct perf_tool *tool __used, union perf_event *event __used, struct perf_sample *sample __used, struct machine *machine __used){ dump_printf(": unhandled!\n"); return 0;} static int process_finished_round_stub(struct perf_tool *tool __used, union perf_event *event __used, struct perf_session *perf_session __used){ dump_printf(": unhandled!\n"); return 0;} static int process_event_type_stub(struct perf_tool *tool __used, union perf_event *event __used){ dump_printf(": unhandled!\n"); return 0;} static int process_finished_round(struct perf_tool *tool, union perf_event *event, struct perf_session *session); static void perf_tool__fill_defaults(struct perf_tool *tool){ if (tool->sample == NULL) tool->sample = process_event_sample_stub; if (tool->mmap == NULL) tool->mmap = process_event_stub; if (tool->comm == NULL) tool->comm = process_event_stub; if (tool->fork == NULL) tool->fork = process_event_stub; if (tool->exit == NULL) tool->exit = process_event_stub; if (tool->lost == NULL) tool->lost = perf_event__process_lost; if (tool->read == NULL) tool->read = process_event_sample_stub; if (tool->throttle == NULL) tool->throttle = process_event_stub; if (tool->unthrottle == NULL) tool->unthrottle = process_event_stub; if (tool->attr == NULL) tool->attr = process_event_synth_attr_stub; if (tool->event_type == NULL) tool->event_type = process_event_type_stub; if (tool->tracing_data == NULL) tool->tracing_data = process_event_synth_tracing_data_stub; if (tool->build_id == NULL) tool->build_id = process_finished_round_stub; if (tool->finished_round == NULL) { if (tool->ordered_samples) tool->finished_round = process_finished_round; else tool->finished_round = process_finished_round_stub; }} void mem_bswap_64(void *src, int byte_size){ u64 *m = src; while (byte_size > 0) { *m = bswap_64(*m); byte_size -= sizeof(u64); ++m; }} static void swap_sample_id_all(union perf_event *event, void *data){ void *end = (void *) event + event->header.size; int size = end - data; BUG_ON(size % sizeof(u64)); mem_bswap_64(data, size);} static void perf_event__all64_swap(union perf_event *event, bool sample_id_all __used){ struct perf_event_header *hdr = &event->header; mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));} static void perf_event__comm_swap(union perf_event *event, bool sample_id_all){ event->comm.pid = bswap_32(event->comm.pid); event->comm.tid = bswap_32(event->comm.tid); if (sample_id_all) { void *data = &event->comm.comm; data += ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); }} static void perf_event__mmap_swap(union perf_event *event, bool sample_id_all){ event->mmap.pid = bswap_32(event->mmap.pid); event->mmap.tid = bswap_32(event->mmap.tid); event->mmap.start = bswap_64(event->mmap.start); event->mmap.len = bswap_64(event->mmap.len); event->mmap.pgoff = bswap_64(event->mmap.pgoff); if (sample_id_all) { void *data = &event->mmap.filename; data += ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); }Lines 1–500 of 1603. Load more
#define _FILE_OFFSET_BITS 64 #include <linux/kernel.h> #include <byteswap.h> #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> #include "evlist.h" #include "evsel.h" #include "session.h" #include "tool.h" #include "sort.h" #include "util.h" #include "cpumap.h" static int perf_session__open(struct perf_session *self, bool force) { struct stat input_stat; if (!strcmp(self->filename, "-")) { self->fd_pipe = true; self->fd = STDIN_FILENO; if (perf_session__read_header(self, self->fd) < 0) pr_err("incompatible file format (rerun with -v to learn more)"); return 0; } self->fd = open(self->filename, O_RDONLY); if (self->fd < 0) { int err = errno; pr_err("failed to open %s: %s", self->filename, strerror(err)); if (err == ENOENT && !strcmp(self->filename, "perf.data")) pr_err(" (try 'perf record' first)"); pr_err("\n"); return -errno; } if (fstat(self->fd, &input_stat) < 0) goto out_close; if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { pr_err("file %s not owned by current user or root\n", self->filename); goto out_close; } if (!input_stat.st_size) { pr_info("zero-sized file (%s), nothing to do!\n", self->filename); goto out_close; } if (perf_session__read_header(self, self->fd) < 0) { pr_err("incompatible file format (rerun with -v to learn more)"); goto out_close; } if (!perf_evlist__valid_sample_type(self->evlist)) { pr_err("non matching sample_type"); goto out_close; } if (!perf_evlist__valid_sample_id_all(self->evlist)) { pr_err("non matching sample_id_all"); goto out_close; } self->size = input_stat.st_size; return 0; out_close: close(self->fd); self->fd = -1; return -1; } void perf_session__update_sample_type(struct perf_session *self) { self->sample_type = perf_evlist__sample_type(self->evlist); self->sample_size = __perf_evsel__sample_size(self->sample_type); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); self->host_machine.id_hdr_size = self->id_hdr_size; } int perf_session__create_kernel_maps(struct perf_session *self) { int ret = machine__create_kernel_maps(&self->host_machine); if (ret >= 0) ret = machines__create_guest_kernel_maps(&self->machines); return ret; } static void perf_session__destroy_kernel_maps(struct perf_session *self) { machine__destroy_kernel_maps(&self->host_machine); machines__destroy_guest_kernel_maps(&self->machines); } struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe, struct perf_tool *tool) { struct perf_session *self; struct stat st; size_t len; if (!filename || !strlen(filename)) { if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) filename = "-"; else filename = "perf.data"; } len = strlen(filename); self = zalloc(sizeof(*self) + len); if (self == NULL) goto out; memcpy(self->filename, filename, len); /* * On 64bit we can mmap the data file in one go. No need for tiny mmap * slices. On 32bit we use 32MB. */ #if BITS_PER_LONG == 64 self->mmap_window = ULLONG_MAX; #else self->mmap_window = 32 * 1024 * 1024ULL; #endif self->machines = RB_ROOT; self->repipe = repipe; INIT_LIST_HEAD(&self->ordered_samples.samples); INIT_LIST_HEAD(&self->ordered_samples.sample_cache); INIT_LIST_HEAD(&self->ordered_samples.to_free); machine__init(&self->host_machine, "", HOST_KERNEL_ID); hists__init(&self->hists); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) goto out_delete; perf_session__update_sample_type(self); } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the * kernel MMAP event, in perf_event__process_mmap(). */ if (perf_session__create_kernel_maps(self) < 0) goto out_delete; } if (tool && tool->ordering_requires_timestamps && tool->ordered_samples && !self->sample_id_all) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } out: return self; out_delete: perf_session__delete(self); return NULL; } static void machine__delete_dead_threads(struct machine *machine) { struct thread *n, *t; list_for_each_entry_safe(t, n, &machine->dead_threads, node) { list_del(&t->node); thread__delete(t); } } static void perf_session__delete_dead_threads(struct perf_session *session) { machine__delete_dead_threads(&session->host_machine); } static void machine__delete_threads(struct machine *self) { struct rb_node *nd = rb_first(&self->threads); while (nd) { struct thread *t = rb_entry(nd, struct thread, rb_node); rb_erase(&t->rb_node, &self->threads); nd = rb_next(nd); thread__delete(t); } } static void perf_session__delete_threads(struct perf_session *session) { machine__delete_threads(&session->host_machine); } void perf_session__delete(struct perf_session *self) { perf_session__destroy_kernel_maps(self); perf_session__delete_dead_threads(self); perf_session__delete_threads(self); machine__exit(&self->host_machine); close(self->fd); free(self); } void machine__remove_thread(struct machine *self, struct thread *th) { self->last_match = NULL; rb_erase(&th->rb_node, &self->threads); /* * We may have references to this thread, for instance in some hist_entry * instances, so just move them to a separate list. */ list_add_tail(&th->node, &self->dead_threads); } static bool symbol__match_parent_regex(struct symbol *sym) { if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) return 1; return 0; } static const u8 cpumodes[] = { PERF_RECORD_MISC_USER, PERF_RECORD_MISC_KERNEL, PERF_RECORD_MISC_GUEST_USER, PERF_RECORD_MISC_GUEST_KERNEL }; #define NCPUMODES (sizeof(cpumodes)/sizeof(u8)) static void ip__resolve_ams(struct machine *self, struct thread *thread, struct addr_map_symbol *ams, u64 ip) { struct addr_location al; size_t i; u8 m; memset(&al, 0, sizeof(al)); for (i = 0; i < NCPUMODES; i++) { m = cpumodes[i]; /* * We cannot use the header.misc hint to determine whether a * branch stack address is user, kernel, guest, hypervisor. * Branches may straddle the kernel/user/hypervisor boundaries. * Thus, we have to try consecutively until we find a match * or else, the symbol is unknown */ thread__find_addr_location(thread, self, m, MAP__FUNCTION, ip, &al, NULL); if (al.sym) goto found; } found: ams->addr = ip; ams->al_addr = al.addr; ams->sym = al.sym; ams->map = al.map; } struct branch_info *machine__resolve_bstack(struct machine *self, struct thread *thr, struct branch_stack *bs) { struct branch_info *bi; unsigned int i; bi = calloc(bs->nr, sizeof(struct branch_info)); if (!bi) return NULL; for (i = 0; i < bs->nr; i++) { ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to); ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from); bi[i].flags = bs->entries[i].flags; } return bi; } int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel __used, struct thread *thread, struct ip_callchain *chain, struct symbol **parent) { u8 cpumode = PERF_RECORD_MISC_USER; unsigned int i; int err; callchain_cursor_reset(&callchain_cursor); if (chain->nr > PERF_MAX_STACK_DEPTH) { pr_warning("corrupted callchain. skipping...\n"); return 0; } for (i = 0; i < chain->nr; i++) { u64 ip; struct addr_location al; if (callchain_param.order == ORDER_CALLEE) ip = chain->ips[i]; else ip = chain->ips[chain->nr - i - 1]; if (ip >= PERF_CONTEXT_MAX) { switch (ip) { case PERF_CONTEXT_HV: cpumode = PERF_RECORD_MISC_HYPERVISOR; break; case PERF_CONTEXT_KERNEL: cpumode = PERF_RECORD_MISC_KERNEL; break; case PERF_CONTEXT_USER: cpumode = PERF_RECORD_MISC_USER; break; default: pr_debug("invalid callchain context: " "%"PRId64"\n", (s64) ip); /* * It seems the callchain is corrupted. * Discard all. */ callchain_cursor_reset(&callchain_cursor); return 0; } continue; } al.filtered = false; thread__find_addr_location(thread, self, cpumode, MAP__FUNCTION, ip, &al, NULL); if (al.sym != NULL) { if (sort__has_parent && !*parent && symbol__match_parent_regex(al.sym)) *parent = al.sym; if (!symbol_conf.use_callchain) break; } err = callchain_cursor_append(&callchain_cursor, ip, al.map, al.sym); if (err) return err; } return 0; } static int process_event_synth_tracing_data_stub(union perf_event *event __used, struct perf_session *session __used) { dump_printf(": unhandled!\n"); return 0; } static int process_event_synth_attr_stub(union perf_event *event __used, struct perf_evlist **pevlist __used) { dump_printf(": unhandled!\n"); return 0; } static int process_event_sample_stub(struct perf_tool *tool __used, union perf_event *event __used, struct perf_sample *sample __used, struct perf_evsel *evsel __used, struct machine *machine __used) { dump_printf(": unhandled!\n"); return 0; } static int process_event_stub(struct perf_tool *tool __used, union perf_event *event __used, struct perf_sample *sample __used, struct machine *machine __used) { dump_printf(": unhandled!\n"); return 0; } static int process_finished_round_stub(struct perf_tool *tool __used, union perf_event *event __used, struct perf_session *perf_session __used) { dump_printf(": unhandled!\n"); return 0; } static int process_event_type_stub(struct perf_tool *tool __used, union perf_event *event __used) { dump_printf(": unhandled!\n"); return 0; } static int process_finished_round(struct perf_tool *tool, union perf_event *event, struct perf_session *session); static void perf_tool__fill_defaults(struct perf_tool *tool) { if (tool->sample == NULL) tool->sample = process_event_sample_stub; if (tool->mmap == NULL) tool->mmap = process_event_stub; if (tool->comm == NULL) tool->comm = process_event_stub; if (tool->fork == NULL) tool->fork = process_event_stub; if (tool->exit == NULL) tool->exit = process_event_stub; if (tool->lost == NULL) tool->lost = perf_event__process_lost; if (tool->read == NULL) tool->read = process_event_sample_stub; if (tool->throttle == NULL) tool->throttle = process_event_stub; if (tool->unthrottle == NULL) tool->unthrottle = process_event_stub; if (tool->attr == NULL) tool->attr = process_event_synth_attr_stub; if (tool->event_type == NULL) tool->event_type = process_event_type_stub; if (tool->tracing_data == NULL) tool->tracing_data = process_event_synth_tracing_data_stub; if (tool->build_id == NULL) tool->build_id = process_finished_round_stub; if (tool->finished_round == NULL) { if (tool->ordered_samples) tool->finished_round = process_finished_round; else tool->finished_round = process_finished_round_stub; } } void mem_bswap_64(void *src, int byte_size) { u64 *m = src; while (byte_size > 0) { *m = bswap_64(*m); byte_size -= sizeof(u64); ++m; } } static void swap_sample_id_all(union perf_event *event, void *data) { void *end = (void *) event + event->header.size; int size = end - data; BUG_ON(size % sizeof(u64)); mem_bswap_64(data, size); } static void perf_event__all64_swap(union perf_event *event, bool sample_id_all __used) { struct perf_event_header *hdr = &event->header; mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); } static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) { event->comm.pid = bswap_32(event->comm.pid); event->comm.tid = bswap_32(event->comm.tid); if (sample_id_all) { void *data = &event->comm.comm; data += ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); } } static void perf_event__mmap_swap(union perf_event *event, bool sample_id_all) { event->mmap.pid = bswap_32(event->mmap.pid); event->mmap.tid = bswap_32(event->mmap.tid); event->mmap.start = bswap_64(event->mmap.start); event->mmap.len = bswap_64(event->mmap.len); event->mmap.pgoff = bswap_64(event->mmap.pgoff); if (sample_id_all) { void *data = &event->mmap.filename; data += ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); }