Пример #1
0
/* Event entry printers */
enum print_line_t
print_kprobe_event(struct trace_iterator *iter, int flags)
{
	struct kprobe_trace_entry *field;
	struct trace_seq *s = &iter->seq;
	struct trace_event *event;
	struct trace_probe *tp;
	int i;

	field = (struct kprobe_trace_entry *)iter->ent;
	event = ftrace_find_event(field->ent.type);
	tp = container_of(event, struct trace_probe, event);

	if (!trace_seq_printf(s, "%s: (", tp->call.name))
		goto partial;

	if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
		goto partial;

	if (!trace_seq_puts(s, ")"))
		goto partial;

	for (i = 0; i < field->nargs; i++)
		if (!trace_seq_printf(s, " %s=%lx",
				      tp->args[i].name, field->args[i]))
			goto partial;

	if (!trace_seq_puts(s, "\n"))
		goto partial;

	return TRACE_TYPE_HANDLED;
partial:
	return TRACE_TYPE_PARTIAL_LINE;
}
Пример #2
0
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, "|  ");
}
Пример #3
0
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, ") ");
}
Пример #4
0
void kp_event_tostring(ktap_state *ks, struct trace_seq *seq)
{
	struct ktap_event *e = ks->current_event;
	struct trace_iterator *iter;
	struct trace_event *ev;
	enum print_line_t ret = TRACE_TYPE_NO_CONSUME;

	/* Simulate the iterator */

	/*
	 * use temp percpu buffer as trace_iterator
	 * we cannot use same temp buffer as printf.
	 */
	iter = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER2);

	trace_seq_init(&iter->seq);
	iter->ent = e->entry;

	ev = &(e->call->event);
	if (ev)
		ret = ev->funcs->trace(iter, 0, ev);

	if (ret != TRACE_TYPE_NO_CONSUME) {
		struct trace_seq *s = &iter->seq;
		int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;

		s->buffer[len] = '\0';
		trace_seq_puts(seq, s->buffer);
	}
}
Пример #5
0
/*
 * 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);
}
Пример #6
0
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');
}
Пример #7
0
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, ") ");
}
Пример #8
0
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;
}
Пример #9
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;
}
Пример #10
0
static int
trace_stack_handler(struct trace_seq *s, struct tep_record *record,
		    struct tep_event *event, void *context)
{
	struct tracecmd_ftrace *finfo = context;
	struct tep_format_field *field;
	unsigned long long addr;
	const char *func;
	void *data = record->data;

	field = tep_find_any_field(event, "caller");
	if (!field) {
		trace_seq_printf(s, "<CANT FIND FIELD %s>", "caller");
		return 0;
	}

	trace_seq_puts(s, "<stack trace>\n");

	long_size_check(finfo);

	for (data += field->offset; data < record->data + record->size;
	     data += finfo->long_size) {
		addr = tep_read_number(event->tep, data, finfo->long_size);

		if ((finfo->long_size == 8 && addr == (unsigned long long)-1) ||
		    ((int)addr == -1))
			break;

		func = tep_find_function(event->tep, addr);
		if (func)
			trace_seq_printf(s, "=> %s (%llx)\n", func, addr);
		else
			trace_seq_printf(s, "=> %llx\n", addr);
	}

	return 0;
}
Пример #11
0
int ras_mc_event_handler(struct trace_seq *s,
			 struct pevent_record *record,
			 struct event_format *event, void *context)
{
	int len;
	unsigned long long val;
	struct ras_events *ras = context;
	time_t now;
	struct tm *tm;
	struct ras_mc_event ev;
	int parsed_fields = 0;

	/*
	 * Newer kernels (3.10-rc1 or upper) provide an uptime clock.
	 * On previous kernels, the way to properly generate an event would
	 * be to inject a fake one, measure its timestamp and diff it against
	 * gettimeofday. We won't do it here. Instead, let's use uptime,
	 * falling-back to the event report's time, if "uptime" clock is
	 * not available (legacy kernels).
	 */

	if (ras->use_uptime)
		now = record->ts/user_hz + ras->uptime_diff;
	else
		now = time(NULL);

	tm = localtime(&now);
	if (tm)
		strftime(ev.timestamp, sizeof(ev.timestamp),
			 "%Y-%m-%d %H:%M:%S %z", tm);
	trace_seq_printf(s, "%s ", ev.timestamp);

	if (pevent_get_field_val(s,  event, "error_count", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;

	ev.error_count = val;
	trace_seq_printf(s, "%d ", ev.error_count);

	if (pevent_get_field_val(s, event, "error_type", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;

	switch (val) {
	case HW_EVENT_ERR_CORRECTED:
		ev.error_type = "Corrected";
		break;
	case HW_EVENT_ERR_UNCORRECTED:
		ev.error_type = "Uncorrected";
		break;
	case HW_EVENT_ERR_FATAL:
		ev.error_type = "Fatal";
		break;
	default:
	case HW_EVENT_ERR_INFO:
		ev.error_type = "Info";
	}

	trace_seq_puts(s, ev.error_type);
	if (ev.error_count > 1)
		trace_seq_puts(s, " errors:");
	else
		trace_seq_puts(s, " error:");

	ev.msg = pevent_get_field_raw(s, event, "msg", record, &len, 1);
	if (!ev.msg)
		goto parse_error;
	parsed_fields++;

	if (*ev.msg) {
		trace_seq_puts(s, " ");
		trace_seq_puts(s, ev.msg);
	}

	ev.label = pevent_get_field_raw(s, event, "label", record, &len, 1);
	if (!ev.label)
		goto parse_error;
	parsed_fields++;

	if (*ev.label) {
		trace_seq_puts(s, " on ");
		trace_seq_puts(s, ev.label);
	}

	trace_seq_puts(s, " (");
	if (pevent_get_field_val(s,  event, "mc_index", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;

	ev.mc_index = val;
	trace_seq_printf(s, "mc: %d", ev.mc_index);

	if (pevent_get_field_val(s,  event, "top_layer", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;
	ev.top_layer = (signed char) val;

	if (pevent_get_field_val(s,  event, "middle_layer", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;
	ev.middle_layer = (signed char) val;

	if (pevent_get_field_val(s,  event, "lower_layer", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;
	ev.lower_layer = (signed char) val;

	if (ev.top_layer >= 0 || ev.middle_layer >= 0 || ev.lower_layer >= 0) {
		if (ev.lower_layer >= 0)
			trace_seq_printf(s, " location: %d:%d:%d",
					ev.top_layer, ev.middle_layer, ev.lower_layer);
		else if (ev.middle_layer >= 0)
			trace_seq_printf(s, " location: %d:%d",
					 ev.top_layer, ev.middle_layer);
		else
			trace_seq_printf(s, " location: %d", ev.top_layer);
	}

	if (pevent_get_field_val(s,  event, "address", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;

	ev.address = val;
	if (ev.address)
		trace_seq_printf(s, " address: 0x%08llx", ev.address);

	if (pevent_get_field_val(s,  event, "grain_bits", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;

	ev.grain = val;
	trace_seq_printf(s, " grain: %lld", ev.grain);


	if (pevent_get_field_val(s,  event, "syndrome", record, &val, 1) < 0)
		goto parse_error;
	parsed_fields++;

	ev.syndrome = val;
	if (val)
		trace_seq_printf(s, " syndrome: 0x%08llx", ev.syndrome);

	ev.driver_detail = pevent_get_field_raw(s, event, "driver_detail", record,
					     &len, 1);
	if (!ev.driver_detail)
		goto parse_error;
	parsed_fields++;

	if (*ev.driver_detail) {
		trace_seq_puts(s, " ");
		trace_seq_puts(s, ev.driver_detail);
	}
	trace_seq_puts(s, ")");

	/* Insert data into the SGBD */

	ras_store_mc_event(ras, &ev);

#ifdef HAVE_ABRT_REPORT
	/* Report event to ABRT */
	ras_report_mc_event(ras, &ev);
#endif

	return 0;

parse_error:
	/* FIXME: add a logic here to also store parse errors to SDBD */

	log(ALL, LOG_ERR, "MC error handler: can't parse field #%d\n",
	    parsed_fields);

	return 0;
}
Пример #12
0
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;
}