mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	tracing: Add kprobe-based event tracer
Add kprobes-based event tracer on ftrace. This tracer is similar to the events tracer which is based on Tracepoint infrastructure. Instead of Tracepoint, this tracer is based on kprobes (kprobe and kretprobe). It probes anywhere where kprobes can probe(this means, all functions body except for __kprobes functions). Similar to the events tracer, this tracer doesn't need to be activated via current_tracer, instead of that, just set probe points via /sys/kernel/debug/tracing/kprobe_events. And you can set filters on each probe events via /sys/kernel/debug/tracing/events/kprobes/<EVENT>/filter. This tracer supports following probe arguments for each probe. %REG : Fetch register REG sN : Fetch Nth entry of stack (N >= 0) sa : Fetch stack address. @ADDR : Fetch memory at ADDR (ADDR should be in kernel) @SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol) aN : Fetch function argument. (N >= 0) rv : Fetch return value. ra : Fetch return address. +|-offs(FETCHARG) : fetch memory at FETCHARG +|- offs address. See Documentation/trace/kprobetrace.txt in the next patch for details. Changes from v13: - Support 'sa' for stack address. - Use call->data instead of container_of() macro. [fweisbec@gmail.com: Fixed conflict against latest tracing/core] Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Avi Kivity <avi@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jason Baron <jbaron@redhat.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Przemysław Pawełczyk <przemyslaw@pawelczyk.it> Cc: Roland McGrath <roland@redhat.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Vegard Nossum <vegard.nossum@gmail.com> LKML-Reference: <20090813203510.31965.29123.stgit@localhost.localdomain> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
This commit is contained in:
		
							parent
							
								
									d93f12f3f4
								
							
						
					
					
						commit
						413d37d1eb
					
				
					 5 changed files with 1263 additions and 0 deletions
				
			
		| 
						 | 
					@ -411,6 +411,18 @@ config BLK_DEV_IO_TRACE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  If unsure, say N.
 | 
						  If unsure, say N.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config KPROBE_TRACER
 | 
				
			||||||
 | 
						depends on KPROBES
 | 
				
			||||||
 | 
						depends on X86
 | 
				
			||||||
 | 
						bool "Trace kprobes"
 | 
				
			||||||
 | 
						select TRACING
 | 
				
			||||||
 | 
						select GENERIC_TRACER
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  This tracer probes everywhere where kprobes can probe it, and
 | 
				
			||||||
 | 
						  records various registers and memories specified by user.
 | 
				
			||||||
 | 
						  This also allows you to trace kprobe probe points as a dynamic
 | 
				
			||||||
 | 
						  defined events. It provides per-probe event filtering interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config DYNAMIC_FTRACE
 | 
					config DYNAMIC_FTRACE
 | 
				
			||||||
	bool "enable/disable ftrace tracepoints dynamically"
 | 
						bool "enable/disable ftrace tracepoints dynamically"
 | 
				
			||||||
	depends on FUNCTION_TRACER
 | 
						depends on FUNCTION_TRACER
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,5 +54,6 @@ obj-$(CONFIG_EVENT_TRACING) += trace_export.o
 | 
				
			||||||
obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
 | 
					obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
 | 
				
			||||||
obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
 | 
					obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
 | 
				
			||||||
obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 | 
					obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_KPROBE_TRACER) += trace_kprobe.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libftrace-y := ftrace.o
 | 
					libftrace-y := ftrace.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,8 @@ enum trace_type {
 | 
				
			||||||
	TRACE_KMEM_FREE,
 | 
						TRACE_KMEM_FREE,
 | 
				
			||||||
	TRACE_POWER,
 | 
						TRACE_POWER,
 | 
				
			||||||
	TRACE_BLK,
 | 
						TRACE_BLK,
 | 
				
			||||||
 | 
						TRACE_KPROBE,
 | 
				
			||||||
 | 
						TRACE_KRETPROBE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__TRACE_LAST_TYPE,
 | 
						__TRACE_LAST_TYPE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -205,6 +207,30 @@ struct syscall_trace_exit {
 | 
				
			||||||
	unsigned long		ret;
 | 
						unsigned long		ret;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct kprobe_trace_entry {
 | 
				
			||||||
 | 
						struct trace_entry	ent;
 | 
				
			||||||
 | 
						unsigned long		ip;
 | 
				
			||||||
 | 
						int			nargs;
 | 
				
			||||||
 | 
						unsigned long		args[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SIZEOF_KPROBE_TRACE_ENTRY(n)			\
 | 
				
			||||||
 | 
						(offsetof(struct kprobe_trace_entry, args) +	\
 | 
				
			||||||
 | 
						(sizeof(unsigned long) * (n)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct kretprobe_trace_entry {
 | 
				
			||||||
 | 
						struct trace_entry	ent;
 | 
				
			||||||
 | 
						unsigned long		func;
 | 
				
			||||||
 | 
						unsigned long		ret_ip;
 | 
				
			||||||
 | 
						int			nargs;
 | 
				
			||||||
 | 
						unsigned long		args[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SIZEOF_KRETPROBE_TRACE_ENTRY(n)			\
 | 
				
			||||||
 | 
						(offsetof(struct kretprobe_trace_entry, args) +	\
 | 
				
			||||||
 | 
						(sizeof(unsigned long) * (n)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * trace_flag_type is an enumeration that holds different
 | 
					 * trace_flag_type is an enumeration that holds different
 | 
				
			||||||
| 
						 | 
					@ -317,6 +343,10 @@ extern void __ftrace_bad_type(void);
 | 
				
			||||||
			  TRACE_KMEM_ALLOC);	\
 | 
								  TRACE_KMEM_ALLOC);	\
 | 
				
			||||||
		IF_ASSIGN(var, ent, struct kmemtrace_free_entry,	\
 | 
							IF_ASSIGN(var, ent, struct kmemtrace_free_entry,	\
 | 
				
			||||||
			  TRACE_KMEM_FREE);	\
 | 
								  TRACE_KMEM_FREE);	\
 | 
				
			||||||
 | 
							IF_ASSIGN(var, ent, struct kprobe_trace_entry,		\
 | 
				
			||||||
 | 
								  TRACE_KPROBE);				\
 | 
				
			||||||
 | 
							IF_ASSIGN(var, ent, struct kretprobe_trace_entry,	\
 | 
				
			||||||
 | 
								  TRACE_KRETPROBE);				\
 | 
				
			||||||
		__ftrace_bad_type();					\
 | 
							__ftrace_bad_type();					\
 | 
				
			||||||
	} while (0)
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,4 +175,22 @@ TRACE_EVENT_FORMAT(kmem_free, TRACE_KMEM_FREE, kmemtrace_free_entry, ignore,
 | 
				
			||||||
	TP_RAW_FMT("type:%u call_site:%lx ptr:%p")
 | 
						TP_RAW_FMT("type:%u call_site:%lx ptr:%p")
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TRACE_EVENT_FORMAT(kprobe, TRACE_KPROBE, kprobe_trace_entry, ignore,
 | 
				
			||||||
 | 
						TRACE_STRUCT(
 | 
				
			||||||
 | 
							TRACE_FIELD(unsigned long, ip, ip)
 | 
				
			||||||
 | 
							TRACE_FIELD(int, nargs, nargs)
 | 
				
			||||||
 | 
							TRACE_FIELD_ZERO(unsigned long, args)
 | 
				
			||||||
 | 
						),
 | 
				
			||||||
 | 
						TP_RAW_FMT("%08lx: args:0x%lx ...")
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TRACE_EVENT_FORMAT(kretprobe, TRACE_KRETPROBE, kretprobe_trace_entry, ignore,
 | 
				
			||||||
 | 
						TRACE_STRUCT(
 | 
				
			||||||
 | 
							TRACE_FIELD(unsigned long, func, func)
 | 
				
			||||||
 | 
							TRACE_FIELD(unsigned long, ret_ip, ret_ip)
 | 
				
			||||||
 | 
							TRACE_FIELD(int, nargs, nargs)
 | 
				
			||||||
 | 
							TRACE_FIELD_ZERO(unsigned long, args)
 | 
				
			||||||
 | 
						),
 | 
				
			||||||
 | 
						TP_RAW_FMT("%08lx <- %08lx: args:0x%lx ...")
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
#undef TRACE_SYSTEM
 | 
					#undef TRACE_SYSTEM
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1202
									
								
								kernel/trace/trace_kprobe.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1202
									
								
								kernel/trace/trace_kprobe.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
		Reference in a new issue