static int function_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { struct tep_handle *pevent = event->tep; unsigned long long function; const char *func; if (tep_get_field_val(s, event, "ip", record, &function, 1)) return trace_seq_putc(s, '!'); func = tep_find_function(pevent, function); if (func) trace_seq_printf(s, "%s <-- ", func); else trace_seq_printf(s, "0x%llx", function); if (tep_get_field_val(s, event, "parent_ip", record, &function, 1)) return trace_seq_putc(s, '!'); func = tep_find_function(pevent, function); if (func) trace_seq_printf(s, "%s", func); else trace_seq_printf(s, "0x%llx", function); return 0; }
static int fgraph_ent_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { struct tracecmd_ftrace *finfo = context; struct tep_record *rec; unsigned long long val, pid; int cpu; ret_event_check(finfo, event->tep); if (tep_get_common_field_val(s, event, "common_pid", record, &pid, 1)) return trace_seq_putc(s, '!'); if (tep_get_field_val(s, event, "func", record, &val, 1)) return trace_seq_putc(s, '!'); rec = tracecmd_peek_next_data(tracecmd_curr_thread_handle, &cpu); if (rec) rec = get_return_for_leaf(s, cpu, pid, val, rec, finfo); if (rec) { /* * If this is a leaf function, then get_return_for_leaf * returns the return of the function */ print_graph_entry_leaf(s, event, record, rec, finfo); free_record(rec); } else print_graph_nested(s, event, record); return 0; }
static int sched_wakeup_handler(struct trace_seq *s, struct tep_record *record, struct event_format *event, void *context) { struct format_field *field; unsigned long long val; if (tep_get_field_val(s, event, "pid", record, &val, 1)) return trace_seq_putc(s, '!'); field = tep_find_any_field(event, "comm"); if (field) { write_and_save_comm(field, record, s, val); trace_seq_putc(s, ':'); } trace_seq_printf(s, "%lld", val); if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0) trace_seq_printf(s, " [%lld]", val); if (tep_get_field_val(s, event, "success", record, &val, 1) == 0) trace_seq_printf(s, " success=%lld", val); if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) trace_seq_printf(s, " CPU:%03llu", val); return 0; }
enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags, struct trace_event *event) { struct trace_seq *s = &iter->seq; struct trace_entry *ent = iter->ent; struct syscall_trace_enter *trace; struct syscall_metadata *entry; int i, ret, syscall; trace = (typeof(trace))ent; syscall = trace->nr; entry = syscall_nr_to_meta(syscall); if (!entry) goto end; if (entry->enter_event->event.type != ent->type) { WARN_ON_ONCE(1); goto end; } ret = trace_seq_printf(s, "%s(", entry->name); if (!ret) return TRACE_TYPE_PARTIAL_LINE; for (i = 0; i < entry->nb_args; i++) { /* parameter types */ if (trace_flags & TRACE_ITER_VERBOSE) { ret = trace_seq_printf(s, "%s ", entry->types[i]); if (!ret) return TRACE_TYPE_PARTIAL_LINE; } /* parameter values */ ret = trace_seq_printf(s, "%s: %lx%s", entry->args[i], trace->args[i], i == entry->nb_args - 1 ? "" : ", "); if (!ret) return TRACE_TYPE_PARTIAL_LINE; } ret = trace_seq_putc(s, ')'); if (!ret) return TRACE_TYPE_PARTIAL_LINE; end: ret = trace_seq_putc(s, '\n'); if (!ret) return TRACE_TYPE_PARTIAL_LINE; return TRACE_TYPE_HANDLED; }
int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) { int i; int nr; int ret; struct syscall_metadata *entry; struct syscall_trace_enter trace; int offset = offsetof(struct syscall_trace_enter, args); nr = syscall_name_to_nr(call->data); entry = syscall_nr_to_meta(nr); if (!entry) return 0; ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", SYSCALL_FIELD(int, nr)); if (!ret) return 0; for (i = 0; i < entry->nb_args; i++) { ret = trace_seq_printf(s, "\tfield:%s %s;", entry->types[i], entry->args[i]); if (!ret) return 0; ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;\n", offset, sizeof(unsigned long)); if (!ret) return 0; offset += sizeof(unsigned long); } trace_seq_puts(s, "\nprint fmt: \""); for (i = 0; i < entry->nb_args; i++) { ret = trace_seq_printf(s, "%s: 0x%%0%zulx%s", entry->args[i], sizeof(unsigned long), i == entry->nb_args - 1 ? "" : ", "); if (!ret) return 0; } trace_seq_putc(s, '"'); for (i = 0; i < entry->nb_args; i++) { ret = trace_seq_printf(s, ", ((unsigned long)(REC->%s))", entry->args[i]); if (!ret) return 0; } return trace_seq_putc(s, '\n'); }
static int print_graph_entry_leaf(struct trace_seq *s, struct tep_event *event, struct tep_record *record, struct tep_record *ret_rec, struct tracecmd_ftrace *finfo) { struct tep_handle *pevent = event->tep; unsigned long long rettime, calltime; unsigned long long duration, depth; unsigned long long val; const char *func; int ret; int i; if (tep_get_field_val(s, finfo->fgraph_ret_event, "rettime", ret_rec, &rettime, 1)) return trace_seq_putc(s, '!'); if (tep_get_field_val(s, finfo->fgraph_ret_event, "calltime", ret_rec, &calltime, 1)) return trace_seq_putc(s, '!'); duration = rettime - calltime; /* Overhead */ print_graph_overhead(s, duration); /* Duration */ print_graph_duration(s, duration); if (tep_get_field_val(s, event, "depth", record, &depth, 1)) return trace_seq_putc(s, '!'); /* Function */ for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) trace_seq_putc(s, ' '); if (tep_get_field_val(s, event, "func", record, &val, 1)) return trace_seq_putc(s, '!'); func = tep_find_function(pevent, val); if (func) ret = trace_seq_printf(s, "%s();", func); else ret = trace_seq_printf(s, "%llx();", val); if (ret && fgraph_depth->set) ret = trace_seq_printf(s, " (%lld)", depth); return ret; }
static int fgraph_ret_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { struct tracecmd_ftrace *finfo = context; unsigned long long rettime, calltime; unsigned long long duration, depth; unsigned long long val; const char *func; int i; ret_event_check(finfo, event->tep); if (tep_get_field_val(s, event, "rettime", record, &rettime, 1)) return trace_seq_putc(s, '!'); if (tep_get_field_val(s, event, "calltime", record, &calltime, 1)) return trace_seq_putc(s, '!'); duration = rettime - calltime; /* Overhead */ print_graph_overhead(s, duration); /* Duration */ print_graph_duration(s, duration); if (tep_get_field_val(s, event, "depth", record, &depth, 1)) return trace_seq_putc(s, '!'); /* Function */ for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) trace_seq_putc(s, ' '); trace_seq_putc(s, '}'); if (fgraph_tail->set) { if (tep_get_field_val(s, event, "func", record, &val, 0)) return 0; func = tep_find_function(event->tep, val); if (!func) return 0; trace_seq_printf(s, " /* %s */", func); } if (fgraph_depth->set) trace_seq_printf(s, " (%lld)", depth); return 0; }
static enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags, struct trace_event *event) { struct trace_seq *s = &iter->seq; struct trace_entry *ent = iter->ent; struct syscall_trace_exit *trace; int syscall; struct syscall_metadata *entry; trace = (typeof(trace))ent; syscall = trace->nr; entry = syscall_nr_to_meta(syscall); if (!entry) { trace_seq_putc(s, '\n'); goto out; } if (entry->exit_event->event.type != ent->type) { WARN_ON_ONCE(1); return TRACE_TYPE_UNHANDLED; } trace_seq_printf(s, "%s -> 0x%lx\n", entry->name, trace->ret); out: return trace_handle_return(s); }
static void print_graph_duration(struct trace_seq *s, unsigned long long duration) { unsigned long usecs = duration / 1000; unsigned long nsecs_rem = duration % 1000; /* log10(ULONG_MAX) + '\0' */ char msecs_str[21]; char nsecs_str[5]; int len; int i; sprintf(msecs_str, "%lu", usecs); /* Print msecs */ len = s->len; trace_seq_printf(s, "%lu", usecs); /* Print nsecs (we don't want to exceed 7 numbers) */ if ((s->len - len) < 7) { snprintf(nsecs_str, MIN(sizeof(nsecs_str), 8 - len), "%03lu", nsecs_rem); trace_seq_printf(s, ".%s", nsecs_str); } len = s->len - len; trace_seq_puts(s, " us "); /* Print remaining spaces to fit the row's width */ for (i = len; i < 7; i++) trace_seq_putc(s, ' '); trace_seq_puts(s, "| "); }
static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent) { const unsigned char *pdu_buf; int pdu_len; int i, end, ret; pdu_buf = pdu_start(ent); pdu_len = te_blk_io_trace(ent)->pdu_len; if (!pdu_len) return 1; for (end = pdu_len - 1; end >= 0; end--) if (pdu_buf[end]) break; end++; if (!trace_seq_putc(s, '(')) return 0; for (i = 0; i < pdu_len; i++) { ret = trace_seq_printf(s, "%s%02x", i == 0 ? "" : " ", pdu_buf[i]); if (!ret) return ret; if (i == end && end != pdu_len - 1) return trace_seq_puts(s, " ..) "); } return trace_seq_puts(s, ") "); }
static enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags, struct trace_event *event) { struct trace_array *tr = iter->tr; struct trace_seq *s = &iter->seq; struct trace_entry *ent = iter->ent; struct syscall_trace_enter *trace; struct syscall_metadata *entry; int i, syscall; trace = (typeof(trace))ent; syscall = trace->nr; entry = syscall_nr_to_meta(syscall); if (!entry) goto end; if (entry->enter_event->event.type != ent->type) { WARN_ON_ONCE(1); goto end; } trace_seq_printf(s, "%s(", entry->name); for (i = 0; i < entry->nb_args; i++) { if (trace_seq_has_overflowed(s)) goto end; /* parameter types */ if (tr->trace_flags & TRACE_ITER_VERBOSE) trace_seq_printf(s, "%s ", entry->types[i]); /* parameter values */ trace_seq_printf(s, "%s: %lx%s", entry->args[i], trace->args[i], i == entry->nb_args - 1 ? "" : ", "); } trace_seq_putc(s, ')'); end: trace_seq_putc(s, '\n'); return trace_handle_return(s); }
static const char *nvme_trace_common(struct trace_seq *p, u8 *cdw10) { const char *ret = trace_seq_buffer_ptr(p); trace_seq_printf(p, "cdw10=%*ph", 24, cdw10); trace_seq_putc(p, 0); return ret; }
const char *nvme_trace_disk_name(struct trace_seq *p, char *name) { const char *ret = trace_seq_buffer_ptr(p); if (*name) trace_seq_printf(p, "disk=%s, ", name); trace_seq_putc(p, 0); return ret; }
static int blk_log_msg(struct trace_seq *s, const struct trace_entry *ent) { int ret; const struct blk_io_trace *t = te_blk_io_trace(ent); ret = trace_seq_putmem(s, t + 1, t->pdu_len); if (ret) return trace_seq_putc(s, '\n'); return ret; }
static const char *nvme_trace_admin_identify(struct trace_seq *p, u8 *cdw10) { const char *ret = trace_seq_buffer_ptr(p); u8 cns = cdw10[0]; u16 ctrlid = get_unaligned_le16(cdw10 + 2); trace_seq_printf(p, "cns=%u, ctrlid=%u", cns, ctrlid); trace_seq_putc(p, 0); return ret; }
static void write_state(struct trace_seq *s, int val) { const char states[] = "SDTtZXxW"; int found = 0; int i; for (i = 0; i < (sizeof(states) - 1); i++) { if (!(val & (1 << i))) continue; if (found) trace_seq_putc(s, '|'); found = 1; trace_seq_putc(s, states[i]); } if (!found) trace_seq_putc(s, 'R'); }
static const char *nvme_trace_dsm(struct trace_seq *p, u8 *cdw10) { const char *ret = trace_seq_buffer_ptr(p); trace_seq_printf(p, "nr=%u, attributes=%u", get_unaligned_le32(cdw10), get_unaligned_le32(cdw10 + 4)); trace_seq_putc(p, 0); return ret; }
static void dbg_printf_pevent_info(struct event_format *event, struct pevent_record *rec) { static struct trace_seq s; event->pevent->print_raw = 1; trace_seq_init(&s); pevent_event_info(&s, event, rec); trace_seq_putc(&s, '\n'); trace_seq_terminate(&s); fprintf(stderr, "%.*s", s.len, s.buffer); trace_seq_destroy(&s); }
static int sched_switch_handler(struct trace_seq *s, struct tep_record *record, struct event_format *event, void *context) { struct format_field *field; unsigned long long val; if (tep_get_field_val(s, event, "prev_pid", record, &val, 1)) return trace_seq_putc(s, '!'); field = tep_find_any_field(event, "prev_comm"); if (field) { write_and_save_comm(field, record, s, val); trace_seq_putc(s, ':'); } trace_seq_printf(s, "%lld ", val); if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) trace_seq_printf(s, "[%d] ", (int) val); if (tep_get_field_val(s, event, "prev_state", record, &val, 0) == 0) write_state(s, val); trace_seq_puts(s, " ==> "); if (tep_get_field_val(s, event, "next_pid", record, &val, 1)) return trace_seq_putc(s, '!'); field = tep_find_any_field(event, "next_comm"); if (field) { write_and_save_comm(field, record, s, val); trace_seq_putc(s, ':'); } trace_seq_printf(s, "%lld", val); if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0) trace_seq_printf(s, " [%d]", (int) val); return 0; }
static int print_graph_nested(struct trace_seq *s, struct tep_event *event, struct tep_record *record) { struct tep_handle *pevent = event->tep; unsigned long long depth; unsigned long long val; const char *func; int ret; int i; /* No overhead */ print_graph_overhead(s, -1); /* No time */ trace_seq_puts(s, " | "); if (tep_get_field_val(s, event, "depth", record, &depth, 1)) return trace_seq_putc(s, '!'); /* Function */ for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) trace_seq_putc(s, ' '); if (tep_get_field_val(s, event, "func", record, &val, 1)) return trace_seq_putc(s, '!'); func = tep_find_function(pevent, val); if (func) ret = trace_seq_printf(s, "%s() {", func); else ret = trace_seq_printf(s, "%llx() {", val); if (ret && fgraph_depth->set) ret = trace_seq_printf(s, " (%lld)", depth); return ret; }
const char *cper_mem_err_unpack(struct trace_seq *p, struct cper_mem_err_compact *cmem) { const char *ret = trace_seq_buffer_ptr(p); if (cper_mem_err_location(cmem, rcd_decode_str)) trace_seq_printf(p, "%s", rcd_decode_str); if (cper_dimm_err_location(cmem, rcd_decode_str)) trace_seq_printf(p, "%s", rcd_decode_str); trace_seq_putc(p, '\0'); return ret; }
static const char *nvme_trace_create_cq(struct trace_seq *p, u8 *cdw10) { const char *ret = trace_seq_buffer_ptr(p); u16 cqid = get_unaligned_le16(cdw10); u16 qsize = get_unaligned_le16(cdw10 + 2); u16 cq_flags = get_unaligned_le16(cdw10 + 4); u16 irq_vector = get_unaligned_le16(cdw10 + 6); trace_seq_printf(p, "cqid=%u, qsize=%u, cq_flags=0x%x, irq_vector=%u", cqid, qsize, cq_flags, irq_vector); trace_seq_putc(p, 0); return ret; }
static int function_handler(struct trace_seq *s, struct pevent_record *record, struct event_format *event, void *context) { struct pevent *pevent = event->pevent; unsigned long long function; unsigned long long pfunction; const char *func; const char *parent; int index; if (pevent_get_field_val(s, event, "ip", record, &function, 1)) return trace_seq_putc(s, '!'); func = pevent_find_function(pevent, function); if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1)) return trace_seq_putc(s, '!'); parent = pevent_find_function(pevent, pfunction); index = add_and_get_index(parent, func, record->cpu); trace_seq_printf(s, "%*s", index*3, ""); if (func) trace_seq_printf(s, "%s", func); else trace_seq_printf(s, "0x%llx", function); trace_seq_printf(s, " <-- "); if (parent) trace_seq_printf(s, "%s", parent); else trace_seq_printf(s, "0x%llx", pfunction); return 0; }
static const char *nvme_trace_read_write(struct trace_seq *p, u8 *cdw10) { const char *ret = trace_seq_buffer_ptr(p); u64 slba = get_unaligned_le64(cdw10); u16 length = get_unaligned_le16(cdw10 + 8); u16 control = get_unaligned_le16(cdw10 + 10); u32 dsmgmt = get_unaligned_le32(cdw10 + 12); u32 reftag = get_unaligned_le32(cdw10 + 16); trace_seq_printf(p, "slba=%llu, len=%u, ctrl=0x%x, dsmgmt=%u, reftag=%u", slba, length, control, dsmgmt, reftag); trace_seq_putc(p, 0); return ret; }
/* * The ring buffer header is special. We must manually up keep it. */ int ring_buffer_print_entry_header(struct trace_seq *s) { trace_seq_puts(s, "# compressed entry header\n"); trace_seq_puts(s, "\ttype_len : 5 bits\n"); trace_seq_puts(s, "\ttime_delta : 27 bits\n"); trace_seq_puts(s, "\tarray : 32 bits\n"); trace_seq_putc(s, '\n'); trace_seq_printf(s, "\tpadding : type == %d\n", RINGBUF_TYPE_PADDING); trace_seq_printf(s, "\ttime_extend : type == %d\n", RINGBUF_TYPE_TIME_EXTEND); trace_seq_printf(s, "\tdata max type_len == %d\n", RINGBUF_TYPE_DATA_TYPE_LEN_MAX); return !trace_seq_has_overflowed(s); }
static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent) { const unsigned char *pdu_buf; int pdu_len; int i, end, ret; pdu_buf = pdu_start(ent); pdu_len = te_blk_io_trace(ent)->pdu_len; if (!pdu_len) return 1; /* find the last zero that needs to be printed */ for (end = pdu_len - 1; end >= 0; end--) if (pdu_buf[end]) break; end++; if (!trace_seq_putc(s, '(')) return 0; for (i = 0; i < pdu_len; i++) { ret = trace_seq_printf(s, "%s%02x", i == 0 ? "" : " ", pdu_buf[i]); if (!ret) return ret; /* * stop when the rest is just zeroes and indicate so * with a ".." appended */ if (i == end && end != pdu_len - 1) return trace_seq_puts(s, " ..) "); } return trace_seq_puts(s, ") "); }
int kp_strfmt(ktap_state *ks, struct trace_seq *seq) { int arg = 1; size_t sfl; ktap_value *arg_fmt = kp_arg(ks, 1); int argnum = kp_arg_nr(ks); const char *strfrmt, *strfrmt_end; strfrmt = svalue(arg_fmt); sfl = rawtsvalue(arg_fmt)->tsv.len; strfrmt_end = strfrmt + sfl; while (strfrmt < strfrmt_end) { if (*strfrmt != L_ESC) trace_seq_putc(seq, *strfrmt++); else if (*++strfrmt == L_ESC) trace_seq_putc(seq, *strfrmt++); else { /* format item */ char form[MAX_FORMAT]; if (++arg > argnum) { ktap_argerror(ks, arg, "no value"); return -1; } strfrmt = scanformat(ks, strfrmt, form); switch (*strfrmt++) { case 'c': trace_seq_printf(seq, form, nvalue(kp_arg(ks, arg))); break; case 'd': case 'i': { ktap_number n = nvalue(kp_arg(ks, arg)); INTFRM_T ni = (INTFRM_T)n; addlenmod(form, INTFRMLEN); trace_seq_printf(seq, form, ni); break; } case 'p': { char str[KSYM_SYMBOL_LEN]; SPRINT_SYMBOL(str, nvalue(kp_arg(ks, arg))); trace_seq_puts(seq, str); break; } case 'o': case 'u': case 'x': case 'X': { ktap_number n = nvalue(kp_arg(ks, arg)); unsigned INTFRM_T ni = (unsigned INTFRM_T)n; addlenmod(form, INTFRMLEN); trace_seq_printf(seq, form, ni); break; } case 's': { ktap_value *v = kp_arg(ks, arg); const char *s; size_t l; if (isnil(v)) { trace_seq_puts(seq, "nil"); return 0; } if (ttisevent(v)) { kp_event_tostring(ks, seq); return 0; } s = svalue(v); l = rawtsvalue(v)->tsv.len; if (!strchr(form, '.') && l >= 100) { /* * no precision and string is too long * to be formatted; * keep original string */ trace_seq_puts(seq, s); break; } else { trace_seq_printf(seq, form, s); break; } } default: /* also treat cases `pnLlh' */ kp_error(ks, "invalid option " KTAP_QL("%%%c") " to " KTAP_QL("format"), *(strfrmt - 1)); } } } return 0; }