xref: /aosp_15_r20/external/libtracefs/Documentation/libtracefs-dynevents.txt (revision 287e80b3a36113050663245e7f2c00d274188f18)
1libtracefs(3)
2=============
3
4NAME
5----
6tracefs_dynevent_create, tracefs_dynevent_destroy, tracefs_dynevent_destroy_all,
7tracefs_dynevent_free, tracefs_dynevent_list_free, tracefs_dynevent_get, tracefs_dynevent_get_all,
8tracefs_dynevent_info, tracefs_dynevent_get_event - Create, destroy, free and get dynamic events.
9
10SYNOPSIS
11--------
12[verse]
13--
14*#include <tracefs.h>*
15
16struct *tracefs_dynevent*;
17enum *tracefs_dynevent_type*;
18int *tracefs_dynevent_create*(struct tracefs_dynevent pass:[*]_devent_);
19int *tracefs_dynevent_destroy*(struct tracefs_dynevent pass:[*]_devent_, bool _force_);
20int *tracefs_dynevent_destroy_all*(unsigned int _types_, bool _force_);
21void *tracefs_dynevent_free*(struct tracefs_dynevent pass:[*]_devent_);
22void *tracefs_dynevent_list_free*(struct tracefs_dynevent pass:[*]pass:[*]_events_);
23struct tracefs_dynevent pass:[*]*tracefs_dynevent_get*(enum tracefs_dynevent_type _type_, const char pass:[*]_system_, const char pass:[*]_event_);
24struct tracefs_dynevent pass:[*]pass:[*]*tracefs_dynevent_get_all*(unsigned int _types_, const char pass:[*]_system_);
25enum tracefs_dynevent_type *tracefs_dynevent_info*(struct tracefs_dynevent pass:[*]_dynevent_, char pass:[*]pass:[*]_system_, char pass:[*]pass:[*]_event_, char pass:[*]pass:[*]_prefix_, char pass:[*]pass:[*]_addr_, char pass:[*]pass:[*]_format_);
26struct tep_event pass:[*]*tracefs_dynevent_get_event*(struct tep_handle pass:[*]_tep_, struct tracefs_dynevent pass:[*]_dynevent_);
27--
28
29DESCRIPTION
30-----------
31
32The *tracefs_dynevent_create*() function creates dynamic event _devent_ in the system.
33
34The *tracefs_dynevent_destroy*() function removes dynamic event _devent_ from the system. If _force_
35is true, the function will attempt to disable all events in all trace instances, before removing
36the dynamic event. The _devent_ context is not freed, use *tracefs_dynevent_free*() to free it.
37
38The *tracefs_dynevent_destroy_all*() function removes all dynamic events of given types from the
39system. The _types_ parameter is a type of specific dynamic event, or a bitmask of dynamic events
40types *tracefs_dynevent_type*, that will be removed. If _types_ is 0, dynamic events from all types
41will be removed.  If _force_ is true, the function will attempt to disable all events in all trace
42instances, before removing the dynamic events.
43
44The *tracefs_dynevent_get*() function allocates and returns a single instance of a dynamic
45event that matches the given *type*, *system* and *event* that is passed to it. NULL is returned
46if there is no match. The returned event is what is found in the system, and must be freed
47with *tracefs_dynevent_free*(). If *system* is NULL, then the first *event* of any system
48of the given type that has the name of *event* will be returned.
49
50The *tracefs_dynevent_get_all*() function allocates and returns an array of pointers to dynamic
51events of given types that exist in the system. The last element of the array is a NULL pointer.
52The array must be freed with *tracefs_dynevent_list_free*(). If there are no events a NULL pointer is
53returned. The _types_ parameter is a type of specific dynamic event, or a bitmask of dynamic events
54types *tracefs_dynevent_type*, that will be retrieved. If _types_ is 0, dynamic events from all
55types will be retrieved.
56
57The *tracefs_dynevent_free*() function frees a dynamic event context _devent_.
58
59The *tracefs_dynevent_list_free*() function frees an array of pointers to dynamic event, returned
60by *tracefs_dynevent_get_all()* API.
61
62The *tracefs_dynevent_info*() function returns the type and information of a given dynamic event
63_dynevent_. If any of the _system_, _event_, _prefix_, _addr_ or _format_ arguments are not NULL,
64then strings are allocated and returned back via these arguments. The _system_ and _event_ holds the
65system and the name of the dynamic event. If _prefix_ is non NULL, then it will hold an allocated
66string that holds the prefix portion of the dynamic event (the content up to the ":", exluding it).
67If _addr_ is non NULL, it will hold the address or function that the dynamic event is attached to,
68if relevant for this event type. If _format_ is non NULL, it will hold the format string of the
69dynamic event. Note, that the content in _group_, _event_, _prefix_, _addr_, and _format_ must be
70freed with free(3) if they are set.
71
72The *tracefs_dynevent_get_event*() function returns a tep event, describing the given dynamic event.
73The API detects any newly created or removed dynamic events. The returned pointer to tep event is
74controlled by @tep and must not be freed.
75
76RETURN VALUE
77------------
78
79*tracefs_dynevent_create*() returns 0 on success, or -1 on error. If a parsing error occurs then
80*tracefs_error_last*(3) may be used to retrieve the error message explaining the parsing issue.
81
82*tracefs_dynevent_destroy*() and *tracefs_dynevent_destroy_all*() return 0 on success, or -1 on
83error. If _force_ is enabled, the functions may fail on disabling the events.
84
85*tracefs_dynevent_get*() function returns an allocated dynamic event from the system that matches
86the type, system and event given.
87
88*tracefs_dynevent_get_all*() function returns allocated array of pointers to dynamic events, or NULL
89in case of an error or in case there are no events in the system. That array must be freed by
90*tracefs_dynevent_list_free*().
91
92*tracefs_dynevent_info*() returns the type of the given dynamic event  or TRACEFS_DYNEVENT_UNKNOWN
93on error. If _system_, _event_, _prefix_, _addr_, or _format_ are non NULL, they will contain
94allocated strings that must be freed by free(3).
95
96The *tracefs_dynevent_get_event*() function returns a pointer to a tep event or NULL in case of an
97error or if the requested dynamic event is missing. The returned pointer to tep event is controlled
98by @tep and must not be freed.
99
100ERRORS
101------
102The following errors are for all the above calls:
103
104*ENODEV* dynamic events of requested type are not configured for the running kernel.
105
106*ENOMEM* Memory allocation error.
107
108*tracefs_dynevent_create*() can fail with the following errors:
109
110*EINVAL*  Most likely a parsing error occurred (use *tracefs_error_last*(3) to possibly
111          see what that error was).
112
113Other errors may also happen caused by internal system calls.
114
115EXAMPLE
116-------
117[source,c]
118--
119#include <stdlib.h>
120#include <unistd.h>
121#include <sys/wait.h>
122
123#include <tracefs.h>
124
125static struct tep_event *open_event;
126static struct tep_format_field *file_field;
127
128static struct tep_event *openret_event;
129static struct tep_format_field *ret_field;
130
131static int callback(struct tep_event *event, struct tep_record *record,
132		    int cpu, void *data)
133{
134	struct trace_seq seq;
135
136	trace_seq_init(&seq);
137	tep_print_event(event->tep, &seq, record, "%d-%s: ", TEP_PRINT_PID, TEP_PRINT_COMM);
138
139	if (event->id == open_event->id) {
140		trace_seq_puts(&seq, "open file='");
141		tep_print_field(&seq, record->data, file_field);
142		trace_seq_puts(&seq, "'\n");
143	} else if (event->id == openret_event->id) {
144		unsigned long long ret;
145		tep_read_number_field(ret_field, record->data, &ret);
146		trace_seq_printf(&seq, "open ret=%lld\n", ret);
147	} else {
148		goto out;
149	}
150
151	trace_seq_terminate(&seq);
152	trace_seq_do_printf(&seq);
153out:
154	trace_seq_destroy(&seq);
155
156	return 0;
157}
158
159static pid_t run_exec(char **argv, char **env)
160{
161	pid_t pid;
162
163	pid = fork();
164	if (pid)
165		return pid;
166
167	execve(argv[0], argv, env);
168	perror("exec");
169	exit(-1);
170}
171
172const char *mykprobe = "my_kprobes";
173
174int main (int argc, char **argv, char **env)
175{
176	struct tracefs_dynevent *kprobe, *kretprobe;
177	const char *sysnames[] = { mykprobe, NULL };
178	struct tracefs_instance *instance;
179	struct tep_handle *tep;
180	pid_t pid;
181
182	if (argc < 2) {
183		printf("usage: %s command\n", argv[0]);
184		exit(-1);
185	}
186
187	instance = tracefs_instance_create("exec_open");
188	if (!instance) {
189		perror("creating instance");
190		exit(-1);
191	}
192
193	tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, true);
194
195	kprobe = tracefs_kprobe_alloc(mykprobe, "open", "do_sys_openat2",
196				      "file=+0($arg2):ustring flags=+0($arg3):x64 mode=+8($arg3):x64\n");
197	kretprobe = tracefs_kretprobe_alloc(mykprobe, "openret", "do_sys_openat2", "ret=%ax", 0);
198	if (!kprobe || !kretprobe) {
199		perror("allocating dynamic events");
200		exit(-1);
201	}
202
203	if (tracefs_dynevent_create(kprobe) || tracefs_dynevent_create(kretprobe)){
204		char *err = tracefs_error_last(NULL);
205		perror("Failed to create kprobes:");
206		if (err && strlen(err))
207			fprintf(stderr, "%s\n", err);
208		exit(-1);
209	}
210
211	tep = tracefs_local_events_system(NULL, sysnames);
212	if (!tep) {
213		perror("reading events");
214		exit(-1);
215	}
216	open_event = tep_find_event_by_name(tep, mykprobe, "open");
217	file_field = tep_find_field(open_event, "file");
218
219	openret_event = tep_find_event_by_name(tep, mykprobe, "openret");
220	ret_field = tep_find_field(openret_event, "ret");
221
222	tracefs_event_enable(instance, mykprobe, NULL);
223	pid = run_exec(&argv[1], env);
224
225	/* Let the child start to run */
226	sched_yield();
227
228	do {
229		tracefs_load_cmdlines(NULL, tep);
230		tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, NULL);
231	} while (waitpid(pid, NULL, WNOHANG) != pid);
232
233	/* Will disable the events */
234	tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, true);
235	tracefs_dynevent_free(kprobe);
236	tracefs_dynevent_free(kretprobe);
237	tracefs_instance_destroy(instance);
238	tep_free(tep);
239
240	return 0;
241}
242--
243
244FILES
245-----
246[verse]
247--
248*tracefs.h*
249	Header file to include in order to have access to the library APIs.
250*-ltracefs*
251	Linker switch to add when building a program that uses the library.
252--
253
254SEE ALSO
255--------
256*libtracefs*(3),
257*libtraceevent*(3),
258*trace-cmd*(1)
259
260AUTHOR
261------
262[verse]
263--
264*Steven Rostedt* <[email protected]>
265*Tzvetomir Stoyanov* <[email protected]>
266*Yordan Karadzhov* <[email protected]>
267--
268REPORTING BUGS
269--------------
270Report bugs to  <[email protected]>
271
272LICENSE
273-------
274libtracefs is Free Software licensed under the GNU LGPL 2.1
275
276RESOURCES
277---------
278https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
279
280COPYING
281-------
282Copyright \(C) 2021 VMware, Inc. Free use of this software is granted under
283the terms of the GNU Public License (GPL).
284