}
switch (entry->type) {
case TRACE_FN: {
- struct ftrace_entry *field = (struct ftrace_entry *)entry;
+ struct ftrace_entry *field;
+
+ trace_assign_type(field, entry);
seq_print_ip_sym(s, field->ip, sym_flags);
trace_seq_puts(s, " (");
}
case TRACE_CTX:
case TRACE_WAKE: {
- struct ctx_switch_entry *field =
- (struct ctx_switch_entry *)entry;
+ struct ctx_switch_entry *field;
+
+ trace_assign_type(field, entry);
T = field->next_state < sizeof(state_to_char) ?
state_to_char[field->next_state] : 'X';
break;
}
case TRACE_SPECIAL: {
- struct special_entry *field = (struct special_entry *)entry;
+ struct special_entry *field;
+
+ trace_assign_type(field, entry);
trace_seq_printf(s, "# %ld %ld %ld\n",
field->arg1,
break;
}
case TRACE_STACK: {
- struct stack_entry *field = (struct stack_entry *)entry;
+ struct stack_entry *field;
+
+ trace_assign_type(field, entry);
for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
if (i)
break;
}
case TRACE_PRINT: {
- struct print_entry *field = (struct print_entry *)entry;
+ struct print_entry *field;
+
+ trace_assign_type(field, entry);
seq_print_ip_sym(s, field->ip, sym_flags);
trace_seq_printf(s, ": %s", field->buf);
switch (entry->type) {
case TRACE_FN: {
- struct ftrace_entry *field = (struct ftrace_entry *)entry;
+ struct ftrace_entry *field;
+
+ trace_assign_type(field, entry);
ret = seq_print_ip_sym(s, field->ip, sym_flags);
if (!ret)
}
case TRACE_CTX:
case TRACE_WAKE: {
- struct ctx_switch_entry *field =
- (struct ctx_switch_entry *)entry;
+ struct ctx_switch_entry *field;
+
+ trace_assign_type(field, entry);
S = field->prev_state < sizeof(state_to_char) ?
state_to_char[field->prev_state] : 'X';
break;
}
case TRACE_SPECIAL: {
- struct special_entry *field = (struct special_entry *)entry;
+ struct special_entry *field;
+
+ trace_assign_type(field, entry);
ret = trace_seq_printf(s, "# %ld %ld %ld\n",
field->arg1,
break;
}
case TRACE_STACK: {
- struct stack_entry *field = (struct stack_entry *)entry;
+ struct stack_entry *field;
+
+ trace_assign_type(field, entry);
for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
if (i) {
break;
}
case TRACE_PRINT: {
- struct print_entry *field = (struct print_entry *)entry;
+ struct print_entry *field;
+
+ trace_assign_type(field, entry);
seq_print_ip_sym(s, field->ip, sym_flags);
trace_seq_printf(s, ": %s", field->buf);
switch (entry->type) {
case TRACE_FN: {
- struct ftrace_entry *field = (struct ftrace_entry *)entry;
+ struct ftrace_entry *field;
+
+ trace_assign_type(field, entry);
ret = trace_seq_printf(s, "%x %x\n",
field->ip,
}
case TRACE_CTX:
case TRACE_WAKE: {
- struct ctx_switch_entry *field =
- (struct ctx_switch_entry *)entry;
+ struct ctx_switch_entry *field;
+
+ trace_assign_type(field, entry);
S = field->prev_state < sizeof(state_to_char) ?
state_to_char[field->prev_state] : 'X';
}
case TRACE_SPECIAL:
case TRACE_STACK: {
- struct special_entry *field = (struct special_entry *)entry;
+ struct special_entry *field;
+
+ trace_assign_type(field, entry);
ret = trace_seq_printf(s, "# %ld %ld %ld\n",
field->arg1,
break;
}
case TRACE_PRINT: {
- struct print_entry *field = (struct print_entry *)entry;
+ struct print_entry *field;
+
+ trace_assign_type(field, entry);
trace_seq_printf(s, "# %lx %s", field->ip, field->buf);
if (entry->flags & TRACE_FLAG_CONT)
switch (entry->type) {
case TRACE_FN: {
- struct ftrace_entry *field = (struct ftrace_entry *)entry;
+ struct ftrace_entry *field;
+
+ trace_assign_type(field, entry);
SEQ_PUT_HEX_FIELD_RET(s, field->ip);
SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
}
case TRACE_CTX:
case TRACE_WAKE: {
- struct ctx_switch_entry *field =
- (struct ctx_switch_entry *)entry;
+ struct ctx_switch_entry *field;
+
+ trace_assign_type(field, entry);
S = field->prev_state < sizeof(state_to_char) ?
state_to_char[field->prev_state] : 'X';
}
case TRACE_SPECIAL:
case TRACE_STACK: {
- struct special_entry *field = (struct special_entry *)entry;
+ struct special_entry *field;
+
+ trace_assign_type(field, entry);
SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
switch (entry->type) {
case TRACE_FN: {
- struct ftrace_entry *field = (struct ftrace_entry *)entry;
+ struct ftrace_entry *field;
+
+ trace_assign_type(field, entry);
SEQ_PUT_FIELD_RET(s, field->ip);
SEQ_PUT_FIELD_RET(s, field->parent_ip);
break;
}
case TRACE_CTX: {
- struct ctx_switch_entry *field =
- (struct ctx_switch_entry *)entry;
+ struct ctx_switch_entry *field;
+
+ trace_assign_type(field, entry);
SEQ_PUT_FIELD_RET(s, field->prev_pid);
SEQ_PUT_FIELD_RET(s, field->prev_prio);
}
case TRACE_SPECIAL:
case TRACE_STACK: {
- struct special_entry *field = (struct special_entry *)entry;
+ struct special_entry *field;
+
+ trace_assign_type(field, entry);
SEQ_PUT_FIELD_RET(s, field->arg1);
SEQ_PUT_FIELD_RET(s, field->arg2);
struct trace_array_cpu *data[NR_CPUS];
};
+#define FTRACE_CMP_TYPE(var, type) \
+ __builtin_types_compatible_p(typeof(var), type *)
+
+#undef IF_ASSIGN
+#define IF_ASSIGN(var, entry, etype, id) \
+ if (FTRACE_CMP_TYPE(var, etype)) { \
+ var = (typeof(var))(entry); \
+ WARN_ON(id && (entry)->type != id); \
+ break; \
+ }
+
+/* Will cause compile errors if type is not found. */
+extern void __ftrace_bad_type(void);
+
+/*
+ * The trace_assign_type is a verifier that the entry type is
+ * the same as the type being assigned. To add new types simply
+ * add a line with the following format:
+ *
+ * IF_ASSIGN(var, ent, type, id);
+ *
+ * Where "type" is the trace type that includes the trace_entry
+ * as the "ent" item. And "id" is the trace identifier that is
+ * used in the trace_type enum.
+ *
+ * If the type can have more than one id, then use zero.
+ */
+#define trace_assign_type(var, ent) \
+ do { \
+ IF_ASSIGN(var, ent, struct ftrace_entry, TRACE_FN); \
+ IF_ASSIGN(var, ent, struct ctx_switch_entry, 0); \
+ IF_ASSIGN(var, ent, struct trace_field_cont, TRACE_CONT); \
+ IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \
+ IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \
+ IF_ASSIGN(var, ent, struct special_entry, 0); \
+ IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \
+ TRACE_MMIO_RW); \
+ IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \
+ TRACE_MMIO_MAP); \
+ IF_ASSIGN(var, ent, struct trace_boot, TRACE_BOOT); \
+ __ftrace_bad_type(); \
+ } while (0)
/* Return values for print_line callback */
enum print_line_t {
static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
{
struct trace_entry *entry = iter->ent;
- struct trace_mmiotrace_rw *field =
- (struct trace_mmiotrace_rw *)entry;
- struct mmiotrace_rw *rw = &field->rw;
+ struct trace_mmiotrace_rw *field;
+ struct mmiotrace_rw *rw;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret = 1;
+ trace_assign_type(field, entry);
+ rw = &field->rw;
+
switch (rw->opcode) {
case MMIO_READ:
ret = trace_seq_printf(s,
static enum print_line_t mmio_print_map(struct trace_iterator *iter)
{
struct trace_entry *entry = iter->ent;
- struct mmiotrace_map *m = (struct mmiotrace_map *)entry;
+ struct trace_mmiotrace_map *field;
+ struct mmiotrace_map *m;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret;
+ trace_assign_type(field, entry);
+ m = &field->map;
+
switch (m->opcode) {
case MMIO_PROBE:
ret = trace_seq_printf(s,