xref: /linux-6.15/kernel/trace/trace_kprobe.c (revision fd837de3)
1bcea3f96SSteven Rostedt (VMware) // SPDX-License-Identifier: GPL-2.0
2413d37d1SMasami Hiramatsu /*
377b44d1bSMasami Hiramatsu  * Kprobes-based tracing events
4413d37d1SMasami Hiramatsu  *
5413d37d1SMasami Hiramatsu  * Created by Masami Hiramatsu <[email protected]>
6413d37d1SMasami Hiramatsu  *
7413d37d1SMasami Hiramatsu  */
872576341SMasami Hiramatsu #define pr_fmt(fmt)	"trace_kprobe: " fmt
9413d37d1SMasami Hiramatsu 
10aef2fedaSJakub Kicinski #include <linux/bpf-cgroup.h>
117dcc3520SMasami Hiramatsu (Google) #include <linux/cleanup.h>
1217911ff3SSteven Rostedt (VMware) #include <linux/security.h>
13413d37d1SMasami Hiramatsu #include <linux/module.h>
14413d37d1SMasami Hiramatsu #include <linux/uaccess.h>
15b2d09103SIngo Molnar #include <linux/rculist.h>
16540adea3SMasami Hiramatsu #include <linux/error-injection.h>
17413d37d1SMasami Hiramatsu 
18970988e1SMasami Hiramatsu #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
19970988e1SMasami Hiramatsu 
206212dd29SMasami Hiramatsu #include "trace_dynevent.h"
21d899926fSFrancis Deslauriers #include "trace_kprobe_selftest.h"
228ab83f56SSrikar Dronamraju #include "trace_probe.h"
2353305928SMasami Hiramatsu #include "trace_probe_tmpl.h"
24f1d3cbfaSSteven Rostedt (Google) #include "trace_probe_kernel.h"
25413d37d1SMasami Hiramatsu 
26f52487e9SMasami Hiramatsu #define KPROBE_EVENT_SYSTEM "kprobes"
27696ced4fSAlban Crequy #define KRETPROBE_MAXACTIVE_MAX 4096
28970988e1SMasami Hiramatsu 
29970988e1SMasami Hiramatsu /* Kprobe early definition from command line */
30970988e1SMasami Hiramatsu static char kprobe_boot_events_buf[COMMAND_LINE_SIZE] __initdata;
31970988e1SMasami Hiramatsu 
set_kprobe_boot_events(char * str)32970988e1SMasami Hiramatsu static int __init set_kprobe_boot_events(char *str)
33970988e1SMasami Hiramatsu {
34c7dce4c5SAzeem Shaikh 	strscpy(kprobe_boot_events_buf, str, COMMAND_LINE_SIZE);
3560efe21eSMasami Hiramatsu 	disable_tracing_selftest("running kprobe events");
3660efe21eSMasami Hiramatsu 
371d02b444SRandy Dunlap 	return 1;
38970988e1SMasami Hiramatsu }
39970988e1SMasami Hiramatsu __setup("kprobe_event=", set_kprobe_boot_events);
40413d37d1SMasami Hiramatsu 
41d262271dSMasami Hiramatsu static int trace_kprobe_create(const char *raw_command);
426212dd29SMasami Hiramatsu static int trace_kprobe_show(struct seq_file *m, struct dyn_event *ev);
436212dd29SMasami Hiramatsu static int trace_kprobe_release(struct dyn_event *ev);
446212dd29SMasami Hiramatsu static bool trace_kprobe_is_busy(struct dyn_event *ev);
456212dd29SMasami Hiramatsu static bool trace_kprobe_match(const char *system, const char *event,
4630199137SMasami Hiramatsu 			int argc, const char **argv, struct dyn_event *ev);
476212dd29SMasami Hiramatsu 
486212dd29SMasami Hiramatsu static struct dyn_event_operations trace_kprobe_ops = {
496212dd29SMasami Hiramatsu 	.create = trace_kprobe_create,
506212dd29SMasami Hiramatsu 	.show = trace_kprobe_show,
516212dd29SMasami Hiramatsu 	.is_busy = trace_kprobe_is_busy,
526212dd29SMasami Hiramatsu 	.free = trace_kprobe_release,
536212dd29SMasami Hiramatsu 	.match = trace_kprobe_match,
546212dd29SMasami Hiramatsu };
556212dd29SMasami Hiramatsu 
56cede666eSValdis Klētnieks /*
5777b44d1bSMasami Hiramatsu  * Kprobe event core functions
58413d37d1SMasami Hiramatsu  */
59c31ffb3fSNamhyung Kim struct trace_kprobe {
606212dd29SMasami Hiramatsu 	struct dyn_event	devent;
614a846b44SMasami Hiramatsu 	struct kretprobe	rp;	/* Use rp.kp for kprobe use */
62a7636d9eSMartin KaFai Lau 	unsigned long __percpu *nhit;
63413d37d1SMasami Hiramatsu 	const char		*symbol;	/* symbol name */
64c31ffb3fSNamhyung Kim 	struct trace_probe	tp;
65413d37d1SMasami Hiramatsu };
66413d37d1SMasami Hiramatsu 
is_trace_kprobe(struct dyn_event * ev)676212dd29SMasami Hiramatsu static bool is_trace_kprobe(struct dyn_event *ev)
686212dd29SMasami Hiramatsu {
696212dd29SMasami Hiramatsu 	return ev->ops == &trace_kprobe_ops;
706212dd29SMasami Hiramatsu }
716212dd29SMasami Hiramatsu 
to_trace_kprobe(struct dyn_event * ev)726212dd29SMasami Hiramatsu static struct trace_kprobe *to_trace_kprobe(struct dyn_event *ev)
736212dd29SMasami Hiramatsu {
746212dd29SMasami Hiramatsu 	return container_of(ev, struct trace_kprobe, devent);
756212dd29SMasami Hiramatsu }
766212dd29SMasami Hiramatsu 
776212dd29SMasami Hiramatsu /**
786212dd29SMasami Hiramatsu  * for_each_trace_kprobe - iterate over the trace_kprobe list
796212dd29SMasami Hiramatsu  * @pos:	the struct trace_kprobe * for each entry
806212dd29SMasami Hiramatsu  * @dpos:	the struct dyn_event * to use as a loop cursor
816212dd29SMasami Hiramatsu  */
826212dd29SMasami Hiramatsu #define for_each_trace_kprobe(pos, dpos)	\
836212dd29SMasami Hiramatsu 	for_each_dyn_event(dpos)		\
846212dd29SMasami Hiramatsu 		if (is_trace_kprobe(dpos) && (pos = to_trace_kprobe(dpos)))
856212dd29SMasami Hiramatsu 
trace_kprobe_is_return(struct trace_kprobe * tk)863da0f180SMasami Hiramatsu static nokprobe_inline bool trace_kprobe_is_return(struct trace_kprobe *tk)
87413d37d1SMasami Hiramatsu {
88c31ffb3fSNamhyung Kim 	return tk->rp.handler != NULL;
89413d37d1SMasami Hiramatsu }
90413d37d1SMasami Hiramatsu 
trace_kprobe_symbol(struct trace_kprobe * tk)913da0f180SMasami Hiramatsu static nokprobe_inline const char *trace_kprobe_symbol(struct trace_kprobe *tk)
92413d37d1SMasami Hiramatsu {
93c31ffb3fSNamhyung Kim 	return tk->symbol ? tk->symbol : "unknown";
94413d37d1SMasami Hiramatsu }
95413d37d1SMasami Hiramatsu 
trace_kprobe_offset(struct trace_kprobe * tk)963da0f180SMasami Hiramatsu static nokprobe_inline unsigned long trace_kprobe_offset(struct trace_kprobe *tk)
9761424318SMasami Hiramatsu {
98c31ffb3fSNamhyung Kim 	return tk->rp.kp.offset;
9961424318SMasami Hiramatsu }
10061424318SMasami Hiramatsu 
trace_kprobe_has_gone(struct trace_kprobe * tk)1013da0f180SMasami Hiramatsu static nokprobe_inline bool trace_kprobe_has_gone(struct trace_kprobe *tk)
10261424318SMasami Hiramatsu {
10329e8077aSMasami Hiramatsu 	return kprobe_gone(&tk->rp.kp);
10461424318SMasami Hiramatsu }
10561424318SMasami Hiramatsu 
trace_kprobe_within_module(struct trace_kprobe * tk,struct module * mod)1063da0f180SMasami Hiramatsu static nokprobe_inline bool trace_kprobe_within_module(struct trace_kprobe *tk,
10761424318SMasami Hiramatsu 						 struct module *mod)
10861424318SMasami Hiramatsu {
109f3d36426SJarkko Sakkinen 	int len = strlen(module_name(mod));
110c31ffb3fSNamhyung Kim 	const char *name = trace_kprobe_symbol(tk);
111f3d36426SJarkko Sakkinen 
112f3d36426SJarkko Sakkinen 	return strncmp(module_name(mod), name, len) == 0 && name[len] == ':';
11361424318SMasami Hiramatsu }
11461424318SMasami Hiramatsu 
1157582b7beSMike Rapoport (IBM) #ifdef CONFIG_MODULES
trace_kprobe_module_exist(struct trace_kprobe * tk)11659158ec4SMasami Hiramatsu static nokprobe_inline bool trace_kprobe_module_exist(struct trace_kprobe *tk)
11761424318SMasami Hiramatsu {
11859158ec4SMasami Hiramatsu 	char *p;
11959158ec4SMasami Hiramatsu 	bool ret;
12059158ec4SMasami Hiramatsu 
12159158ec4SMasami Hiramatsu 	if (!tk->symbol)
12259158ec4SMasami Hiramatsu 		return false;
12359158ec4SMasami Hiramatsu 	p = strchr(tk->symbol, ':');
12459158ec4SMasami Hiramatsu 	if (!p)
12559158ec4SMasami Hiramatsu 		return true;
12659158ec4SMasami Hiramatsu 	*p = '\0';
127febaa65cSSebastian Andrzej Siewior 	scoped_guard(rcu)
12859158ec4SMasami Hiramatsu 		ret = !!find_module(tk->symbol);
12959158ec4SMasami Hiramatsu 	*p = ':';
13059158ec4SMasami Hiramatsu 
13159158ec4SMasami Hiramatsu 	return ret;
13261424318SMasami Hiramatsu }
1337582b7beSMike Rapoport (IBM) #else
trace_kprobe_module_exist(struct trace_kprobe * tk)1347582b7beSMike Rapoport (IBM) static inline bool trace_kprobe_module_exist(struct trace_kprobe *tk)
1357582b7beSMike Rapoport (IBM) {
1367582b7beSMike Rapoport (IBM) 	return false;
1377582b7beSMike Rapoport (IBM) }
1387582b7beSMike Rapoport (IBM) #endif
13961424318SMasami Hiramatsu 
trace_kprobe_is_busy(struct dyn_event * ev)1406212dd29SMasami Hiramatsu static bool trace_kprobe_is_busy(struct dyn_event *ev)
1416212dd29SMasami Hiramatsu {
1426212dd29SMasami Hiramatsu 	struct trace_kprobe *tk = to_trace_kprobe(ev);
1436212dd29SMasami Hiramatsu 
1446212dd29SMasami Hiramatsu 	return trace_probe_is_enabled(&tk->tp);
1456212dd29SMasami Hiramatsu }
1466212dd29SMasami Hiramatsu 
trace_kprobe_match_command_head(struct trace_kprobe * tk,int argc,const char ** argv)147eb5bf813SMasami Hiramatsu static bool trace_kprobe_match_command_head(struct trace_kprobe *tk,
148eb5bf813SMasami Hiramatsu 					    int argc, const char **argv)
149eb5bf813SMasami Hiramatsu {
150eb5bf813SMasami Hiramatsu 	char buf[MAX_ARGSTR_LEN + 1];
151eb5bf813SMasami Hiramatsu 
152eb5bf813SMasami Hiramatsu 	if (!argc)
153eb5bf813SMasami Hiramatsu 		return true;
154eb5bf813SMasami Hiramatsu 
155eb5bf813SMasami Hiramatsu 	if (!tk->symbol)
156eb5bf813SMasami Hiramatsu 		snprintf(buf, sizeof(buf), "0x%p", tk->rp.kp.addr);
157eb5bf813SMasami Hiramatsu 	else if (tk->rp.kp.offset)
158eb5bf813SMasami Hiramatsu 		snprintf(buf, sizeof(buf), "%s+%u",
159eb5bf813SMasami Hiramatsu 			 trace_kprobe_symbol(tk), tk->rp.kp.offset);
160eb5bf813SMasami Hiramatsu 	else
161eb5bf813SMasami Hiramatsu 		snprintf(buf, sizeof(buf), "%s", trace_kprobe_symbol(tk));
162eb5bf813SMasami Hiramatsu 	if (strcmp(buf, argv[0]))
163eb5bf813SMasami Hiramatsu 		return false;
164eb5bf813SMasami Hiramatsu 	argc--; argv++;
165eb5bf813SMasami Hiramatsu 
166eb5bf813SMasami Hiramatsu 	return trace_probe_match_command_args(&tk->tp, argc, argv);
167eb5bf813SMasami Hiramatsu }
168eb5bf813SMasami Hiramatsu 
trace_kprobe_match(const char * system,const char * event,int argc,const char ** argv,struct dyn_event * ev)1696212dd29SMasami Hiramatsu static bool trace_kprobe_match(const char *system, const char *event,
17030199137SMasami Hiramatsu 			int argc, const char **argv, struct dyn_event *ev)
1716212dd29SMasami Hiramatsu {
1726212dd29SMasami Hiramatsu 	struct trace_kprobe *tk = to_trace_kprobe(ev);
1736212dd29SMasami Hiramatsu 
17495c104c3SLinyu Yuan 	return (event[0] == '\0' ||
17595c104c3SLinyu Yuan 		strcmp(trace_probe_name(&tk->tp), event) == 0) &&
176eb5bf813SMasami Hiramatsu 	    (!system || strcmp(trace_probe_group_name(&tk->tp), system) == 0) &&
177eb5bf813SMasami Hiramatsu 	    trace_kprobe_match_command_head(tk, argc, argv);
1786212dd29SMasami Hiramatsu }
1796212dd29SMasami Hiramatsu 
trace_kprobe_nhit(struct trace_kprobe * tk)180f18f97acSMarcin Nowakowski static nokprobe_inline unsigned long trace_kprobe_nhit(struct trace_kprobe *tk)
181f18f97acSMarcin Nowakowski {
182f18f97acSMarcin Nowakowski 	unsigned long nhit = 0;
183f18f97acSMarcin Nowakowski 	int cpu;
184f18f97acSMarcin Nowakowski 
185f18f97acSMarcin Nowakowski 	for_each_possible_cpu(cpu)
186f18f97acSMarcin Nowakowski 		nhit += *per_cpu_ptr(tk->nhit, cpu);
187f18f97acSMarcin Nowakowski 
188f18f97acSMarcin Nowakowski 	return nhit;
189f18f97acSMarcin Nowakowski }
190f18f97acSMarcin Nowakowski 
trace_kprobe_is_registered(struct trace_kprobe * tk)191715fa2fdSMasami Hiramatsu static nokprobe_inline bool trace_kprobe_is_registered(struct trace_kprobe *tk)
192715fa2fdSMasami Hiramatsu {
193715fa2fdSMasami Hiramatsu 	return !(list_empty(&tk->rp.kp.list) &&
194715fa2fdSMasami Hiramatsu 		 hlist_unhashed(&tk->rp.kp.hlist));
195715fa2fdSMasami Hiramatsu }
196715fa2fdSMasami Hiramatsu 
1976bc6c77cSMasami Hiramatsu /* Return 0 if it fails to find the symbol address */
19845408c4fSMasami Hiramatsu static nokprobe_inline
trace_kprobe_address(struct trace_kprobe * tk)19945408c4fSMasami Hiramatsu unsigned long trace_kprobe_address(struct trace_kprobe *tk)
20045408c4fSMasami Hiramatsu {
20145408c4fSMasami Hiramatsu 	unsigned long addr;
20245408c4fSMasami Hiramatsu 
20345408c4fSMasami Hiramatsu 	if (tk->symbol) {
20445408c4fSMasami Hiramatsu 		addr = (unsigned long)
20545408c4fSMasami Hiramatsu 			kallsyms_lookup_name(trace_kprobe_symbol(tk));
2066bc6c77cSMasami Hiramatsu 		if (addr)
20745408c4fSMasami Hiramatsu 			addr += tk->rp.kp.offset;
20845408c4fSMasami Hiramatsu 	} else {
20945408c4fSMasami Hiramatsu 		addr = (unsigned long)tk->rp.kp.addr;
21045408c4fSMasami Hiramatsu 	}
21145408c4fSMasami Hiramatsu 	return addr;
21245408c4fSMasami Hiramatsu }
21345408c4fSMasami Hiramatsu 
21460d53e2cSMasami Hiramatsu static nokprobe_inline struct trace_kprobe *
trace_kprobe_primary_from_call(struct trace_event_call * call)21560d53e2cSMasami Hiramatsu trace_kprobe_primary_from_call(struct trace_event_call *call)
21660d53e2cSMasami Hiramatsu {
21760d53e2cSMasami Hiramatsu 	struct trace_probe *tp;
21860d53e2cSMasami Hiramatsu 
21960d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(call);
22060d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
22160d53e2cSMasami Hiramatsu 		return NULL;
22260d53e2cSMasami Hiramatsu 
22360d53e2cSMasami Hiramatsu 	return container_of(tp, struct trace_kprobe, tp);
22460d53e2cSMasami Hiramatsu }
22560d53e2cSMasami Hiramatsu 
trace_kprobe_on_func_entry(struct trace_event_call * call)226b4da3340SMasami Hiramatsu bool trace_kprobe_on_func_entry(struct trace_event_call *call)
2279802d865SJosef Bacik {
22860d53e2cSMasami Hiramatsu 	struct trace_kprobe *tk = trace_kprobe_primary_from_call(call);
229b4da3340SMasami Hiramatsu 
23097c753e6SMasami Hiramatsu 	return tk ? (kprobe_on_func_entry(tk->rp.kp.addr,
231b4da3340SMasami Hiramatsu 			tk->rp.kp.addr ? NULL : tk->rp.kp.symbol_name,
23297c753e6SMasami Hiramatsu 			tk->rp.kp.addr ? 0 : tk->rp.kp.offset) == 0) : false;
2339802d865SJosef Bacik }
2349802d865SJosef Bacik 
trace_kprobe_error_injectable(struct trace_event_call * call)235b4da3340SMasami Hiramatsu bool trace_kprobe_error_injectable(struct trace_event_call *call)
2369802d865SJosef Bacik {
23760d53e2cSMasami Hiramatsu 	struct trace_kprobe *tk = trace_kprobe_primary_from_call(call);
2389802d865SJosef Bacik 
23960d53e2cSMasami Hiramatsu 	return tk ? within_error_injection_list(trace_kprobe_address(tk)) :
24060d53e2cSMasami Hiramatsu 	       false;
2419802d865SJosef Bacik }
2429802d865SJosef Bacik 
243c31ffb3fSNamhyung Kim static int register_kprobe_event(struct trace_kprobe *tk);
244c31ffb3fSNamhyung Kim static int unregister_kprobe_event(struct trace_kprobe *tk);
245413d37d1SMasami Hiramatsu 
24650d78056SMasami Hiramatsu static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
24750d78056SMasami Hiramatsu static int kretprobe_dispatcher(struct kretprobe_instance *ri,
24850d78056SMasami Hiramatsu 				struct pt_regs *regs);
24950d78056SMasami Hiramatsu 
free_trace_kprobe(struct trace_kprobe * tk)250455b2899SMasami Hiramatsu static void free_trace_kprobe(struct trace_kprobe *tk)
251455b2899SMasami Hiramatsu {
252455b2899SMasami Hiramatsu 	if (tk) {
253455b2899SMasami Hiramatsu 		trace_probe_cleanup(&tk->tp);
254455b2899SMasami Hiramatsu 		kfree(tk->symbol);
255455b2899SMasami Hiramatsu 		free_percpu(tk->nhit);
256455b2899SMasami Hiramatsu 		kfree(tk);
257455b2899SMasami Hiramatsu 	}
258455b2899SMasami Hiramatsu }
259455b2899SMasami Hiramatsu 
2607dcc3520SMasami Hiramatsu (Google) DEFINE_FREE(free_trace_kprobe, struct trace_kprobe *,
2617dcc3520SMasami Hiramatsu (Google) 	if (!IS_ERR_OR_NULL(_T)) free_trace_kprobe(_T))
2627dcc3520SMasami Hiramatsu (Google) 
2634a846b44SMasami Hiramatsu /*
2644a846b44SMasami Hiramatsu  * Allocate new trace_probe and initialize it (including kprobes).
2654a846b44SMasami Hiramatsu  */
alloc_trace_kprobe(const char * group,const char * event,void * addr,const char * symbol,unsigned long offs,int maxactive,int nargs,bool is_return)266c31ffb3fSNamhyung Kim static struct trace_kprobe *alloc_trace_kprobe(const char *group,
267f52487e9SMasami Hiramatsu 					     const char *event,
2684a846b44SMasami Hiramatsu 					     void *addr,
2694a846b44SMasami Hiramatsu 					     const char *symbol,
2704a846b44SMasami Hiramatsu 					     unsigned long offs,
271696ced4fSAlban Crequy 					     int maxactive,
2723a6b7666SSrikar Dronamraju 					     int nargs, bool is_return)
273413d37d1SMasami Hiramatsu {
2747dcc3520SMasami Hiramatsu (Google) 	struct trace_kprobe *tk __free(free_trace_kprobe) = NULL;
2756f3cf440SMasami Hiramatsu 	int ret = -ENOMEM;
276413d37d1SMasami Hiramatsu 
277845cbf3eSSteven Rostedt (VMware) 	tk = kzalloc(struct_size(tk, tp.args, nargs), GFP_KERNEL);
278c31ffb3fSNamhyung Kim 	if (!tk)
2796f3cf440SMasami Hiramatsu 		return ERR_PTR(ret);
280413d37d1SMasami Hiramatsu 
281a7636d9eSMartin KaFai Lau 	tk->nhit = alloc_percpu(unsigned long);
282a7636d9eSMartin KaFai Lau 	if (!tk->nhit)
2837dcc3520SMasami Hiramatsu (Google) 		return ERR_PTR(ret);
284a7636d9eSMartin KaFai Lau 
285413d37d1SMasami Hiramatsu 	if (symbol) {
286c31ffb3fSNamhyung Kim 		tk->symbol = kstrdup(symbol, GFP_KERNEL);
287c31ffb3fSNamhyung Kim 		if (!tk->symbol)
2887dcc3520SMasami Hiramatsu (Google) 			return ERR_PTR(ret);
289c31ffb3fSNamhyung Kim 		tk->rp.kp.symbol_name = tk->symbol;
290c31ffb3fSNamhyung Kim 		tk->rp.kp.offset = offs;
2914a846b44SMasami Hiramatsu 	} else
292c31ffb3fSNamhyung Kim 		tk->rp.kp.addr = addr;
2934a846b44SMasami Hiramatsu 
2944a846b44SMasami Hiramatsu 	if (is_return)
295c31ffb3fSNamhyung Kim 		tk->rp.handler = kretprobe_dispatcher;
2964a846b44SMasami Hiramatsu 	else
297c31ffb3fSNamhyung Kim 		tk->rp.kp.pre_handler = kprobe_dispatcher;
2984a846b44SMasami Hiramatsu 
299696ced4fSAlban Crequy 	tk->rp.maxactive = maxactive;
300715fa2fdSMasami Hiramatsu 	INIT_HLIST_NODE(&tk->rp.kp.hlist);
301715fa2fdSMasami Hiramatsu 	INIT_LIST_HEAD(&tk->rp.kp.list);
302696ced4fSAlban Crequy 
303035ba760SMasami Hiramatsu (Google) 	ret = trace_probe_init(&tk->tp, event, group, false, nargs);
304455b2899SMasami Hiramatsu 	if (ret < 0)
3057dcc3520SMasami Hiramatsu (Google) 		return ERR_PTR(ret);
306f52487e9SMasami Hiramatsu 
3076212dd29SMasami Hiramatsu 	dyn_event_init(&tk->devent, &trace_kprobe_ops);
3087dcc3520SMasami Hiramatsu (Google) 	return_ptr(tk);
309413d37d1SMasami Hiramatsu }
310413d37d1SMasami Hiramatsu 
find_trace_kprobe(const char * event,const char * group)311c31ffb3fSNamhyung Kim static struct trace_kprobe *find_trace_kprobe(const char *event,
312dd004c47SMasami Hiramatsu 					      const char *group)
313413d37d1SMasami Hiramatsu {
3146212dd29SMasami Hiramatsu 	struct dyn_event *pos;
315c31ffb3fSNamhyung Kim 	struct trace_kprobe *tk;
316413d37d1SMasami Hiramatsu 
3176212dd29SMasami Hiramatsu 	for_each_trace_kprobe(tk, pos)
318b55ce203SMasami Hiramatsu 		if (strcmp(trace_probe_name(&tk->tp), event) == 0 &&
319b55ce203SMasami Hiramatsu 		    strcmp(trace_probe_group_name(&tk->tp), group) == 0)
320c31ffb3fSNamhyung Kim 			return tk;
321413d37d1SMasami Hiramatsu 	return NULL;
322413d37d1SMasami Hiramatsu }
323413d37d1SMasami Hiramatsu 
__enable_trace_kprobe(struct trace_kprobe * tk)32487107a25SSteven Rostedt (VMware) static inline int __enable_trace_kprobe(struct trace_kprobe *tk)
32587107a25SSteven Rostedt (VMware) {
32687107a25SSteven Rostedt (VMware) 	int ret = 0;
32787107a25SSteven Rostedt (VMware) 
328715fa2fdSMasami Hiramatsu 	if (trace_kprobe_is_registered(tk) && !trace_kprobe_has_gone(tk)) {
32987107a25SSteven Rostedt (VMware) 		if (trace_kprobe_is_return(tk))
33087107a25SSteven Rostedt (VMware) 			ret = enable_kretprobe(&tk->rp);
33187107a25SSteven Rostedt (VMware) 		else
33287107a25SSteven Rostedt (VMware) 			ret = enable_kprobe(&tk->rp.kp);
33387107a25SSteven Rostedt (VMware) 	}
33487107a25SSteven Rostedt (VMware) 
33587107a25SSteven Rostedt (VMware) 	return ret;
33687107a25SSteven Rostedt (VMware) }
33787107a25SSteven Rostedt (VMware) 
__disable_trace_kprobe(struct trace_probe * tp)33860d53e2cSMasami Hiramatsu static void __disable_trace_kprobe(struct trace_probe *tp)
33960d53e2cSMasami Hiramatsu {
34060d53e2cSMasami Hiramatsu 	struct trace_kprobe *tk;
34160d53e2cSMasami Hiramatsu 
342e161c6bfSJiri Olsa 	list_for_each_entry(tk, trace_probe_probe_list(tp), tp.list) {
34360d53e2cSMasami Hiramatsu 		if (!trace_kprobe_is_registered(tk))
34460d53e2cSMasami Hiramatsu 			continue;
34560d53e2cSMasami Hiramatsu 		if (trace_kprobe_is_return(tk))
34660d53e2cSMasami Hiramatsu 			disable_kretprobe(&tk->rp);
34760d53e2cSMasami Hiramatsu 		else
34860d53e2cSMasami Hiramatsu 			disable_kprobe(&tk->rp.kp);
34960d53e2cSMasami Hiramatsu 	}
35060d53e2cSMasami Hiramatsu }
35160d53e2cSMasami Hiramatsu 
3523fe3d619SOleg Nesterov /*
35341a7dd42SMasami Hiramatsu  * Enable trace_probe
35441a7dd42SMasami Hiramatsu  * if the file is NULL, enable "perf" handler, or enable "trace" handler.
35541a7dd42SMasami Hiramatsu  */
enable_trace_kprobe(struct trace_event_call * call,struct trace_event_file * file)35660d53e2cSMasami Hiramatsu static int enable_trace_kprobe(struct trace_event_call *call,
35760d53e2cSMasami Hiramatsu 				struct trace_event_file *file)
3581538f888SMasami Hiramatsu {
359e161c6bfSJiri Olsa 	struct trace_probe *tp;
36060d53e2cSMasami Hiramatsu 	struct trace_kprobe *tk;
36160d53e2cSMasami Hiramatsu 	bool enabled;
3621538f888SMasami Hiramatsu 	int ret = 0;
3631538f888SMasami Hiramatsu 
36460d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(call);
36560d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
36660d53e2cSMasami Hiramatsu 		return -ENODEV;
36760d53e2cSMasami Hiramatsu 	enabled = trace_probe_is_enabled(tp);
36860d53e2cSMasami Hiramatsu 
36960d53e2cSMasami Hiramatsu 	/* This also changes "enabled" state */
37041a7dd42SMasami Hiramatsu 	if (file) {
37160d53e2cSMasami Hiramatsu 		ret = trace_probe_add_file(tp, file);
372b5f935eeSMasami Hiramatsu 		if (ret)
373b5f935eeSMasami Hiramatsu 			return ret;
374b5f935eeSMasami Hiramatsu 	} else
37560d53e2cSMasami Hiramatsu 		trace_probe_set_flag(tp, TP_FLAG_PROFILE);
37641a7dd42SMasami Hiramatsu 
377b5f935eeSMasami Hiramatsu 	if (enabled)
378b5f935eeSMasami Hiramatsu 		return 0;
379b04d52e3SOleg Nesterov 
380e161c6bfSJiri Olsa 	list_for_each_entry(tk, trace_probe_probe_list(tp), tp.list) {
38160d53e2cSMasami Hiramatsu 		if (trace_kprobe_has_gone(tk))
38260d53e2cSMasami Hiramatsu 			continue;
38387107a25SSteven Rostedt (VMware) 		ret = __enable_trace_kprobe(tk);
38444d00dc7SMasami Hiramatsu 		if (ret)
38560d53e2cSMasami Hiramatsu 			break;
38660d53e2cSMasami Hiramatsu 		enabled = true;
38760d53e2cSMasami Hiramatsu 	}
38860d53e2cSMasami Hiramatsu 
38944d00dc7SMasami Hiramatsu 	if (ret) {
39044d00dc7SMasami Hiramatsu 		/* Failed to enable one of them. Roll back all */
39144d00dc7SMasami Hiramatsu 		if (enabled)
39244d00dc7SMasami Hiramatsu 			__disable_trace_kprobe(tp);
393b5f935eeSMasami Hiramatsu 		if (file)
39460d53e2cSMasami Hiramatsu 			trace_probe_remove_file(tp, file);
395b5f935eeSMasami Hiramatsu 		else
39660d53e2cSMasami Hiramatsu 			trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
39757ea2a34SArtem Savkov 	}
398b5f935eeSMasami Hiramatsu 
3991538f888SMasami Hiramatsu 	return ret;
4001538f888SMasami Hiramatsu }
4011538f888SMasami Hiramatsu 
40241a7dd42SMasami Hiramatsu /*
40341a7dd42SMasami Hiramatsu  * Disable trace_probe
40441a7dd42SMasami Hiramatsu  * if the file is NULL, disable "perf" handler, or disable "trace" handler.
40541a7dd42SMasami Hiramatsu  */
disable_trace_kprobe(struct trace_event_call * call,struct trace_event_file * file)40660d53e2cSMasami Hiramatsu static int disable_trace_kprobe(struct trace_event_call *call,
40760d53e2cSMasami Hiramatsu 				struct trace_event_file *file)
40841a7dd42SMasami Hiramatsu {
40960d53e2cSMasami Hiramatsu 	struct trace_probe *tp;
41060d53e2cSMasami Hiramatsu 
41160d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(call);
41260d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
41360d53e2cSMasami Hiramatsu 		return -ENODEV;
41441a7dd42SMasami Hiramatsu 
41541a7dd42SMasami Hiramatsu 	if (file) {
416b5f935eeSMasami Hiramatsu 		if (!trace_probe_get_file_link(tp, file))
417b5f935eeSMasami Hiramatsu 			return -ENOENT;
418b5f935eeSMasami Hiramatsu 		if (!trace_probe_has_single_file(tp))
4193fe3d619SOleg Nesterov 			goto out;
420747774d6SMasami Hiramatsu 		trace_probe_clear_flag(tp, TP_FLAG_TRACE);
42141a7dd42SMasami Hiramatsu 	} else
422747774d6SMasami Hiramatsu 		trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
42341a7dd42SMasami Hiramatsu 
42460d53e2cSMasami Hiramatsu 	if (!trace_probe_is_enabled(tp))
42560d53e2cSMasami Hiramatsu 		__disable_trace_kprobe(tp);
426e12f03d7SSong Liu 
4273fe3d619SOleg Nesterov  out:
428b5f935eeSMasami Hiramatsu 	if (file)
429a232e270SMasami Hiramatsu 		/*
430b5f935eeSMasami Hiramatsu 		 * Synchronization is done in below function. For perf event,
431b5f935eeSMasami Hiramatsu 		 * file == NULL and perf_trace_event_unreg() calls
432b5f935eeSMasami Hiramatsu 		 * tracepoint_synchronize_unregister() to ensure synchronize
433b5f935eeSMasami Hiramatsu 		 * event. We don't need to care about it.
434a232e270SMasami Hiramatsu 		 */
435b5f935eeSMasami Hiramatsu 		trace_probe_remove_file(tp, file);
436a232e270SMasami Hiramatsu 
43760d53e2cSMasami Hiramatsu 	return 0;
4381538f888SMasami Hiramatsu }
4391538f888SMasami Hiramatsu 
4407bb83f6fSMasami Hiramatsu #if defined(CONFIG_DYNAMIC_FTRACE) && \
44145408c4fSMasami Hiramatsu 	!defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE)
__within_notrace_func(unsigned long addr)442c7411a1aSMasami Hiramatsu static bool __within_notrace_func(unsigned long addr)
44345408c4fSMasami Hiramatsu {
444c7411a1aSMasami Hiramatsu 	unsigned long offset, size;
44545408c4fSMasami Hiramatsu 
4466bc6c77cSMasami Hiramatsu 	if (!addr || !kallsyms_lookup_size_offset(addr, &size, &offset))
4476bc6c77cSMasami Hiramatsu 		return false;
44845408c4fSMasami Hiramatsu 
4499161a864SMasami Hiramatsu 	/* Get the entry address of the target function */
4509161a864SMasami Hiramatsu 	addr -= offset;
4519161a864SMasami Hiramatsu 
4529161a864SMasami Hiramatsu 	/*
4539161a864SMasami Hiramatsu 	 * Since ftrace_location_range() does inclusive range check, we need
4549161a864SMasami Hiramatsu 	 * to subtract 1 byte from the end address.
4559161a864SMasami Hiramatsu 	 */
4569161a864SMasami Hiramatsu 	return !ftrace_location_range(addr, addr + size - 1);
45745408c4fSMasami Hiramatsu }
458c7411a1aSMasami Hiramatsu 
within_notrace_func(struct trace_kprobe * tk)459c7411a1aSMasami Hiramatsu static bool within_notrace_func(struct trace_kprobe *tk)
460c7411a1aSMasami Hiramatsu {
461dcbd21c9SMasami Hiramatsu 	unsigned long addr = trace_kprobe_address(tk);
462c7411a1aSMasami Hiramatsu 	char symname[KSYM_NAME_LEN], *p;
463c7411a1aSMasami Hiramatsu 
464c7411a1aSMasami Hiramatsu 	if (!__within_notrace_func(addr))
465c7411a1aSMasami Hiramatsu 		return false;
466c7411a1aSMasami Hiramatsu 
467c7411a1aSMasami Hiramatsu 	/* Check if the address is on a suffixed-symbol */
468c7411a1aSMasami Hiramatsu 	if (!lookup_symbol_name(addr, symname)) {
469c7411a1aSMasami Hiramatsu 		p = strchr(symname, '.');
470c7411a1aSMasami Hiramatsu 		if (!p)
471c7411a1aSMasami Hiramatsu 			return true;
472c7411a1aSMasami Hiramatsu 		*p = '\0';
473c7411a1aSMasami Hiramatsu 		addr = (unsigned long)kprobe_lookup_name(symname, 0);
474c7411a1aSMasami Hiramatsu 		if (addr)
475c7411a1aSMasami Hiramatsu 			return __within_notrace_func(addr);
476c7411a1aSMasami Hiramatsu 	}
477c7411a1aSMasami Hiramatsu 
478c7411a1aSMasami Hiramatsu 	return true;
479c7411a1aSMasami Hiramatsu }
48045408c4fSMasami Hiramatsu #else
48145408c4fSMasami Hiramatsu #define within_notrace_func(tk)	(false)
48245408c4fSMasami Hiramatsu #endif
48345408c4fSMasami Hiramatsu 
48461424318SMasami Hiramatsu /* Internal register function - just handle k*probes and flags */
__register_trace_kprobe(struct trace_kprobe * tk)485c31ffb3fSNamhyung Kim static int __register_trace_kprobe(struct trace_kprobe *tk)
486413d37d1SMasami Hiramatsu {
487a6682814SMasami Hiramatsu 	int i, ret;
48861424318SMasami Hiramatsu 
489a94549ddSDavid Howells 	ret = security_locked_down(LOCKDOWN_KPROBES);
490a94549ddSDavid Howells 	if (ret)
491a94549ddSDavid Howells 		return ret;
492a94549ddSDavid Howells 
493715fa2fdSMasami Hiramatsu 	if (trace_kprobe_is_registered(tk))
49461424318SMasami Hiramatsu 		return -EINVAL;
49561424318SMasami Hiramatsu 
49645408c4fSMasami Hiramatsu 	if (within_notrace_func(tk)) {
4979c556b7cSNaveen N Rao 		pr_warn("Could not probe notrace function %ps\n",
4989c556b7cSNaveen N Rao 			(void *)trace_kprobe_address(tk));
49945408c4fSMasami Hiramatsu 		return -EINVAL;
50045408c4fSMasami Hiramatsu 	}
50145408c4fSMasami Hiramatsu 
502a6682814SMasami Hiramatsu 	for (i = 0; i < tk->tp.nr_args; i++) {
503a6682814SMasami Hiramatsu 		ret = traceprobe_update_arg(&tk->tp.args[i]);
504a6682814SMasami Hiramatsu 		if (ret)
505a6682814SMasami Hiramatsu 			return ret;
506a6682814SMasami Hiramatsu 	}
507a6682814SMasami Hiramatsu 
50861424318SMasami Hiramatsu 	/* Set/clear disabled flag according to tp->flag */
509c31ffb3fSNamhyung Kim 	if (trace_probe_is_enabled(&tk->tp))
510c31ffb3fSNamhyung Kim 		tk->rp.kp.flags &= ~KPROBE_FLAG_DISABLED;
51161424318SMasami Hiramatsu 	else
512c31ffb3fSNamhyung Kim 		tk->rp.kp.flags |= KPROBE_FLAG_DISABLED;
51361424318SMasami Hiramatsu 
514c31ffb3fSNamhyung Kim 	if (trace_kprobe_is_return(tk))
515c31ffb3fSNamhyung Kim 		ret = register_kretprobe(&tk->rp);
51661424318SMasami Hiramatsu 	else
517c31ffb3fSNamhyung Kim 		ret = register_kprobe(&tk->rp.kp);
51861424318SMasami Hiramatsu 
51961424318SMasami Hiramatsu 	return ret;
52061424318SMasami Hiramatsu }
52161424318SMasami Hiramatsu 
52261424318SMasami Hiramatsu /* Internal unregister function - just handle k*probes and flags */
__unregister_trace_kprobe(struct trace_kprobe * tk)523c31ffb3fSNamhyung Kim static void __unregister_trace_kprobe(struct trace_kprobe *tk)
52461424318SMasami Hiramatsu {
525715fa2fdSMasami Hiramatsu 	if (trace_kprobe_is_registered(tk)) {
526c31ffb3fSNamhyung Kim 		if (trace_kprobe_is_return(tk))
527c31ffb3fSNamhyung Kim 			unregister_kretprobe(&tk->rp);
528413d37d1SMasami Hiramatsu 		else
529c31ffb3fSNamhyung Kim 			unregister_kprobe(&tk->rp.kp);
530715fa2fdSMasami Hiramatsu 		/* Cleanup kprobe for reuse and mark it unregistered */
531715fa2fdSMasami Hiramatsu 		INIT_HLIST_NODE(&tk->rp.kp.hlist);
532715fa2fdSMasami Hiramatsu 		INIT_LIST_HEAD(&tk->rp.kp.list);
533c31ffb3fSNamhyung Kim 		if (tk->rp.kp.symbol_name)
534c31ffb3fSNamhyung Kim 			tk->rp.kp.addr = NULL;
53561424318SMasami Hiramatsu 	}
53661424318SMasami Hiramatsu }
53761424318SMasami Hiramatsu 
5386212dd29SMasami Hiramatsu /* Unregister a trace_probe and probe_event */
unregister_trace_kprobe(struct trace_kprobe * tk)539c31ffb3fSNamhyung Kim static int unregister_trace_kprobe(struct trace_kprobe *tk)
54061424318SMasami Hiramatsu {
541ca89bc07SMasami Hiramatsu 	/* If other probes are on the event, just unregister kprobe */
542ca89bc07SMasami Hiramatsu 	if (trace_probe_has_sibling(&tk->tp))
543ca89bc07SMasami Hiramatsu 		goto unreg;
544ca89bc07SMasami Hiramatsu 
54502ca1521SMasami Hiramatsu 	/* Enabled event can not be unregistered */
546c31ffb3fSNamhyung Kim 	if (trace_probe_is_enabled(&tk->tp))
54702ca1521SMasami Hiramatsu 		return -EBUSY;
54802ca1521SMasami Hiramatsu 
5491d18538eSSteven Rostedt (VMware) 	/* If there's a reference to the dynamic event */
5501d18538eSSteven Rostedt (VMware) 	if (trace_event_dyn_busy(trace_probe_event_call(&tk->tp)))
5511d18538eSSteven Rostedt (VMware) 		return -EBUSY;
5521d18538eSSteven Rostedt (VMware) 
55340c32592SSteven Rostedt (Red Hat) 	/* Will fail if probe is being used by ftrace or perf */
554c31ffb3fSNamhyung Kim 	if (unregister_kprobe_event(tk))
55540c32592SSteven Rostedt (Red Hat) 		return -EBUSY;
55640c32592SSteven Rostedt (Red Hat) 
557ca89bc07SMasami Hiramatsu unreg:
558c31ffb3fSNamhyung Kim 	__unregister_trace_kprobe(tk);
5596212dd29SMasami Hiramatsu 	dyn_event_remove(&tk->devent);
560ca89bc07SMasami Hiramatsu 	trace_probe_unlink(&tk->tp);
56102ca1521SMasami Hiramatsu 
56202ca1521SMasami Hiramatsu 	return 0;
563413d37d1SMasami Hiramatsu }
564413d37d1SMasami Hiramatsu 
trace_kprobe_has_same_kprobe(struct trace_kprobe * orig,struct trace_kprobe * comp)565fe60b0ceSMasami Hiramatsu static bool trace_kprobe_has_same_kprobe(struct trace_kprobe *orig,
566fe60b0ceSMasami Hiramatsu 					 struct trace_kprobe *comp)
567fe60b0ceSMasami Hiramatsu {
568fe60b0ceSMasami Hiramatsu 	struct trace_probe_event *tpe = orig->tp.event;
569fe60b0ceSMasami Hiramatsu 	int i;
570fe60b0ceSMasami Hiramatsu 
571e161c6bfSJiri Olsa 	list_for_each_entry(orig, &tpe->probes, tp.list) {
572fe60b0ceSMasami Hiramatsu 		if (strcmp(trace_kprobe_symbol(orig),
573fe60b0ceSMasami Hiramatsu 			   trace_kprobe_symbol(comp)) ||
574fe60b0ceSMasami Hiramatsu 		    trace_kprobe_offset(orig) != trace_kprobe_offset(comp))
575fe60b0ceSMasami Hiramatsu 			continue;
576fe60b0ceSMasami Hiramatsu 
577fe60b0ceSMasami Hiramatsu 		/*
578fe60b0ceSMasami Hiramatsu 		 * trace_probe_compare_arg_type() ensured that nr_args and
579fe60b0ceSMasami Hiramatsu 		 * each argument name and type are same. Let's compare comm.
580fe60b0ceSMasami Hiramatsu 		 */
581fe60b0ceSMasami Hiramatsu 		for (i = 0; i < orig->tp.nr_args; i++) {
582fe60b0ceSMasami Hiramatsu 			if (strcmp(orig->tp.args[i].comm,
583fe60b0ceSMasami Hiramatsu 				   comp->tp.args[i].comm))
584f8d7ab2bSSrikar Dronamraju 				break;
585fe60b0ceSMasami Hiramatsu 		}
586fe60b0ceSMasami Hiramatsu 
587f8d7ab2bSSrikar Dronamraju 		if (i == orig->tp.nr_args)
588fe60b0ceSMasami Hiramatsu 			return true;
589fe60b0ceSMasami Hiramatsu 	}
590fe60b0ceSMasami Hiramatsu 
591fe60b0ceSMasami Hiramatsu 	return false;
592fe60b0ceSMasami Hiramatsu }
593fe60b0ceSMasami Hiramatsu 
append_trace_kprobe(struct trace_kprobe * tk,struct trace_kprobe * to)594ca89bc07SMasami Hiramatsu static int append_trace_kprobe(struct trace_kprobe *tk, struct trace_kprobe *to)
595ca89bc07SMasami Hiramatsu {
596ca89bc07SMasami Hiramatsu 	int ret;
597ca89bc07SMasami Hiramatsu 
598fe60b0ceSMasami Hiramatsu 	ret = trace_probe_compare_arg_type(&tk->tp, &to->tp);
599fe60b0ceSMasami Hiramatsu 	if (ret) {
600fe60b0ceSMasami Hiramatsu 		/* Note that argument starts index = 2 */
601fe60b0ceSMasami Hiramatsu 		trace_probe_log_set_index(ret + 1);
602fe60b0ceSMasami Hiramatsu 		trace_probe_log_err(0, DIFF_ARG_TYPE);
603fe60b0ceSMasami Hiramatsu 		return -EEXIST;
604fe60b0ceSMasami Hiramatsu 	}
605fe60b0ceSMasami Hiramatsu 	if (trace_kprobe_has_same_kprobe(to, tk)) {
606fe60b0ceSMasami Hiramatsu 		trace_probe_log_set_index(0);
607fe60b0ceSMasami Hiramatsu 		trace_probe_log_err(0, SAME_PROBE);
608fe60b0ceSMasami Hiramatsu 		return -EEXIST;
609fe60b0ceSMasami Hiramatsu 	}
610fe60b0ceSMasami Hiramatsu 
611ca89bc07SMasami Hiramatsu 	/* Append to existing event */
612ca89bc07SMasami Hiramatsu 	ret = trace_probe_append(&tk->tp, &to->tp);
613ca89bc07SMasami Hiramatsu 	if (ret)
614ca89bc07SMasami Hiramatsu 		return ret;
615ca89bc07SMasami Hiramatsu 
616ca89bc07SMasami Hiramatsu 	/* Register k*probe */
617ca89bc07SMasami Hiramatsu 	ret = __register_trace_kprobe(tk);
618ca89bc07SMasami Hiramatsu 	if (ret == -ENOENT && !trace_kprobe_module_exist(tk)) {
619ca89bc07SMasami Hiramatsu 		pr_warn("This probe might be able to register after target module is loaded. Continue.\n");
620ca89bc07SMasami Hiramatsu 		ret = 0;
621ca89bc07SMasami Hiramatsu 	}
622ca89bc07SMasami Hiramatsu 
623ca89bc07SMasami Hiramatsu 	if (ret)
624ca89bc07SMasami Hiramatsu 		trace_probe_unlink(&tk->tp);
625ca89bc07SMasami Hiramatsu 	else
6268b0e6c74SSteven Rostedt (VMware) 		dyn_event_add(&tk->devent, trace_probe_event_call(&tk->tp));
627ca89bc07SMasami Hiramatsu 
628ca89bc07SMasami Hiramatsu 	return ret;
629ca89bc07SMasami Hiramatsu }
630ca89bc07SMasami Hiramatsu 
631413d37d1SMasami Hiramatsu /* Register a trace_probe and probe_event */
register_trace_kprobe(struct trace_kprobe * tk)632c31ffb3fSNamhyung Kim static int register_trace_kprobe(struct trace_kprobe *tk)
633413d37d1SMasami Hiramatsu {
634c31ffb3fSNamhyung Kim 	struct trace_kprobe *old_tk;
635413d37d1SMasami Hiramatsu 	int ret;
636413d37d1SMasami Hiramatsu 
6372cba0070SMasami Hiramatsu (Google) 	guard(mutex)(&event_mutex);
638413d37d1SMasami Hiramatsu 
639b55ce203SMasami Hiramatsu 	old_tk = find_trace_kprobe(trace_probe_name(&tk->tp),
640b55ce203SMasami Hiramatsu 				   trace_probe_group_name(&tk->tp));
641c31ffb3fSNamhyung Kim 	if (old_tk) {
642ca89bc07SMasami Hiramatsu 		if (trace_kprobe_is_return(tk) != trace_kprobe_is_return(old_tk)) {
643ca89bc07SMasami Hiramatsu 			trace_probe_log_set_index(0);
644ca89bc07SMasami Hiramatsu 			trace_probe_log_err(0, DIFF_PROBE_TYPE);
6452cba0070SMasami Hiramatsu (Google) 			return -EEXIST;
646ca89bc07SMasami Hiramatsu 		}
6472cba0070SMasami Hiramatsu (Google) 		return append_trace_kprobe(tk, old_tk);
6482d5e067eSMasami Hiramatsu 	}
64961424318SMasami Hiramatsu 
65061424318SMasami Hiramatsu 	/* Register new event */
651c31ffb3fSNamhyung Kim 	ret = register_kprobe_event(tk);
6522d5e067eSMasami Hiramatsu 	if (ret) {
6538e242060SMasami Hiramatsu 		if (ret == -EEXIST) {
6548e242060SMasami Hiramatsu 			trace_probe_log_set_index(0);
6558e242060SMasami Hiramatsu 			trace_probe_log_err(0, EVENT_EXIST);
6568e242060SMasami Hiramatsu 		} else
657a395d6a7SJoe Perches 			pr_warn("Failed to register probe event(%d)\n", ret);
6582cba0070SMasami Hiramatsu (Google) 		return ret;
6592d5e067eSMasami Hiramatsu 	}
6602d5e067eSMasami Hiramatsu 
66161424318SMasami Hiramatsu 	/* Register k*probe */
662c31ffb3fSNamhyung Kim 	ret = __register_trace_kprobe(tk);
66359158ec4SMasami Hiramatsu 	if (ret == -ENOENT && !trace_kprobe_module_exist(tk)) {
66459158ec4SMasami Hiramatsu 		pr_warn("This probe might be able to register after target module is loaded. Continue.\n");
66559158ec4SMasami Hiramatsu 		ret = 0;
66659158ec4SMasami Hiramatsu 	}
66759158ec4SMasami Hiramatsu 
66861424318SMasami Hiramatsu 	if (ret < 0)
669c31ffb3fSNamhyung Kim 		unregister_kprobe_event(tk);
67061424318SMasami Hiramatsu 	else
6718b0e6c74SSteven Rostedt (VMware) 		dyn_event_add(&tk->devent, trace_probe_event_call(&tk->tp));
67261424318SMasami Hiramatsu 
673413d37d1SMasami Hiramatsu 	return ret;
674413d37d1SMasami Hiramatsu }
675413d37d1SMasami Hiramatsu 
6767582b7beSMike Rapoport (IBM) #ifdef CONFIG_MODULES
6779d861603SMasami Hiramatsu (Google) static int validate_module_probe_symbol(const char *modname, const char *symbol);
6789d861603SMasami Hiramatsu (Google) 
register_module_trace_kprobe(struct module * mod,struct trace_kprobe * tk)6799d861603SMasami Hiramatsu (Google) static int register_module_trace_kprobe(struct module *mod, struct trace_kprobe *tk)
6809d861603SMasami Hiramatsu (Google) {
6819d861603SMasami Hiramatsu (Google) 	const char *p;
6829d861603SMasami Hiramatsu (Google) 	int ret = 0;
6839d861603SMasami Hiramatsu (Google) 
6849d861603SMasami Hiramatsu (Google) 	p = strchr(trace_kprobe_symbol(tk), ':');
6859d861603SMasami Hiramatsu (Google) 	if (p)
6869d861603SMasami Hiramatsu (Google) 		ret = validate_module_probe_symbol(module_name(mod), p + 1);
6879d861603SMasami Hiramatsu (Google) 	if (!ret)
6889d861603SMasami Hiramatsu (Google) 		ret = __register_trace_kprobe(tk);
6899d861603SMasami Hiramatsu (Google) 	return ret;
6909d861603SMasami Hiramatsu (Google) }
6919d861603SMasami Hiramatsu (Google) 
69261424318SMasami Hiramatsu /* Module notifier call back, checking event on the module */
trace_kprobe_module_callback(struct notifier_block * nb,unsigned long val,void * data)693c31ffb3fSNamhyung Kim static int trace_kprobe_module_callback(struct notifier_block *nb,
69461424318SMasami Hiramatsu 				       unsigned long val, void *data)
69561424318SMasami Hiramatsu {
69661424318SMasami Hiramatsu 	struct module *mod = data;
6976212dd29SMasami Hiramatsu 	struct dyn_event *pos;
698c31ffb3fSNamhyung Kim 	struct trace_kprobe *tk;
69961424318SMasami Hiramatsu 	int ret;
70061424318SMasami Hiramatsu 
70161424318SMasami Hiramatsu 	if (val != MODULE_STATE_COMING)
70261424318SMasami Hiramatsu 		return NOTIFY_DONE;
70361424318SMasami Hiramatsu 
70461424318SMasami Hiramatsu 	/* Update probes on coming module */
7052cba0070SMasami Hiramatsu (Google) 	guard(mutex)(&event_mutex);
7066212dd29SMasami Hiramatsu 	for_each_trace_kprobe(tk, pos) {
707c31ffb3fSNamhyung Kim 		if (trace_kprobe_within_module(tk, mod)) {
70802ca1521SMasami Hiramatsu 			/* Don't need to check busy - this should have gone. */
709c31ffb3fSNamhyung Kim 			__unregister_trace_kprobe(tk);
7109d861603SMasami Hiramatsu (Google) 			ret = register_module_trace_kprobe(mod, tk);
71161424318SMasami Hiramatsu 			if (ret)
712a395d6a7SJoe Perches 				pr_warn("Failed to re-register probe %s on %s: %d\n",
713b55ce203SMasami Hiramatsu 					trace_probe_name(&tk->tp),
714f3d36426SJarkko Sakkinen 					module_name(mod), ret);
71561424318SMasami Hiramatsu 		}
71661424318SMasami Hiramatsu 	}
71761424318SMasami Hiramatsu 
71861424318SMasami Hiramatsu 	return NOTIFY_DONE;
71961424318SMasami Hiramatsu }
72061424318SMasami Hiramatsu 
721c31ffb3fSNamhyung Kim static struct notifier_block trace_kprobe_module_nb = {
722c31ffb3fSNamhyung Kim 	.notifier_call = trace_kprobe_module_callback,
723d685d55dSMasami Hiramatsu (Google) 	.priority = 2	/* Invoked after kprobe and jump_label module callback */
72461424318SMasami Hiramatsu };
trace_kprobe_register_module_notifier(void)7257582b7beSMike Rapoport (IBM) static int trace_kprobe_register_module_notifier(void)
7267582b7beSMike Rapoport (IBM) {
7277582b7beSMike Rapoport (IBM) 	return register_module_notifier(&trace_kprobe_module_nb);
7287582b7beSMike Rapoport (IBM) }
7297582b7beSMike Rapoport (IBM) #else
trace_kprobe_register_module_notifier(void)7307582b7beSMike Rapoport (IBM) static int trace_kprobe_register_module_notifier(void)
7317582b7beSMike Rapoport (IBM) {
7327582b7beSMike Rapoport (IBM) 	return 0;
7337582b7beSMike Rapoport (IBM) }
7347582b7beSMike Rapoport (IBM) #endif /* CONFIG_MODULES */
73561424318SMasami Hiramatsu 
count_symbols(void * data,unsigned long unused)736b022f0c7SFrancis Laniel static int count_symbols(void *data, unsigned long unused)
737b022f0c7SFrancis Laniel {
738b022f0c7SFrancis Laniel 	unsigned int *count = data;
739b022f0c7SFrancis Laniel 
740b022f0c7SFrancis Laniel 	(*count)++;
741b022f0c7SFrancis Laniel 
742b022f0c7SFrancis Laniel 	return 0;
743b022f0c7SFrancis Laniel }
744b022f0c7SFrancis Laniel 
745926fe783SAndrii Nakryiko struct sym_count_ctx {
746926fe783SAndrii Nakryiko 	unsigned int count;
747926fe783SAndrii Nakryiko 	const char *name;
748926fe783SAndrii Nakryiko };
749926fe783SAndrii Nakryiko 
count_mod_symbols(void * data,const char * name,unsigned long unused)750926fe783SAndrii Nakryiko static int count_mod_symbols(void *data, const char *name, unsigned long unused)
751926fe783SAndrii Nakryiko {
752926fe783SAndrii Nakryiko 	struct sym_count_ctx *ctx = data;
753926fe783SAndrii Nakryiko 
754926fe783SAndrii Nakryiko 	if (strcmp(name, ctx->name) == 0)
755926fe783SAndrii Nakryiko 		ctx->count++;
756926fe783SAndrii Nakryiko 
757926fe783SAndrii Nakryiko 	return 0;
758926fe783SAndrii Nakryiko }
759926fe783SAndrii Nakryiko 
number_of_same_symbols(const char * mod,const char * func_name)7609d861603SMasami Hiramatsu (Google) static unsigned int number_of_same_symbols(const char *mod, const char *func_name)
761b022f0c7SFrancis Laniel {
762926fe783SAndrii Nakryiko 	struct sym_count_ctx ctx = { .count = 0, .name = func_name };
763b022f0c7SFrancis Laniel 
7649d861603SMasami Hiramatsu (Google) 	if (!mod)
765926fe783SAndrii Nakryiko 		kallsyms_on_each_match_symbol(count_symbols, func_name, &ctx.count);
766b022f0c7SFrancis Laniel 
7679d861603SMasami Hiramatsu (Google) 	module_kallsyms_on_each_symbol(mod, count_mod_symbols, &ctx);
768926fe783SAndrii Nakryiko 
769926fe783SAndrii Nakryiko 	return ctx.count;
770b022f0c7SFrancis Laniel }
771b022f0c7SFrancis Laniel 
validate_module_probe_symbol(const char * modname,const char * symbol)7729d861603SMasami Hiramatsu (Google) static int validate_module_probe_symbol(const char *modname, const char *symbol)
7739d861603SMasami Hiramatsu (Google) {
7749d861603SMasami Hiramatsu (Google) 	unsigned int count = number_of_same_symbols(modname, symbol);
7759d861603SMasami Hiramatsu (Google) 
7769d861603SMasami Hiramatsu (Google) 	if (count > 1) {
7779d861603SMasami Hiramatsu (Google) 		/*
7789d861603SMasami Hiramatsu (Google) 		 * Users should use ADDR to remove the ambiguity of
7799d861603SMasami Hiramatsu (Google) 		 * using KSYM only.
7809d861603SMasami Hiramatsu (Google) 		 */
7819d861603SMasami Hiramatsu (Google) 		return -EADDRNOTAVAIL;
7829d861603SMasami Hiramatsu (Google) 	} else if (count == 0) {
7839d861603SMasami Hiramatsu (Google) 		/*
7849d861603SMasami Hiramatsu (Google) 		 * We can return ENOENT earlier than when register the
7859d861603SMasami Hiramatsu (Google) 		 * kprobe.
7869d861603SMasami Hiramatsu (Google) 		 */
7879d861603SMasami Hiramatsu (Google) 		return -ENOENT;
7889d861603SMasami Hiramatsu (Google) 	}
7899d861603SMasami Hiramatsu (Google) 	return 0;
7909d861603SMasami Hiramatsu (Google) }
7919d861603SMasami Hiramatsu (Google) 
792b10545b6SMasami Hiramatsu (Google) #ifdef CONFIG_MODULES
793b10545b6SMasami Hiramatsu (Google) /* Return NULL if the module is not loaded or under unloading. */
try_module_get_by_name(const char * name)794b10545b6SMasami Hiramatsu (Google) static struct module *try_module_get_by_name(const char *name)
795b10545b6SMasami Hiramatsu (Google) {
796b10545b6SMasami Hiramatsu (Google) 	struct module *mod;
797b10545b6SMasami Hiramatsu (Google) 
798febaa65cSSebastian Andrzej Siewior 	guard(rcu)();
799b10545b6SMasami Hiramatsu (Google) 	mod = find_module(name);
800b10545b6SMasami Hiramatsu (Google) 	if (mod && !try_module_get(mod))
801b10545b6SMasami Hiramatsu (Google) 		mod = NULL;
802b10545b6SMasami Hiramatsu (Google) 	return mod;
803b10545b6SMasami Hiramatsu (Google) }
804b10545b6SMasami Hiramatsu (Google) #else
805b10545b6SMasami Hiramatsu (Google) #define try_module_get_by_name(name)	(NULL)
806b10545b6SMasami Hiramatsu (Google) #endif
807b10545b6SMasami Hiramatsu (Google) 
validate_probe_symbol(char * symbol)8089d861603SMasami Hiramatsu (Google) static int validate_probe_symbol(char *symbol)
8099d861603SMasami Hiramatsu (Google) {
8109d861603SMasami Hiramatsu (Google) 	struct module *mod = NULL;
8119d861603SMasami Hiramatsu (Google) 	char *modname = NULL, *p;
8129d861603SMasami Hiramatsu (Google) 	int ret = 0;
8139d861603SMasami Hiramatsu (Google) 
8149d861603SMasami Hiramatsu (Google) 	p = strchr(symbol, ':');
8159d861603SMasami Hiramatsu (Google) 	if (p) {
8169d861603SMasami Hiramatsu (Google) 		modname = symbol;
8179d861603SMasami Hiramatsu (Google) 		symbol = p + 1;
8189d861603SMasami Hiramatsu (Google) 		*p = '\0';
819b10545b6SMasami Hiramatsu (Google) 		mod = try_module_get_by_name(modname);
8209d861603SMasami Hiramatsu (Google) 		if (!mod)
8219d861603SMasami Hiramatsu (Google) 			goto out;
8229d861603SMasami Hiramatsu (Google) 	}
8239d861603SMasami Hiramatsu (Google) 
8249d861603SMasami Hiramatsu (Google) 	ret = validate_module_probe_symbol(modname, symbol);
8259d861603SMasami Hiramatsu (Google) out:
8269d861603SMasami Hiramatsu (Google) 	if (p)
8279d861603SMasami Hiramatsu (Google) 		*p = ':';
8289d861603SMasami Hiramatsu (Google) 	if (mod)
8299d861603SMasami Hiramatsu (Google) 		module_put(mod);
8309d861603SMasami Hiramatsu (Google) 	return ret;
8319d861603SMasami Hiramatsu (Google) }
8329d861603SMasami Hiramatsu (Google) 
83325f00e40SMasami Hiramatsu (Google) static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
83425f00e40SMasami Hiramatsu (Google) 				      struct pt_regs *regs);
83525f00e40SMasami Hiramatsu (Google) 
trace_kprobe_create_internal(int argc,const char * argv[],struct traceprobe_parse_context * ctx)83692705460SMasami Hiramatsu (Google) static int trace_kprobe_create_internal(int argc, const char *argv[],
83792705460SMasami Hiramatsu (Google) 					struct traceprobe_parse_context *ctx)
838413d37d1SMasami Hiramatsu {
839413d37d1SMasami Hiramatsu 	/*
840413d37d1SMasami Hiramatsu 	 * Argument syntax:
841696ced4fSAlban Crequy 	 *  - Add kprobe:
84295c104c3SLinyu Yuan 	 *      p[:[GRP/][EVENT]] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
843696ced4fSAlban Crequy 	 *  - Add kretprobe:
84495c104c3SLinyu Yuan 	 *      r[MAXACTIVE][:[GRP/][EVENT]] [MOD:]KSYM[+0] [FETCHARGS]
8454725cd89SMasami Hiramatsu 	 *    Or
84695c104c3SLinyu Yuan 	 *      p[:[GRP/][EVENT]] [MOD:]KSYM[+0]%return [FETCHARGS]
8474725cd89SMasami Hiramatsu 	 *
848413d37d1SMasami Hiramatsu 	 * Fetch args:
8492e06ff63SMasami Hiramatsu 	 *  $retval	: fetch return value
8502e06ff63SMasami Hiramatsu 	 *  $stack	: fetch stack address
8512e06ff63SMasami Hiramatsu 	 *  $stackN	: fetch Nth of stack (N:0-)
85235abb67dSOmar Sandoval 	 *  $comm       : fetch current task comm
853413d37d1SMasami Hiramatsu 	 *  @ADDR	: fetch memory at ADDR (ADDR should be in kernel)
854413d37d1SMasami Hiramatsu 	 *  @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol)
855413d37d1SMasami Hiramatsu 	 *  %REG	: fetch register REG
85693ccae7aSMasami Hiramatsu 	 * Dereferencing memory fetch:
857413d37d1SMasami Hiramatsu 	 *  +|-offs(ARG) : fetch memory at ARG +|- offs address.
858eca0d916SMasami Hiramatsu 	 * Alias name of args:
859eca0d916SMasami Hiramatsu 	 *  NAME=FETCHARG : set NAME as alias of FETCHARG.
86093ccae7aSMasami Hiramatsu 	 * Type of args:
86193ccae7aSMasami Hiramatsu 	 *  FETCHARG:TYPE : use TYPE instead of unsigned long.
862413d37d1SMasami Hiramatsu 	 */
8637dcc3520SMasami Hiramatsu (Google) 	struct trace_kprobe *tk __free(free_trace_kprobe) = NULL;
86418b1e870SMasami Hiramatsu (Google) 	int i, len, new_argc = 0, ret = 0;
8656212dd29SMasami Hiramatsu 	bool is_return = false;
8667dcc3520SMasami Hiramatsu (Google) 	char *symbol __free(kfree) = NULL;
8677dcc3520SMasami Hiramatsu (Google) 	char *tmp = NULL;
8687dcc3520SMasami Hiramatsu (Google) 	const char **new_argv __free(kfree) = NULL;
8696212dd29SMasami Hiramatsu 	const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
870007517a0SSteven Rostedt (VMware) 	enum probe_print_type ptype;
871696ced4fSAlban Crequy 	int maxactive = 0;
872c5d343b6SMasami Hiramatsu 	long offset = 0;
873413d37d1SMasami Hiramatsu 	void *addr = NULL;
8744a846b44SMasami Hiramatsu 	char buf[MAX_EVENT_NAME_LEN];
87595c104c3SLinyu Yuan 	char gbuf[MAX_EVENT_NAME_LEN];
87618b1e870SMasami Hiramatsu (Google) 	char abuf[MAX_BTF_ARGS_LEN];
8777dcc3520SMasami Hiramatsu (Google) 	char *dbuf __free(kfree) = NULL;
878413d37d1SMasami Hiramatsu 
8798b05a3a7SAndrea Righi 	switch (argv[0][0]) {
8808b05a3a7SAndrea Righi 	case 'r':
8813a6b7666SSrikar Dronamraju 		is_return = true;
8828b05a3a7SAndrea Righi 		break;
8838b05a3a7SAndrea Righi 	case 'p':
8848b05a3a7SAndrea Righi 		break;
8858b05a3a7SAndrea Righi 	default:
8868b05a3a7SAndrea Righi 		return -ECANCELED;
8878b05a3a7SAndrea Righi 	}
8888b05a3a7SAndrea Righi 	if (argc < 2)
8896212dd29SMasami Hiramatsu 		return -ECANCELED;
890413d37d1SMasami Hiramatsu 
891696ced4fSAlban Crequy 	event = strchr(&argv[0][1], ':');
8926212dd29SMasami Hiramatsu 	if (event)
893696ced4fSAlban Crequy 		event++;
8946212dd29SMasami Hiramatsu 
895287c038cSMasami Hiramatsu 	if (isdigit(argv[0][1])) {
896287c038cSMasami Hiramatsu 		if (!is_return) {
897334e5519SMasami Hiramatsu (Google) 			trace_probe_log_err(1, BAD_MAXACT_TYPE);
89892705460SMasami Hiramatsu (Google) 			return -EINVAL;
899287c038cSMasami Hiramatsu 		}
9006212dd29SMasami Hiramatsu 		if (event)
9016212dd29SMasami Hiramatsu 			len = event - &argv[0][1] - 1;
9026212dd29SMasami Hiramatsu 		else
9036212dd29SMasami Hiramatsu 			len = strlen(&argv[0][1]);
904ab105a4fSMasami Hiramatsu 		if (len > MAX_EVENT_NAME_LEN - 1) {
905ab105a4fSMasami Hiramatsu 			trace_probe_log_err(1, BAD_MAXACT);
90692705460SMasami Hiramatsu (Google) 			return -EINVAL;
907ab105a4fSMasami Hiramatsu 		}
9086212dd29SMasami Hiramatsu 		memcpy(buf, &argv[0][1], len);
9096212dd29SMasami Hiramatsu 		buf[len] = '\0';
9106212dd29SMasami Hiramatsu 		ret = kstrtouint(buf, 0, &maxactive);
911287c038cSMasami Hiramatsu 		if (ret || !maxactive) {
912ab105a4fSMasami Hiramatsu 			trace_probe_log_err(1, BAD_MAXACT);
91392705460SMasami Hiramatsu (Google) 			return -EINVAL;
914696ced4fSAlban Crequy 		}
915696ced4fSAlban Crequy 		/* kretprobes instances are iterated over via a list. The
916696ced4fSAlban Crequy 		 * maximum should stay reasonable.
917696ced4fSAlban Crequy 		 */
918696ced4fSAlban Crequy 		if (maxactive > KRETPROBE_MAXACTIVE_MAX) {
919ab105a4fSMasami Hiramatsu 			trace_probe_log_err(1, MAXACT_TOO_BIG);
92092705460SMasami Hiramatsu (Google) 			return -EINVAL;
921696ced4fSAlban Crequy 		}
922696ced4fSAlban Crequy 	}
923696ced4fSAlban Crequy 
9249e52b325SSabrina Dubroca 	/* try to parse an address. if that fails, try to read the
9259e52b325SSabrina Dubroca 	 * input as a symbol. */
9269e52b325SSabrina Dubroca 	if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
927ab105a4fSMasami Hiramatsu 		trace_probe_log_set_index(1);
9286212dd29SMasami Hiramatsu 		/* Check whether uprobe event specified */
92992705460SMasami Hiramatsu (Google) 		if (strchr(argv[1], '/') && strchr(argv[1], ':'))
93092705460SMasami Hiramatsu (Google) 			return -ECANCELED;
93192705460SMasami Hiramatsu (Google) 
932413d37d1SMasami Hiramatsu 		/* a symbol specified */
9336212dd29SMasami Hiramatsu 		symbol = kstrdup(argv[1], GFP_KERNEL);
93492705460SMasami Hiramatsu (Google) 		if (!symbol)
93592705460SMasami Hiramatsu (Google) 			return -ENOMEM;
9364725cd89SMasami Hiramatsu 
9374725cd89SMasami Hiramatsu 		tmp = strchr(symbol, '%');
9384725cd89SMasami Hiramatsu 		if (tmp) {
9394725cd89SMasami Hiramatsu 			if (!strcmp(tmp, "%return")) {
9404725cd89SMasami Hiramatsu 				*tmp = '\0';
9414725cd89SMasami Hiramatsu 				is_return = true;
9424725cd89SMasami Hiramatsu 			} else {
9434725cd89SMasami Hiramatsu 				trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX);
94492705460SMasami Hiramatsu (Google) 				return -EINVAL;
9454725cd89SMasami Hiramatsu 			}
9464725cd89SMasami Hiramatsu 		}
9474725cd89SMasami Hiramatsu 
948413d37d1SMasami Hiramatsu 		/* TODO: support .init module functions */
9498ab83f56SSrikar Dronamraju 		ret = traceprobe_split_symbol_offset(symbol, &offset);
950c5d343b6SMasami Hiramatsu 		if (ret || offset < 0 || offset > UINT_MAX) {
951ab105a4fSMasami Hiramatsu 			trace_probe_log_err(0, BAD_PROBE_ADDR);
95292705460SMasami Hiramatsu (Google) 			return -EINVAL;
953e63cc239SMasami Hiramatsu 		}
9549d861603SMasami Hiramatsu (Google) 		ret = validate_probe_symbol(symbol);
9559d861603SMasami Hiramatsu (Google) 		if (ret) {
9569d861603SMasami Hiramatsu (Google) 			if (ret == -EADDRNOTAVAIL)
9579d861603SMasami Hiramatsu (Google) 				trace_probe_log_err(0, NON_UNIQ_SYMBOL);
9589d861603SMasami Hiramatsu (Google) 			else
9599d861603SMasami Hiramatsu (Google) 				trace_probe_log_err(0, BAD_PROBE_ADDR);
96092705460SMasami Hiramatsu (Google) 			return -EINVAL;
9619d861603SMasami Hiramatsu (Google) 		}
9624725cd89SMasami Hiramatsu 		if (is_return)
96392705460SMasami Hiramatsu (Google) 			ctx->flags |= TPARG_FL_RETURN;
96497c753e6SMasami Hiramatsu 		ret = kprobe_on_func_entry(NULL, symbol, offset);
96530460c21SMasami Hiramatsu (Google) 		if (ret == 0 && !is_return)
96692705460SMasami Hiramatsu (Google) 			ctx->flags |= TPARG_FL_FENTRY;
96797c753e6SMasami Hiramatsu 		/* Defer the ENOENT case until register kprobe */
96897c753e6SMasami Hiramatsu 		if (ret == -EINVAL && is_return) {
969ab105a4fSMasami Hiramatsu 			trace_probe_log_err(0, BAD_RETPROBE);
97092705460SMasami Hiramatsu (Google) 			return -EINVAL;
971413d37d1SMasami Hiramatsu 		}
972e63cc239SMasami Hiramatsu 	}
973413d37d1SMasami Hiramatsu 
974ab105a4fSMasami Hiramatsu 	trace_probe_log_set_index(0);
9756212dd29SMasami Hiramatsu 	if (event) {
97695c104c3SLinyu Yuan 		ret = traceprobe_parse_event_name(&event, &group, gbuf,
977ab105a4fSMasami Hiramatsu 						  event - argv[0]);
9786212dd29SMasami Hiramatsu 		if (ret)
97992705460SMasami Hiramatsu (Google) 			return ret;
98095c104c3SLinyu Yuan 	}
98195c104c3SLinyu Yuan 
98295c104c3SLinyu Yuan 	if (!event) {
9834263565dSMasami Hiramatsu 		/* Make a new event name */
9844263565dSMasami Hiramatsu 		if (symbol)
9856f3cf440SMasami Hiramatsu 			snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld",
9864263565dSMasami Hiramatsu 				 is_return ? 'r' : 'p', symbol, offset);
9874263565dSMasami Hiramatsu 		else
9886f3cf440SMasami Hiramatsu 			snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p",
9894263565dSMasami Hiramatsu 				 is_return ? 'r' : 'p', addr);
990fca18a47SNaveen N. Rao 		sanitize_event_name(buf);
9914a846b44SMasami Hiramatsu 		event = buf;
9924a846b44SMasami Hiramatsu 	}
9936212dd29SMasami Hiramatsu 
99418b1e870SMasami Hiramatsu (Google) 	argc -= 2; argv += 2;
99592705460SMasami Hiramatsu (Google) 	ctx->funcname = symbol;
99618b1e870SMasami Hiramatsu (Google) 	new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,
99792705460SMasami Hiramatsu (Google) 					       abuf, MAX_BTF_ARGS_LEN, ctx);
99818b1e870SMasami Hiramatsu (Google) 	if (IS_ERR(new_argv)) {
99918b1e870SMasami Hiramatsu (Google) 		ret = PTR_ERR(new_argv);
100018b1e870SMasami Hiramatsu (Google) 		new_argv = NULL;
100192705460SMasami Hiramatsu (Google) 		return ret;
100218b1e870SMasami Hiramatsu (Google) 	}
100318b1e870SMasami Hiramatsu (Google) 	if (new_argv) {
100418b1e870SMasami Hiramatsu (Google) 		argc = new_argc;
100518b1e870SMasami Hiramatsu (Google) 		argv = new_argv;
100618b1e870SMasami Hiramatsu (Google) 	}
100757faaa04SMasami Hiramatsu (Google) 	if (argc > MAX_TRACE_ARGS) {
100857faaa04SMasami Hiramatsu (Google) 		trace_probe_log_set_index(2);
100957faaa04SMasami Hiramatsu (Google) 		trace_probe_log_err(0, TOO_MANY_ARGS);
101092705460SMasami Hiramatsu (Google) 		return -E2BIG;
101157faaa04SMasami Hiramatsu (Google) 	}
101218b1e870SMasami Hiramatsu (Google) 
1013d9b15224SYe Bin 	ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
1014d9b15224SYe Bin 	if (ret)
101592705460SMasami Hiramatsu (Google) 		return ret;
1016d9b15224SYe Bin 
10176212dd29SMasami Hiramatsu 	/* setup a probe */
1018696ced4fSAlban Crequy 	tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
101918b1e870SMasami Hiramatsu (Google) 				argc, is_return);
1020c31ffb3fSNamhyung Kim 	if (IS_ERR(tk)) {
10216212dd29SMasami Hiramatsu 		ret = PTR_ERR(tk);
1022ab105a4fSMasami Hiramatsu 		/* This must return -ENOMEM, else there is a bug */
1023a039480eSMasami Hiramatsu 		WARN_ON_ONCE(ret != -ENOMEM);
102492705460SMasami Hiramatsu (Google) 		return ret;	/* We know tk is not allocated */
1025e63cc239SMasami Hiramatsu 	}
1026413d37d1SMasami Hiramatsu 
1027413d37d1SMasami Hiramatsu 	/* parse arguments */
102873f35080SMikel Rychliski 	for (i = 0; i < argc; i++) {
1029ab105a4fSMasami Hiramatsu 		trace_probe_log_set_index(i + 2);
103092705460SMasami Hiramatsu (Google) 		ctx->offset = 0;
103192705460SMasami Hiramatsu (Google) 		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], ctx);
1032d00bbea9SMasami Hiramatsu 		if (ret)
103392705460SMasami Hiramatsu (Google) 			return ret;	/* This can be -ENOMEM */
1034da34634fSMasami Hiramatsu 	}
103525f00e40SMasami Hiramatsu (Google) 	/* entry handler for kretprobe */
103625f00e40SMasami Hiramatsu (Google) 	if (is_return && tk->tp.entry_arg) {
103725f00e40SMasami Hiramatsu (Google) 		tk->rp.entry_handler = trace_kprobe_entry_handler;
103825f00e40SMasami Hiramatsu (Google) 		tk->rp.data_size = traceprobe_get_entry_data_size(&tk->tp);
103925f00e40SMasami Hiramatsu (Google) 	}
104093ccae7aSMasami Hiramatsu 
1041007517a0SSteven Rostedt (VMware) 	ptype = is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
1042007517a0SSteven Rostedt (VMware) 	ret = traceprobe_set_print_fmt(&tk->tp, ptype);
1043f730e0f2SMasami Hiramatsu 	if (ret < 0)
104492705460SMasami Hiramatsu (Google) 		return ret;
1045f730e0f2SMasami Hiramatsu 
1046c31ffb3fSNamhyung Kim 	ret = register_trace_kprobe(tk);
1047ab105a4fSMasami Hiramatsu 	if (ret) {
1048ab105a4fSMasami Hiramatsu 		trace_probe_log_set_index(1);
1049ab105a4fSMasami Hiramatsu 		if (ret == -EILSEQ)
1050ab105a4fSMasami Hiramatsu 			trace_probe_log_err(0, BAD_INSN_BNDRY);
1051ab105a4fSMasami Hiramatsu 		else if (ret == -ENOENT)
1052ab105a4fSMasami Hiramatsu 			trace_probe_log_err(0, BAD_PROBE_ADDR);
1053ca89bc07SMasami Hiramatsu 		else if (ret != -ENOMEM && ret != -EEXIST)
1054ab105a4fSMasami Hiramatsu 			trace_probe_log_err(0, FAIL_REG_PROBE);
105592705460SMasami Hiramatsu (Google) 		return ret;
105692705460SMasami Hiramatsu (Google) 	}
10577dcc3520SMasami Hiramatsu (Google) 	/*
10587dcc3520SMasami Hiramatsu (Google) 	 * Here, 'tk' has been registered to the list successfully,
10597dcc3520SMasami Hiramatsu (Google) 	 * so we don't need to free it.
10607dcc3520SMasami Hiramatsu (Google) 	 */
10617dcc3520SMasami Hiramatsu (Google) 	tk = NULL;
1062ab105a4fSMasami Hiramatsu 
106392705460SMasami Hiramatsu (Google) 	return 0;
106492705460SMasami Hiramatsu (Google) }
106592705460SMasami Hiramatsu (Google) 
trace_kprobe_create_cb(int argc,const char * argv[])106692705460SMasami Hiramatsu (Google) static int trace_kprobe_create_cb(int argc, const char *argv[])
106792705460SMasami Hiramatsu (Google) {
106892705460SMasami Hiramatsu (Google) 	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
106992705460SMasami Hiramatsu (Google) 	int ret;
107092705460SMasami Hiramatsu (Google) 
107192705460SMasami Hiramatsu (Google) 	trace_probe_log_init("trace_kprobe", argc, argv);
107292705460SMasami Hiramatsu (Google) 
107392705460SMasami Hiramatsu (Google) 	ret = trace_kprobe_create_internal(argc, argv, &ctx);
107492705460SMasami Hiramatsu (Google) 
1075b1d1e904SMasami Hiramatsu (Google) 	traceprobe_finish_parse(&ctx);
1076ab105a4fSMasami Hiramatsu 	trace_probe_log_clear();
10776212dd29SMasami Hiramatsu 	return ret;
1078413d37d1SMasami Hiramatsu }
1079413d37d1SMasami Hiramatsu 
trace_kprobe_create(const char * raw_command)1080d262271dSMasami Hiramatsu static int trace_kprobe_create(const char *raw_command)
1081d262271dSMasami Hiramatsu {
108292705460SMasami Hiramatsu (Google) 	return trace_probe_create(raw_command, trace_kprobe_create_cb);
1083d262271dSMasami Hiramatsu }
1084d262271dSMasami Hiramatsu 
create_or_delete_trace_kprobe(const char * raw_command)1085d262271dSMasami Hiramatsu static int create_or_delete_trace_kprobe(const char *raw_command)
1086413d37d1SMasami Hiramatsu {
10876212dd29SMasami Hiramatsu 	int ret;
1088413d37d1SMasami Hiramatsu 
1089d262271dSMasami Hiramatsu 	if (raw_command[0] == '-')
1090d262271dSMasami Hiramatsu 		return dyn_event_release(raw_command, &trace_kprobe_ops);
10916212dd29SMasami Hiramatsu 
1092*fd837de3SMasami Hiramatsu (Google) 	ret = dyn_event_create(raw_command, &trace_kprobe_ops);
10936212dd29SMasami Hiramatsu 	return ret == -ECANCELED ? -EINVAL : ret;
109402ca1521SMasami Hiramatsu }
10956212dd29SMasami Hiramatsu 
trace_kprobe_run_command(struct dynevent_cmd * cmd)109629a15481STom Zanussi static int trace_kprobe_run_command(struct dynevent_cmd *cmd)
10972a588dd1STom Zanussi {
1098d262271dSMasami Hiramatsu 	return create_or_delete_trace_kprobe(cmd->seq.buffer);
10992a588dd1STom Zanussi }
11002a588dd1STom Zanussi 
11012a588dd1STom Zanussi /**
11022a588dd1STom Zanussi  * kprobe_event_cmd_init - Initialize a kprobe event command object
11032a588dd1STom Zanussi  * @cmd: A pointer to the dynevent_cmd struct representing the new event
11042a588dd1STom Zanussi  * @buf: A pointer to the buffer used to build the command
11052a588dd1STom Zanussi  * @maxlen: The length of the buffer passed in @buf
11062a588dd1STom Zanussi  *
11072a588dd1STom Zanussi  * Initialize a synthetic event command object.  Use this before
11082a588dd1STom Zanussi  * calling any of the other kprobe_event functions.
11092a588dd1STom Zanussi  */
kprobe_event_cmd_init(struct dynevent_cmd * cmd,char * buf,int maxlen)11102a588dd1STom Zanussi void kprobe_event_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen)
11112a588dd1STom Zanussi {
11122a588dd1STom Zanussi 	dynevent_cmd_init(cmd, buf, maxlen, DYNEVENT_TYPE_KPROBE,
111329a15481STom Zanussi 			  trace_kprobe_run_command);
11142a588dd1STom Zanussi }
11152a588dd1STom Zanussi EXPORT_SYMBOL_GPL(kprobe_event_cmd_init);
11162a588dd1STom Zanussi 
11172a588dd1STom Zanussi /**
11182a588dd1STom Zanussi  * __kprobe_event_gen_cmd_start - Generate a kprobe event command from arg list
11192a588dd1STom Zanussi  * @cmd: A pointer to the dynevent_cmd struct representing the new event
1120f032c53bSYujie Liu  * @kretprobe: Is this a return probe?
11212a588dd1STom Zanussi  * @name: The name of the kprobe event
11222a588dd1STom Zanussi  * @loc: The location of the kprobe event
1123e0f83183SYujie Liu  * @...: Variable number of arg (pairs), one pair for each field
11242a588dd1STom Zanussi  *
11252a588dd1STom Zanussi  * NOTE: Users normally won't want to call this function directly, but
11262a588dd1STom Zanussi  * rather use the kprobe_event_gen_cmd_start() wrapper, which automatically
11272a588dd1STom Zanussi  * adds a NULL to the end of the arg list.  If this function is used
11282a588dd1STom Zanussi  * directly, make sure the last arg in the variable arg list is NULL.
11292a588dd1STom Zanussi  *
11302a588dd1STom Zanussi  * Generate a kprobe event command to be executed by
11312a588dd1STom Zanussi  * kprobe_event_gen_cmd_end().  This function can be used to generate the
11322a588dd1STom Zanussi  * complete command or only the first part of it; in the latter case,
11332a588dd1STom Zanussi  * kprobe_event_add_fields() can be used to add more fields following this.
11342a588dd1STom Zanussi  *
11355b4dcd2dSMasami Hiramatsu  * Unlikely the synth_event_gen_cmd_start(), @loc must be specified. This
11365b4dcd2dSMasami Hiramatsu  * returns -EINVAL if @loc == NULL.
11375b4dcd2dSMasami Hiramatsu  *
11382a588dd1STom Zanussi  * Return: 0 if successful, error otherwise.
11392a588dd1STom Zanussi  */
__kprobe_event_gen_cmd_start(struct dynevent_cmd * cmd,bool kretprobe,const char * name,const char * loc,...)11402a588dd1STom Zanussi int __kprobe_event_gen_cmd_start(struct dynevent_cmd *cmd, bool kretprobe,
11412a588dd1STom Zanussi 				 const char *name, const char *loc, ...)
11422a588dd1STom Zanussi {
11432a588dd1STom Zanussi 	char buf[MAX_EVENT_NAME_LEN];
11442a588dd1STom Zanussi 	struct dynevent_arg arg;
11452a588dd1STom Zanussi 	va_list args;
11462a588dd1STom Zanussi 	int ret;
11472a588dd1STom Zanussi 
11482a588dd1STom Zanussi 	if (cmd->type != DYNEVENT_TYPE_KPROBE)
11492a588dd1STom Zanussi 		return -EINVAL;
11502a588dd1STom Zanussi 
11515b4dcd2dSMasami Hiramatsu 	if (!loc)
11525b4dcd2dSMasami Hiramatsu 		return -EINVAL;
11535b4dcd2dSMasami Hiramatsu 
11542a588dd1STom Zanussi 	if (kretprobe)
11552a588dd1STom Zanussi 		snprintf(buf, MAX_EVENT_NAME_LEN, "r:kprobes/%s", name);
11562a588dd1STom Zanussi 	else
11572a588dd1STom Zanussi 		snprintf(buf, MAX_EVENT_NAME_LEN, "p:kprobes/%s", name);
11582a588dd1STom Zanussi 
11592a588dd1STom Zanussi 	ret = dynevent_str_add(cmd, buf);
11602a588dd1STom Zanussi 	if (ret)
11612a588dd1STom Zanussi 		return ret;
11622a588dd1STom Zanussi 
116374403b6cSTom Zanussi 	dynevent_arg_init(&arg, 0);
11642a588dd1STom Zanussi 	arg.str = loc;
116574403b6cSTom Zanussi 	ret = dynevent_arg_add(cmd, &arg, NULL);
11662a588dd1STom Zanussi 	if (ret)
11672a588dd1STom Zanussi 		return ret;
11682a588dd1STom Zanussi 
11692a588dd1STom Zanussi 	va_start(args, loc);
11702a588dd1STom Zanussi 	for (;;) {
11712a588dd1STom Zanussi 		const char *field;
11722a588dd1STom Zanussi 
11732a588dd1STom Zanussi 		field = va_arg(args, const char *);
11742a588dd1STom Zanussi 		if (!field)
11752a588dd1STom Zanussi 			break;
11762a588dd1STom Zanussi 
11772a588dd1STom Zanussi 		if (++cmd->n_fields > MAX_TRACE_ARGS) {
11782a588dd1STom Zanussi 			ret = -EINVAL;
11792a588dd1STom Zanussi 			break;
11802a588dd1STom Zanussi 		}
11812a588dd1STom Zanussi 
11822a588dd1STom Zanussi 		arg.str = field;
118374403b6cSTom Zanussi 		ret = dynevent_arg_add(cmd, &arg, NULL);
11842a588dd1STom Zanussi 		if (ret)
11852a588dd1STom Zanussi 			break;
11862a588dd1STom Zanussi 	}
11872a588dd1STom Zanussi 	va_end(args);
11882a588dd1STom Zanussi 
11892a588dd1STom Zanussi 	return ret;
11902a588dd1STom Zanussi }
11912a588dd1STom Zanussi EXPORT_SYMBOL_GPL(__kprobe_event_gen_cmd_start);
11922a588dd1STom Zanussi 
11932a588dd1STom Zanussi /**
11942a588dd1STom Zanussi  * __kprobe_event_add_fields - Add probe fields to a kprobe command from arg list
11952a588dd1STom Zanussi  * @cmd: A pointer to the dynevent_cmd struct representing the new event
1196e0f83183SYujie Liu  * @...: Variable number of arg (pairs), one pair for each field
11972a588dd1STom Zanussi  *
11982a588dd1STom Zanussi  * NOTE: Users normally won't want to call this function directly, but
11992a588dd1STom Zanussi  * rather use the kprobe_event_add_fields() wrapper, which
12002a588dd1STom Zanussi  * automatically adds a NULL to the end of the arg list.  If this
12012a588dd1STom Zanussi  * function is used directly, make sure the last arg in the variable
12022a588dd1STom Zanussi  * arg list is NULL.
12032a588dd1STom Zanussi  *
12042a588dd1STom Zanussi  * Add probe fields to an existing kprobe command using a variable
12052a588dd1STom Zanussi  * list of args.  Fields are added in the same order they're listed.
12062a588dd1STom Zanussi  *
12072a588dd1STom Zanussi  * Return: 0 if successful, error otherwise.
12082a588dd1STom Zanussi  */
__kprobe_event_add_fields(struct dynevent_cmd * cmd,...)12092a588dd1STom Zanussi int __kprobe_event_add_fields(struct dynevent_cmd *cmd, ...)
12102a588dd1STom Zanussi {
12112a588dd1STom Zanussi 	struct dynevent_arg arg;
12122a588dd1STom Zanussi 	va_list args;
121310f129cbSGustavo A. R. Silva 	int ret = 0;
12142a588dd1STom Zanussi 
12152a588dd1STom Zanussi 	if (cmd->type != DYNEVENT_TYPE_KPROBE)
12162a588dd1STom Zanussi 		return -EINVAL;
12172a588dd1STom Zanussi 
121874403b6cSTom Zanussi 	dynevent_arg_init(&arg, 0);
12192a588dd1STom Zanussi 
12202a588dd1STom Zanussi 	va_start(args, cmd);
12212a588dd1STom Zanussi 	for (;;) {
12222a588dd1STom Zanussi 		const char *field;
12232a588dd1STom Zanussi 
12242a588dd1STom Zanussi 		field = va_arg(args, const char *);
12252a588dd1STom Zanussi 		if (!field)
12262a588dd1STom Zanussi 			break;
12272a588dd1STom Zanussi 
12282a588dd1STom Zanussi 		if (++cmd->n_fields > MAX_TRACE_ARGS) {
12292a588dd1STom Zanussi 			ret = -EINVAL;
12302a588dd1STom Zanussi 			break;
12312a588dd1STom Zanussi 		}
12322a588dd1STom Zanussi 
12332a588dd1STom Zanussi 		arg.str = field;
123474403b6cSTom Zanussi 		ret = dynevent_arg_add(cmd, &arg, NULL);
12352a588dd1STom Zanussi 		if (ret)
12362a588dd1STom Zanussi 			break;
12372a588dd1STom Zanussi 	}
12382a588dd1STom Zanussi 	va_end(args);
12392a588dd1STom Zanussi 
12402a588dd1STom Zanussi 	return ret;
12412a588dd1STom Zanussi }
12422a588dd1STom Zanussi EXPORT_SYMBOL_GPL(__kprobe_event_add_fields);
12432a588dd1STom Zanussi 
12442a588dd1STom Zanussi /**
12452a588dd1STom Zanussi  * kprobe_event_delete - Delete a kprobe event
12462a588dd1STom Zanussi  * @name: The name of the kprobe event to delete
12472a588dd1STom Zanussi  *
12482a588dd1STom Zanussi  * Delete a kprobe event with the give @name from kernel code rather
12492a588dd1STom Zanussi  * than directly from the command line.
12502a588dd1STom Zanussi  *
12512a588dd1STom Zanussi  * Return: 0 if successful, error otherwise.
12522a588dd1STom Zanussi  */
kprobe_event_delete(const char * name)12532a588dd1STom Zanussi int kprobe_event_delete(const char *name)
12542a588dd1STom Zanussi {
12552a588dd1STom Zanussi 	char buf[MAX_EVENT_NAME_LEN];
12562a588dd1STom Zanussi 
12572a588dd1STom Zanussi 	snprintf(buf, MAX_EVENT_NAME_LEN, "-:%s", name);
12582a588dd1STom Zanussi 
1259d262271dSMasami Hiramatsu 	return create_or_delete_trace_kprobe(buf);
12602a588dd1STom Zanussi }
12612a588dd1STom Zanussi EXPORT_SYMBOL_GPL(kprobe_event_delete);
12622a588dd1STom Zanussi 
trace_kprobe_release(struct dyn_event * ev)12636212dd29SMasami Hiramatsu static int trace_kprobe_release(struct dyn_event *ev)
12646212dd29SMasami Hiramatsu {
12656212dd29SMasami Hiramatsu 	struct trace_kprobe *tk = to_trace_kprobe(ev);
12666212dd29SMasami Hiramatsu 	int ret = unregister_trace_kprobe(tk);
12676212dd29SMasami Hiramatsu 
12686212dd29SMasami Hiramatsu 	if (!ret)
1269c31ffb3fSNamhyung Kim 		free_trace_kprobe(tk);
127002ca1521SMasami Hiramatsu 	return ret;
1271413d37d1SMasami Hiramatsu }
1272413d37d1SMasami Hiramatsu 
trace_kprobe_show(struct seq_file * m,struct dyn_event * ev)12736212dd29SMasami Hiramatsu static int trace_kprobe_show(struct seq_file *m, struct dyn_event *ev)
1274413d37d1SMasami Hiramatsu {
12756212dd29SMasami Hiramatsu 	struct trace_kprobe *tk = to_trace_kprobe(ev);
127693ccae7aSMasami Hiramatsu 	int i;
1277413d37d1SMasami Hiramatsu 
1278fa6f0cc7SRasmus Villemoes 	seq_putc(m, trace_kprobe_is_return(tk) ? 'r' : 'p');
12796a13a0d7SMasami Hiramatsu 	if (trace_kprobe_is_return(tk) && tk->rp.maxactive)
12806a13a0d7SMasami Hiramatsu 		seq_printf(m, "%d", tk->rp.maxactive);
1281b55ce203SMasami Hiramatsu 	seq_printf(m, ":%s/%s", trace_probe_group_name(&tk->tp),
1282b55ce203SMasami Hiramatsu 				trace_probe_name(&tk->tp));
1283413d37d1SMasami Hiramatsu 
1284c31ffb3fSNamhyung Kim 	if (!tk->symbol)
1285c31ffb3fSNamhyung Kim 		seq_printf(m, " 0x%p", tk->rp.kp.addr);
1286c31ffb3fSNamhyung Kim 	else if (tk->rp.kp.offset)
1287c31ffb3fSNamhyung Kim 		seq_printf(m, " %s+%u", trace_kprobe_symbol(tk),
1288c31ffb3fSNamhyung Kim 			   tk->rp.kp.offset);
1289413d37d1SMasami Hiramatsu 	else
1290c31ffb3fSNamhyung Kim 		seq_printf(m, " %s", trace_kprobe_symbol(tk));
1291413d37d1SMasami Hiramatsu 
1292c31ffb3fSNamhyung Kim 	for (i = 0; i < tk->tp.nr_args; i++)
1293c31ffb3fSNamhyung Kim 		seq_printf(m, " %s=%s", tk->tp.args[i].name, tk->tp.args[i].comm);
1294fa6f0cc7SRasmus Villemoes 	seq_putc(m, '\n');
129593ccae7aSMasami Hiramatsu 
1296413d37d1SMasami Hiramatsu 	return 0;
1297413d37d1SMasami Hiramatsu }
1298413d37d1SMasami Hiramatsu 
probes_seq_show(struct seq_file * m,void * v)12996212dd29SMasami Hiramatsu static int probes_seq_show(struct seq_file *m, void *v)
13006212dd29SMasami Hiramatsu {
13016212dd29SMasami Hiramatsu 	struct dyn_event *ev = v;
13026212dd29SMasami Hiramatsu 
13036212dd29SMasami Hiramatsu 	if (!is_trace_kprobe(ev))
13046212dd29SMasami Hiramatsu 		return 0;
13056212dd29SMasami Hiramatsu 
13066212dd29SMasami Hiramatsu 	return trace_kprobe_show(m, ev);
13076212dd29SMasami Hiramatsu }
13086212dd29SMasami Hiramatsu 
1309413d37d1SMasami Hiramatsu static const struct seq_operations probes_seq_op = {
13106212dd29SMasami Hiramatsu 	.start  = dyn_event_seq_start,
13116212dd29SMasami Hiramatsu 	.next   = dyn_event_seq_next,
13126212dd29SMasami Hiramatsu 	.stop   = dyn_event_seq_stop,
1313413d37d1SMasami Hiramatsu 	.show   = probes_seq_show
1314413d37d1SMasami Hiramatsu };
1315413d37d1SMasami Hiramatsu 
probes_open(struct inode * inode,struct file * file)1316413d37d1SMasami Hiramatsu static int probes_open(struct inode *inode, struct file *file)
1317413d37d1SMasami Hiramatsu {
131802ca1521SMasami Hiramatsu 	int ret;
131902ca1521SMasami Hiramatsu 
132017911ff3SSteven Rostedt (VMware) 	ret = security_locked_down(LOCKDOWN_TRACEFS);
132117911ff3SSteven Rostedt (VMware) 	if (ret)
132217911ff3SSteven Rostedt (VMware) 		return ret;
132317911ff3SSteven Rostedt (VMware) 
132402ca1521SMasami Hiramatsu 	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
13256212dd29SMasami Hiramatsu 		ret = dyn_events_release_all(&trace_kprobe_ops);
132602ca1521SMasami Hiramatsu 		if (ret < 0)
132702ca1521SMasami Hiramatsu 			return ret;
132802ca1521SMasami Hiramatsu 	}
1329413d37d1SMasami Hiramatsu 
1330413d37d1SMasami Hiramatsu 	return seq_open(file, &probes_seq_op);
1331413d37d1SMasami Hiramatsu }
1332413d37d1SMasami Hiramatsu 
probes_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)1333413d37d1SMasami Hiramatsu static ssize_t probes_write(struct file *file, const char __user *buffer,
1334413d37d1SMasami Hiramatsu 			    size_t count, loff_t *ppos)
1335413d37d1SMasami Hiramatsu {
13367e465baaSTom Zanussi 	return trace_parse_run_command(file, buffer, count, ppos,
13376212dd29SMasami Hiramatsu 				       create_or_delete_trace_kprobe);
1338413d37d1SMasami Hiramatsu }
1339413d37d1SMasami Hiramatsu 
1340413d37d1SMasami Hiramatsu static const struct file_operations kprobe_events_ops = {
1341413d37d1SMasami Hiramatsu 	.owner          = THIS_MODULE,
1342413d37d1SMasami Hiramatsu 	.open           = probes_open,
1343413d37d1SMasami Hiramatsu 	.read           = seq_read,
1344413d37d1SMasami Hiramatsu 	.llseek         = seq_lseek,
1345413d37d1SMasami Hiramatsu 	.release        = seq_release,
1346413d37d1SMasami Hiramatsu 	.write		= probes_write,
1347413d37d1SMasami Hiramatsu };
1348413d37d1SMasami Hiramatsu 
trace_kprobe_missed(struct trace_kprobe * tk)13493acf8aceSJiri Olsa static unsigned long trace_kprobe_missed(struct trace_kprobe *tk)
13503acf8aceSJiri Olsa {
13513acf8aceSJiri Olsa 	return trace_kprobe_is_return(tk) ?
13523acf8aceSJiri Olsa 		tk->rp.kp.nmissed + tk->rp.nmissed : tk->rp.kp.nmissed;
13533acf8aceSJiri Olsa }
13543acf8aceSJiri Olsa 
1355cd7e7bd5SMasami Hiramatsu /* Probes profiling interfaces */
probes_profile_seq_show(struct seq_file * m,void * v)1356cd7e7bd5SMasami Hiramatsu static int probes_profile_seq_show(struct seq_file *m, void *v)
1357cd7e7bd5SMasami Hiramatsu {
13586212dd29SMasami Hiramatsu 	struct dyn_event *ev = v;
13596212dd29SMasami Hiramatsu 	struct trace_kprobe *tk;
1360dfea08a2SXiangyang Zhang 	unsigned long nmissed;
1361cd7e7bd5SMasami Hiramatsu 
13626212dd29SMasami Hiramatsu 	if (!is_trace_kprobe(ev))
13636212dd29SMasami Hiramatsu 		return 0;
13646212dd29SMasami Hiramatsu 
13656212dd29SMasami Hiramatsu 	tk = to_trace_kprobe(ev);
13663acf8aceSJiri Olsa 	nmissed = trace_kprobe_missed(tk);
1367de7b2973SMathieu Desnoyers 	seq_printf(m, "  %-44s %15lu %15lu\n",
1368b55ce203SMasami Hiramatsu 		   trace_probe_name(&tk->tp),
1369f18f97acSMarcin Nowakowski 		   trace_kprobe_nhit(tk),
1370dfea08a2SXiangyang Zhang 		   nmissed);
1371cd7e7bd5SMasami Hiramatsu 
1372cd7e7bd5SMasami Hiramatsu 	return 0;
1373cd7e7bd5SMasami Hiramatsu }
1374cd7e7bd5SMasami Hiramatsu 
1375cd7e7bd5SMasami Hiramatsu static const struct seq_operations profile_seq_op = {
13766212dd29SMasami Hiramatsu 	.start  = dyn_event_seq_start,
13776212dd29SMasami Hiramatsu 	.next   = dyn_event_seq_next,
13786212dd29SMasami Hiramatsu 	.stop   = dyn_event_seq_stop,
1379cd7e7bd5SMasami Hiramatsu 	.show   = probes_profile_seq_show
1380cd7e7bd5SMasami Hiramatsu };
1381cd7e7bd5SMasami Hiramatsu 
profile_open(struct inode * inode,struct file * file)1382cd7e7bd5SMasami Hiramatsu static int profile_open(struct inode *inode, struct file *file)
1383cd7e7bd5SMasami Hiramatsu {
138417911ff3SSteven Rostedt (VMware) 	int ret;
138517911ff3SSteven Rostedt (VMware) 
138617911ff3SSteven Rostedt (VMware) 	ret = security_locked_down(LOCKDOWN_TRACEFS);
138717911ff3SSteven Rostedt (VMware) 	if (ret)
138817911ff3SSteven Rostedt (VMware) 		return ret;
138917911ff3SSteven Rostedt (VMware) 
1390cd7e7bd5SMasami Hiramatsu 	return seq_open(file, &profile_seq_op);
1391cd7e7bd5SMasami Hiramatsu }
1392cd7e7bd5SMasami Hiramatsu 
1393cd7e7bd5SMasami Hiramatsu static const struct file_operations kprobe_profile_ops = {
1394cd7e7bd5SMasami Hiramatsu 	.owner          = THIS_MODULE,
1395cd7e7bd5SMasami Hiramatsu 	.open           = profile_open,
1396cd7e7bd5SMasami Hiramatsu 	.read           = seq_read,
1397cd7e7bd5SMasami Hiramatsu 	.llseek         = seq_lseek,
1398cd7e7bd5SMasami Hiramatsu 	.release        = seq_release,
1399cd7e7bd5SMasami Hiramatsu };
1400cd7e7bd5SMasami Hiramatsu 
140153305928SMasami Hiramatsu /* Note that we don't verify it, since the code does not come from user space */
140253305928SMasami Hiramatsu static int
process_fetch_insn(struct fetch_insn * code,void * rec,void * edata,void * dest,void * base)140325f00e40SMasami Hiramatsu (Google) process_fetch_insn(struct fetch_insn *code, void *rec, void *edata,
140425f00e40SMasami Hiramatsu (Google) 		   void *dest, void *base)
140553305928SMasami Hiramatsu {
14068565a45dSSteven Rostedt (VMware) 	struct pt_regs *regs = rec;
140753305928SMasami Hiramatsu 	unsigned long val;
1408bd78acc8SSong Chen 	int ret;
140953305928SMasami Hiramatsu 
1410a6682814SMasami Hiramatsu retry:
141153305928SMasami Hiramatsu 	/* 1st stage: get value from context */
141253305928SMasami Hiramatsu 	switch (code->op) {
141353305928SMasami Hiramatsu 	case FETCH_OP_REG:
141453305928SMasami Hiramatsu 		val = regs_get_register(regs, code->param);
141553305928SMasami Hiramatsu 		break;
141653305928SMasami Hiramatsu 	case FETCH_OP_STACK:
141753305928SMasami Hiramatsu 		val = regs_get_kernel_stack_nth(regs, code->param);
141853305928SMasami Hiramatsu 		break;
141953305928SMasami Hiramatsu 	case FETCH_OP_STACKP:
142053305928SMasami Hiramatsu 		val = kernel_stack_pointer(regs);
142153305928SMasami Hiramatsu 		break;
142253305928SMasami Hiramatsu 	case FETCH_OP_RETVAL:
142353305928SMasami Hiramatsu 		val = regs_return_value(regs);
142453305928SMasami Hiramatsu 		break;
1425a1303af5SMasami Hiramatsu #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
1426a1303af5SMasami Hiramatsu 	case FETCH_OP_ARG:
1427a1303af5SMasami Hiramatsu 		val = regs_get_kernel_argument(regs, code->param);
1428a1303af5SMasami Hiramatsu 		break;
142925f00e40SMasami Hiramatsu (Google) 	case FETCH_OP_EDATA:
143025f00e40SMasami Hiramatsu (Google) 		val = *(unsigned long *)((unsigned long)edata + code->offset);
143125f00e40SMasami Hiramatsu (Google) 		break;
1432a1303af5SMasami Hiramatsu #endif
1433a6682814SMasami Hiramatsu 	case FETCH_NOP_SYMBOL:	/* Ignore a place holder */
1434a6682814SMasami Hiramatsu 		code++;
1435a6682814SMasami Hiramatsu 		goto retry;
143653305928SMasami Hiramatsu 	default:
1437bd78acc8SSong Chen 		ret = process_common_fetch_insn(code, &val);
1438bd78acc8SSong Chen 		if (ret < 0)
1439bd78acc8SSong Chen 			return ret;
144053305928SMasami Hiramatsu 	}
144153305928SMasami Hiramatsu 	code++;
144253305928SMasami Hiramatsu 
14439b960a38SMasami Hiramatsu 	return process_fetch_insn_bottom(code, val, dest, base);
144453305928SMasami Hiramatsu }
NOKPROBE_SYMBOL(process_fetch_insn)144553305928SMasami Hiramatsu NOKPROBE_SYMBOL(process_fetch_insn)
144653305928SMasami Hiramatsu 
1447413d37d1SMasami Hiramatsu /* Kprobe handler */
14483da0f180SMasami Hiramatsu static nokprobe_inline void
1449c31ffb3fSNamhyung Kim __kprobe_trace_func(struct trace_kprobe *tk, struct pt_regs *regs,
14507f1d2f82SSteven Rostedt (Red Hat) 		    struct trace_event_file *trace_file)
1451413d37d1SMasami Hiramatsu {
145293ccae7aSMasami Hiramatsu 	struct kprobe_trace_entry_head *entry;
1453e3dc9f89SMasami Hiramatsu 	struct trace_event_call *call = trace_probe_event_call(&tk->tp);
14548cfcf155SMasami Hiramatsu 	struct trace_event_buffer fbuffer;
14558cfcf155SMasami Hiramatsu 	int dsize;
1456413d37d1SMasami Hiramatsu 
14577f1d2f82SSteven Rostedt (Red Hat) 	WARN_ON(call != trace_file->event_call);
145841a7dd42SMasami Hiramatsu 
145909a5059aSSteven Rostedt (Red Hat) 	if (trace_trigger_soft_disabled(trace_file))
1460b8820084SMasami Hiramatsu 		return;
1461b8820084SMasami Hiramatsu 
146225f00e40SMasami Hiramatsu (Google) 	dsize = __get_data_size(&tk->tp, regs, NULL);
1463413d37d1SMasami Hiramatsu 
14645e6cd84eSSteven Rostedt (VMware) 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,
14655e6cd84eSSteven Rostedt (VMware) 					   sizeof(*entry) + tk->tp.size + dsize);
14665e6cd84eSSteven Rostedt (VMware) 	if (!entry)
14671e12a4a7SXiao Guangrong 		return;
1468413d37d1SMasami Hiramatsu 
14698cfcf155SMasami Hiramatsu 	fbuffer.regs = regs;
1470c31ffb3fSNamhyung Kim 	entry->ip = (unsigned long)tk->rp.kp.addr;
147125f00e40SMasami Hiramatsu (Google) 	store_trace_args(&entry[1], &tk->tp, regs, NULL, sizeof(*entry), dsize);
1472413d37d1SMasami Hiramatsu 
14738cfcf155SMasami Hiramatsu 	trace_event_buffer_commit(&fbuffer);
1474413d37d1SMasami Hiramatsu }
1475413d37d1SMasami Hiramatsu 
14763da0f180SMasami Hiramatsu static void
kprobe_trace_func(struct trace_kprobe * tk,struct pt_regs * regs)1477c31ffb3fSNamhyung Kim kprobe_trace_func(struct trace_kprobe *tk, struct pt_regs *regs)
147841a7dd42SMasami Hiramatsu {
1479b04d52e3SOleg Nesterov 	struct event_file_link *link;
148041a7dd42SMasami Hiramatsu 
1481b5f935eeSMasami Hiramatsu 	trace_probe_for_each_link_rcu(link, &tk->tp)
1482c31ffb3fSNamhyung Kim 		__kprobe_trace_func(tk, regs, link->file);
148341a7dd42SMasami Hiramatsu }
14843da0f180SMasami Hiramatsu NOKPROBE_SYMBOL(kprobe_trace_func);
148541a7dd42SMasami Hiramatsu 
1486413d37d1SMasami Hiramatsu /* Kretprobe handler */
148725f00e40SMasami Hiramatsu (Google) 
trace_kprobe_entry_handler(struct kretprobe_instance * ri,struct pt_regs * regs)148825f00e40SMasami Hiramatsu (Google) static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
148925f00e40SMasami Hiramatsu (Google) 				      struct pt_regs *regs)
149025f00e40SMasami Hiramatsu (Google) {
149125f00e40SMasami Hiramatsu (Google) 	struct kretprobe *rp = get_kretprobe(ri);
149225f00e40SMasami Hiramatsu (Google) 	struct trace_kprobe *tk;
149325f00e40SMasami Hiramatsu (Google) 
149425f00e40SMasami Hiramatsu (Google) 	/*
149525f00e40SMasami Hiramatsu (Google) 	 * There is a small chance that get_kretprobe(ri) returns NULL when
149625f00e40SMasami Hiramatsu (Google) 	 * the kretprobe is unregister on another CPU between kretprobe's
149725f00e40SMasami Hiramatsu (Google) 	 * trampoline_handler and this function.
149825f00e40SMasami Hiramatsu (Google) 	 */
149925f00e40SMasami Hiramatsu (Google) 	if (unlikely(!rp))
150025f00e40SMasami Hiramatsu (Google) 		return -ENOENT;
150125f00e40SMasami Hiramatsu (Google) 
150225f00e40SMasami Hiramatsu (Google) 	tk = container_of(rp, struct trace_kprobe, rp);
150325f00e40SMasami Hiramatsu (Google) 
150425f00e40SMasami Hiramatsu (Google) 	/* store argument values into ri->data as entry data */
150525f00e40SMasami Hiramatsu (Google) 	if (tk->tp.entry_arg)
150625f00e40SMasami Hiramatsu (Google) 		store_trace_entry_data(ri->data, &tk->tp, regs);
150725f00e40SMasami Hiramatsu (Google) 
150825f00e40SMasami Hiramatsu (Google) 	return 0;
150925f00e40SMasami Hiramatsu (Google) }
151025f00e40SMasami Hiramatsu (Google) 
151125f00e40SMasami Hiramatsu (Google) 
15123da0f180SMasami Hiramatsu static nokprobe_inline void
__kretprobe_trace_func(struct trace_kprobe * tk,struct kretprobe_instance * ri,struct pt_regs * regs,struct trace_event_file * trace_file)1513c31ffb3fSNamhyung Kim __kretprobe_trace_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
151441a7dd42SMasami Hiramatsu 		       struct pt_regs *regs,
15157f1d2f82SSteven Rostedt (Red Hat) 		       struct trace_event_file *trace_file)
1516413d37d1SMasami Hiramatsu {
151793ccae7aSMasami Hiramatsu 	struct kretprobe_trace_entry_head *entry;
15188cfcf155SMasami Hiramatsu 	struct trace_event_buffer fbuffer;
1519e3dc9f89SMasami Hiramatsu 	struct trace_event_call *call = trace_probe_event_call(&tk->tp);
15208cfcf155SMasami Hiramatsu 	int dsize;
1521413d37d1SMasami Hiramatsu 
15227f1d2f82SSteven Rostedt (Red Hat) 	WARN_ON(call != trace_file->event_call);
152341a7dd42SMasami Hiramatsu 
152409a5059aSSteven Rostedt (Red Hat) 	if (trace_trigger_soft_disabled(trace_file))
1525b8820084SMasami Hiramatsu 		return;
1526b8820084SMasami Hiramatsu 
152725f00e40SMasami Hiramatsu (Google) 	dsize = __get_data_size(&tk->tp, regs, ri->data);
15285e6cd84eSSteven Rostedt (VMware) 
15295e6cd84eSSteven Rostedt (VMware) 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,
15305e6cd84eSSteven Rostedt (VMware) 					   sizeof(*entry) + tk->tp.size + dsize);
15315e6cd84eSSteven Rostedt (VMware) 	if (!entry)
15321e12a4a7SXiao Guangrong 		return;
1533413d37d1SMasami Hiramatsu 
15348cfcf155SMasami Hiramatsu 	fbuffer.regs = regs;
1535c31ffb3fSNamhyung Kim 	entry->func = (unsigned long)tk->rp.kp.addr;
153673f9b911SMasami Hiramatsu 	entry->ret_ip = get_kretprobe_retaddr(ri);
153725f00e40SMasami Hiramatsu (Google) 	store_trace_args(&entry[1], &tk->tp, regs, ri->data, sizeof(*entry), dsize);
1538413d37d1SMasami Hiramatsu 
15398cfcf155SMasami Hiramatsu 	trace_event_buffer_commit(&fbuffer);
1540413d37d1SMasami Hiramatsu }
1541413d37d1SMasami Hiramatsu 
15423da0f180SMasami Hiramatsu static void
kretprobe_trace_func(struct trace_kprobe * tk,struct kretprobe_instance * ri,struct pt_regs * regs)1543c31ffb3fSNamhyung Kim kretprobe_trace_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
154441a7dd42SMasami Hiramatsu 		     struct pt_regs *regs)
154541a7dd42SMasami Hiramatsu {
1546b04d52e3SOleg Nesterov 	struct event_file_link *link;
154741a7dd42SMasami Hiramatsu 
1548b5f935eeSMasami Hiramatsu 	trace_probe_for_each_link_rcu(link, &tk->tp)
1549c31ffb3fSNamhyung Kim 		__kretprobe_trace_func(tk, ri, regs, link->file);
155041a7dd42SMasami Hiramatsu }
15513da0f180SMasami Hiramatsu NOKPROBE_SYMBOL(kretprobe_trace_func);
155241a7dd42SMasami Hiramatsu 
1553413d37d1SMasami Hiramatsu /* Event entry printers */
1554b62fdd97SMasami Hiramatsu static enum print_line_t
print_kprobe_event(struct trace_iterator * iter,int flags,struct trace_event * event)1555a9a57763SSteven Rostedt print_kprobe_event(struct trace_iterator *iter, int flags,
1556a9a57763SSteven Rostedt 		   struct trace_event *event)
1557413d37d1SMasami Hiramatsu {
155893ccae7aSMasami Hiramatsu 	struct kprobe_trace_entry_head *field;
1559413d37d1SMasami Hiramatsu 	struct trace_seq *s = &iter->seq;
1560eca0d916SMasami Hiramatsu 	struct trace_probe *tp;
1561413d37d1SMasami Hiramatsu 
156293ccae7aSMasami Hiramatsu 	field = (struct kprobe_trace_entry_head *)iter->ent;
156360d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(
156460d53e2cSMasami Hiramatsu 		container_of(event, struct trace_event_call, event));
156560d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
156660d53e2cSMasami Hiramatsu 		goto out;
1567413d37d1SMasami Hiramatsu 
1568b55ce203SMasami Hiramatsu 	trace_seq_printf(s, "%s: (", trace_probe_name(tp));
15696e9f23d1SMasami Hiramatsu 
1570413d37d1SMasami Hiramatsu 	if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
157185224da0SSteven Rostedt (Red Hat) 		goto out;
1572413d37d1SMasami Hiramatsu 
157385224da0SSteven Rostedt (Red Hat) 	trace_seq_putc(s, ')');
1574413d37d1SMasami Hiramatsu 
1575196b6389SSong Chen 	if (trace_probe_print_args(s, tp->args, tp->nr_args,
157656de7630SMasami Hiramatsu 			     (u8 *)&field[1], field) < 0)
157785224da0SSteven Rostedt (Red Hat) 		goto out;
1578413d37d1SMasami Hiramatsu 
157985224da0SSteven Rostedt (Red Hat) 	trace_seq_putc(s, '\n');
158085224da0SSteven Rostedt (Red Hat)  out:
158185224da0SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1582413d37d1SMasami Hiramatsu }
1583413d37d1SMasami Hiramatsu 
1584b62fdd97SMasami Hiramatsu static enum print_line_t
print_kretprobe_event(struct trace_iterator * iter,int flags,struct trace_event * event)1585a9a57763SSteven Rostedt print_kretprobe_event(struct trace_iterator *iter, int flags,
1586a9a57763SSteven Rostedt 		      struct trace_event *event)
1587413d37d1SMasami Hiramatsu {
158893ccae7aSMasami Hiramatsu 	struct kretprobe_trace_entry_head *field;
1589413d37d1SMasami Hiramatsu 	struct trace_seq *s = &iter->seq;
1590eca0d916SMasami Hiramatsu 	struct trace_probe *tp;
1591413d37d1SMasami Hiramatsu 
159293ccae7aSMasami Hiramatsu 	field = (struct kretprobe_trace_entry_head *)iter->ent;
159360d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(
159460d53e2cSMasami Hiramatsu 		container_of(event, struct trace_event_call, event));
159560d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
159660d53e2cSMasami Hiramatsu 		goto out;
1597413d37d1SMasami Hiramatsu 
1598b55ce203SMasami Hiramatsu 	trace_seq_printf(s, "%s: (", trace_probe_name(tp));
15996e9f23d1SMasami Hiramatsu 
1600413d37d1SMasami Hiramatsu 	if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET))
160185224da0SSteven Rostedt (Red Hat) 		goto out;
1602413d37d1SMasami Hiramatsu 
160385224da0SSteven Rostedt (Red Hat) 	trace_seq_puts(s, " <- ");
1604413d37d1SMasami Hiramatsu 
1605413d37d1SMasami Hiramatsu 	if (!seq_print_ip_sym(s, field->func, flags & ~TRACE_ITER_SYM_OFFSET))
160685224da0SSteven Rostedt (Red Hat) 		goto out;
1607413d37d1SMasami Hiramatsu 
160885224da0SSteven Rostedt (Red Hat) 	trace_seq_putc(s, ')');
1609413d37d1SMasami Hiramatsu 
1610196b6389SSong Chen 	if (trace_probe_print_args(s, tp->args, tp->nr_args,
161156de7630SMasami Hiramatsu 			     (u8 *)&field[1], field) < 0)
161285224da0SSteven Rostedt (Red Hat) 		goto out;
1613413d37d1SMasami Hiramatsu 
161485224da0SSteven Rostedt (Red Hat) 	trace_seq_putc(s, '\n');
1615413d37d1SMasami Hiramatsu 
161685224da0SSteven Rostedt (Red Hat)  out:
161785224da0SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1618413d37d1SMasami Hiramatsu }
1619413d37d1SMasami Hiramatsu 
1620413d37d1SMasami Hiramatsu 
kprobe_event_define_fields(struct trace_event_call * event_call)16212425bcb9SSteven Rostedt (Red Hat) static int kprobe_event_define_fields(struct trace_event_call *event_call)
1622413d37d1SMasami Hiramatsu {
1623eeb07b06SMasami Hiramatsu 	int ret;
162493ccae7aSMasami Hiramatsu 	struct kprobe_trace_entry_head field;
162560d53e2cSMasami Hiramatsu 	struct trace_probe *tp;
162660d53e2cSMasami Hiramatsu 
162760d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(event_call);
162860d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
162960d53e2cSMasami Hiramatsu 		return -ENOENT;
1630413d37d1SMasami Hiramatsu 
1631a703d946SMasami Hiramatsu 	DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
1632c31ffb3fSNamhyung Kim 
163360d53e2cSMasami Hiramatsu 	return traceprobe_define_arg_fields(event_call, sizeof(field), tp);
1634413d37d1SMasami Hiramatsu }
1635413d37d1SMasami Hiramatsu 
kretprobe_event_define_fields(struct trace_event_call * event_call)16362425bcb9SSteven Rostedt (Red Hat) static int kretprobe_event_define_fields(struct trace_event_call *event_call)
1637413d37d1SMasami Hiramatsu {
1638eeb07b06SMasami Hiramatsu 	int ret;
163993ccae7aSMasami Hiramatsu 	struct kretprobe_trace_entry_head field;
164060d53e2cSMasami Hiramatsu 	struct trace_probe *tp;
164160d53e2cSMasami Hiramatsu 
164260d53e2cSMasami Hiramatsu 	tp = trace_probe_primary_from_call(event_call);
164360d53e2cSMasami Hiramatsu 	if (WARN_ON_ONCE(!tp))
164460d53e2cSMasami Hiramatsu 		return -ENOENT;
1645413d37d1SMasami Hiramatsu 
1646a703d946SMasami Hiramatsu 	DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
1647a703d946SMasami Hiramatsu 	DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
1648c31ffb3fSNamhyung Kim 
164960d53e2cSMasami Hiramatsu 	return traceprobe_define_arg_fields(event_call, sizeof(field), tp);
1650413d37d1SMasami Hiramatsu }
1651413d37d1SMasami Hiramatsu 
165207b139c8SLi Zefan #ifdef CONFIG_PERF_EVENTS
1653e08d1c65SMasami Hiramatsu 
1654e08d1c65SMasami Hiramatsu /* Kprobe profile handler */
16559802d865SJosef Bacik static int
kprobe_perf_func(struct trace_kprobe * tk,struct pt_regs * regs)1656c31ffb3fSNamhyung Kim kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs)
1657e08d1c65SMasami Hiramatsu {
1658e3dc9f89SMasami Hiramatsu 	struct trace_event_call *call = trace_probe_event_call(&tk->tp);
165993ccae7aSMasami Hiramatsu 	struct kprobe_trace_entry_head *entry;
16601c024ecaSPeter Zijlstra 	struct hlist_head *head;
1661e09c8614SMasami Hiramatsu 	int size, __size, dsize;
16624ed7c92dSPeter Zijlstra 	int rctx;
1663e08d1c65SMasami Hiramatsu 
16649802d865SJosef Bacik 	if (bpf_prog_array_valid(call)) {
166566665ad2SMasami Hiramatsu 		unsigned long orig_ip = instruction_pointer(regs);
16669802d865SJosef Bacik 		int ret;
16679802d865SJosef Bacik 
16689802d865SJosef Bacik 		ret = trace_call_bpf(call, regs);
16699802d865SJosef Bacik 
16709802d865SJosef Bacik 		/*
16719802d865SJosef Bacik 		 * We need to check and see if we modified the pc of the
1672cce188bdSMasami Hiramatsu 		 * pt_regs, and if so return 1 so that we don't do the
1673cce188bdSMasami Hiramatsu 		 * single stepping.
16749802d865SJosef Bacik 		 */
1675cce188bdSMasami Hiramatsu 		if (orig_ip != instruction_pointer(regs))
16769802d865SJosef Bacik 			return 1;
16779802d865SJosef Bacik 		if (!ret)
16789802d865SJosef Bacik 			return 0;
16799802d865SJosef Bacik 	}
16802541517cSAlexei Starovoitov 
1681288e984eSOleg Nesterov 	head = this_cpu_ptr(call->perf_events);
1682288e984eSOleg Nesterov 	if (hlist_empty(head))
16839802d865SJosef Bacik 		return 0;
1684288e984eSOleg Nesterov 
168525f00e40SMasami Hiramatsu (Google) 	dsize = __get_data_size(&tk->tp, regs, NULL);
1686c31ffb3fSNamhyung Kim 	__size = sizeof(*entry) + tk->tp.size + dsize;
168774ebb63eSMasami Hiramatsu 	size = ALIGN(__size + sizeof(u32), sizeof(u64));
168874ebb63eSMasami Hiramatsu 	size -= sizeof(u32);
1689e08d1c65SMasami Hiramatsu 
16901e1dcd93SAlexei Starovoitov 	entry = perf_trace_buf_alloc(size, NULL, &rctx);
1691430ad5a6SXiao Guangrong 	if (!entry)
16929802d865SJosef Bacik 		return 0;
1693ce71b9dfSFrederic Weisbecker 
1694c31ffb3fSNamhyung Kim 	entry->ip = (unsigned long)tk->rp.kp.addr;
1695e09c8614SMasami Hiramatsu 	memset(&entry[1], 0, dsize);
169625f00e40SMasami Hiramatsu (Google) 	store_trace_args(&entry[1], &tk->tp, regs, NULL, sizeof(*entry), dsize);
16971e1dcd93SAlexei Starovoitov 	perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs,
16988fd0fbbeSPeter Zijlstra 			      head, NULL);
16999802d865SJosef Bacik 	return 0;
1700e08d1c65SMasami Hiramatsu }
17013da0f180SMasami Hiramatsu NOKPROBE_SYMBOL(kprobe_perf_func);
1702e08d1c65SMasami Hiramatsu 
1703e08d1c65SMasami Hiramatsu /* Kretprobe profile handler */
17043da0f180SMasami Hiramatsu static void
kretprobe_perf_func(struct trace_kprobe * tk,struct kretprobe_instance * ri,struct pt_regs * regs)1705c31ffb3fSNamhyung Kim kretprobe_perf_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
1706e08d1c65SMasami Hiramatsu 		    struct pt_regs *regs)
1707e08d1c65SMasami Hiramatsu {
1708e3dc9f89SMasami Hiramatsu 	struct trace_event_call *call = trace_probe_event_call(&tk->tp);
170993ccae7aSMasami Hiramatsu 	struct kretprobe_trace_entry_head *entry;
17101c024ecaSPeter Zijlstra 	struct hlist_head *head;
1711e09c8614SMasami Hiramatsu 	int size, __size, dsize;
17124ed7c92dSPeter Zijlstra 	int rctx;
1713e08d1c65SMasami Hiramatsu 
1714e87c6bc3SYonghong Song 	if (bpf_prog_array_valid(call) && !trace_call_bpf(call, regs))
17152541517cSAlexei Starovoitov 		return;
17162541517cSAlexei Starovoitov 
1717288e984eSOleg Nesterov 	head = this_cpu_ptr(call->perf_events);
1718288e984eSOleg Nesterov 	if (hlist_empty(head))
1719288e984eSOleg Nesterov 		return;
1720288e984eSOleg Nesterov 
172125f00e40SMasami Hiramatsu (Google) 	dsize = __get_data_size(&tk->tp, regs, ri->data);
1722c31ffb3fSNamhyung Kim 	__size = sizeof(*entry) + tk->tp.size + dsize;
172374ebb63eSMasami Hiramatsu 	size = ALIGN(__size + sizeof(u32), sizeof(u64));
172474ebb63eSMasami Hiramatsu 	size -= sizeof(u32);
1725e08d1c65SMasami Hiramatsu 
17261e1dcd93SAlexei Starovoitov 	entry = perf_trace_buf_alloc(size, NULL, &rctx);
1727430ad5a6SXiao Guangrong 	if (!entry)
17281e12a4a7SXiao Guangrong 		return;
1729ce71b9dfSFrederic Weisbecker 
1730c31ffb3fSNamhyung Kim 	entry->func = (unsigned long)tk->rp.kp.addr;
173173f9b911SMasami Hiramatsu 	entry->ret_ip = get_kretprobe_retaddr(ri);
173225f00e40SMasami Hiramatsu (Google) 	store_trace_args(&entry[1], &tk->tp, regs, ri->data, sizeof(*entry), dsize);
17331e1dcd93SAlexei Starovoitov 	perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs,
17348fd0fbbeSPeter Zijlstra 			      head, NULL);
1735e08d1c65SMasami Hiramatsu }
17363da0f180SMasami Hiramatsu NOKPROBE_SYMBOL(kretprobe_perf_func);
173741bdc4b4SYonghong Song 
bpf_get_kprobe_info(const struct perf_event * event,u32 * fd_type,const char ** symbol,u64 * probe_offset,u64 * probe_addr,unsigned long * missed,bool perf_type_tracepoint)173841bdc4b4SYonghong Song int bpf_get_kprobe_info(const struct perf_event *event, u32 *fd_type,
173941bdc4b4SYonghong Song 			const char **symbol, u64 *probe_offset,
17403acf8aceSJiri Olsa 			u64 *probe_addr, unsigned long *missed,
17413acf8aceSJiri Olsa 			bool perf_type_tracepoint)
174241bdc4b4SYonghong Song {
174341bdc4b4SYonghong Song 	const char *pevent = trace_event_name(event->tp_event);
174441bdc4b4SYonghong Song 	const char *group = event->tp_event->class->system;
174541bdc4b4SYonghong Song 	struct trace_kprobe *tk;
174641bdc4b4SYonghong Song 
174741bdc4b4SYonghong Song 	if (perf_type_tracepoint)
174841bdc4b4SYonghong Song 		tk = find_trace_kprobe(pevent, group);
174941bdc4b4SYonghong Song 	else
175022d5bd68SJean-Philippe Brucker 		tk = trace_kprobe_primary_from_call(event->tp_event);
175141bdc4b4SYonghong Song 	if (!tk)
175241bdc4b4SYonghong Song 		return -EINVAL;
175341bdc4b4SYonghong Song 
175441bdc4b4SYonghong Song 	*fd_type = trace_kprobe_is_return(tk) ? BPF_FD_TYPE_KRETPROBE
175541bdc4b4SYonghong Song 					      : BPF_FD_TYPE_KPROBE;
175641bdc4b4SYonghong Song 	*probe_offset = tk->rp.kp.offset;
1757cd3910d0SYafang Shao 	*probe_addr = kallsyms_show_value(current_cred()) ?
1758cd3910d0SYafang Shao 		      (unsigned long)tk->rp.kp.addr : 0;
1759cd3910d0SYafang Shao 	*symbol = tk->symbol;
17603acf8aceSJiri Olsa 	if (missed)
17613acf8aceSJiri Olsa 		*missed = trace_kprobe_missed(tk);
176241bdc4b4SYonghong Song 	return 0;
176341bdc4b4SYonghong Song }
176407b139c8SLi Zefan #endif	/* CONFIG_PERF_EVENTS */
176550d78056SMasami Hiramatsu 
17663fe3d619SOleg Nesterov /*
17673fe3d619SOleg Nesterov  * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex.
17683fe3d619SOleg Nesterov  *
17693fe3d619SOleg Nesterov  * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe
17703fe3d619SOleg Nesterov  * lockless, but we can't race with this __init function.
17713fe3d619SOleg Nesterov  */
kprobe_register(struct trace_event_call * event,enum trace_reg type,void * data)17722425bcb9SSteven Rostedt (Red Hat) static int kprobe_register(struct trace_event_call *event,
1773ceec0b6fSJiri Olsa 			   enum trace_reg type, void *data)
17742239291aSSteven Rostedt {
17757f1d2f82SSteven Rostedt (Red Hat) 	struct trace_event_file *file = data;
17761538f888SMasami Hiramatsu 
17772239291aSSteven Rostedt 	switch (type) {
17782239291aSSteven Rostedt 	case TRACE_REG_REGISTER:
177960d53e2cSMasami Hiramatsu 		return enable_trace_kprobe(event, file);
17802239291aSSteven Rostedt 	case TRACE_REG_UNREGISTER:
178160d53e2cSMasami Hiramatsu 		return disable_trace_kprobe(event, file);
17822239291aSSteven Rostedt 
17832239291aSSteven Rostedt #ifdef CONFIG_PERF_EVENTS
17842239291aSSteven Rostedt 	case TRACE_REG_PERF_REGISTER:
178560d53e2cSMasami Hiramatsu 		return enable_trace_kprobe(event, NULL);
17862239291aSSteven Rostedt 	case TRACE_REG_PERF_UNREGISTER:
178760d53e2cSMasami Hiramatsu 		return disable_trace_kprobe(event, NULL);
1788ceec0b6fSJiri Olsa 	case TRACE_REG_PERF_OPEN:
1789ceec0b6fSJiri Olsa 	case TRACE_REG_PERF_CLOSE:
1790489c75c3SJiri Olsa 	case TRACE_REG_PERF_ADD:
1791489c75c3SJiri Olsa 	case TRACE_REG_PERF_DEL:
1792ceec0b6fSJiri Olsa 		return 0;
17932239291aSSteven Rostedt #endif
17942239291aSSteven Rostedt 	}
17952239291aSSteven Rostedt 	return 0;
17962239291aSSteven Rostedt }
179750d78056SMasami Hiramatsu 
kprobe_dispatcher(struct kprobe * kp,struct pt_regs * regs)17983da0f180SMasami Hiramatsu static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
179950d78056SMasami Hiramatsu {
1800c31ffb3fSNamhyung Kim 	struct trace_kprobe *tk = container_of(kp, struct trace_kprobe, rp.kp);
18019802d865SJosef Bacik 	int ret = 0;
180250d78056SMasami Hiramatsu 
1803a7636d9eSMartin KaFai Lau 	raw_cpu_inc(*tk->nhit);
180448182bd2SMasami Hiramatsu 
1805747774d6SMasami Hiramatsu 	if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE))
1806c31ffb3fSNamhyung Kim 		kprobe_trace_func(tk, regs);
180707b139c8SLi Zefan #ifdef CONFIG_PERF_EVENTS
1808747774d6SMasami Hiramatsu 	if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE))
18099802d865SJosef Bacik 		ret = kprobe_perf_func(tk, regs);
181007b139c8SLi Zefan #endif
18119802d865SJosef Bacik 	return ret;
1812e08d1c65SMasami Hiramatsu }
18133da0f180SMasami Hiramatsu NOKPROBE_SYMBOL(kprobe_dispatcher);
1814e08d1c65SMasami Hiramatsu 
18153da0f180SMasami Hiramatsu static int
kretprobe_dispatcher(struct kretprobe_instance * ri,struct pt_regs * regs)18163da0f180SMasami Hiramatsu kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
181750d78056SMasami Hiramatsu {
1818d741bf41SPeter Zijlstra 	struct kretprobe *rp = get_kretprobe(ri);
1819cc72b720SMasami Hiramatsu (Google) 	struct trace_kprobe *tk;
182050d78056SMasami Hiramatsu 
1821cc72b720SMasami Hiramatsu (Google) 	/*
1822cc72b720SMasami Hiramatsu (Google) 	 * There is a small chance that get_kretprobe(ri) returns NULL when
1823cc72b720SMasami Hiramatsu (Google) 	 * the kretprobe is unregister on another CPU between kretprobe's
1824cc72b720SMasami Hiramatsu (Google) 	 * trampoline_handler and this function.
1825cc72b720SMasami Hiramatsu (Google) 	 */
1826cc72b720SMasami Hiramatsu (Google) 	if (unlikely(!rp))
1827cc72b720SMasami Hiramatsu (Google) 		return 0;
1828cc72b720SMasami Hiramatsu (Google) 
1829cc72b720SMasami Hiramatsu (Google) 	tk = container_of(rp, struct trace_kprobe, rp);
1830a7636d9eSMartin KaFai Lau 	raw_cpu_inc(*tk->nhit);
183148182bd2SMasami Hiramatsu 
1832747774d6SMasami Hiramatsu 	if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE))
1833c31ffb3fSNamhyung Kim 		kretprobe_trace_func(tk, ri, regs);
183407b139c8SLi Zefan #ifdef CONFIG_PERF_EVENTS
1835747774d6SMasami Hiramatsu 	if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE))
1836c31ffb3fSNamhyung Kim 		kretprobe_perf_func(tk, ri, regs);
183707b139c8SLi Zefan #endif
1838f2cc020dSIngo Molnar 	return 0;	/* We don't tweak kernel, so just return 0 */
183950d78056SMasami Hiramatsu }
18403da0f180SMasami Hiramatsu NOKPROBE_SYMBOL(kretprobe_dispatcher);
1841e08d1c65SMasami Hiramatsu 
1842a9a57763SSteven Rostedt static struct trace_event_functions kretprobe_funcs = {
1843a9a57763SSteven Rostedt 	.trace		= print_kretprobe_event
1844a9a57763SSteven Rostedt };
1845a9a57763SSteven Rostedt 
1846a9a57763SSteven Rostedt static struct trace_event_functions kprobe_funcs = {
1847a9a57763SSteven Rostedt 	.trace		= print_kprobe_event
1848a9a57763SSteven Rostedt };
1849a9a57763SSteven Rostedt 
185004ae87a5SPeter Zijlstra static struct trace_event_fields kretprobe_fields_array[] = {
185104ae87a5SPeter Zijlstra 	{ .type = TRACE_FUNCTION_TYPE,
185204ae87a5SPeter Zijlstra 	  .define_fields = kretprobe_event_define_fields },
185304ae87a5SPeter Zijlstra 	{}
185404ae87a5SPeter Zijlstra };
185504ae87a5SPeter Zijlstra 
185604ae87a5SPeter Zijlstra static struct trace_event_fields kprobe_fields_array[] = {
185704ae87a5SPeter Zijlstra 	{ .type = TRACE_FUNCTION_TYPE,
185804ae87a5SPeter Zijlstra 	  .define_fields = kprobe_event_define_fields },
185904ae87a5SPeter Zijlstra 	{}
186004ae87a5SPeter Zijlstra };
186104ae87a5SPeter Zijlstra 
init_trace_event_call(struct trace_kprobe * tk)1862e3dc9f89SMasami Hiramatsu static inline void init_trace_event_call(struct trace_kprobe *tk)
1863413d37d1SMasami Hiramatsu {
1864e3dc9f89SMasami Hiramatsu 	struct trace_event_call *call = trace_probe_event_call(&tk->tp);
1865e3dc9f89SMasami Hiramatsu 
1866c31ffb3fSNamhyung Kim 	if (trace_kprobe_is_return(tk)) {
186780decc70SSteven Rostedt 		call->event.funcs = &kretprobe_funcs;
186804ae87a5SPeter Zijlstra 		call->class->fields_array = kretprobe_fields_array;
1869413d37d1SMasami Hiramatsu 	} else {
187080decc70SSteven Rostedt 		call->event.funcs = &kprobe_funcs;
187104ae87a5SPeter Zijlstra 		call->class->fields_array = kprobe_fields_array;
1872413d37d1SMasami Hiramatsu 	}
1873e12f03d7SSong Liu 
1874e12f03d7SSong Liu 	call->flags = TRACE_EVENT_FL_KPROBE;
1875e12f03d7SSong Liu 	call->class->reg = kprobe_register;
1876e12f03d7SSong Liu }
1877e12f03d7SSong Liu 
register_kprobe_event(struct trace_kprobe * tk)1878e12f03d7SSong Liu static int register_kprobe_event(struct trace_kprobe *tk)
1879e12f03d7SSong Liu {
1880e3dc9f89SMasami Hiramatsu 	init_trace_event_call(tk);
1881e12f03d7SSong Liu 
188246e5376dSMasami Hiramatsu 	return trace_probe_register_event_call(&tk->tp);
1883413d37d1SMasami Hiramatsu }
1884413d37d1SMasami Hiramatsu 
unregister_kprobe_event(struct trace_kprobe * tk)1885c31ffb3fSNamhyung Kim static int unregister_kprobe_event(struct trace_kprobe *tk)
1886413d37d1SMasami Hiramatsu {
188746e5376dSMasami Hiramatsu 	return trace_probe_unregister_event_call(&tk->tp);
1888413d37d1SMasami Hiramatsu }
1889413d37d1SMasami Hiramatsu 
1890e12f03d7SSong Liu #ifdef CONFIG_PERF_EVENTS
1891b022f0c7SFrancis Laniel 
1892e12f03d7SSong Liu /* create a trace_kprobe, but don't add it to global lists */
1893e12f03d7SSong Liu struct trace_event_call *
create_local_trace_kprobe(char * func,void * addr,unsigned long offs,bool is_return)1894e12f03d7SSong Liu create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
1895e12f03d7SSong Liu 			  bool is_return)
1896e12f03d7SSong Liu {
1897007517a0SSteven Rostedt (VMware) 	enum probe_print_type ptype;
18987dcc3520SMasami Hiramatsu (Google) 	struct trace_kprobe *tk __free(free_trace_kprobe) = NULL;
1899e12f03d7SSong Liu 	int ret;
1900e12f03d7SSong Liu 	char *event;
1901e12f03d7SSong Liu 
1902b022f0c7SFrancis Laniel 	if (func) {
19039d861603SMasami Hiramatsu (Google) 		ret = validate_probe_symbol(func);
19049d861603SMasami Hiramatsu (Google) 		if (ret)
19059d861603SMasami Hiramatsu (Google) 			return ERR_PTR(ret);
1906b022f0c7SFrancis Laniel 	}
1907b022f0c7SFrancis Laniel 
1908e12f03d7SSong Liu 	/*
19096212dd29SMasami Hiramatsu 	 * local trace_kprobes are not added to dyn_event, so they are never
1910e12f03d7SSong Liu 	 * searched in find_trace_kprobe(). Therefore, there is no concern of
1911e12f03d7SSong Liu 	 * duplicated name here.
1912e12f03d7SSong Liu 	 */
1913e12f03d7SSong Liu 	event = func ? func : "DUMMY_EVENT";
1914e12f03d7SSong Liu 
1915e12f03d7SSong Liu 	tk = alloc_trace_kprobe(KPROBE_EVENT_SYSTEM, event, (void *)addr, func,
1916e12f03d7SSong Liu 				offs, 0 /* maxactive */, 0 /* nargs */,
1917e12f03d7SSong Liu 				is_return);
1918e12f03d7SSong Liu 
1919e12f03d7SSong Liu 	if (IS_ERR(tk)) {
1920e12f03d7SSong Liu 		pr_info("Failed to allocate trace_probe.(%d)\n",
1921e12f03d7SSong Liu 			(int)PTR_ERR(tk));
1922e12f03d7SSong Liu 		return ERR_CAST(tk);
1923e12f03d7SSong Liu 	}
1924e12f03d7SSong Liu 
1925e3dc9f89SMasami Hiramatsu 	init_trace_event_call(tk);
1926e12f03d7SSong Liu 
1927007517a0SSteven Rostedt (VMware) 	ptype = trace_kprobe_is_return(tk) ?
1928007517a0SSteven Rostedt (VMware) 		PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
19297dcc3520SMasami Hiramatsu (Google) 	if (traceprobe_set_print_fmt(&tk->tp, ptype) < 0)
19307dcc3520SMasami Hiramatsu (Google) 		return ERR_PTR(-ENOMEM);
1931e12f03d7SSong Liu 
1932e12f03d7SSong Liu 	ret = __register_trace_kprobe(tk);
1933f730e0f2SMasami Hiramatsu 	if (ret < 0)
1934e12f03d7SSong Liu 		return ERR_PTR(ret);
19357dcc3520SMasami Hiramatsu (Google) 
19367dcc3520SMasami Hiramatsu (Google) 	return trace_probe_event_call(&(no_free_ptr(tk)->tp));
1937e12f03d7SSong Liu }
1938e12f03d7SSong Liu 
destroy_local_trace_kprobe(struct trace_event_call * event_call)1939e12f03d7SSong Liu void destroy_local_trace_kprobe(struct trace_event_call *event_call)
1940e12f03d7SSong Liu {
1941e12f03d7SSong Liu 	struct trace_kprobe *tk;
1942e12f03d7SSong Liu 
194360d53e2cSMasami Hiramatsu 	tk = trace_kprobe_primary_from_call(event_call);
194460d53e2cSMasami Hiramatsu 	if (unlikely(!tk))
194560d53e2cSMasami Hiramatsu 		return;
1946e12f03d7SSong Liu 
1947e12f03d7SSong Liu 	if (trace_probe_is_enabled(&tk->tp)) {
1948e12f03d7SSong Liu 		WARN_ON(1);
1949e12f03d7SSong Liu 		return;
1950e12f03d7SSong Liu 	}
1951e12f03d7SSong Liu 
1952e12f03d7SSong Liu 	__unregister_trace_kprobe(tk);
19530fc8c358SJiri Olsa 
1954e12f03d7SSong Liu 	free_trace_kprobe(tk);
1955e12f03d7SSong Liu }
1956e12f03d7SSong Liu #endif /* CONFIG_PERF_EVENTS */
1957e12f03d7SSong Liu 
enable_boot_kprobe_events(void)1958970988e1SMasami Hiramatsu static __init void enable_boot_kprobe_events(void)
1959970988e1SMasami Hiramatsu {
1960970988e1SMasami Hiramatsu 	struct trace_array *tr = top_trace_array();
1961970988e1SMasami Hiramatsu 	struct trace_event_file *file;
1962970988e1SMasami Hiramatsu 	struct trace_kprobe *tk;
1963970988e1SMasami Hiramatsu 	struct dyn_event *pos;
1964970988e1SMasami Hiramatsu 
19652cba0070SMasami Hiramatsu (Google) 	guard(mutex)(&event_mutex);
1966970988e1SMasami Hiramatsu 	for_each_trace_kprobe(tk, pos) {
1967970988e1SMasami Hiramatsu 		list_for_each_entry(file, &tr->events, list)
1968e3dc9f89SMasami Hiramatsu 			if (file->event_call == trace_probe_event_call(&tk->tp))
1969970988e1SMasami Hiramatsu 				trace_event_enable_disable(file, 1, 0);
1970970988e1SMasami Hiramatsu 	}
1971970988e1SMasami Hiramatsu }
1972970988e1SMasami Hiramatsu 
setup_boot_kprobe_events(void)1973970988e1SMasami Hiramatsu static __init void setup_boot_kprobe_events(void)
1974970988e1SMasami Hiramatsu {
1975970988e1SMasami Hiramatsu 	char *p, *cmd = kprobe_boot_events_buf;
1976970988e1SMasami Hiramatsu 	int ret;
1977970988e1SMasami Hiramatsu 
1978970988e1SMasami Hiramatsu 	strreplace(kprobe_boot_events_buf, ',', ' ');
1979970988e1SMasami Hiramatsu 
1980970988e1SMasami Hiramatsu 	while (cmd && *cmd != '\0') {
1981970988e1SMasami Hiramatsu 		p = strchr(cmd, ';');
1982970988e1SMasami Hiramatsu 		if (p)
1983970988e1SMasami Hiramatsu 			*p++ = '\0';
1984970988e1SMasami Hiramatsu 
1985d262271dSMasami Hiramatsu 		ret = create_or_delete_trace_kprobe(cmd);
1986970988e1SMasami Hiramatsu 		if (ret)
1987970988e1SMasami Hiramatsu 			pr_warn("Failed to add event(%d): %s\n", ret, cmd);
1988970988e1SMasami Hiramatsu 
1989970988e1SMasami Hiramatsu 		cmd = p;
1990970988e1SMasami Hiramatsu 	}
1991970988e1SMasami Hiramatsu 
1992970988e1SMasami Hiramatsu 	enable_boot_kprobe_events();
1993970988e1SMasami Hiramatsu }
1994970988e1SMasami Hiramatsu 
1995d8d4c6d0SMasami Hiramatsu /*
1996ba0fbfbbSMasami Hiramatsu  * Register dynevent at core_initcall. This allows kernel to setup kprobe
1997ba0fbfbbSMasami Hiramatsu  * events in postcore_initcall without tracefs.
1998d8d4c6d0SMasami Hiramatsu  */
init_kprobe_trace_early(void)1999d8d4c6d0SMasami Hiramatsu static __init int init_kprobe_trace_early(void)
2000413d37d1SMasami Hiramatsu {
20016212dd29SMasami Hiramatsu 	int ret;
20026212dd29SMasami Hiramatsu 
20036212dd29SMasami Hiramatsu 	ret = dyn_event_register(&trace_kprobe_ops);
20046212dd29SMasami Hiramatsu 	if (ret)
20056212dd29SMasami Hiramatsu 		return ret;
2006413d37d1SMasami Hiramatsu 
20077582b7beSMike Rapoport (IBM) 	if (trace_kprobe_register_module_notifier())
200861424318SMasami Hiramatsu 		return -EINVAL;
200961424318SMasami Hiramatsu 
2010d8d4c6d0SMasami Hiramatsu 	return 0;
2011d8d4c6d0SMasami Hiramatsu }
2012ba0fbfbbSMasami Hiramatsu core_initcall(init_kprobe_trace_early);
2013d8d4c6d0SMasami Hiramatsu 
2014d8d4c6d0SMasami Hiramatsu /* Make a tracefs interface for controlling probe points */
init_kprobe_trace(void)2015d8d4c6d0SMasami Hiramatsu static __init int init_kprobe_trace(void)
2016d8d4c6d0SMasami Hiramatsu {
201722c36b18SWei Yang 	int ret;
2018d8d4c6d0SMasami Hiramatsu 
201922c36b18SWei Yang 	ret = tracing_init_dentry();
202022c36b18SWei Yang 	if (ret)
2021413d37d1SMasami Hiramatsu 		return 0;
2022413d37d1SMasami Hiramatsu 
2023e4931b82SYuntao Wang 	/* Event list interface */
2024e4931b82SYuntao Wang 	trace_create_file("kprobe_events", TRACE_MODE_WRITE,
202521ccc9cdSSteven Rostedt (VMware) 			  NULL, NULL, &kprobe_events_ops);
2026413d37d1SMasami Hiramatsu 
2027cd7e7bd5SMasami Hiramatsu 	/* Profile interface */
2028e4931b82SYuntao Wang 	trace_create_file("kprobe_profile", TRACE_MODE_READ,
202921ccc9cdSSteven Rostedt (VMware) 			  NULL, NULL, &kprobe_profile_ops);
2030cd7e7bd5SMasami Hiramatsu 
2031970988e1SMasami Hiramatsu 	setup_boot_kprobe_events();
2032970988e1SMasami Hiramatsu 
2033413d37d1SMasami Hiramatsu 	return 0;
2034413d37d1SMasami Hiramatsu }
2035413d37d1SMasami Hiramatsu fs_initcall(init_kprobe_trace);
2036413d37d1SMasami Hiramatsu 
2037413d37d1SMasami Hiramatsu 
2038413d37d1SMasami Hiramatsu #ifdef CONFIG_FTRACE_STARTUP_TEST
203926a346f2SArnd Bergmann static __init struct trace_event_file *
find_trace_probe_file(struct trace_kprobe * tk,struct trace_array * tr)2040c31ffb3fSNamhyung Kim find_trace_probe_file(struct trace_kprobe *tk, struct trace_array *tr)
204141a7dd42SMasami Hiramatsu {
20427f1d2f82SSteven Rostedt (Red Hat) 	struct trace_event_file *file;
204341a7dd42SMasami Hiramatsu 
204441a7dd42SMasami Hiramatsu 	list_for_each_entry(file, &tr->events, list)
2045e3dc9f89SMasami Hiramatsu 		if (file->event_call == trace_probe_event_call(&tk->tp))
204641a7dd42SMasami Hiramatsu 			return file;
204741a7dd42SMasami Hiramatsu 
204841a7dd42SMasami Hiramatsu 	return NULL;
204941a7dd42SMasami Hiramatsu }
205041a7dd42SMasami Hiramatsu 
20513fe3d619SOleg Nesterov /*
2052c31ffb3fSNamhyung Kim  * Nobody but us can call enable_trace_kprobe/disable_trace_kprobe at this
20533fe3d619SOleg Nesterov  * stage, we can do this lockless.
20543fe3d619SOleg Nesterov  */
kprobe_trace_self_tests_init(void)2055413d37d1SMasami Hiramatsu static __init int kprobe_trace_self_tests_init(void)
2056413d37d1SMasami Hiramatsu {
2057231e36f4SMasami Hiramatsu 	int ret, warn = 0;
2058413d37d1SMasami Hiramatsu 	int (*target)(int, int, int, int, int, int);
2059c31ffb3fSNamhyung Kim 	struct trace_kprobe *tk;
20607f1d2f82SSteven Rostedt (Red Hat) 	struct trace_event_file *file;
2061413d37d1SMasami Hiramatsu 
2062748ec3a2SYoshihiro YUNOMAE 	if (tracing_is_disabled())
2063748ec3a2SYoshihiro YUNOMAE 		return -ENODEV;
2064748ec3a2SYoshihiro YUNOMAE 
206560efe21eSMasami Hiramatsu 	if (tracing_selftest_disabled)
2066b6399cc7SSteven Rostedt (VMware) 		return 0;
2067b6399cc7SSteven Rostedt (VMware) 
2068413d37d1SMasami Hiramatsu 	target = kprobe_trace_selftest_target;
2069413d37d1SMasami Hiramatsu 
2070413d37d1SMasami Hiramatsu 	pr_info("Testing kprobe tracing: ");
2071413d37d1SMasami Hiramatsu 
2072d262271dSMasami Hiramatsu 	ret = create_or_delete_trace_kprobe("p:testprobe kprobe_trace_selftest_target $stack $stack0 +0($stack)");
207341051daaSMasami Hiramatsu (Google) 	if (WARN_ONCE(ret, "error on probing function entry.")) {
2074231e36f4SMasami Hiramatsu 		warn++;
2075231e36f4SMasami Hiramatsu 	} else {
2076231e36f4SMasami Hiramatsu 		/* Enable trace point */
2077c31ffb3fSNamhyung Kim 		tk = find_trace_kprobe("testprobe", KPROBE_EVENT_SYSTEM);
207841051daaSMasami Hiramatsu (Google) 		if (WARN_ONCE(tk == NULL, "error on probing function entry.")) {
207941a7dd42SMasami Hiramatsu 			warn++;
208041a7dd42SMasami Hiramatsu 		} else {
2081c31ffb3fSNamhyung Kim 			file = find_trace_probe_file(tk, top_trace_array());
208241051daaSMasami Hiramatsu (Google) 			if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
2083231e36f4SMasami Hiramatsu 				warn++;
2084231e36f4SMasami Hiramatsu 			} else
208560d53e2cSMasami Hiramatsu 				enable_trace_kprobe(
208660d53e2cSMasami Hiramatsu 					trace_probe_event_call(&tk->tp), file);
208741a7dd42SMasami Hiramatsu 		}
2088231e36f4SMasami Hiramatsu 	}
2089413d37d1SMasami Hiramatsu 
2090d262271dSMasami Hiramatsu 	ret = create_or_delete_trace_kprobe("r:testprobe2 kprobe_trace_selftest_target $retval");
209141051daaSMasami Hiramatsu (Google) 	if (WARN_ONCE(ret, "error on probing function return.")) {
2092231e36f4SMasami Hiramatsu 		warn++;
2093231e36f4SMasami Hiramatsu 	} else {
2094231e36f4SMasami Hiramatsu 		/* Enable trace point */
2095c31ffb3fSNamhyung Kim 		tk = find_trace_kprobe("testprobe2", KPROBE_EVENT_SYSTEM);
209641051daaSMasami Hiramatsu (Google) 		if (WARN_ONCE(tk == NULL, "error on getting 2nd new probe.")) {
209741a7dd42SMasami Hiramatsu 			warn++;
209841a7dd42SMasami Hiramatsu 		} else {
2099c31ffb3fSNamhyung Kim 			file = find_trace_probe_file(tk, top_trace_array());
210041051daaSMasami Hiramatsu (Google) 			if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
2101231e36f4SMasami Hiramatsu 				warn++;
2102231e36f4SMasami Hiramatsu 			} else
210360d53e2cSMasami Hiramatsu 				enable_trace_kprobe(
210460d53e2cSMasami Hiramatsu 					trace_probe_event_call(&tk->tp), file);
210541a7dd42SMasami Hiramatsu 		}
2106231e36f4SMasami Hiramatsu 	}
2107231e36f4SMasami Hiramatsu 
2108231e36f4SMasami Hiramatsu 	if (warn)
2109231e36f4SMasami Hiramatsu 		goto end;
2110413d37d1SMasami Hiramatsu 
2111413d37d1SMasami Hiramatsu 	ret = target(1, 2, 3, 4, 5, 6);
2112413d37d1SMasami Hiramatsu 
2113d4d7ccc8SMarcin Nowakowski 	/*
2114d4d7ccc8SMarcin Nowakowski 	 * Not expecting an error here, the check is only to prevent the
2115d4d7ccc8SMarcin Nowakowski 	 * optimizer from removing the call to target() as otherwise there
2116d4d7ccc8SMarcin Nowakowski 	 * are no side-effects and the call is never performed.
2117d4d7ccc8SMarcin Nowakowski 	 */
2118d4d7ccc8SMarcin Nowakowski 	if (ret != 21)
2119d4d7ccc8SMarcin Nowakowski 		warn++;
2120d4d7ccc8SMarcin Nowakowski 
212102ca1521SMasami Hiramatsu 	/* Disable trace points before removing it */
2122c31ffb3fSNamhyung Kim 	tk = find_trace_kprobe("testprobe", KPROBE_EVENT_SYSTEM);
212341051daaSMasami Hiramatsu (Google) 	if (WARN_ONCE(tk == NULL, "error on getting test probe.")) {
212441a7dd42SMasami Hiramatsu 		warn++;
212541a7dd42SMasami Hiramatsu 	} else {
212641051daaSMasami Hiramatsu (Google) 		if (WARN_ONCE(trace_kprobe_nhit(tk) != 1,
212741051daaSMasami Hiramatsu (Google) 				 "incorrect number of testprobe hits."))
2128d4d7ccc8SMarcin Nowakowski 			warn++;
2129d4d7ccc8SMarcin Nowakowski 
2130c31ffb3fSNamhyung Kim 		file = find_trace_probe_file(tk, top_trace_array());
213141051daaSMasami Hiramatsu (Google) 		if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
213202ca1521SMasami Hiramatsu 			warn++;
213302ca1521SMasami Hiramatsu 		} else
213460d53e2cSMasami Hiramatsu 			disable_trace_kprobe(
213560d53e2cSMasami Hiramatsu 				trace_probe_event_call(&tk->tp), file);
213641a7dd42SMasami Hiramatsu 	}
213702ca1521SMasami Hiramatsu 
2138c31ffb3fSNamhyung Kim 	tk = find_trace_kprobe("testprobe2", KPROBE_EVENT_SYSTEM);
213941051daaSMasami Hiramatsu (Google) 	if (WARN_ONCE(tk == NULL, "error on getting 2nd test probe.")) {
214041a7dd42SMasami Hiramatsu 		warn++;
214141a7dd42SMasami Hiramatsu 	} else {
214241051daaSMasami Hiramatsu (Google) 		if (WARN_ONCE(trace_kprobe_nhit(tk) != 1,
214341051daaSMasami Hiramatsu (Google) 				 "incorrect number of testprobe2 hits."))
2144d4d7ccc8SMarcin Nowakowski 			warn++;
2145d4d7ccc8SMarcin Nowakowski 
2146c31ffb3fSNamhyung Kim 		file = find_trace_probe_file(tk, top_trace_array());
214741051daaSMasami Hiramatsu (Google) 		if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
214802ca1521SMasami Hiramatsu 			warn++;
214902ca1521SMasami Hiramatsu 		} else
215060d53e2cSMasami Hiramatsu 			disable_trace_kprobe(
215160d53e2cSMasami Hiramatsu 				trace_probe_event_call(&tk->tp), file);
215241a7dd42SMasami Hiramatsu 	}
215302ca1521SMasami Hiramatsu 
2154d262271dSMasami Hiramatsu 	ret = create_or_delete_trace_kprobe("-:testprobe");
215541051daaSMasami Hiramatsu (Google) 	if (WARN_ONCE(ret, "error on deleting a probe."))
2156231e36f4SMasami Hiramatsu 		warn++;
2157413d37d1SMasami Hiramatsu 
2158d262271dSMasami Hiramatsu 	ret = create_or_delete_trace_kprobe("-:testprobe2");
215941051daaSMasami Hiramatsu (Google) 	if (WARN_ONCE(ret, "error on deleting a probe."))
2160231e36f4SMasami Hiramatsu 		warn++;
216141051daaSMasami Hiramatsu (Google) 
2162231e36f4SMasami Hiramatsu 
2163231e36f4SMasami Hiramatsu end:
216430e7d894SThomas Gleixner 	/*
216530e7d894SThomas Gleixner 	 * Wait for the optimizer work to finish. Otherwise it might fiddle
216630e7d894SThomas Gleixner 	 * with probes in already freed __init text.
216730e7d894SThomas Gleixner 	 */
216830e7d894SThomas Gleixner 	wait_for_kprobe_optimizer();
2169231e36f4SMasami Hiramatsu 	if (warn)
2170231e36f4SMasami Hiramatsu 		pr_cont("NG: Some tests are failed. Please check them.\n");
2171231e36f4SMasami Hiramatsu 	else
2172413d37d1SMasami Hiramatsu 		pr_cont("OK\n");
2173413d37d1SMasami Hiramatsu 	return 0;
2174413d37d1SMasami Hiramatsu }
2175413d37d1SMasami Hiramatsu 
2176413d37d1SMasami Hiramatsu late_initcall(kprobe_trace_self_tests_init);
2177413d37d1SMasami Hiramatsu 
2178413d37d1SMasami Hiramatsu #endif
2179