예제 #1
0
/* Kretprobe handler */
static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
					  struct pt_regs *regs)
{
	struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
	struct kretprobe_trace_entry *entry;
	struct ring_buffer_event *event;
	struct ring_buffer *buffer;
	int size, i, pc;
	unsigned long irq_flags;
	struct ftrace_event_call *call = &tp->call;

	local_save_flags(irq_flags);
	pc = preempt_count();

	size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);

	event = trace_current_buffer_lock_reserve(&buffer, call->id, size,
						  irq_flags, pc);
	if (!event)
		return;

	entry = ring_buffer_event_data(event);
	entry->nargs = tp->nr_args;
	entry->func = (unsigned long)tp->rp.kp.addr;
	entry->ret_ip = (unsigned long)ri->ret_addr;
	for (i = 0; i < tp->nr_args; i++)
		entry->args[i] = call_fetch(&tp->args[i].fetch, regs);

	if (!filter_current_check_discard(buffer, call, entry, event))
		trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
}
예제 #2
0
/* Kretprobe profile handler */
static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri,
					    struct pt_regs *regs)
{
	struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
	struct ftrace_event_call *call = &tp->call;
	struct kretprobe_trace_entry *entry;
	int size, __size, i;
	unsigned long irq_flags;
	int rctx;

	__size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
	size = ALIGN(__size + sizeof(u32), sizeof(u64));
	size -= sizeof(u32);
	if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE,
		     "profile buffer not large enough"))
		return;

	entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags);
	if (!entry)
		return;

	entry->nargs = tp->nr_args;
	entry->func = (unsigned long)tp->rp.kp.addr;
	entry->ret_ip = (unsigned long)ri->ret_addr;
	for (i = 0; i < tp->nr_args; i++)
		entry->args[i] = call_fetch(&tp->args[i].fetch, regs);

	ftrace_perf_buf_submit(entry, size, rctx, entry->ret_ip, 1, irq_flags);
}
예제 #3
0
static __kprobes unsigned long fetch_indirect(struct pt_regs *regs, void *data)
{
	struct indirect_fetch_data *ind = data;
	unsigned long addr;

	addr = call_fetch(&ind->orig, regs);
	if (addr) {
		addr += ind->offset;
		return fetch_memory(regs, (void *)addr);
	} else
		return 0;
}
예제 #4
0
파일: trace_probe.c 프로젝트: 020gzh/linux
void FETCH_FUNC_NAME(deref, string_size)(struct pt_regs *regs,
					 void *data, void *dest)
{
	struct deref_fetch_param *dprm = data;
	unsigned long addr;

	call_fetch(&dprm->orig, regs, &addr);
	if (addr && dprm->fetch_size) {
		addr += dprm->offset;
		dprm->fetch_size(regs, (void *)addr, dest);
	} else
		*(string_size *)dest = 0;
}