• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
4  *
5  * Updates:
6  * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com>
7  *
8  */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <dirent.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <limits.h>
16 
17 #include "tracefs.h"
18 #include "tracefs-local.h"
19 
20 #define KPROBE_EVENTS "kprobe_events"
21 #define KPROBE_DEFAULT_GROUP "kprobes"
22 
23 static struct tracefs_dynevent *
kprobe_alloc(enum tracefs_dynevent_type type,const char * system,const char * event,const char * addr,const char * format)24 kprobe_alloc(enum tracefs_dynevent_type type, const char *system, const char *event,
25 	     const char *addr, const char *format)
26 {
27 	struct tracefs_dynevent *kp;
28 	const char *sys = system;
29 	const char *ename = event;
30 	char *tmp;
31 
32 	if (!addr) {
33 		errno = EBADMSG;
34 		return NULL;
35 	}
36 	if (!sys)
37 		sys = KPROBE_DEFAULT_GROUP;
38 
39 	if (!event) {
40 		ename = strdup(addr);
41 		if (!ename)
42 			return NULL;
43 		tmp = strchr(ename, ':');
44 		if (tmp)
45 			*tmp = '\0';
46 	}
47 
48 	kp = dynevent_alloc(type, sys, ename, addr, format);
49 	if (!event)
50 		free((char *)ename);
51 
52 	return kp;
53 }
54 
55 /**
56  * tracefs_kprobe_alloc - Allocate new kprobe
57  * @system: The system name (NULL for the default kprobes)
58  * @event: The event to create (NULL to use @addr for the event)
59  * @addr: The function and offset (or address) to insert the probe
60  * @format: The format string to define the probe.
61  *
62  * Allocate a kprobe context that will be in the @system group (or kprobes if
63  * @system is NULL). Have the name of @event (or @addr if @event is NULL). Will
64  * be inserted to @addr (function name, with or without offset, or a address).
65  * And the @format will define the format of the kprobe.
66  *
67  * See the Linux documentation file under:
68  *  Documentation/trace/kprobetrace.rst
69  *
70  * The kprobe is not created in the system.
71  *
72  * Return a pointer to a kprobe context on success, or NULL on error.
73  * The returned pointer must be freed with tracefs_dynevent_free()
74  *
75  * errno will be set to EBADMSG if addr is NULL.
76  */
77 struct tracefs_dynevent *
tracefs_kprobe_alloc(const char * system,const char * event,const char * addr,const char * format)78 tracefs_kprobe_alloc(const char *system, const char *event, const char *addr, const char *format)
79 
80 {
81 	return kprobe_alloc(TRACEFS_DYNEVENT_KPROBE, system, event, addr, format);
82 }
83 
84 /**
85  * tracefs_kretprobe_alloc - Allocate new kretprobe
86  * @system: The system name (NULL for the default kprobes)
87  * @event: The event to create (NULL to use @addr for the event)
88  * @addr: The function and offset (or address) to insert the retprobe
89  * @format: The format string to define the retprobe.
90  * @max: Maximum number of instances of the specified function that
91  *	 can be probed simultaneously, or 0 for the default value.
92  *
93  * Allocate a kretprobe that will be in the @system group (or kprobes if
94  * @system is NULL). Have the name of @event (or @addr if @event is
95  * NULL). Will be inserted to @addr (function name, with or without
96  * offset, or a address). And the @format will define the raw format
97  * of the kprobe. See the Linux documentation file under:
98  * Documentation/trace/kprobetrace.rst
99  * The kretprobe is not created in the system.
100  *
101  * Return a pointer to a kprobe context on success, or NULL on error.
102  * The returned pointer must be freed with tracefs_dynevent_free()
103  *
104  * errno will be set to EBADMSG if addr is NULL.
105  */
106 struct tracefs_dynevent *
tracefs_kretprobe_alloc(const char * system,const char * event,const char * addr,const char * format,unsigned int max)107 tracefs_kretprobe_alloc(const char *system, const char *event,
108 			const char *addr, const char *format, unsigned int max)
109 {
110 	struct tracefs_dynevent *kp;
111 	int ret;
112 
113 	kp = kprobe_alloc(TRACEFS_DYNEVENT_KRETPROBE, system, event, addr, format);
114 	if (!kp)
115 		return NULL;
116 
117 	if (!max)
118 		return kp;
119 
120 	free(kp->prefix);
121 	kp->prefix = NULL;
122 	ret = asprintf(&kp->prefix, "r%d:", max);
123 	if (ret < 0)
124 		goto error;
125 
126 	return kp;
127 error:
128 	tracefs_dynevent_free(kp);
129 	return NULL;
130 }
131 
kprobe_raw(enum tracefs_dynevent_type type,const char * system,const char * event,const char * addr,const char * format)132 static int kprobe_raw(enum tracefs_dynevent_type type, const char *system,
133 		      const char *event, const char *addr, const char *format)
134 {
135 	static struct tracefs_dynevent *kp;
136 	int ret;
137 
138 	kp = kprobe_alloc(type, system, event, addr, format);
139 	if (!kp)
140 		return -1;
141 
142 	ret = tracefs_dynevent_create(kp);
143 	tracefs_dynevent_free(kp);
144 
145 	return ret;
146 }
147 
148 /**
149  * tracefs_kprobe_raw - Create a kprobe using raw format
150  * @system: The system name (NULL for the default kprobes)
151  * @event: The event to create (NULL to use @addr for the event)
152  * @addr: The function and offset (or address) to insert the probe
153  * @format: The raw format string to define the probe.
154  *
155  * Create a kprobe that will be in the @system group (or kprobes if
156  * @system is NULL). Have the name of @event (or @addr if @event is
157  * NULL). Will be inserted to @addr (function name, with or without
158  * offset, or a address). And the @format will define the raw format
159  * of the kprobe. See the Linux documentation file under:
160  * Documentation/trace/kprobetrace.rst
161  *
162  * Return 0 on success, or -1 on error.
163  *   If the syntex of @format was incorrect, running
164  *   tracefs_error_last(NULL) may show what went wrong.
165  *
166  * errno will be set to EBADMSG if addr or format is NULL.
167  */
tracefs_kprobe_raw(const char * system,const char * event,const char * addr,const char * format)168 int tracefs_kprobe_raw(const char *system, const char *event,
169 		       const char *addr, const char *format)
170 {
171 	return kprobe_raw(TRACEFS_DYNEVENT_KPROBE, system, event, addr, format);
172 }
173 
174 /**
175  * tracefs_kretprobe_raw - Create a kretprobe using raw format
176  * @system: The system name (NULL for the default kprobes)
177  * @event: The event to create (NULL to use @addr for the event)
178  * @addr: The function and offset (or address) to insert the retprobe
179  * @format: The raw format string to define the retprobe.
180  *
181  * Create a kretprobe that will be in the @system group (or kprobes if
182  * @system is NULL). Have the name of @event (or @addr if @event is
183  * NULL). Will be inserted to @addr (function name, with or without
184  * offset, or a address). And the @format will define the raw format
185  * of the kprobe. See the Linux documentation file under:
186  * Documentation/trace/kprobetrace.rst
187  *
188  * Return 0 on success, or -1 on error.
189  *   If the syntex of @format was incorrect, running
190  *   tracefs_error_last(NULL) may show what went wrong.
191  *
192  * errno will be set to EBADMSG if addr or format is NULL.
193  */
tracefs_kretprobe_raw(const char * system,const char * event,const char * addr,const char * format)194 int tracefs_kretprobe_raw(const char *system, const char *event,
195 			  const char *addr, const char *format)
196 {
197 	return kprobe_raw(TRACEFS_DYNEVENT_KRETPROBE, system, event, addr, format);
198 }
199