[PATCH 2/2] libtraceevent: Add man page for the new BTF functions

Steven Rostedt <[email protected]> Thu, 31 Jul 2025 14:52:34 -0400
Newsgroups org.kernel.vger.linux-trace-devel
Message-ID <[email protected]>
From: "Steven Rostedt (Google)" <[email protected]>

Add a man page for tep_load_btf() and tep_btf_print_args()

Signed-off-by: Steven Rostedt (Google) <[email protected]>
---
 Documentation/libtraceevent-btf.txt | 158 ++++++++++++++++++++++++++++
 Documentation/libtraceevent.txt     |   5 +
 2 files changed, 163 insertions(+)
 create mode 100644 Documentation/libtraceevent-btf.txt

diff --git a/Documentation/libtraceevent-btf.txt b/Documentation/libtraceevent-btf.txt
new file mode 100644
index 000000000000..802d953a6ef1
--- /dev/null
+++ b/Documentation/libtraceevent-btf.txt
@@ -0,0 +1,158 @@
+libtraceevent(3)
+================
+
+NAME
+----
+tep_load_btf, tep_btf_print_args -
+Load BTF file and use it to pretty print function arguments.
+
+SYNOPSIS
+--------
+[verse]
+--
+*#include <event-parse.h>*
+
+int *tep_load_btf*(struct tep_handle pass:[*]_tep_, void pass:[*]_raw_data_, size_t _data_size_);
+int *tep_btf_print_args*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, void pass:[*]_args_,
+		       int nmem, int size, const char pass:[*]_func_);
+--
+
+DESCRIPTION
+-----------
+If the Linux kernel has BTF configured, then a binary file will exist
+in the path of */sys/kernel/btf/vmlinux*. If this file is read into memory
+and passed to *tep_load_btf()* function, then it will be used to parse
+the arguments of a given function, if that function data is found within
+the BTF file.
+
+The *tep_load_btf()* takes the _tep_ handle and will load the allocated _raw_data_
+into it. NOTE, the _raw_data_ must be allocated via glibc() allocations as on
+success, it will save the _raw_data_ internally, and will be freed when the
+_tep_ handler is destroyed. If it is called twice, it will free the old _raw_data_
+and reinitialize itself with the new _raw_data_. The _data_size_ should be set
+to the size of the content in _raw_data_.
+
+The *tep_btf_print_args()* takes a _tep_ handle, a trace_seq _s_ pointer
+(that was initialized by *trace_seq_init(3)*), an _args_ array that holds either
+4 byte or 8 byte values, the _nmem_ that is the number of values in the _args_
+parameter, a _size_ that is either 4 or 8 to denote the size of each value in _args_,
+and a _func_ string that is the name of the function to find the BTF information
+to use for parsing. If BTF is not loaded or the _func_ name is not found it
+will just print a hex value of all the _args_ into the _s_ descriptor.
+
+RETURN VALUE
+------------
+*tep_load_btf()* function returns 0 on success and the _raw_data_ is now
+owned by the _tep_ descriptor and will be freed when it is destroyed.
+It returns -1 on failure and the _raw_data_ will need to be freed by the caller.
+
+*tep_btf_print_args()* returns 0 on success and -1 on failure, which happens
+if the _size_ is not valid or the BTF file that was loaded is corrupted.
+
+EXAMPLE
+-------
+[source,c]
+--
+#include <event-parse.h>
+...
+int print_args(const char *func, unsigned long *args, int nr)
+{
+	struct tep_handle *tep;
+	struct trace_seq s;
+	struct stat st;
+	ssize_t r;
+	size_t tot = 0;
+	void *buf;
+	int fd;
+
+	if (!tep)
+		return -1;
+
+	fd = open("/sys/kernel/btf/vmlinux", O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	if (fstat(fd, &st) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	buf = malloc(st.st_size);
+	if (!buf) {
+		close(fd);
+		return -1;
+	}
+
+	while (tot < st.size) {
+		r = read(fd, buf + tot, st.st_size - tot);
+		if (r <= 0)
+			break;
+		tot += r;
+	}
+	close(fd);
+
+	tep = tep_alloc();
+	if (!tep) {
+		free(buf);
+		return -1;
+	}
+
+	if (tep_load_btf(tep, buf, tot) < 0) {
+		free(buf);
+		return -1;
+	}
+
+	/* Now buf belongs to tep and does not need to be freed */
+
+	trace_seq_init(&s);
+
+	printf("%s(", func);
+	tep_btf_print_args(tep, &s, args, nr, sizeof(long), func);
+
+	/* This will also free buf */
+	tep_free(tep);
+}
+...
+The above may output:
+
+  getname_flags(filename=0x7ffe7d33f3d0, flags=0)
+
+If BTF is loaded and the function was found, or it may show:
+
+  getname_flags(7ffe7d33f3d0, 0, 0, 0, 0, 0)
+
+If it was not.
+...
+--
+FILES
+-----
+[verse]
+--
+*event-parse.h*
+	Header file to include in order to have access to the library APIs.
+*-ltraceevent*
+	Linker switch to add when building a program that uses the library.
+--
+
+SEE ALSO
+--------
+*libtraceevent*(3), *trace-cmd*(1)
+
+AUTHOR
+------
+[verse]
+--
+*Steven Rostedt* <[email protected]>, author of *libtraceevent*.
+*Tzvetomir Stoyanov* <[email protected]>, author of this man page.
+--
+REPORTING BUGS
+--------------
+Report bugs to  <[email protected]>
+
+LICENSE
+-------
+libtraceevent is Free Software licensed under the GNU LGPL 2.1
+
+RESOURCES
+---------
+https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
diff --git a/Documentation/libtraceevent.txt b/Documentation/libtraceevent.txt
index 9e7777283c52..5fb5fc19ffc1 100644
--- a/Documentation/libtraceevent.txt
+++ b/Documentation/libtraceevent.txt
@@ -166,6 +166,11 @@ KVM plugin calllbacks: (Defined by the application and complied with -rdynamic)
 				    unsigned long long pass:[*]paddr);
 	void *tep_plugin_kvm_put_func*(const char pass:[*]func);
 
+BTF parsing:
+	int *tep_load_btf*(struct tep_handle pass:[*]_tep_, void pass:[*]_raw_data_, size_t _data_size_);
+	int *tep_btf_print_args*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, void pass:[*]_args_,
+		       int nmem, int size, const char pass:[*]_func_);
+
 Trace sequences:
 *#include <trace-seq.h>*
 	void *trace_seq_init*(struct trace_seq pass:[*]_s_);
-- 
2.47.2