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