xref: /aosp_15_r20/external/libtraceevent/Documentation/libtraceevent-kbuffer-create.txt (revision 436bf2bcd5202612ffffe471bbcc1f277cc8d28e)
1libtraceevent(3)
2================
3
4NAME
5----
6kbuffer_alloc, kbuffer_dup, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer,
7kbuffer_refresh, kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
8the Linux kernel tracing ring buffer
9
10SYNOPSIS
11--------
12[verse]
13--
14*#include <kbuffer.h>*
15
16enum kbuffer_endian {
17	KBUFFER_ENDIAN_BIG,
18	KBUFFER_ENDIAN_LITTLE,
19	KBUFFER_ENDIAN_SAME_AS_HOST,
20};
21
22enum kbuffer_long_size {
23	KBUFFER_LSIZE_4,
24	KBUFFER_LSIZE_8,
25	KBUFFER_LSIZE_SAME_AS_HOST,
26};
27
28struct kbuffer;
29struct tep_handle;
30
31struct kbuffer pass:[*]*kbuffer_alloc*(enum kbuffer_long_size _size_, enum kbuffer_endian _endian_);
32struct kbuffer pass:[*]*kbuffer_dup*(struct kbuffer pass:[*]_kbuf_);
33void *kbuffer_free*(struct kbuffer pass:[*]_kbuf_);
34int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
35int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf_);
36int *kbuffer_refresh*(struct kbuffer pass:[*]_kbuf_);
37int *kbuffer_start_of_data*(struct kbuffer pass:[*]_kbuf_);
38void pass:[*]*kbuffer_subbuffer*(struct kbuffer pass:[*]_kbuf);
39--
40
41DESCRIPTION
42-----------
43These functions create a _kbuffer_ handle that can be used to parse the raw sub buffers
44of the Linux kernel tracing ring buffer. The ring buffer is found in the tracefs
45directory, and can be retrieved by *tracefs_instance_get_file(3)* at
46*per_cpu/cpuX/trace_pipe_raw* where *X* is replaced by the per CPU number of
47the specified ring buffer. The ring buffer inside the kernel is split up per
48CPU, such that the raw ring buffer must be retrieved per CPU as well.
49
50The *kbuffer_alloc()* will create a descriptor that can be used to manage a sub buffer
51read by the ring buffer. The _size_ parameter denotes what the word size is
52for the given buffer (note, this works from reading raw data from machines other
53than the machine that is calling this function). The _endian_ denotes the endian
54for the machine.
55
56If _endian_ is set to _KBUFFER_ENDIAN_SAME_AS_HOST_ the endian will be set to the same
57as the host endianess, which is useful when the application is reading the
58ring buffer data directly from the same machine it is running on.
59
60If _size_ is set to _KBUFFER_LSIZE_SAME_AS_HOST_, if the word size is 8, it will
61set the kbuffer descriptor to long size of 8. But if the size is 4, then it
62will then perform a *uname(2)* call, and if the _machine_ field has the string "64"
63in it, it will be set to 8 byte long size and not 4 byte. This is because the
64ring buffer long size is dependent on the kernel and not user space.
65
66The *kbuffer_dup()* function will duplicate an existing kbuffer structure with
67an allocated new one. It will have all the properties of the passed in _kbuf_,
68including pointing to the same subbuffer that was loaded in the _kbuf_.
69It must be freed with *kbuffer_free()*.
70
71The *kbuffer_free()* function will free the resources created by *kbuffer_alloc()*.
72
73The *kbuffer_load_subbuffer()* will take a _subbuffer_ which is a raw data blob
74from the tracefs *trace_pipe_raw* file. The Linux tracing ring buffer is broken up
75into sub buffers. Each sub buffer is as stand alone data segment that has all the
76information to split out the individual events and time stamps. This sub buffer
77is what kbuffer uses to walk the events.
78
79The *kbuffer_subbuffer_size()* returns the location of the end of the last event
80on the sub-buffer. It does not return the size of the sub-buffer itself.
81
82The *kbuffer_refresh()* is to be used if more writes were done on the loaded kbuffer
83where the size of the kbuffer needs to be refreshed to be able to read the new
84events that were written since the last *kbuffer_load_subbuffer()* was called on it.
85
86Note, no memory barriers are implemented with this function and any synchronization
87with the writer is the responsibility of the application.
88
89The *kbuffer_start_of_data()* function returns the offset of where the actual
90data load of the sub-buffer begins.
91
92The *kbuffer_subbuffer()* function returns the pointer to the currently loaded
93subbuffer. That is, the last subbuffer that was loaded by *kbuffer_load_subbuffer()*.
94If no subbuffer was loaded NULL is returned.
95
96RETURN VALUE
97------------
98*kbuffer_alloc()* returns an allocated kbuffer descriptor or NULL on error.
99The returned descriptor must be freed with *kbuffer_free()*
100
101*kbuffer_load_subbuffer()* returns 0 on success and -1 on error.
102
103*kbuffer_subbuffer_size()* returns the index on the subbuffer where the end
104of the last event is located.
105
106*kbuffer_start_of_data()* returns the offset of where the data begins on the
107sub-buffer loaded in _kbuf_.
108
109*kbuffer_subbuffer()* returns the last loaded subbuffer to _kbuf_ that was loaded
110by *kbuffer_load_subbuffer()* or NULL if none was loaded.
111
112*kbuffer_refresh()* returns 0 on success and -1 if _kbuf_ is NULL or it does not
113have a subbuffer loaded via *kbuffer_load_subbuffer()*.
114
115EXAMPLE
116-------
117[source,c]
118--
119#include <stdio.h>
120#include <stdlib.h>
121#include <fcntl.h>
122#include <unistd.h>
123#include <sys/stat.h>
124
125#include <kbuffer.h>
126
127int main (int argc, char **argv)
128{
129	unsigned long long ts;
130	struct kbuffer *kbuf;
131	struct stat st;
132	char *buf;
133	void *event;
134	int ret;
135	int fd;
136	int i = 0;
137
138	if (argc < 2) {
139		printf("usage: %s raw-subbuffer-page\n", argv[0]);
140		printf(" Try: dd count=1 bs=4096 if=/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw of=/tmp/file\n");
141		exit(0);
142	}
143
144	if (stat(argv[1], &st) < 0) {
145		perror("stat");
146		exit(-1);
147	}
148
149	buf = malloc(st.st_size);
150	if (!buf) {
151		perror("Allocating buffer");
152		exit(-1);
153	}
154
155	fd = open(argv[1], O_RDONLY);
156	if (fd < 0) {
157		perror(argv[1]);
158		exit(-1);
159	}
160
161	ret = read(fd, buf, st.st_size);
162	if (ret < 0) {
163		perror("Reading buffer");
164		exit(-1);
165	}
166	close(fd);
167
168	kbuf = kbuffer_alloc(KBUFFER_ENDIAN_SAME_AS_HOST,
169			     KBUFFER_LSIZE_SAME_AS_HOST);
170	if (!kbuf) {
171		perror("Creating kbuffer");
172		exit(-1);
173	}
174	ret = kbuffer_load_subbuffer(kbuf, buf);
175	if (ret < 0) {
176		perror("Loading sub bufer");
177		exit(-1);
178	}
179
180	if (kbuffer_subbuffer_size(kbuf) > st.st_size) {
181		fprintf(stderr, "kbuffer is bigger than raw size %d > %ld\n",
182			kbuffer_subbuffer_size(kbuf), st.st_size);
183		exit(-1);
184	}
185
186	printf("Kbuffer data starts at %d\n", kbuffer_start_of_data(kbuf));
187	do {
188		event = kbuffer_read_event(kbuf, &ts);
189		if (event) {
190			printf(" event %3d ts:%lld\n", i++, ts);
191			event = kbuffer_next_event(kbuf, NULL);
192		}
193	} while (event);
194
195	if (!event)
196		printf("Finished sub buffer\n");
197
198	kbuffer_free(kbuf);
199
200	return 0;
201}
202--
203FILES
204-----
205[verse]
206--
207*event-parse.h*
208	Header file to include in order to have access to the library APIs.
209*-ltraceevent*
210	Linker switch to add when building a program that uses the library.
211--
212
213SEE ALSO
214--------
215*libtraceevent*(3), *trace-cmd*(1)
216
217AUTHOR
218------
219[verse]
220--
221*Steven Rostedt* <[email protected]>, author of *libtraceevent*.
222--
223REPORTING BUGS
224--------------
225Report bugs to  <[email protected]>
226
227LICENSE
228-------
229libtraceevent is Free Software licensed under the GNU LGPL 2.1
230
231RESOURCES
232---------
233https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
234