// SPDX-License-Identifier: GPL-2.0/* * trace_events_synth - synthetic trace events * * Copyright (C) 2015, 2020 Tom Zanussi <tom.zanussi@linux.intel.com> */ #include <linux/module.h>#include <linux/kallsyms.h>#include <linux/security.h>#include <linux/mutex.h>#include <linux/slab.h>#include <linux/stacktrace.h>#include <linux/rculist.h>#include <linux/tracefs.h> /* for gfp flag names */#include <linux/trace_events.h>#include <trace/events/mmflags.h> #include "trace_synth.h" #undef ERRORS#define ERRORS \ C(BAD_NAME, "Illegal name"), \ C(INVALID_CMD, "Command must be of the form: <name> field[;field] ..."),\ C(INVALID_DYN_CMD, "Command must be of the form: s or -:[synthetic/]<name> field[;field] ..."),\ C(EVENT_EXISTS, "Event already exists"), \ C(TOO_MANY_FIELDS, "Too many fields"), \ C(INCOMPLETE_TYPE, "Incomplete type"), \ C(INVALID_TYPE, "Invalid type"), \ C(INVALID_FIELD, "Invalid field"), \ C(INVALID_ARRAY_SPEC, "Invalid array specification"), #undef C#define C(a, b) SYNTH_ERR_##a enum { ERRORS }; #undef C#define C(a, b) b static const char *err_text[] = { ERRORS }; static char last_cmd[MAX_FILTER_STR_VAL]; static int errpos(const char *str){ return err_pos(last_cmd, str);} static void last_cmd_set(const char *str){ if (!str) return; strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1);} static void synth_err(u8 err_type, u8 err_pos){ tracing_log_err(NULL, "synthetic_events", last_cmd, err_text, err_type, err_pos);} static int create_synth_event(const char *raw_command);static int synth_event_show(struct seq_file *m, struct dyn_event *ev);static int synth_event_release(struct dyn_event *ev);static bool synth_event_is_busy(struct dyn_event *ev);static bool synth_event_match(const char *system, const char *event, int argc, const char **argv, struct dyn_event *ev); static struct dyn_event_operations synth_event_ops = { .create = create_synth_event, .show = synth_event_show, .is_busy = synth_event_is_busy, .free = synth_event_release, .match = synth_event_match,}; static bool is_synth_event(struct dyn_event *ev){ return ev->ops == &synth_event_ops;} static struct synth_event *to_synth_event(struct dyn_event *ev){ return container_of(ev, struct synth_event, devent);} static bool synth_event_is_busy(struct dyn_event *ev){ struct synth_event *event = to_synth_event(ev); return event->ref != 0;} static bool synth_event_match(const char *system, const char *event, int argc, const char **argv, struct dyn_event *ev){ struct synth_event *sev = to_synth_event(ev); return strcmp(sev->name, event) == 0 && (!system || strcmp(system, SYNTH_SYSTEM) == 0);} struct synth_trace_event { struct trace_entry ent; u64 fields[];}; static int synth_event_define_fields(struct trace_event_call *call){ struct synth_trace_event trace; int offset = offsetof(typeof(trace), fields); struct synth_event *event = call->data; unsigned int i, size, n_u64; char *name, *type; bool is_signed; int ret = 0; for (i = 0, n_u64 = 0; i < event->n_fields; i++) { size = event->fields[i]->size; is_signed = event->fields[i]->is_signed; type = event->fields[i]->type; name = event->fields[i]->name; ret = trace_define_field(call, type, name, offset, size, is_signed, FILTER_OTHER); if (ret) break; event->fields[i]->offset = n_u64; if (event->fields[i]->is_string && !event->fields[i]->is_dynamic) { offset += STR_VAR_LEN_MAX; n_u64 += STR_VAR_LEN_MAX / sizeof(u64); } else { offset += sizeof(u64); n_u64++; } } event->n_u64 = n_u64; return ret;} static bool synth_field_signed(char *type){ if (str_has_prefix(type, "u")) return false; if (strcmp(type, "gfp_t") == 0) return false; return true;} static int synth_field_is_string(char *type){ if (strstr(type, "char[") != NULL) return true; return false;} static int synth_field_string_size(char *type){ char buf[4], *end, *start; unsigned int len; int size, err; start = strstr(type, "char["); if (start == NULL) return -EINVAL; start += sizeof("char[") - 1; end = strchr(type, ']'); if (!end || end < start || type + strlen(type) > end + 1) return -EINVAL; len = end - start; if (len > 3) return -EINVAL; if (len == 0) return 0; /* variable-length string */ strncpy(buf, start, len); buf[len] = '\0'; err = kstrtouint(buf, 0, &size); if (err) return err; if (size > STR_VAR_LEN_MAX) return -EINVAL; return size;} static int synth_field_size(char *type){ int size = 0; if (strcmp(type, "s64") == 0) size = sizeof(s64); else if (strcmp(type, "u64") == 0) size = sizeof(u64); else if (strcmp(type, "s32") == 0) size = sizeof(s32); else if (strcmp(type, "u32") == 0) size = sizeof(u32); else if (strcmp(type, "s16") == 0) size = sizeof(s16); else if (strcmp(type, "u16") == 0) size = sizeof(u16); else if (strcmp(type, "s8") == 0) size = sizeof(s8); else if (strcmp(type, "u8") == 0) size = sizeof(u8); else if (strcmp(type, "char") == 0) size = sizeof(char); else if (strcmp(type, "unsigned char") == 0) size = sizeof(unsigned char); else if (strcmp(type, "int") == 0) size = sizeof(int); else if (strcmp(type, "unsigned int") == 0) size = sizeof(unsigned int); else if (strcmp(type, "long") == 0) size = sizeof(long); else if (strcmp(type, "unsigned long") == 0) size = sizeof(unsigned long); else if (strcmp(type, "bool") == 0) size = sizeof(bool); else if (strcmp(type, "pid_t") == 0) size = sizeof(pid_t); else if (strcmp(type, "gfp_t") == 0) size = sizeof(gfp_t); else if (synth_field_is_string(type)) size = synth_field_string_size(type); return size;} static const char *synth_field_fmt(char *type){ const char *fmt = "%llu"; if (strcmp(type, "s64") == 0) fmt = "%lld"; else if (strcmp(type, "u64") == 0) fmt = "%llu"; else if (strcmp(type, "s32") == 0) fmt = "%d"; else if (strcmp(type, "u32") == 0) fmt = "%u"; else if (strcmp(type, "s16") == 0) fmt = "%d"; else if (strcmp(type, "u16") == 0) fmt = "%u"; else if (strcmp(type, "s8") == 0) fmt = "%d"; else if (strcmp(type, "u8") == 0) fmt = "%u"; else if (strcmp(type, "char") == 0) fmt = "%d"; else if (strcmp(type, "unsigned char") == 0) fmt = "%u"; else if (strcmp(type, "int") == 0) fmt = "%d"; else if (strcmp(type, "unsigned int") == 0) fmt = "%u"; else if (strcmp(type, "long") == 0) fmt = "%ld"; else if (strcmp(type, "unsigned long") == 0) fmt = "%lu"; else if (strcmp(type, "bool") == 0) fmt = "%d"; else if (strcmp(type, "pid_t") == 0) fmt = "%d"; else if (strcmp(type, "gfp_t") == 0) fmt = "%x"; else if (synth_field_is_string(type)) fmt = "%.*s"; return fmt;} static void print_synth_event_num_val(struct trace_seq *s, char *print_fmt, char *name, int size, u64 val, char *space){ switch (size) { case 1: trace_seq_printf(s, print_fmt, name, (u8)val, space); break; case 2: trace_seq_printf(s, print_fmt, name, (u16)val, space); break; case 4: trace_seq_printf(s, print_fmt, name, (u32)val, space); break; default: trace_seq_printf(s, print_fmt, name, val, space); break; }} static enum print_line_t print_synth_event(struct trace_iterator *iter, int flags, struct trace_event *event){ struct trace_array *tr = iter->tr; struct trace_seq *s = &iter->seq; struct synth_trace_event *entry; struct synth_event *se; unsigned int i, n_u64; char print_fmt[32]; const char *fmt; entry = (struct synth_trace_event *)iter->ent; se = container_of(event, struct synth_event, call.event); trace_seq_printf(s, "%s: ", se->name); for (i = 0, n_u64 = 0; i < se->n_fields; i++) { if (trace_seq_has_overflowed(s)) goto end; fmt = synth_field_fmt(se->fields[i]->type); /* parameter types */ if (tr && tr->trace_flags & TRACE_ITER_VERBOSE) trace_seq_printf(s, "%s ", fmt); snprintf(print_fmt, sizeof(print_fmt), "%%s=%s%%s", fmt); /* parameter values */ if (se->fields[i]->is_string) { if (se->fields[i]->is_dynamic) { u32 offset, data_offset; char *str_field; offset = (u32)entry->fields[n_u64]; data_offset = offset & 0xffff; str_field = (char *)entry + data_offset; trace_seq_printf(s, print_fmt, se->fields[i]->name, STR_VAR_LEN_MAX, str_field, i == se->n_fields - 1 ? "" : " "); n_u64++; } else { trace_seq_printf(s, print_fmt, se->fields[i]->name, STR_VAR_LEN_MAX, (char *)&entry->fields[n_u64], i == se->n_fields - 1 ? "" : " "); n_u64 += STR_VAR_LEN_MAX / sizeof(u64); } } else { struct trace_print_flags __flags[] = { __def_gfpflag_names, {-1, NULL} }; char *space = (i == se->n_fields - 1 ? "" : " "); print_synth_event_num_val(s, print_fmt, se->fields[i]->name, se->fields[i]->size, entry->fields[n_u64], space); if (strcmp(se->fields[i]->type, "gfp_t") == 0) { trace_seq_puts(s, " ("); trace_print_flags_seq(s, "|", entry->fields[n_u64], __flags); trace_seq_putc(s, ')'); } n_u64++; } }end: trace_seq_putc(s, '\n'); return trace_handle_return(s);} static struct trace_event_functions synth_event_funcs = { .trace = print_synth_event}; static unsigned int trace_string(struct synth_trace_event *entry, struct synth_event *event, char *str_val, bool is_dynamic, unsigned int data_size, unsigned int *n_u64){ unsigned int len = 0; char *str_field; if (is_dynamic) { u32 data_offset; data_offset = offsetof(typeof(*entry), fields); data_offset += event->n_u64 * sizeof(u64); data_offset += data_size; str_field = (char *)entry + data_offset; len = strlen(str_val) + 1; strscpy(str_field, str_val, len); data_offset |= len << 16; *(u32 *)&entry->fields[*n_u64] = data_offset; (*n_u64)++; } else { str_field = (char *)&entry->fields[*n_u64]; strscpy(str_field, str_val, STR_VAR_LEN_MAX); (*n_u64) += STR_VAR_LEN_MAX / sizeof(u64); } return len;} static notrace void trace_event_raw_event_synth(void *__data, u64 *var_ref_vals, unsigned int *var_ref_idx){ unsigned int i, n_u64, val_idx, len, data_size = 0; struct trace_event_file *trace_file = __data; struct synth_trace_event *entry; struct trace_event_buffer fbuffer; struct trace_buffer *buffer; struct synth_event *event; int fields_size = 0; event = trace_file->event_call->data; if (trace_trigger_soft_disabled(trace_file)) return; fields_size = event->n_u64 * sizeof(u64); for (i = 0; i < event->n_dynamic_fields; i++) { unsigned int field_pos = event->dynamic_fields[i]->field_pos; char *str_val; val_idx = var_ref_idx[field_pos]; str_val = (char *)(long)var_ref_vals[val_idx]; len = strlen(str_val) + 1; fields_size += len; } /* * Avoid ring buffer recursion detection, as this event * is being performed within another event. */ buffer = trace_file->tr->array_buffer.buffer; ring_buffer_nest_start(buffer); entry = trace_event_buffer_reserve(&fbuffer, trace_file, sizeof(*entry) + fields_size); if (!entry) goto out; for (i = 0, n_u64 = 0; i < event->n_fields; i++) { val_idx = var_ref_idx[i]; if (event->fields[i]->is_string) { char *str_val = (char *)(long)var_ref_vals[val_idx]; len = trace_string(entry, event, str_val, event->fields[i]->is_dynamic, data_size, &n_u64); data_size += len; /* only dynamic string increments */ } else { struct synth_field *field = event->fields[i]; u64 val = var_ref_vals[val_idx]; switch (field->size) { case 1: *(u8 *)&entry->fields[n_u64] = (u8)val; break; case 2: *(u16 *)&entry->fields[n_u64] = (u16)val; break; case 4: *(u32 *)&entry->fields[n_u64] = (u32)val; break; default:Lines 1–500 of 2241. Load more
// SPDX-License-Identifier: GPL-2.0 /* * trace_events_synth - synthetic trace events * * Copyright (C) 2015, 2020 Tom Zanussi <tom.zanussi@linux.intel.com> */ #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/security.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/stacktrace.h> #include <linux/rculist.h> #include <linux/tracefs.h> /* for gfp flag names */ #include <linux/trace_events.h> #include <trace/events/mmflags.h> #include "trace_synth.h" #undef ERRORS #define ERRORS \ C(BAD_NAME, "Illegal name"), \ C(INVALID_CMD, "Command must be of the form: <name> field[;field] ..."),\ C(INVALID_DYN_CMD, "Command must be of the form: s or -:[synthetic/]<name> field[;field] ..."),\ C(EVENT_EXISTS, "Event already exists"), \ C(TOO_MANY_FIELDS, "Too many fields"), \ C(INCOMPLETE_TYPE, "Incomplete type"), \ C(INVALID_TYPE, "Invalid type"), \ C(INVALID_FIELD, "Invalid field"), \ C(INVALID_ARRAY_SPEC, "Invalid array specification"), #undef C #define C(a, b) SYNTH_ERR_##a enum { ERRORS }; #undef C #define C(a, b) b static const char *err_text[] = { ERRORS }; static char last_cmd[MAX_FILTER_STR_VAL]; static int errpos(const char *str) { return err_pos(last_cmd, str); } static void last_cmd_set(const char *str) { if (!str) return; strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1); } static void synth_err(u8 err_type, u8 err_pos) { tracing_log_err(NULL, "synthetic_events", last_cmd, err_text, err_type, err_pos); } static int create_synth_event(const char *raw_command); static int synth_event_show(struct seq_file *m, struct dyn_event *ev); static int synth_event_release(struct dyn_event *ev); static bool synth_event_is_busy(struct dyn_event *ev); static bool synth_event_match(const char *system, const char *event, int argc, const char **argv, struct dyn_event *ev); static struct dyn_event_operations synth_event_ops = { .create = create_synth_event, .show = synth_event_show, .is_busy = synth_event_is_busy, .free = synth_event_release, .match = synth_event_match, }; static bool is_synth_event(struct dyn_event *ev) { return ev->ops == &synth_event_ops; } static struct synth_event *to_synth_event(struct dyn_event *ev) { return container_of(ev, struct synth_event, devent); } static bool synth_event_is_busy(struct dyn_event *ev) { struct synth_event *event = to_synth_event(ev); return event->ref != 0; } static bool synth_event_match(const char *system, const char *event, int argc, const char **argv, struct dyn_event *ev) { struct synth_event *sev = to_synth_event(ev); return strcmp(sev->name, event) == 0 && (!system || strcmp(system, SYNTH_SYSTEM) == 0); } struct synth_trace_event { struct trace_entry ent; u64 fields[]; }; static int synth_event_define_fields(struct trace_event_call *call) { struct synth_trace_event trace; int offset = offsetof(typeof(trace), fields); struct synth_event *event = call->data; unsigned int i, size, n_u64; char *name, *type; bool is_signed; int ret = 0; for (i = 0, n_u64 = 0; i < event->n_fields; i++) { size = event->fields[i]->size; is_signed = event->fields[i]->is_signed; type = event->fields[i]->type; name = event->fields[i]->name; ret = trace_define_field(call, type, name, offset, size, is_signed, FILTER_OTHER); if (ret) break; event->fields[i]->offset = n_u64; if (event->fields[i]->is_string && !event->fields[i]->is_dynamic) { offset += STR_VAR_LEN_MAX; n_u64 += STR_VAR_LEN_MAX / sizeof(u64); } else { offset += sizeof(u64); n_u64++; } } event->n_u64 = n_u64; return ret; } static bool synth_field_signed(char *type) { if (str_has_prefix(type, "u")) return false; if (strcmp(type, "gfp_t") == 0) return false; return true; } static int synth_field_is_string(char *type) { if (strstr(type, "char[") != NULL) return true; return false; } static int synth_field_string_size(char *type) { char buf[4], *end, *start; unsigned int len; int size, err; start = strstr(type, "char["); if (start == NULL) return -EINVAL; start += sizeof("char[") - 1; end = strchr(type, ']'); if (!end || end < start || type + strlen(type) > end + 1) return -EINVAL; len = end - start; if (len > 3) return -EINVAL; if (len == 0) return 0; /* variable-length string */ strncpy(buf, start, len); buf[len] = '\0'; err = kstrtouint(buf, 0, &size); if (err) return err; if (size > STR_VAR_LEN_MAX) return -EINVAL; return size; } static int synth_field_size(char *type) { int size = 0; if (strcmp(type, "s64") == 0) size = sizeof(s64); else if (strcmp(type, "u64") == 0) size = sizeof(u64); else if (strcmp(type, "s32") == 0) size = sizeof(s32); else if (strcmp(type, "u32") == 0) size = sizeof(u32); else if (strcmp(type, "s16") == 0) size = sizeof(s16); else if (strcmp(type, "u16") == 0) size = sizeof(u16); else if (strcmp(type, "s8") == 0) size = sizeof(s8); else if (strcmp(type, "u8") == 0) size = sizeof(u8); else if (strcmp(type, "char") == 0) size = sizeof(char); else if (strcmp(type, "unsigned char") == 0) size = sizeof(unsigned char); else if (strcmp(type, "int") == 0) size = sizeof(int); else if (strcmp(type, "unsigned int") == 0) size = sizeof(unsigned int); else if (strcmp(type, "long") == 0) size = sizeof(long); else if (strcmp(type, "unsigned long") == 0) size = sizeof(unsigned long); else if (strcmp(type, "bool") == 0) size = sizeof(bool); else if (strcmp(type, "pid_t") == 0) size = sizeof(pid_t); else if (strcmp(type, "gfp_t") == 0) size = sizeof(gfp_t); else if (synth_field_is_string(type)) size = synth_field_string_size(type); return size; } static const char *synth_field_fmt(char *type) { const char *fmt = "%llu"; if (strcmp(type, "s64") == 0) fmt = "%lld"; else if (strcmp(type, "u64") == 0) fmt = "%llu"; else if (strcmp(type, "s32") == 0) fmt = "%d"; else if (strcmp(type, "u32") == 0) fmt = "%u"; else if (strcmp(type, "s16") == 0) fmt = "%d"; else if (strcmp(type, "u16") == 0) fmt = "%u"; else if (strcmp(type, "s8") == 0) fmt = "%d"; else if (strcmp(type, "u8") == 0) fmt = "%u"; else if (strcmp(type, "char") == 0) fmt = "%d"; else if (strcmp(type, "unsigned char") == 0) fmt = "%u"; else if (strcmp(type, "int") == 0) fmt = "%d"; else if (strcmp(type, "unsigned int") == 0) fmt = "%u"; else if (strcmp(type, "long") == 0) fmt = "%ld"; else if (strcmp(type, "unsigned long") == 0) fmt = "%lu"; else if (strcmp(type, "bool") == 0) fmt = "%d"; else if (strcmp(type, "pid_t") == 0) fmt = "%d"; else if (strcmp(type, "gfp_t") == 0) fmt = "%x"; else if (synth_field_is_string(type)) fmt = "%.*s"; return fmt; } static void print_synth_event_num_val(struct trace_seq *s, char *print_fmt, char *name, int size, u64 val, char *space) { switch (size) { case 1: trace_seq_printf(s, print_fmt, name, (u8)val, space); break; case 2: trace_seq_printf(s, print_fmt, name, (u16)val, space); break; case 4: trace_seq_printf(s, print_fmt, name, (u32)val, space); break; default: trace_seq_printf(s, print_fmt, name, val, space); break; } } static enum print_line_t print_synth_event(struct trace_iterator *iter, int flags, struct trace_event *event) { struct trace_array *tr = iter->tr; struct trace_seq *s = &iter->seq; struct synth_trace_event *entry; struct synth_event *se; unsigned int i, n_u64; char print_fmt[32]; const char *fmt; entry = (struct synth_trace_event *)iter->ent; se = container_of(event, struct synth_event, call.event); trace_seq_printf(s, "%s: ", se->name); for (i = 0, n_u64 = 0; i < se->n_fields; i++) { if (trace_seq_has_overflowed(s)) goto end; fmt = synth_field_fmt(se->fields[i]->type); /* parameter types */ if (tr && tr->trace_flags & TRACE_ITER_VERBOSE) trace_seq_printf(s, "%s ", fmt); snprintf(print_fmt, sizeof(print_fmt), "%%s=%s%%s", fmt); /* parameter values */ if (se->fields[i]->is_string) { if (se->fields[i]->is_dynamic) { u32 offset, data_offset; char *str_field; offset = (u32)entry->fields[n_u64]; data_offset = offset & 0xffff; str_field = (char *)entry + data_offset; trace_seq_printf(s, print_fmt, se->fields[i]->name, STR_VAR_LEN_MAX, str_field, i == se->n_fields - 1 ? "" : " "); n_u64++; } else { trace_seq_printf(s, print_fmt, se->fields[i]->name, STR_VAR_LEN_MAX, (char *)&entry->fields[n_u64], i == se->n_fields - 1 ? "" : " "); n_u64 += STR_VAR_LEN_MAX / sizeof(u64); } } else { struct trace_print_flags __flags[] = { __def_gfpflag_names, {-1, NULL} }; char *space = (i == se->n_fields - 1 ? "" : " "); print_synth_event_num_val(s, print_fmt, se->fields[i]->name, se->fields[i]->size, entry->fields[n_u64], space); if (strcmp(se->fields[i]->type, "gfp_t") == 0) { trace_seq_puts(s, " ("); trace_print_flags_seq(s, "|", entry->fields[n_u64], __flags); trace_seq_putc(s, ')'); } n_u64++; } } end: trace_seq_putc(s, '\n'); return trace_handle_return(s); } static struct trace_event_functions synth_event_funcs = { .trace = print_synth_event }; static unsigned int trace_string(struct synth_trace_event *entry, struct synth_event *event, char *str_val, bool is_dynamic, unsigned int data_size, unsigned int *n_u64) { unsigned int len = 0; char *str_field; if (is_dynamic) { u32 data_offset; data_offset = offsetof(typeof(*entry), fields); data_offset += event->n_u64 * sizeof(u64); data_offset += data_size; str_field = (char *)entry + data_offset; len = strlen(str_val) + 1; strscpy(str_field, str_val, len); data_offset |= len << 16; *(u32 *)&entry->fields[*n_u64] = data_offset; (*n_u64)++; } else { str_field = (char *)&entry->fields[*n_u64]; strscpy(str_field, str_val, STR_VAR_LEN_MAX); (*n_u64) += STR_VAR_LEN_MAX / sizeof(u64); } return len; } static notrace void trace_event_raw_event_synth(void *__data, u64 *var_ref_vals, unsigned int *var_ref_idx) { unsigned int i, n_u64, val_idx, len, data_size = 0; struct trace_event_file *trace_file = __data; struct synth_trace_event *entry; struct trace_event_buffer fbuffer; struct trace_buffer *buffer; struct synth_event *event; int fields_size = 0; event = trace_file->event_call->data; if (trace_trigger_soft_disabled(trace_file)) return; fields_size = event->n_u64 * sizeof(u64); for (i = 0; i < event->n_dynamic_fields; i++) { unsigned int field_pos = event->dynamic_fields[i]->field_pos; char *str_val; val_idx = var_ref_idx[field_pos]; str_val = (char *)(long)var_ref_vals[val_idx]; len = strlen(str_val) + 1; fields_size += len; } /* * Avoid ring buffer recursion detection, as this event * is being performed within another event. */ buffer = trace_file->tr->array_buffer.buffer; ring_buffer_nest_start(buffer); entry = trace_event_buffer_reserve(&fbuffer, trace_file, sizeof(*entry) + fields_size); if (!entry) goto out; for (i = 0, n_u64 = 0; i < event->n_fields; i++) { val_idx = var_ref_idx[i]; if (event->fields[i]->is_string) { char *str_val = (char *)(long)var_ref_vals[val_idx]; len = trace_string(entry, event, str_val, event->fields[i]->is_dynamic, data_size, &n_u64); data_size += len; /* only dynamic string increments */ } else { struct synth_field *field = event->fields[i]; u64 val = var_ref_vals[val_idx]; switch (field->size) { case 1: *(u8 *)&entry->fields[n_u64] = (u8)val; break; case 2: *(u16 *)&entry->fields[n_u64] = (u16)val; break; case 4: *(u32 *)&entry->fields[n_u64] = (u32)val; break; default: