├── .gitignore ├── Documentation ├── .gitignore ├── Makefile ├── asciidoc.conf ├── install-docs.sh.in ├── libtraceevent-commands.txt ├── libtraceevent-cpus.txt ├── libtraceevent-debug.txt ├── libtraceevent-endian_read.txt ├── libtraceevent-event_find.txt ├── libtraceevent-event_get.txt ├── libtraceevent-event_list.txt ├── libtraceevent-event_print.txt ├── libtraceevent-field_find.txt ├── libtraceevent-field_get_val.txt ├── libtraceevent-field_print.txt ├── libtraceevent-field_read.txt ├── libtraceevent-fields.txt ├── libtraceevent-file_endian.txt ├── libtraceevent-filter.txt ├── libtraceevent-func_apis.txt ├── libtraceevent-func_find.txt ├── libtraceevent-handle.txt ├── libtraceevent-header_page.txt ├── libtraceevent-host_endian.txt ├── libtraceevent-kbuffer-create.txt ├── libtraceevent-kbuffer-read.txt ├── libtraceevent-kbuffer-timestamp.txt ├── libtraceevent-kvm-plugin.txt ├── libtraceevent-log.txt ├── libtraceevent-long_size.txt ├── libtraceevent-page_size.txt ├── libtraceevent-parse-files.txt ├── libtraceevent-parse_event.txt ├── libtraceevent-parse_head.txt ├── libtraceevent-plugins.txt ├── libtraceevent-record_parse.txt ├── libtraceevent-reg_event_handler.txt ├── libtraceevent-reg_print_func.txt ├── libtraceevent-set_flag.txt ├── libtraceevent-strerror.txt ├── libtraceevent-tseq.txt ├── libtraceevent.txt ├── manpage-1.72.xsl ├── manpage-base.xsl ├── manpage-bold-literal.xsl ├── manpage-normal.xsl ├── manpage-suppress-sp.xsl └── meson.build ├── LICENSES ├── GPL-2.0 └── LGPL-2.1 ├── Makefile ├── Makefile.meson ├── README ├── check-manpages.sh ├── include ├── asm │ └── bug.h ├── linux │ ├── compiler-gcc.h │ ├── compiler.h │ └── time64.h └── traceevent │ ├── event-parse.h │ ├── event-utils.h │ ├── kbuffer.h │ ├── meson.build │ └── trace-seq.h ├── libtraceevent.pc.template ├── meson.build ├── meson_options.txt ├── plugins ├── Build ├── Makefile ├── dynamic_list.sh ├── meson.build ├── plugin_cfg80211.c ├── plugin_function.c ├── plugin_futex.c ├── plugin_hrtimer.c ├── plugin_jbd2.c ├── plugin_kmem.c ├── plugin_kvm.c ├── plugin_mac80211.c ├── plugin_net.c ├── plugin_sched_switch.c ├── plugin_scsi.c ├── plugin_tlb.c └── plugin_xen.c ├── samples ├── Makefile ├── meson.build └── test-event.c ├── scripts ├── features.mk ├── utilities.mak └── utils.mk ├── src ├── Build ├── Makefile ├── event-parse-api.c ├── event-parse-local.h ├── event-parse.c ├── event-plugin.c ├── kbuffer-parse.c ├── meson.build ├── parse-filter.c ├── parse-utils.c ├── tep_strerror.c └── trace-seq.c ├── test.c └── utest ├── .gitignore ├── Makefile ├── README ├── meson.build ├── trace-utest.c ├── trace-utest.h └── traceevent-utest.c /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0-only 2 | TRACEEVENT-CFLAGS 3 | libtraceevent-dynamic-list 4 | libtraceevent.so.* 5 | .pc 6 | patches 7 | *.o 8 | build_prefix 9 | build_uninstall 10 | *~ 11 | \#*\# 12 | .#* 13 | *.cmd 14 | *.so 15 | .*.d 16 | ep_version.h 17 | libtraceevent.pc 18 | lib/ 19 | -------------------------------------------------------------------------------- /Documentation/.gitignore: -------------------------------------------------------------------------------- 1 | *.m 2 | *.3 3 | *.html 4 | -------------------------------------------------------------------------------- /Documentation/asciidoc.conf: -------------------------------------------------------------------------------- 1 | ## linktep: macro 2 | # 3 | # Usage: linktep:command[manpage-section] 4 | # 5 | # Note, {0} is the manpage section, while {target} is the command. 6 | # 7 | # Show TEP link as: (
); if section is defined, else just show 8 | # the command. 9 | 10 | [macros] 11 | (?su)[\\]?(?Plinktep):(?P\S*?)\[(?P.*?)\]= 12 | 13 | [attributes] 14 | asterisk=* 15 | plus=+ 16 | caret=^ 17 | startsb=[ 18 | endsb=] 19 | tilde=~ 20 | 21 | ifdef::backend-docbook[] 22 | [linktep-inlinemacro] 23 | {0%{target}} 24 | {0#} 25 | {0#{target}{0}} 26 | {0#} 27 | endif::backend-docbook[] 28 | 29 | ifdef::backend-docbook[] 30 | ifndef::tep-asciidoc-no-roff[] 31 | # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. 32 | # v1.72 breaks with this because it replaces dots not in roff requests. 33 | [listingblock] 34 | {title} 35 | 36 | ifdef::doctype-manpage[] 37 | .ft C 38 | endif::doctype-manpage[] 39 | | 40 | ifdef::doctype-manpage[] 41 | .ft 42 | endif::doctype-manpage[] 43 | 44 | {title#} 45 | endif::tep-asciidoc-no-roff[] 46 | 47 | ifdef::tep-asciidoc-no-roff[] 48 | ifdef::doctype-manpage[] 49 | # The following two small workarounds insert a simple paragraph after screen 50 | [listingblock] 51 | {title} 52 | 53 | | 54 | 55 | {title#} 56 | 57 | [verseblock] 58 | {title} 59 | {title%} 60 | {title#} 61 | | 62 | 63 | {title#} 64 | {title%} 65 | endif::doctype-manpage[] 66 | endif::tep-asciidoc-no-roff[] 67 | endif::backend-docbook[] 68 | 69 | ifdef::doctype-manpage[] 70 | ifdef::backend-docbook[] 71 | [header] 72 | template::[header-declarations] 73 | 74 | 75 | {mantitle} 76 | {manvolnum} 77 | libtraceevent 78 | {libtraceevent_version} 79 | libtraceevent Manual 80 | 81 | 82 | {manname1} 83 | {manname2} 84 | {manname3} 85 | {manname4} 86 | {manname5} 87 | {manname6} 88 | {manname7} 89 | {manname8} 90 | {manname9} 91 | {manname10} 92 | {manname11} 93 | {manname12} 94 | {manname13} 95 | {manname14} 96 | {manname15} 97 | {manname16} 98 | {manname17} 99 | {manname18} 100 | {manname19} 101 | {manname20} 102 | {manname21} 103 | {manname22} 104 | {manname23} 105 | {manname24} 106 | {manname25} 107 | {manname26} 108 | {manname27} 109 | {manname28} 110 | {manname29} 111 | {manname30} 112 | {manpurpose} 113 | 114 | endif::backend-docbook[] 115 | endif::doctype-manpage[] 116 | 117 | ifdef::backend-xhtml11[] 118 | [linktep-inlinemacro] 119 | {target}{0?({0})} 120 | endif::backend-xhtml11[] 121 | -------------------------------------------------------------------------------- /Documentation/install-docs.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: LGPL-2.1 3 | # 4 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 5 | 6 | for section in 1 3 5; do 7 | while IFS= read -r -d '' man; do 8 | [ ! -d "${DESTDIR}@MANDIR@/man${section}" ] && install -d "${DESTDIR}@MANDIR@/man${section}" 9 | 10 | echo Installing "${man}" to "${DESTDIR}@MANDIR@/man${section}" 11 | install -m 0644 "${man}" "${DESTDIR}@MANDIR@/man${section}/" 12 | done< <(find "@SRCDIR@" -name "*\.${section}" -type f -print0) 13 | done 14 | 15 | while IFS= read -r -d '' html; do 16 | [ ! -d "${DESTDIR}@HTMLDIR@" ] && install -d "${DESTDIR}@HTMLDIR@" 17 | 18 | echo Installing "${html}" to "${DESTDIR}@HTMLDIR@" 19 | install -m 0644 "${html}" "${DESTDIR}@HTMLDIR@" 20 | done< <(find "@SRCDIR@" -name "*\.html" -type f -print0) 21 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-commands.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_register_comm, tep_override_comm, tep_is_pid_registered, 7 | tep_data_comm_from_pid, tep_data_pid_from_comm, tep_cmdline_pid - 8 | Manage pid to process name mappings. 9 | 10 | SYNOPSIS 11 | -------- 12 | [verse] 13 | -- 14 | *#include * 15 | 16 | int *tep_register_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); 17 | int *tep_override_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); 18 | bool *tep_is_pid_registered*(struct tep_handle pass:[*]_tep_, int _pid_); 19 | const char pass:[*]*tep_data_comm_from_pid*(struct tep_handle pass:[*]_pevent_, int _pid_); 20 | struct cmdline pass:[*]*tep_data_pid_from_comm*(struct tep_handle pass:[*]_pevent_, const char pass:[*]_comm_, struct cmdline pass:[*]_next_); 21 | int *tep_cmdline_pid*(struct tep_handle pass:[*]_pevent_, struct cmdline pass:[*]_cmdline_); 22 | -- 23 | 24 | DESCRIPTION 25 | ----------- 26 | These functions can be used to handle the mapping between pid and process name. 27 | The library builds a cache of these mappings, which is used to display the name 28 | of the process, instead of its pid. This information can be retrieved from 29 | tracefs/saved_cmdlines file. 30 | 31 | The *tep_register_comm()* function registers a _pid_ / process name mapping. 32 | If a command with the same _pid_ is already registered, an error is returned. 33 | The _pid_ argument is the process ID, the _comm_ argument is the process name, 34 | _tep_ is the event context. The _comm_ is duplicated internally. 35 | 36 | The *tep_override_comm()* function registers a _pid_ / process name mapping. 37 | If a process with the same pid is already registered, the process name string is 38 | udapted with the new one. The _pid_ argument is the process ID, the _comm_ 39 | argument is the process name, _tep_ is the event context. The _comm_ is 40 | duplicated internally. 41 | 42 | The *tep_is_pid_registered()* function checks if a pid has a process name 43 | mapping registered. The _pid_ argument is the process ID, _tep_ is the event 44 | context. 45 | 46 | The *tep_data_comm_from_pid()* function returns the process name for a given 47 | pid. The _pid_ argument is the process ID, _tep_ is the event context. 48 | The returned string should not be freed, but will be freed when the _tep_ 49 | handler is closed. 50 | 51 | The *tep_data_pid_from_comm()* function returns a pid for a given process name. 52 | The _comm_ argument is the process name, _tep_ is the event context. 53 | The argument _next_ is the cmdline structure to search for the next pid. 54 | As there may be more than one pid for a given process, the result of this call 55 | can be passed back into a recurring call in the _next_ parameter, to search for 56 | the next pid. If _next_ is NULL, it will return the first pid associated with 57 | the _comm_. The function performs a linear search, so it may be slow. 58 | 59 | The *tep_cmdline_pid()* function returns the pid associated with a given 60 | _cmdline_. The _tep_ argument is the event context. 61 | 62 | RETURN VALUE 63 | ------------ 64 | *tep_register_comm()* function returns 0 on success. In case of an error -1 is 65 | returned and errno is set to indicate the cause of the problem: ENOMEM, if there 66 | is not enough memory to duplicate the _comm_ or EEXIST if a mapping for this 67 | _pid_ is already registered. 68 | 69 | *tep_override_comm()* function returns 0 on success. In case of an error -1 is 70 | returned and errno is set to indicate the cause of the problem: ENOMEM, if there 71 | is not enough memory to duplicate the _comm_. 72 | 73 | *tep_is_pid_registered()* function returns true if the _pid_ has a process name 74 | mapped to it, false otherwise. 75 | 76 | *tep_data_comm_from_pid()* function returns the process name as string, or the 77 | string "<...>" if there is no mapping for the given pid. 78 | 79 | *tep_data_pid_from_comm()* function returns a pointer to a struct cmdline, that 80 | holds a pid for a given process, or NULL if none is found. This result can be 81 | passed back into a recurring call as the _next_ parameter of the function. 82 | 83 | *tep_cmdline_pid()* functions returns the pid for the give cmdline. If _cmdline_ 84 | is NULL, then -1 is returned. 85 | 86 | EXAMPLE 87 | ------- 88 | The following example registers pid for command "ls", in context of event _tep_ 89 | and performs various searches for pid / process name mappings: 90 | [source,c] 91 | -- 92 | #include 93 | ... 94 | int ret; 95 | int ls_pid = 1021; 96 | struct tep_handle *tep = tep_alloc(); 97 | ... 98 | ret = tep_register_comm(tep, "ls", ls_pid); 99 | if (ret != 0 && errno == EEXIST) 100 | ret = tep_override_comm(tep, "ls", ls_pid); 101 | if (ret != 0) { 102 | /* Failed to register pid / command mapping */ 103 | } 104 | ... 105 | if (tep_is_pid_registered(tep, ls_pid) == 0) { 106 | /* Command mapping for ls_pid is not registered */ 107 | } 108 | ... 109 | const char *comm = tep_data_comm_from_pid(tep, ls_pid); 110 | if (comm) { 111 | /* Found process name for ls_pid */ 112 | } 113 | ... 114 | int pid; 115 | struct cmdline *cmd = tep_data_pid_from_comm(tep, "ls", NULL); 116 | while (cmd) { 117 | pid = tep_cmdline_pid(tep, cmd); 118 | /* Found pid for process "ls" */ 119 | cmd = tep_data_pid_from_comm(tep, "ls", cmd); 120 | } 121 | -- 122 | FILES 123 | ----- 124 | [verse] 125 | -- 126 | *event-parse.h* 127 | Header file to include in order to have access to the library APIs. 128 | *-ltraceevent* 129 | Linker switch to add when building a program that uses the library. 130 | -- 131 | 132 | SEE ALSO 133 | -------- 134 | *libtraceevent*(3), *trace-cmd*(1) 135 | 136 | AUTHOR 137 | ------ 138 | [verse] 139 | -- 140 | *Steven Rostedt* , author of *libtraceevent*. 141 | *Tzvetomir Stoyanov* , author of this man page. 142 | -- 143 | REPORTING BUGS 144 | -------------- 145 | Report bugs to 146 | 147 | LICENSE 148 | ------- 149 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 150 | 151 | RESOURCES 152 | --------- 153 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 154 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-cpus.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_get_cpus, tep_set_cpus - Get / set the number of CPUs, which have a tracing 7 | buffer representing it. Note, the buffer may be empty. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | int *tep_get_cpus*(struct tep_handle pass:[*]_tep_); 16 | void *tep_set_cpus*(struct tep_handle pass:[*]_tep_, int _cpus_); 17 | -- 18 | 19 | DESCRIPTION 20 | ----------- 21 | The *tep_get_cpus()* function gets the number of CPUs, which have a tracing 22 | buffer representing it. The _tep_ argument is trace event parser context. 23 | 24 | The *tep_set_cpus()* function sets the number of CPUs, which have a tracing 25 | buffer representing it. The _tep_ argument is trace event parser context. 26 | The _cpu_ argument is the number of CPUs with tracing data. 27 | 28 | RETURN VALUE 29 | ------------ 30 | The *tep_get_cpus()* functions returns the number of CPUs, which have tracing 31 | data recorded. 32 | 33 | EXAMPLE 34 | ------- 35 | [source,c] 36 | -- 37 | #include 38 | ... 39 | struct tep_handle *tep = tep_alloc(); 40 | ... 41 | tep_set_cpus(tep, 5); 42 | ... 43 | printf("We have tracing data for %d CPUs", tep_get_cpus(tep)); 44 | -- 45 | 46 | FILES 47 | ----- 48 | [verse] 49 | -- 50 | *event-parse.h* 51 | Header file to include in order to have access to the library APIs. 52 | *-ltraceevent* 53 | Linker switch to add when building a program that uses the library. 54 | -- 55 | 56 | SEE ALSO 57 | -------- 58 | *libtraceevent*(3), *trace-cmd*(1) 59 | 60 | AUTHOR 61 | ------ 62 | [verse] 63 | -- 64 | *Steven Rostedt* , author of *libtraceevent*. 65 | *Tzvetomir Stoyanov* , author of this man page. 66 | -- 67 | REPORTING BUGS 68 | -------------- 69 | Report bugs to 70 | 71 | LICENSE 72 | ------- 73 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 74 | 75 | RESOURCES 76 | --------- 77 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 78 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-debug.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_print_printk, tep_print_funcs, tep_set_test_filters, tep_plugin_print_options - 7 | Print libtraceevent internal information. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | *#include * 15 | 16 | void *tep_print_printk*(struct tep_handle pass:[*]tep); 17 | void *tep_print_funcs*(struct tep_handle pass:[*]tep); 18 | void *tep_set_test_filters*(struct tep_handle pass:[*]tep, int test_filters); 19 | void *tep_plugin_print_options*(struct trace_seq pass:[*]s); 20 | -- 21 | 22 | DESCRIPTION 23 | ----------- 24 | The *tep_print_printk()* function prints the printk string formats that were 25 | stored for this tracing session. The _tep_ argument is trace event parser context. 26 | 27 | The *tep_print_funcs()* function prints the stored function name to address mapping 28 | for this tracing session. The _tep_ argument is trace event parser context. 29 | 30 | The *tep_set_test_filters()* function sets a flag to test a filter string. If this 31 | flag is set, when *tep_filter_add_filter_str()* API as called, it will print the filter 32 | string instead of adding it. The _tep_ argument is trace event parser context. 33 | The _test_filters_ argument is the test flag that will be set. 34 | 35 | The *tep_plugin_print_options()* function writes a list of the registered plugin options 36 | into _s_. 37 | 38 | EXAMPLE 39 | ------- 40 | [source,c] 41 | -- 42 | #include 43 | #include 44 | ... 45 | struct tep_handle *tep = tep_alloc(); 46 | ... 47 | tep_print_printk(tep); 48 | ... 49 | tep_print_funcs(tep); 50 | ... 51 | struct tep_event_filter *filter = tep_filter_alloc(tep); 52 | tep_set_test_filters(tep, 1); 53 | tep_filter_add_filter_str(filter, "sched/sched_wakeup:target_cpu==1"); 54 | tep_set_test_filters(tep, 0); 55 | tep_filter_free(filter); 56 | ... 57 | struct trace_seq seq; 58 | trace_seq_init(&seq); 59 | 60 | tep_plugin_print_options(&s); 61 | ... 62 | -- 63 | 64 | FILES 65 | ----- 66 | [verse] 67 | -- 68 | *event-parse.h* 69 | Header file to include in order to have access to the library APIs. 70 | *-ltraceevent* 71 | Linker switch to add when building a program that uses the library. 72 | -- 73 | 74 | SEE ALSO 75 | -------- 76 | *libtraceevent*(3), *trace-cmd*(1) 77 | 78 | AUTHOR 79 | ------ 80 | [verse] 81 | -- 82 | *Steven Rostedt* , author of *libtraceevent*. 83 | *Tzvetomir Stoyanov* , author of this man page. 84 | -- 85 | REPORTING BUGS 86 | -------------- 87 | Report bugs to 88 | 89 | LICENSE 90 | ------- 91 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 92 | 93 | RESOURCES 94 | --------- 95 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 96 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-endian_read.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_read_number - Reads a number from raw data. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | unsigned long long *tep_read_number*(struct tep_handle pass:[*]_tep_, const void pass:[*]_ptr_, int _size_); 15 | -- 16 | 17 | DESCRIPTION 18 | ----------- 19 | The *tep_read_number()* function reads an integer from raw data, taking into 20 | account the endianness of the raw data and the current host. The _tep_ argument 21 | is the trace event parser context. The _ptr_ is a pointer to the raw data, where 22 | the integer is, and the _size_ is the size of the integer. 23 | 24 | RETURN VALUE 25 | ------------ 26 | The *tep_read_number()* function returns the integer in the byte order of 27 | the current host. In case of an error, 0 is returned. 28 | 29 | EXAMPLE 30 | ------- 31 | [source,c] 32 | -- 33 | #include 34 | ... 35 | struct tep_handle *tep = tep_alloc(); 36 | ... 37 | void process_record(struct tep_record *record) 38 | { 39 | int offset = 24; 40 | int data = tep_read_number(tep, record->data + offset, 4); 41 | 42 | /* Read the 4 bytes at the offset 24 of data as an integer */ 43 | } 44 | ... 45 | -- 46 | 47 | FILES 48 | ----- 49 | [verse] 50 | -- 51 | *event-parse.h* 52 | Header file to include in order to have access to the library APIs. 53 | *-ltraceevent* 54 | Linker switch to add when building a program that uses the library. 55 | -- 56 | 57 | SEE ALSO 58 | -------- 59 | *libtraceevent*(3), *trace-cmd*(1) 60 | 61 | AUTHOR 62 | ------ 63 | [verse] 64 | -- 65 | *Steven Rostedt* , author of *libtraceevent*. 66 | *Tzvetomir Stoyanov* , author of this man page. 67 | -- 68 | REPORTING BUGS 69 | -------------- 70 | Report bugs to 71 | 72 | LICENSE 73 | ------- 74 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 75 | 76 | RESOURCES 77 | --------- 78 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 79 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-event_find.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_find_event,tep_find_event_by_name,tep_find_event_by_record, tep_record_is_event - 7 | Find events by given key. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); 16 | struct tep_event pass:[*]*tep_find_event_by_name*(struct tep_handle pass:[*]_tep_, const char pass:[*]_sys_, const char pass:[*]_name_); 17 | struct tep_event pass:[*]*tep_find_event_by_record*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_record_); 18 | bool *tep_record_is_event*(struct tep_record pass:[*]record, struct tep_event pass:[*]event); 19 | -- 20 | 21 | DESCRIPTION 22 | ----------- 23 | This set of functions can be used to search for an event, based on a given 24 | criteria. All functions require a pointer to a _tep_, trace event parser 25 | context. 26 | 27 | The *tep_find_event()* function searches for an event by given event _id_. The 28 | event ID is assigned dynamically and can be viewed in event's format file, 29 | "ID" field. 30 | 31 | The *tep_find_event_by_name()* function searches for an event by given 32 | event _name_, under the system _sys_. If the _sys_ is NULL (not specified), 33 | the first event with _name_ is returned. 34 | 35 | The *tep_find_event_by_record()* function searches for an event from a given 36 | _record_. 37 | 38 | The *tep_record_is_event()* function tests if the given _record_ is of the type 39 | of the _event_. This is normally used to know if the _record_ being processed is 40 | of an _event_ where further processing should be done. 41 | 42 | RETURN VALUE 43 | ------------ 44 | All these functions except *tep_record_is_event()* return a pointer to the found event, or NULL if there is no 45 | such event. 46 | 47 | EXAMPLE 48 | ------- 49 | [source,c] 50 | -- 51 | #include 52 | ... 53 | struct tep_handle *tep = tep_alloc(); 54 | ... 55 | struct tep_event *event; 56 | 57 | event = tep_find_event(tep, 1857); 58 | if (event == NULL) { 59 | /* There is no event with ID 1857 */ 60 | } 61 | 62 | event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); 63 | if (event == NULL) { 64 | /* There is no kvm_exit event, from kvm system */ 65 | } 66 | 67 | void event_from_record(struct tep_record *record) 68 | { 69 | struct tep_event *event = tep_find_event_by_record(tep, record); 70 | if (event == NULL) { 71 | /* There is no event from given record */ 72 | } 73 | } 74 | ... 75 | -- 76 | 77 | FILES 78 | ----- 79 | [verse] 80 | -- 81 | *event-parse.h* 82 | Header file to include in order to have access to the library APIs. 83 | *-ltraceevent* 84 | Linker switch to add when building a program that uses the library. 85 | -- 86 | 87 | SEE ALSO 88 | -------- 89 | *libtraceevent*(3), *trace-cmd*(1) 90 | 91 | AUTHOR 92 | ------ 93 | [verse] 94 | -- 95 | *Steven Rostedt* , author of *libtraceevent*. 96 | *Tzvetomir Stoyanov* , author of this man page. 97 | -- 98 | REPORTING BUGS 99 | -------------- 100 | Report bugs to 101 | 102 | LICENSE 103 | ------- 104 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 105 | 106 | RESOURCES 107 | --------- 108 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 109 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-event_get.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_get_event, tep_get_first_event, tep_get_events_count - Access events. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | struct tep_event pass:[*]*tep_get_event*(struct tep_handle pass:[*]_tep_, int _index_); 15 | struct tep_event pass:[*]*tep_get_first_event*(struct tep_handle pass:[*]_tep_); 16 | int *tep_get_events_count*(struct tep_handle pass:[*]_tep_); 17 | -- 18 | 19 | DESCRIPTION 20 | ----------- 21 | The *tep_get_event()* function returns a pointer to event at the given _index_. 22 | The _tep_ argument is trace event parser context, the _index_ is the index of 23 | the requested event. 24 | 25 | The *tep_get_first_event()* function returns a pointer to the first event. 26 | As events are stored in an array, this function returns the pointer to the 27 | beginning of the array. The _tep_ argument is trace event parser context. 28 | 29 | The *tep_get_events_count()* function returns the number of the events 30 | in the array. The _tep_ argument is trace event parser context. 31 | 32 | RETURN VALUE 33 | ------------ 34 | The *tep_get_event()* returns a pointer to the event located at _index_. 35 | NULL is returned in case of error, in case there are no events or _index_ is 36 | out of range. 37 | 38 | The *tep_get_first_event()* returns a pointer to the first event. NULL is 39 | returned in case of error, or in case there are no events. 40 | 41 | The *tep_get_events_count()* returns the number of the events. 0 is 42 | returned in case of error, or in case there are no events. 43 | 44 | EXAMPLE 45 | ------- 46 | [source,c] 47 | -- 48 | #include 49 | ... 50 | struct tep_handle *tep = tep_alloc(); 51 | ... 52 | int i,count = tep_get_events_count(tep); 53 | struct tep_event *event, *events = tep_get_first_event(tep); 54 | 55 | if (events == NULL) { 56 | /* There are no events */ 57 | } else { 58 | for (i = 0; i < count; i++) { 59 | event = (events+i); 60 | /* process events[i] */ 61 | } 62 | 63 | /* Get the last event */ 64 | event = tep_get_event(tep, count-1); 65 | } 66 | -- 67 | 68 | FILES 69 | ----- 70 | [verse] 71 | -- 72 | *event-parse.h* 73 | Header file to include in order to have access to the library APIs. 74 | *-ltraceevent* 75 | Linker switch to add when building a program that uses the library. 76 | -- 77 | 78 | SEE ALSO 79 | -------- 80 | *libtraceevent*(3), *trace-cmd*(1) 81 | 82 | AUTHOR 83 | ------ 84 | [verse] 85 | -- 86 | *Steven Rostedt* , author of *libtraceevent*. 87 | *Tzvetomir Stoyanov* , author of this man page. 88 | -- 89 | REPORTING BUGS 90 | -------------- 91 | Report bugs to 92 | 93 | LICENSE 94 | ------- 95 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 96 | 97 | RESOURCES 98 | --------- 99 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 100 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-event_list.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_list_events, tep_list_events_copy - 7 | Get list of events, sorted by given criteria. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *tep_event_sort_type* { 16 | _TEP_EVENT_SORT_ID_, 17 | _TEP_EVENT_SORT_NAME_, 18 | _TEP_EVENT_SORT_SYSTEM_, 19 | }; 20 | 21 | struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); 22 | struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); 23 | -- 24 | 25 | DESCRIPTION 26 | ----------- 27 | The *tep_list_events()* function returns an array of pointers to the events, 28 | sorted by the _sort_type_ criteria. The last element of the array is NULL. 29 | The returned memory must not be freed, it is managed by the library. 30 | The function is not thread safe. The _tep_ argument is trace event parser 31 | context. The _sort_type_ argument is the required sort criteria: 32 | [verse] 33 | -- 34 | _TEP_EVENT_SORT_ID_ - sort by the event ID. 35 | _TEP_EVENT_SORT_NAME_ - sort by the event (name, system, id) triplet. 36 | _TEP_EVENT_SORT_SYSTEM_ - sort by the event (system, name, id) triplet. 37 | -- 38 | 39 | The *tep_list_events_copy()* is a thread safe version of _tep_list_events()_. 40 | It has the same behavior, but the returned array is allocated internally and 41 | must be freed by the caller. Note that the content of the array must not be 42 | freed (see the EXAMPLE below). 43 | 44 | RETURN VALUE 45 | ------------ 46 | The *tep_list_events()* function returns an array of pointers to events. 47 | In case of an error, NULL is returned. The returned array must not be freed, 48 | it is managed by the library. 49 | 50 | The *tep_list_events_copy()* function returns an array of pointers to events. 51 | In case of an error, NULL is returned. The returned array must be freed by 52 | the caller. 53 | 54 | EXAMPLE 55 | ------- 56 | [source,c] 57 | -- 58 | #include 59 | ... 60 | struct tep_handle *tep = tep_alloc(); 61 | ... 62 | int i; 63 | struct tep_event_format **events; 64 | 65 | i=0; 66 | events = tep_list_events(tep, TEP_EVENT_SORT_ID); 67 | if (events == NULL) { 68 | /* Failed to get the events, sorted by ID */ 69 | } else { 70 | while(events[i]) { 71 | /* walk through the list of the events, sorted by ID */ 72 | i++; 73 | } 74 | } 75 | 76 | i=0; 77 | events = tep_list_events_copy(tep, TEP_EVENT_SORT_NAME); 78 | if (events == NULL) { 79 | /* Failed to get the events, sorted by name */ 80 | } else { 81 | while(events[i]) { 82 | /* walk through the list of the events, sorted by name */ 83 | i++; 84 | } 85 | free(events); 86 | } 87 | 88 | ... 89 | -- 90 | 91 | FILES 92 | ----- 93 | [verse] 94 | -- 95 | *event-parse.h* 96 | Header file to include in order to have access to the library APIs. 97 | *-ltraceevent* 98 | Linker switch to add when building a program that uses the library. 99 | -- 100 | 101 | SEE ALSO 102 | -------- 103 | *libtraceevent*(3), *trace-cmd*(1) 104 | 105 | AUTHOR 106 | ------ 107 | [verse] 108 | -- 109 | *Steven Rostedt* , author of *libtraceevent*. 110 | *Tzvetomir Stoyanov* , author of this man page. 111 | -- 112 | REPORTING BUGS 113 | -------------- 114 | Report bugs to 115 | 116 | LICENSE 117 | ------- 118 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 119 | 120 | RESOURCES 121 | --------- 122 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 123 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-event_print.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_print_event - Writes event information into a trace sequence. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | *#include * 14 | 15 | void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seqpass:[*]_s_, struct tep_record pass:[*]_record_, const char pass:[*]_fmt_, _..._) 16 | -- 17 | 18 | DESCRIPTION 19 | ----------- 20 | 21 | The *tep_print_event()* function parses the event information of the given 22 | _record_ and writes it into the trace sequence _s_, according to the format 23 | string _fmt_. The desired information is specified after the format string. 24 | The _fmt_ is printf-like format string, following arguments are supported: 25 | [verse] 26 | -- 27 | TEP_PRINT_PID, "%d" - PID of the event. 28 | TEP_PRINT_CPU, "%d" - Event CPU. 29 | TEP_PRINT_COMM, "%s" - Event command string. 30 | TEP_PRINT_NAME, "%s" - Event name. 31 | TEP_PRINT_LATENCY, "%s" - Latency of the event. It prints 4 or more 32 | fields - interrupt state, scheduling state, 33 | current context, and preemption count. 34 | Field 1 is the interrupt enabled state: 35 | d : Interrupts are disabled 36 | . : Interrupts are enabled 37 | X : The architecture does not support this 38 | information 39 | Field 2 is the "need resched" state. 40 | N : The task is set to call the scheduler when 41 | possible, as another higher priority task 42 | may need to be scheduled in. 43 | . : The task is not set to call the scheduler. 44 | Field 3 is the context state. 45 | . : Normal context 46 | s : Soft interrupt context 47 | h : Hard interrupt context 48 | H : Hard interrupt context which triggered 49 | during soft interrupt context. 50 | z : NMI context 51 | Z : NMI context which triggered during hard 52 | interrupt context 53 | Field 4 is the preemption count. 54 | . : The preempt count is zero. 55 | On preemptible kernels (where the task can be scheduled 56 | out in arbitrary locations while in kernel context), the 57 | preempt count, when non zero, will prevent the kernel 58 | from scheduling out the current task. The preempt count 59 | number is displayed when it is not zero. 60 | Depending on the kernel, it may show other fields 61 | (lock depth, or migration disabled, which are unique to 62 | specialized kernels). 63 | TEP_PRINT_TIME, %d - event time stamp. A divisor and precision can be 64 | specified as part of this format string: 65 | "%precision.divisord". Example: 66 | "%3.1000d" - divide the time by 1000 and print the first 67 | 3 digits before the dot. Thus, the time stamp 68 | "123456000" will be printed as "123.456" 69 | TEP_PRINT_INFO, "%s" - event information. 70 | TEP_PRINT_INFO_RAW, "%s" - event information, in raw format. 71 | 72 | -- 73 | EXAMPLE 74 | ------- 75 | [source,c] 76 | -- 77 | #include 78 | #include 79 | ... 80 | struct trace_seq seq; 81 | trace_seq_init(&seq); 82 | struct tep_handle *tep = tep_alloc(); 83 | ... 84 | void print_my_event(struct tep_record *record) 85 | { 86 | trace_seq_reset(&seq); 87 | tep_print_event(tep, s, record, "%16s-%-5d [%03d] %s %6.1000d %s %s", 88 | TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU, 89 | TEP_PRINT_LATENCY, TEP_PRINT_TIME, TEP_PRINT_NAME, 90 | TEP_PRINT_INFO); 91 | } 92 | ... 93 | -- 94 | 95 | FILES 96 | ----- 97 | [verse] 98 | -- 99 | *event-parse.h* 100 | Header file to include in order to have access to the library APIs. 101 | *trace-seq.h* 102 | Header file to include in order to have access to trace sequences related APIs. 103 | Trace sequences are used to allow a function to call several other functions 104 | to create a string of data to use. 105 | *-ltraceevent* 106 | Linker switch to add when building a program that uses the library. 107 | -- 108 | 109 | SEE ALSO 110 | -------- 111 | *libtraceevent*(3), *trace-cmd*(1) 112 | 113 | AUTHOR 114 | ------ 115 | [verse] 116 | -- 117 | *Steven Rostedt* , author of *libtraceevent*. 118 | *Tzvetomir Stoyanov* , author of this man page. 119 | -- 120 | REPORTING BUGS 121 | -------------- 122 | Report bugs to 123 | 124 | LICENSE 125 | ------- 126 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 127 | 128 | RESOURCES 129 | --------- 130 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 131 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-field_find.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_find_common_field, tep_find_field, tep_find_any_field - 7 | Search for a field in an event. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | struct tep_format_field pass:[*]*tep_find_common_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); 16 | struct tep_format_field pass:[*]*tep_find_field*(struct tep_event_ormat pass:[*]_event_, const char pass:[*]_name_); 17 | struct tep_format_field pass:[*]*tep_find_any_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); 18 | -- 19 | 20 | DESCRIPTION 21 | ----------- 22 | These functions search for a field with given name in an event. The field 23 | returned can be used to find the field content from within a data record. 24 | 25 | The *tep_find_common_field()* function searches for a common field with _name_ 26 | in the _event_. 27 | 28 | The *tep_find_field()* function searches for an event specific field with 29 | _name_ in the _event_. 30 | 31 | The *tep_find_any_field()* function searches for any field with _name_ in the 32 | _event_. 33 | 34 | RETURN VALUE 35 | ------------ 36 | The _tep_find_common_field(), *tep_find_field()* and _tep_find_any_field()_ 37 | functions return a pointer to the found field, or NULL in case there is no field 38 | with the requested name. 39 | 40 | EXAMPLE 41 | ------- 42 | [source,c] 43 | -- 44 | #include 45 | ... 46 | void get_htimer_info(struct tep_handle *tep, struct tep_record *record) 47 | { 48 | struct tep_format_field *field; 49 | struct tep_event *event; 50 | long long softexpires; 51 | int mode; 52 | int pid; 53 | 54 | event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); 55 | 56 | field = tep_find_common_field(event, "common_pid"); 57 | if (field == NULL) { 58 | /* Cannot find "common_pid" field in the event */ 59 | } else { 60 | /* Get pid from the data record */ 61 | pid = tep_read_number(tep, record->data + field->offset, 62 | field->size); 63 | } 64 | 65 | field = tep_find_field(event, "softexpires"); 66 | if (field == NULL) { 67 | /* Cannot find "softexpires" event specific field in the event */ 68 | } else { 69 | /* Get softexpires parameter from the data record */ 70 | softexpires = tep_read_number(tep, record->data + field->offset, 71 | field->size); 72 | } 73 | 74 | field = tep_find_any_field(event, "mode"); 75 | if (field == NULL) { 76 | /* Cannot find "mode" field in the event */ 77 | } else 78 | { 79 | /* Get mode parameter from the data record */ 80 | mode = tep_read_number(tep, record->data + field->offset, 81 | field->size); 82 | } 83 | } 84 | ... 85 | -- 86 | 87 | FILES 88 | ----- 89 | [verse] 90 | -- 91 | *event-parse.h* 92 | Header file to include in order to have access to the library APIs. 93 | *-ltraceevent* 94 | Linker switch to add when building a program that uses the library. 95 | -- 96 | 97 | SEE ALSO 98 | -------- 99 | *libtraceevent*(3), *trace-cmd*(1) 100 | 101 | AUTHOR 102 | ------ 103 | [verse] 104 | -- 105 | *Steven Rostedt* , author of *libtraceevent*. 106 | *Tzvetomir Stoyanov* , author of this man page. 107 | -- 108 | REPORTING BUGS 109 | -------------- 110 | Report bugs to 111 | 112 | LICENSE 113 | ------- 114 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 115 | 116 | RESOURCES 117 | --------- 118 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 119 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-field_get_val.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_get_any_field_val, tep_get_common_field_val, tep_get_field_val, 7 | tep_get_field_raw - Get value of a field. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | *#include * 15 | 16 | int *tep_get_any_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 17 | int *tep_get_common_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 18 | int *tep_get_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 19 | void pass:[*]*tep_get_field_raw*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int pass:[*]_len_, int _err_); 20 | -- 21 | 22 | DESCRIPTION 23 | ----------- 24 | These functions can be used to find a field and retrieve its value. 25 | 26 | The *tep_get_any_field_val()* function searches in the _record_ for a field 27 | with _name_, part of the _event_. If the field is found, its value is stored in 28 | _val_. If there is an error and _err_ is not zero, then an error string is 29 | written into _s_. 30 | 31 | The *tep_get_common_field_val()* function does the same as 32 | *tep_get_any_field_val()*, but searches only in the common fields. This works 33 | for any event as all events include the common fields. 34 | 35 | The *tep_get_field_val()* function does the same as *tep_get_any_field_val()*, 36 | but searches only in the event specific fields. 37 | 38 | The *tep_get_field_raw()* function searches in the _record_ for a field with 39 | _name_, part of the _event_. If the field is found, a pointer to where the field 40 | exists in the record's raw data is returned. The size of the data is stored in 41 | _len_. If there is an error and _err_ is not zero, then an error string is 42 | written into _s_. 43 | 44 | RETURN VALUE 45 | ------------ 46 | The *tep_get_any_field_val()*, *tep_get_common_field_val()* and 47 | *tep_get_field_val()* functions return 0 on success, or -1 in case of an error. 48 | 49 | The *tep_get_field_raw()* function returns a pointer to field's raw data, and 50 | places the length of this data in _len_. In case of an error NULL is returned. 51 | 52 | EXAMPLE 53 | ------- 54 | [source,c] 55 | -- 56 | #include 57 | #include 58 | ... 59 | struct tep_handle *tep = tep_alloc(); 60 | ... 61 | struct tep_event *event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); 62 | ... 63 | void process_record(struct tep_record *record) 64 | { 65 | int len; 66 | char *comm; 67 | struct tep_event *event; 68 | unsigned long long val; 69 | 70 | event = tep_find_event_by_record(tep, record); 71 | if (event != NULL) { 72 | if (tep_get_common_field_val(NULL, event, "common_type", 73 | record, &val, 0) == 0) { 74 | /* Got the value of common type field */ 75 | } 76 | if (tep_get_field_val(NULL, event, "pid", record, &val, 0) == 0) { 77 | /* Got the value of pid specific field */ 78 | } 79 | comm = tep_get_field_raw(NULL, event, "comm", record, &len, 0); 80 | if (comm != NULL) { 81 | /* Got a pointer to the comm event specific field */ 82 | } 83 | } 84 | } 85 | -- 86 | 87 | FILES 88 | ----- 89 | [verse] 90 | -- 91 | *event-parse.h* 92 | Header file to include in order to have access to the library APIs. 93 | *trace-seq.h* 94 | Header file to include in order to have access to trace sequences 95 | related APIs. Trace sequences are used to allow a function to call 96 | several other functions to create a string of data to use. 97 | *-ltraceevent* 98 | Linker switch to add when building a program that uses the library. 99 | -- 100 | 101 | SEE ALSO 102 | -------- 103 | *libtraceevent*(3), *trace-cmd*(1) 104 | 105 | AUTHOR 106 | ------ 107 | [verse] 108 | -- 109 | *Steven Rostedt* , author of *libtraceevent*. 110 | *Tzvetomir Stoyanov* , author of this man page. 111 | -- 112 | REPORTING BUGS 113 | -------------- 114 | Report bugs to 115 | 116 | LICENSE 117 | ------- 118 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 119 | 120 | RESOURCES 121 | --------- 122 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 123 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-field_print.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_print_field_content, tep_print_fields, tep_print_num_field, tep_print_func_field, tep_record_print_fields, tep_record_print_selected_fields - 7 | Print the field content. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | *#include * 15 | 16 | void *tep_print_field_content*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, int size, struct tep_format_field pass:[*]_field_); 17 | void *tep_print_fields*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, int _size_, struct tep_event pass:[*]_event_); 18 | int *tep_print_num_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); 19 | int *tep_print_func_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); 20 | void *tep_record_print_fields*(struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, struct tep_event pass:[*]_event_); 21 | void *tep_record_print_selected_fields*(struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, struct tep_event pass:[*]_event_, int _select_mask_); 22 | -- 23 | 24 | DESCRIPTION 25 | ----------- 26 | These functions print recorded field's data, according to the field's type. 27 | 28 | The *tep_print_field_content()* function extracts from the recorded raw _data_ value of 29 | the _field_ and prints it into _s_, according to the field type. 30 | 31 | The *tep_print_fields()* prints each field name followed by the record's field 32 | value according to the field's type: 33 | [verse] 34 | -- 35 | "field1_name=field1_value field2_name=field2_value ..." 36 | -- 37 | It iterates all fields of the _event_, and calls *tep_print_field_content()* for each of 38 | them. 39 | 40 | The *tep_print_num_field()* function prints a numeric field with given format 41 | string. A search is performed in the _event_ for a field with _name_. If such 42 | field is found, its value is extracted from the _record_ and is printed in the 43 | _s_, according to the given format string _fmt_. If the argument _err_ is 44 | non-zero, and an error occures - it is printed in the _s_. 45 | 46 | The *tep_print_func_field()* function prints a function field with given format 47 | string. A search is performed in the _event_ for a field with _name_. If such 48 | field is found, its value is extracted from the _record_. The value is assumed 49 | to be a function address, and a search is perform to find the name of this 50 | function. The function name (if found) and its address are printed in the _s_, 51 | according to the given format string _fmt_. If the argument _err_ is non-zero, 52 | and an error occures - it is printed in _s_. 53 | 54 | The *tep_record_print_fields()* prints the field's name followed by its value 55 | for all record's field. 56 | 57 | The *tep_record_print_selected_fields()* prints the field's name followed by 58 | its value for selected subset of record field. The fields to be printed are 59 | defined by the _select_mask_ bit mask. 60 | 61 | RETURN VALUE 62 | ------------ 63 | The *tep_print_num_field()* and *tep_print_func_field()* functions return 1 64 | on success, -1 in case of an error or 0 if the print buffer _s_ is full. 65 | 66 | EXAMPLE 67 | ------- 68 | [source,c] 69 | -- 70 | #include 71 | #include 72 | ... 73 | struct tep_handle *tep = tep_alloc(); 74 | ... 75 | struct trace_seq seq; 76 | trace_seq_init(&seq); 77 | struct tep_event *event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); 78 | ... 79 | void process_record(struct tep_record *record) 80 | { 81 | struct tep_format_field *field_pid = tep_find_common_field(event, "common_pid"); 82 | 83 | trace_seq_reset(&seq); 84 | 85 | /* Print the value of "common_pid" */ 86 | tep_print_field_content(&seq, record->data, record->size, field_pid); 87 | 88 | /* Print all fields of the "hrtimer_start" event */ 89 | tep_print_fields(&seq, record->data, record->size, event); 90 | 91 | /* Print the value of "expires" field with custom format string */ 92 | tep_print_num_field(&seq, " timer expires in %llu ", event, "expires", record, 0); 93 | 94 | /* Print the address and the name of "function" field with custom format string */ 95 | tep_print_func_field(&seq, " timer function is %s ", event, "function", record, 0); 96 | } 97 | ... 98 | -- 99 | 100 | FILES 101 | ----- 102 | [verse] 103 | -- 104 | *event-parse.h* 105 | Header file to include in order to have access to the library APIs. 106 | *trace-seq.h* 107 | Header file to include in order to have access to trace sequences related APIs. 108 | Trace sequences are used to allow a function to call several other functions 109 | to create a string of data to use. 110 | *-ltraceevent* 111 | Linker switch to add when building a program that uses the library. 112 | -- 113 | 114 | SEE ALSO 115 | -------- 116 | *libtraceevent*(3), *trace-cmd*(1) 117 | 118 | AUTHOR 119 | ------ 120 | [verse] 121 | -- 122 | *Steven Rostedt* , author of *libtraceevent*. 123 | *Tzvetomir Stoyanov* , author of this man page. 124 | -- 125 | REPORTING BUGS 126 | -------------- 127 | Report bugs to 128 | 129 | LICENSE 130 | ------- 131 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 132 | 133 | RESOURCES 134 | --------- 135 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 136 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-field_read.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_read_number_field - Reads a number from raw data. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | int *tep_read_number_field*(struct tep_format_field pass:[*]_field_, const void pass:[*]_data_, unsigned long long pass:[*]_value_); 15 | -- 16 | 17 | DESCRIPTION 18 | ----------- 19 | The *tep_read_number_field()* function reads the value of the _field_ from the 20 | raw _data_ and stores it in the _value_. The function sets the _value_ according 21 | to the endianness of the raw data and the current machine and stores it in 22 | _value_. 23 | 24 | RETURN VALUE 25 | ------------ 26 | The *tep_read_number_field()* function retunrs 0 in case of success, or -1 in 27 | case of an error. 28 | 29 | EXAMPLE 30 | ------- 31 | [source,c] 32 | -- 33 | #include 34 | ... 35 | struct tep_handle *tep = tep_alloc(); 36 | ... 37 | struct tep_event *event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); 38 | ... 39 | void process_record(struct tep_record *record) 40 | { 41 | unsigned long long pid; 42 | struct tep_format_field *field_pid = tep_find_common_field(event, "common_pid"); 43 | 44 | if (tep_read_number_field(field_pid, record->data, &pid) != 0) { 45 | /* Failed to get "common_pid" value */ 46 | } 47 | } 48 | ... 49 | -- 50 | FILES 51 | ----- 52 | [verse] 53 | -- 54 | *event-parse.h* 55 | Header file to include in order to have access to the library APIs. 56 | *-ltraceevent* 57 | Linker switch to add when building a program that uses the library. 58 | -- 59 | 60 | SEE ALSO 61 | -------- 62 | *libtraceevent*(3), *trace-cmd*(1) 63 | 64 | AUTHOR 65 | ------ 66 | [verse] 67 | -- 68 | *Steven Rostedt* , author of *libtraceevent*. 69 | *Tzvetomir Stoyanov* , author of this man page. 70 | -- 71 | REPORTING BUGS 72 | -------------- 73 | Report bugs to 74 | 75 | LICENSE 76 | ------- 77 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 78 | 79 | RESOURCES 80 | --------- 81 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 82 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-fields.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_event_common_fields, tep_event_fields - Get a list of fields for an event. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | struct tep_format_field pass:[*]pass:[*]*tep_event_common_fields*(struct tep_event pass:[*]_event_); 15 | struct tep_format_field pass:[*]pass:[*]*tep_event_fields*(struct tep_event pass:[*]_event_); 16 | -- 17 | 18 | DESCRIPTION 19 | ----------- 20 | The *tep_event_common_fields()* function returns an array of pointers to common 21 | fields for the _event_. The array is allocated in the function and must be freed 22 | by free(). The last element of the array is NULL. 23 | 24 | The *tep_event_fields()* function returns an array of pointers to event specific 25 | fields for the _event_. The array is allocated in the function and must be freed 26 | by free(). The last element of the array is NULL. 27 | 28 | RETURN VALUE 29 | ------------ 30 | Both *tep_event_common_fields()* and *tep_event_fields()* functions return 31 | an array of pointers to tep_format_field structures in case of success, or 32 | NULL in case of an error. 33 | 34 | EXAMPLE 35 | ------- 36 | [source,c] 37 | -- 38 | #include 39 | ... 40 | struct tep_handle *tep = tep_alloc(); 41 | ... 42 | int i; 43 | struct tep_format_field **fields; 44 | struct tep_event *event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); 45 | if (event != NULL) { 46 | fields = tep_event_common_fields(event); 47 | if (fields != NULL) { 48 | i = 0; 49 | while (fields[i]) { 50 | /* 51 | walk through the list of the common fields 52 | of the kvm_exit event 53 | */ 54 | i++; 55 | } 56 | free(fields); 57 | } 58 | fields = tep_event_fields(event); 59 | if (fields != NULL) { 60 | i = 0; 61 | while (fields[i]) { 62 | /* 63 | walk through the list of the event specific 64 | fields of the kvm_exit event 65 | */ 66 | i++; 67 | } 68 | free(fields); 69 | } 70 | } 71 | ... 72 | -- 73 | 74 | FILES 75 | ----- 76 | [verse] 77 | -- 78 | *event-parse.h* 79 | Header file to include in order to have access to the library APIs. 80 | *-ltraceevent* 81 | Linker switch to add when building a program that uses the library. 82 | -- 83 | 84 | SEE ALSO 85 | -------- 86 | *libtraceevent*(3), *trace-cmd*(1) 87 | 88 | AUTHOR 89 | ------ 90 | [verse] 91 | -- 92 | *Steven Rostedt* , author of *libtraceevent*. 93 | *Tzvetomir Stoyanov* , author of this man page. 94 | -- 95 | REPORTING BUGS 96 | -------------- 97 | Report bugs to 98 | 99 | LICENSE 100 | ------- 101 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 102 | 103 | RESOURCES 104 | --------- 105 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 106 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-file_endian.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_is_file_bigendian, tep_set_file_bigendian - Get / set the endianness of the 7 | raw data being accessed by the tep handler. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *tep_endian* { 16 | TEP_LITTLE_ENDIAN = 0, 17 | TEP_BIG_ENDIAN 18 | }; 19 | 20 | bool *tep_is_file_bigendian*(struct tep_handle pass:[*]_tep_); 21 | void *tep_set_file_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); 22 | 23 | -- 24 | DESCRIPTION 25 | ----------- 26 | The *tep_is_file_bigendian()* function gets the endianness of the raw data, 27 | being accessed by the tep handler. The _tep_ argument is trace event parser 28 | context. 29 | 30 | The *tep_set_file_bigendian()* function sets the endianness of raw data being 31 | accessed by the tep handler. The _tep_ argument is trace event parser context. 32 | [verse] 33 | -- 34 | The _endian_ argument is the endianness: 35 | _TEP_LITTLE_ENDIAN_ - the raw data is in little endian format, 36 | _TEP_BIG_ENDIAN_ - the raw data is in big endian format. 37 | -- 38 | RETURN VALUE 39 | ------------ 40 | The *tep_is_file_bigendian()* function returns true if the data is in bigendian 41 | format, false otherwise. 42 | 43 | EXAMPLE 44 | ------- 45 | [source,c] 46 | -- 47 | #include 48 | ... 49 | struct tep_handle *tep = tep_alloc(); 50 | ... 51 | tep_set_file_bigendian(tep, TEP_LITTLE_ENDIAN); 52 | ... 53 | if (tep_is_file_bigendian(tep)) { 54 | /* The raw data is in big endian */ 55 | } else { 56 | /* The raw data is in little endian */ 57 | } 58 | -- 59 | 60 | FILES 61 | ----- 62 | [verse] 63 | -- 64 | *event-parse.h* 65 | Header file to include in order to have access to the library APIs. 66 | *-ltraceevent* 67 | Linker switch to add when building a program that uses the library. 68 | -- 69 | 70 | SEE ALSO 71 | -------- 72 | *libtraceevent*(3), *trace-cmd*(1) 73 | 74 | AUTHOR 75 | ------ 76 | [verse] 77 | -- 78 | *Steven Rostedt* , author of *libtraceevent*. 79 | *Tzvetomir Stoyanov* , author of this man page. 80 | -- 81 | REPORTING BUGS 82 | -------------- 83 | Report bugs to 84 | 85 | LICENSE 86 | ------- 87 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 88 | 89 | RESOURCES 90 | --------- 91 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 92 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-func_apis.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_set_function_resolver, tep_reset_function_resolver, tep_register_function, tep_register_print_string, 7 | tep_get_function_count - function related tep APIs 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | typedef char pass:[*](*tep_func_resolver_t*)(void pass:[*]_priv_, unsigned long long pass:[*]_addrp_, char pass:[**]_modp_); 16 | int *tep_set_function_resolver*(struct tep_handle pass:[*]_tep_, tep_func_resolver_t pass:[*]_func_, void pass:[*]_priv_); 17 | void *tep_reset_function_resolver*(struct tep_handle pass:[*]_tep_); 18 | int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_); 19 | int *tep_register_print_string*(struct tep_handle pass:[*]_tep_, const char pass:[*]_fmt_, unsigned long long _addr_); 20 | int *tep_get_function_count*(struct tep_handle *_tep_) 21 | -- 22 | 23 | DESCRIPTION 24 | ----------- 25 | Some tools may have already a way to resolve the kernel functions. These APIs 26 | allow them to keep using it instead of duplicating all the entries inside. 27 | 28 | The _tep_func_resolver_t_ type is the prototype of the alternative kernel 29 | functions resolver. This function receives a pointer to its custom context 30 | (set with the *tep_set_function_resolver()* call ) and the address of a kernel 31 | function, which has to be resolved. In case of success, it should return 32 | the name of the function and its module (if any) in _modp_. 33 | 34 | The *tep_set_function_resolver()* function registers _func_ as an alternative 35 | kernel functions resolver. The _tep_ argument is trace event parser context. 36 | The _priv_ argument is a custom context of the _func_ function. The function 37 | resolver is used by the APIs *tep_find_function*(3), 38 | *tep_find_function_address*(3), and *tep_print_func_field()* to resolve 39 | a function address to a function name. 40 | 41 | The *tep_reset_function_resolver()* function resets the kernel functions 42 | resolver to the default function. The _tep_ argument is trace event parser 43 | context. 44 | 45 | 46 | These APIs can be used to find function name and start address, by given 47 | address. The given address does not have to be exact, it will select 48 | the function that would contain it. 49 | 50 | The *tep_register_function()* function registers a function name mapped to an 51 | address and (optional) module. This mapping is used in case the function tracer 52 | or events have "%pS" parameter in its format string. It is common to pass in 53 | the kallsyms function names with their corresponding addresses with this 54 | function. The _tep_ argument is the trace event parser context. The _name_ is 55 | the name of the function, the string is copied internally. The _addr_ is the 56 | start address of the function. The _mod_ is the kernel module the function may 57 | be in (NULL for none). 58 | 59 | The *tep_register_print_string()* function registers a string by the address 60 | it was stored in the kernel. Some strings internal to the kernel with static 61 | address are passed to certain events. The "%s" in the event's format field 62 | which has an address needs to know what string would be at that address. The 63 | tep_register_print_string() supplies the parsing with the mapping between kernel 64 | addresses and those strings. The _tep_ argument is the trace event parser 65 | context. The _fmt_ is the string to register, it is copied internally. 66 | The _addr_ is the address the string was located at. 67 | 68 | *tep_get_function_count*() returns the number of registered functions in a tep handler. 69 | 70 | RETURN VALUE 71 | ------------ 72 | The *tep_set_function_resolver()* function returns 0 in case of success, or -1 73 | in case of an error. 74 | 75 | The *tep_register_function()* function returns 0 in case of success. In case of 76 | an error -1 is returned, and errno is set to the appropriate error number. 77 | 78 | The *tep_register_print_string()* function returns 0 in case of success. In case 79 | of an error -1 is returned, and errno is set to the appropriate error number. 80 | 81 | EXAMPLE 82 | ------- 83 | [source,c] 84 | -- 85 | #include 86 | ... 87 | struct tep_handle *tep = tep_alloc(); 88 | ... 89 | char *my_resolve_kernel_addr(void *context, 90 | unsigned long long *addrp, char **modp) 91 | { 92 | struct db *function_database = context; 93 | struct symbol *sym = sql_lookup(function_database, *addrp); 94 | 95 | if (!sym) 96 | return NULL; 97 | 98 | *modp = sym->module_name; 99 | return sym->name; 100 | } 101 | 102 | void show_function( unsigned long long addr) 103 | { 104 | unsigned long long fstart; 105 | const char *fname; 106 | 107 | if (tep_set_function_resolver(tep, my_resolve_kernel_addr, 108 | function_database) != 0) { 109 | /* failed to register my_resolve_kernel_addr */ 110 | } 111 | 112 | /* These APIs use my_resolve_kernel_addr() to resolve the addr */ 113 | fname = tep_find_function(tep, addr); 114 | fstart = tep_find_function_address(tep, addr); 115 | 116 | /* 117 | addr is in function named fname, starting at fstart address, 118 | at offset (addr - fstart) 119 | */ 120 | 121 | tep_reset_function_resolver(tep); 122 | 123 | } 124 | ... 125 | if (tep_register_function(tep, "kvm_exit", 126 | (unsigned long long) 0x12345678, "kvm") != 0) { 127 | /* Failed to register kvm_exit address mapping */ 128 | } 129 | ... 130 | if (tep_register_print_string(tep, "print string", 131 | (unsigned long long) 0x87654321, NULL) != 0) { 132 | /* Failed to register "print string" address mapping */ 133 | } 134 | ... 135 | -- 136 | 137 | FILES 138 | ----- 139 | [verse] 140 | -- 141 | *event-parse.h* 142 | Header file to include in order to have access to the library APIs. 143 | *-ltraceevent* 144 | Linker switch to add when building a program that uses the library. 145 | -- 146 | 147 | SEE ALSO 148 | -------- 149 | *libtraceevent*(3), *trace-cmd*(1) 150 | 151 | AUTHOR 152 | ------ 153 | [verse] 154 | -- 155 | *Steven Rostedt* , author of *libtraceevent*. 156 | *Tzvetomir Stoyanov* , author of this man page. 157 | -- 158 | REPORTING BUGS 159 | -------------- 160 | Report bugs to 161 | 162 | LICENSE 163 | ------- 164 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 165 | 166 | RESOURCES 167 | --------- 168 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 169 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-func_find.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_find_function,tep_find_function_address,tep_find_function_info - Find function name / start address. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 15 | unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 16 | int *tep_find_function_info*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_, const char pass:[**]_name_, 17 | unsigned long long pass:[*]_start_, unsigned long pass:[*]_size_); 18 | -- 19 | 20 | DESCRIPTION 21 | ----------- 22 | These functions can be used to find function name and start address, by given 23 | address. The given address does not have to be exact, it will select the function 24 | that would contain it. 25 | 26 | The *tep_find_function()* function returns the function name, which contains the 27 | given address _addr_. The _tep_ argument is the trace event parser context. 28 | 29 | The *tep_find_function_address()* function returns the function start address, 30 | by given address _addr_. The _addr_ does not have to be exact, it will select the 31 | function that would contain it. The _tep_ argument is the trace event parser context. 32 | 33 | The *tep_find_function_info()* function retrieves the _name_, starting address (_start_), 34 | and the function text _size_ of the function at _address_, if it is found. Note, 35 | if the _tep_ handle has a function resolver (used by perf), then _size_ is set to 36 | zero. 37 | 38 | RETURN VALUE 39 | ------------ 40 | The *tep_find_function()* function returns the function name, or NULL in case 41 | it cannot be found. 42 | 43 | The *tep_find_function_address()* function returns the function start address, 44 | or 0 in case it cannot be found. 45 | 46 | The *tep_find_function_info()* function returns 1 if a function is found for the 47 | given address, or 0 if it is not. 48 | 49 | EXAMPLE 50 | ------- 51 | [source,c] 52 | -- 53 | #include 54 | ... 55 | struct tep_handle *tep = tep_alloc(); 56 | ... 57 | void show_function_name(unsigned long long addr) 58 | { 59 | const char *fname = tep_find_function(tep, addr); 60 | 61 | if (fname) 62 | printf("Found function %s at 0x%0llx\n", fname, addr); 63 | else 64 | printf("No function found at 0x%0llx\n", addr); 65 | } 66 | 67 | void show_function_start_addr(unsigned long long addr) 68 | { 69 | const char *fname = tep_find_function(tep, addr); 70 | unsigned long long fstart; 71 | 72 | if (!fname) { 73 | printf("No function found at 0x%0llx\n", addr); 74 | return; 75 | } 76 | 77 | fstart = tep_find_function_address(tep, addr); 78 | printf("Function %s at 0x%llx starts at 0x%0llx\n", 79 | fname, addr, fstart); 80 | } 81 | 82 | void show_function_info(unsigned long long addr) 83 | { 84 | const char *fname; 85 | unsigned long long fstart; 86 | unsigned long size; 87 | 88 | ret = tep_find_function_info(tep, addr, &fname, &fstart, &size); 89 | if (!ret) { 90 | printf("No function found at 0x%0lx\n", addr); 91 | return; 92 | } 93 | 94 | printf("Function %s at 0x%lx starts at 0x%0lx and is %ld in size\n", 95 | fname, addr, fstart, size); 96 | } 97 | ... 98 | -- 99 | 100 | FILES 101 | ----- 102 | [verse] 103 | -- 104 | *event-parse.h* 105 | Header file to include in order to have access to the library APIs. 106 | *-ltraceevent* 107 | Linker switch to add when building a program that uses the library. 108 | -- 109 | 110 | SEE ALSO 111 | -------- 112 | *libtraceevent*(3), *trace-cmd*(1) 113 | 114 | AUTHOR 115 | ------ 116 | [verse] 117 | -- 118 | *Steven Rostedt* , author of *libtraceevent*. 119 | *Tzvetomir Stoyanov* , author of this man page. 120 | -- 121 | REPORTING BUGS 122 | -------------- 123 | Report bugs to 124 | 125 | LICENSE 126 | ------- 127 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 128 | 129 | RESOURCES 130 | --------- 131 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 132 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-handle.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_alloc, tep_free,tep_ref, tep_unref,tep_get_ref, tep_kbuffer - Create, destroy, manage 7 | references of trace event parser context. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | struct tep_handle pass:[*]*tep_alloc*(void); 16 | void *tep_free*(struct tep_handle pass:[*]_tep_); 17 | void *tep_ref*(struct tep_handle pass:[*]_tep_); 18 | void *tep_unref*(struct tep_handle pass:[*]_tep_); 19 | int *tep_get_ref*(struct tep_handle pass:[*]_tep_); 20 | struct kbuffer pass:[*]*tep_kbuffer*(struct tep_handle pass:[*]_tep_); 21 | -- 22 | 23 | DESCRIPTION 24 | ----------- 25 | These are the main functions to create and destroy tep_handle - the main 26 | structure, representing the trace event parser context. This context is used as 27 | the input parameter of most library APIs. 28 | 29 | The *tep_alloc()* function allocates and initializes the tep context. 30 | 31 | The *tep_free()* function will decrement the reference of the _tep_ handler. 32 | When there is no more references, then it will free the handler, as well 33 | as clean up all its resources that it had used. The argument _tep_ is 34 | the pointer to the trace event parser context. 35 | 36 | The *tep_ref()* function adds a reference to the _tep_ handler. 37 | 38 | The *tep_unref()* function removes a reference from the _tep_ handler. When 39 | the last reference is removed, the _tep_ is destroyed, and all resources that 40 | it had used are cleaned up. 41 | 42 | The *tep_ref_get()* functions gets the current references of the _tep_ handler. 43 | 44 | The *tep_kbuffer()* function allocates a kbuffer descriptor that can be used to 45 | parse raw data that is represented by the _tep_ handle descriptor. It must be freed 46 | with *kbuf_free(3)*. 47 | 48 | RETURN VALUE 49 | ------------ 50 | *tep_alloc()* returns a pointer to a newly created tep_handle structure. 51 | NULL is returned in case there is not enough free memory to allocate it. 52 | 53 | *tep_ref_get()* returns the current references of _tep_. 54 | If _tep_ is NULL, 0 is returned. 55 | 56 | *tep_kbuffer()* returns a kbuffer descriptor that can parse the raw data that 57 | represents the tep handle. Must be freed with *kbuf_free(3)*. 58 | 59 | EXAMPLE 60 | ------- 61 | [source,c] 62 | -- 63 | #include 64 | 65 | ... 66 | struct tep_handle *tep = tep_alloc(); 67 | ... 68 | int ref = tep_get_ref(tep); 69 | tep_ref(tep); 70 | if ( (ref+1) != tep_get_ref(tep)) { 71 | /* Something wrong happened, the counter is not incremented by 1 */ 72 | } 73 | tep_unref(tep); 74 | ... 75 | tep_free(tep); 76 | ... 77 | -- 78 | FILES 79 | ----- 80 | [verse] 81 | -- 82 | *event-parse.h* 83 | Header file to include in order to have access to the library APIs. 84 | *-ltraceevent* 85 | Linker switch to add when building a program that uses the library. 86 | -- 87 | 88 | SEE ALSO 89 | -------- 90 | *libtraceevent*(3), *trace-cmd*(1) 91 | 92 | AUTHOR 93 | ------ 94 | [verse] 95 | -- 96 | *Steven Rostedt* , author of *libtraceevent*. 97 | *Tzvetomir Stoyanov* , author of this man page. 98 | -- 99 | REPORTING BUGS 100 | -------------- 101 | Report bugs to 102 | 103 | LICENSE 104 | ------- 105 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 106 | 107 | RESOURCES 108 | --------- 109 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 110 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-header_page.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_get_header_page_size, tep_get_header_timestamp_size, tep_is_old_format - 7 | Get the data stored in the header page, in kernel context. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_); 16 | int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_); 17 | bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_); 18 | -- 19 | DESCRIPTION 20 | ----------- 21 | These functions retrieve information from kernel context, stored in tracefs 22 | events/header_page. Old kernels do not have header page info, so default values 23 | from user space context are used. 24 | 25 | The *tep_get_header_page_size()* function returns the size of a long integer, 26 | in kernel context. The _tep_ argument is trace event parser context. 27 | This information is retrieved from tracefs events/header_page, "commit" field. 28 | 29 | The *tep_get_header_timestamp_size()* function returns the size of timestamps, 30 | in kernel context. The _tep_ argument is trace event parser context. This 31 | information is retrieved from tracefs events/header_page, "timestamp" field. 32 | 33 | The *tep_is_old_format()* function returns true if the kernel predates 34 | the addition of events/header_page, otherwise it returns false. 35 | 36 | RETURN VALUE 37 | ------------ 38 | The *tep_get_header_page_size()* function returns the size of a long integer, 39 | in bytes. 40 | 41 | The *tep_get_header_timestamp_size()* function returns the size of timestamps, 42 | in bytes. 43 | 44 | The *tep_is_old_format()* function returns true, if an old kernel is used to 45 | generate the tracing data, which has no event/header_page. If the kernel is new, 46 | or _tep_ is NULL, false is returned. 47 | 48 | EXAMPLE 49 | ------- 50 | [source,c] 51 | -- 52 | #include 53 | ... 54 | struct tep_handle *tep = tep_alloc(); 55 | ... 56 | int longsize; 57 | int timesize; 58 | bool old; 59 | 60 | longsize = tep_get_header_page_size(tep); 61 | timesize = tep_get_header_timestamp_size(tep); 62 | old = tep_is_old_format(tep); 63 | 64 | printf ("%s kernel is used to generate the tracing data.\n", 65 | old?"Old":"New"); 66 | printf("The size of a long integer is %d bytes.\n", longsize); 67 | printf("The timestamps size is %d bytes.\n", timesize); 68 | ... 69 | -- 70 | 71 | FILES 72 | ----- 73 | [verse] 74 | -- 75 | *event-parse.h* 76 | Header file to include in order to have access to the library APIs. 77 | *-ltraceevent* 78 | Linker switch to add when building a program that uses the library. 79 | -- 80 | 81 | SEE ALSO 82 | -------- 83 | *libtraceevent*(3), *trace-cmd*(1) 84 | 85 | AUTHOR 86 | ------ 87 | [verse] 88 | -- 89 | *Steven Rostedt* , author of *libtraceevent*. 90 | *Tzvetomir Stoyanov* , author of this man page. 91 | -- 92 | REPORTING BUGS 93 | -------------- 94 | Report bugs to 95 | 96 | LICENSE 97 | ------- 98 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 99 | 100 | RESOURCES 101 | --------- 102 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 103 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-host_endian.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_is_bigendian, tep_is_local_bigendian, tep_set_local_bigendian - Get / set 7 | the endianness of the local machine. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *tep_endian* { 16 | TEP_LITTLE_ENDIAN = 0, 17 | TEP_BIG_ENDIAN 18 | }; 19 | 20 | int *tep_is_bigendian*(void); 21 | bool *tep_is_local_bigendian*(struct tep_handle pass:[*]_tep_); 22 | void *tep_set_local_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); 23 | -- 24 | 25 | DESCRIPTION 26 | ----------- 27 | 28 | The *tep_is_bigendian()* gets the endianness of the machine, executing 29 | the function. 30 | 31 | The *tep_is_local_bigendian()* function gets the endianness of the local 32 | machine, saved in the _tep_ handler. The _tep_ argument is the trace event 33 | parser context. This API is a bit faster than *tep_is_bigendian()*, as it 34 | returns cached endianness of the local machine instead of checking it each time. 35 | 36 | The *tep_set_local_bigendian()* function sets the endianness of the local 37 | machine in the _tep_ handler. The _tep_ argument is trace event parser context. 38 | The _endian_ argument is the endianness: 39 | [verse] 40 | -- 41 | _TEP_LITTLE_ENDIAN_ - the machine is little endian, 42 | _TEP_BIG_ENDIAN_ - the machine is big endian. 43 | -- 44 | 45 | RETURN VALUE 46 | ------------ 47 | The *tep_is_bigendian()* function returns non zero if the endianness of the 48 | machine, executing the code, is big endian and zero otherwise. 49 | 50 | The *tep_is_local_bigendian()* function returns true, if the endianness of the 51 | local machine, saved in the _tep_ handler, is big endian, or false otherwise. 52 | 53 | EXAMPLE 54 | ------- 55 | [source,c] 56 | -- 57 | #include 58 | ... 59 | struct tep_handle *tep = tep_alloc(); 60 | ... 61 | if (tep_is_bigendian()) 62 | tep_set_local_bigendian(tep, TEP_BIG_ENDIAN); 63 | else 64 | tep_set_local_bigendian(tep, TEP_LITTLE_ENDIAN); 65 | ... 66 | if (tep_is_local_bigendian(tep)) 67 | printf("This machine you are running on is bigendian\n"); 68 | else 69 | printf("This machine you are running on is little endian\n"); 70 | 71 | -- 72 | 73 | FILES 74 | ----- 75 | [verse] 76 | -- 77 | *event-parse.h* 78 | Header file to include in order to have access to the library APIs. 79 | *-ltraceevent* 80 | Linker switch to add when building a program that uses the library. 81 | -- 82 | 83 | SEE ALSO 84 | -------- 85 | *libtraceevent*(3), *trace-cmd*(1) 86 | 87 | AUTHOR 88 | ------ 89 | [verse] 90 | -- 91 | *Steven Rostedt* , author of *libtraceevent*. 92 | *Tzvetomir Stoyanov* , author of this man page. 93 | -- 94 | REPORTING BUGS 95 | -------------- 96 | Report bugs to 97 | 98 | LICENSE 99 | ------- 100 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 101 | 102 | RESOURCES 103 | --------- 104 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 105 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-kbuffer-timestamp.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | kbuffer_timestamp, kbuffer_subbuf_timestamp - 7 | Functions that read various data of a kbuffer descriptor 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | unsigned long long *kbuffer_timestamp*(struct kbuffer pass:[*]_kbuf_); 16 | unsigned long long *kbuffer_subbuf_timestamp*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuf_); 17 | -- 18 | 19 | DESCRIPTION 20 | ----------- 21 | The function *kbuffer_timestamp()* returns the timestamp of the current event of _kbuf_. 22 | 23 | The function *kbuffer_subbuf_timestamp()* returns the timestamp for the sub-buffer 24 | that was loaded in _kbuf_. This usually is (but not guaranteed to be) the timestamp 25 | of the first event on the sub-buffer. 26 | 27 | The function *kbuffer_start_of_data()* returns the offset of where the delta 28 | 29 | RETURN VALUE 30 | ------------ 31 | *kbuffer_read_event()* returns the event that the _kbuf_ descriptor is currently at, 32 | or NULL if the last event was passed (by *kbuffer_next_event()*). 33 | 34 | *kbuffer_next_event()* returns the next event after the current event or NULL if there 35 | are no more events. 36 | 37 | *kbuffer_read_at_offset()* returns the event at a given _offset_ from the start of 38 | the sub-buffer stored in _kbuf_, or NULL if there exists no event. Note, _offset_ 39 | only needs to be an offset that lands on the record, or is at the start of it. It does 40 | not need to be exactly at the beginning of the record. 41 | 42 | *kbuffer_missed_events()* returns 0 if there were no missed events before loaded sub-buffer. 43 | Returns -1 if there were an unknown number of missed events, or if the number of missed events 44 | is known, that number will be returned. 45 | 46 | *kbuffer_event_size()* returns the size of the data payload of the current event of _kbuf_. 47 | 48 | *kbuffer_curr_size()* returns the size of the entire record of the current event of _kbuf_. 49 | This includes the size of the meta data for that record. 50 | 51 | *kbuf_curr_offset()* returns the offset of the current record from the beginning of the _kbuf_ 52 | sub-buffer. 53 | 54 | *kbuf_curr_index()* returns the index of the current record from the beginning of the _kbuf_ 55 | data section. 56 | 57 | EXAMPLE 58 | ------- 59 | [source,c] 60 | -- 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | #include 68 | 69 | int main (int argc, char **argv) 70 | { 71 | unsigned long long ts; 72 | struct kbuffer *kbuf; 73 | struct stat st; 74 | char *buf; 75 | void *event; 76 | int save_offset = -1; 77 | int record_size; 78 | int offset; 79 | int index; 80 | int size; 81 | int ret; 82 | int fd; 83 | int i = 0; 84 | 85 | if (argc < 2) { 86 | printf("usage: %s raw-subbuffer-page\n", argv[0]); 87 | printf(" Try: dd count=1 bs=4096 if=/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw of=/tmp/file\n"); 88 | exit(0); 89 | } 90 | 91 | if (stat(argv[1], &st) < 0) { 92 | perror("stat"); 93 | exit(-1); 94 | } 95 | 96 | buf = malloc(st.st_size); 97 | if (!buf) { 98 | perror("Allocating buffer"); 99 | exit(-1); 100 | } 101 | 102 | fd = open(argv[1], O_RDONLY); 103 | if (fd < 0) { 104 | perror(argv[1]); 105 | exit(-1); 106 | } 107 | 108 | ret = read(fd, buf, st.st_size); 109 | if (ret < 0) { 110 | perror("Reading buffer"); 111 | exit(-1); 112 | } 113 | close(fd); 114 | 115 | kbuf = kbuffer_alloc(KBUFFER_ENDIAN_SAME_AS_HOST, 116 | KBUFFER_LSIZE_SAME_AS_HOST); 117 | if (!kbuf) { 118 | perror("Creating kbuffer"); 119 | exit(-1); 120 | } 121 | ret = kbuffer_load_subbuffer(kbuf, buf); 122 | if (ret < 0) { 123 | perror("Loading sub bufer"); 124 | exit(-1); 125 | } 126 | 127 | if (kbuffer_subbuffer_size(kbuf) > st.st_size) { 128 | fprintf(stderr, "kbuffer is bigger than raw size %d > %ld\n", 129 | kbuffer_subbuffer_size(kbuf), st.st_size); 130 | exit(-1); 131 | } 132 | 133 | ret = kbuffer_missed_events(kbuf); 134 | if (ret) { 135 | if (ret > 0) 136 | printf("Missed %d events before this buffer\n", ret); 137 | else 138 | printf("Missed unknown number of events before this buffer\n"); 139 | } 140 | do { 141 | event = kbuffer_read_event(kbuf, &ts); 142 | if (event) { 143 | record_size = kbuffer_curr_size(kbuf); 144 | offset = kbuffer_curr_offset(kbuf); 145 | index = kbuffer_curr_index(kbuf); 146 | size = kbuffer_event_size(kbuf); 147 | 148 | if (i == 20) 149 | save_offset = offset; 150 | printf(" event %3d ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n", 151 | i++, ts, record_size, size, index, offset); 152 | event = kbuffer_next_event(kbuf, NULL); 153 | } 154 | } while (event); 155 | 156 | if (!event) 157 | printf("Finished sub buffer\n"); 158 | 159 | if (save_offset > 0) { 160 | event = kbuffer_read_at_offset(kbuf, save_offset, &ts); 161 | if (!event) { 162 | fprintf(stderr, "Funny, can't find event 20 at offset %d\n", save_offset); 163 | exit(-1); 164 | } 165 | record_size = kbuffer_curr_size(kbuf); 166 | offset = kbuffer_curr_offset(kbuf); 167 | index = kbuffer_curr_index(kbuf); 168 | size = kbuffer_event_size(kbuf); 169 | 170 | printf("\n saved event 20 ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n\n", 171 | ts, record_size, size, index, offset); 172 | } 173 | kbuffer_free(kbuf); 174 | 175 | return 0; 176 | } 177 | -- 178 | FILES 179 | ----- 180 | [verse] 181 | -- 182 | *event-parse.h* 183 | Header file to include in order to have access to the library APIs. 184 | *-ltraceevent* 185 | Linker switch to add when building a program that uses the library. 186 | -- 187 | 188 | SEE ALSO 189 | -------- 190 | *libtraceevent*(3), *trace-cmd*(1) 191 | 192 | AUTHOR 193 | ------ 194 | [verse] 195 | -- 196 | *Steven Rostedt* , author of *libtraceevent*. 197 | -- 198 | REPORTING BUGS 199 | -------------- 200 | Report bugs to 201 | 202 | LICENSE 203 | ------- 204 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 205 | 206 | RESOURCES 207 | --------- 208 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 209 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-log.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_set_loglevel - Set log level of the library 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | enum *tep_loglevel* { 15 | TEP_LOG_NONE = 0, 16 | TEP_LOG_CRITICAL, 17 | TEP_LOG_ERROR, 18 | TEP_LOG_WARNING, 19 | TEP_LOG_INFO, 20 | TEP_LOG_DEBUG, 21 | TEP_LOG_ALL 22 | }; 23 | 24 | int *tep_set_loglevel*(enum tep_loglevel _level_); 25 | 26 | -- 27 | DESCRIPTION 28 | ----------- 29 | The *tep_set_loglevel()* function sets the level of the library logs that will be printed 30 | on the console. Library log levels are: 31 | [verse] 32 | -- 33 | _TEP_LOG_NONE_ - Do not print any logs. 34 | _TEP_LOG_CRITICAL_ - Print critical logs, problem that may cause a crash. 35 | _TEP_LOG_ERROR_ - Print error logs, problem that could break the main logic of an API. 36 | _TEP_LOG_WARNING_ - Print warnings, problem that could limit the result of an API. 37 | _TEP_LOG_INFO_ - Print information about normal execution of an API. 38 | _TEP_LOG_DEBUG_ - Print debug information. 39 | _TEP_LOG_ALL_ - Print logs from all levels. 40 | -- 41 | Setting the log level to specific value means that logs from the previous levels will be printed 42 | too. For example _TEP_LOG_WARNING_ will print any logs with severity _TEP_LOG_WARNING_, 43 | _TEP_LOG_ERROR_ and _TEP_LOG_CRITICAL_. The default log level is _TEP_LOG_CRITICAL_. 44 | 45 | 46 | EXAMPLE 47 | ------- 48 | [source,c] 49 | -- 50 | #include 51 | 52 | tep_set_loglevel(TEP_LOG_ALL); 53 | ... 54 | /* call libtraceevent APIs and observe any logs they produce */ 55 | ... 56 | tep_set_loglevel(TEP_LOG_CRITICAL); 57 | -- 58 | 59 | FILES 60 | ----- 61 | [verse] 62 | -- 63 | *event-parse.h* 64 | Header file to include in order to have access to the library APIs. 65 | *-ltraceevent* 66 | Linker switch to add when building a program that uses the library. 67 | -- 68 | 69 | SEE ALSO 70 | -------- 71 | *libtraceevent*(3), *trace-cmd*(1) 72 | 73 | AUTHOR 74 | ------ 75 | [verse] 76 | -- 77 | *Steven Rostedt* , author of *libtraceevent*. 78 | *Tzvetomir Stoyanov* , author of this man page. 79 | -- 80 | REPORTING BUGS 81 | -------------- 82 | Report bugs to 83 | 84 | LICENSE 85 | ------- 86 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 87 | 88 | RESOURCES 89 | --------- 90 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 91 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-long_size.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_get_long_size, tep_set_long_size - Get / set the size of a long integer on 7 | the machine, where the trace is generated, in bytes 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | int *tep_get_long_size*(strucqt tep_handle pass:[*]_tep_); 16 | void *tep_set_long_size*(struct tep_handle pass:[*]_tep_, int _long_size_); 17 | -- 18 | 19 | DESCRIPTION 20 | ----------- 21 | The *tep_get_long_size()* function returns the size of a long integer on the machine, 22 | where the trace is generated. The _tep_ argument is trace event parser context. 23 | 24 | The *tep_set_long_size()* function sets the size of a long integer on the machine, 25 | where the trace is generated. The _tep_ argument is trace event parser context. 26 | The _long_size_ is the size of a long integer, in bytes. 27 | 28 | RETURN VALUE 29 | ------------ 30 | The *tep_get_long_size()* function returns the size of a long integer on the machine, 31 | where the trace is generated, in bytes. 32 | 33 | EXAMPLE 34 | ------- 35 | [source,c] 36 | -- 37 | #include 38 | ... 39 | struct tep_handle *tep = tep_alloc(); 40 | ... 41 | tep_set_long_size(tep, 4); 42 | ... 43 | int long_size = tep_get_long_size(tep); 44 | ... 45 | -- 46 | 47 | FILES 48 | ----- 49 | [verse] 50 | -- 51 | *event-parse.h* 52 | Header file to include in order to have access to the library APIs. 53 | *-ltraceevent* 54 | Linker switch to add when building a program that uses the library. 55 | -- 56 | 57 | SEE ALSO 58 | -------- 59 | *libtraceevent*(3), *trace-cmd*(1) 60 | 61 | AUTHOR 62 | ------ 63 | [verse] 64 | -- 65 | *Steven Rostedt* , author of *libtraceevent*. 66 | *Tzvetomir Stoyanov* , author of this man page. 67 | -- 68 | REPORTING BUGS 69 | -------------- 70 | Report bugs to 71 | 72 | LICENSE 73 | ------- 74 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 75 | 76 | RESOURCES 77 | --------- 78 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 79 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-page_size.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_get_page_size, tep_set_page_size, tep_get_sub_buffer_data_size, tep_get_sub_buffer_size - Get / set the size of a memory page on 7 | the machine, where the trace is generated 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | int *tep_get_page_size*(struct tep_handle pass:[*]_tep_); 16 | void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_); 17 | int *tep_get_sub_buffer_size*(struct tep_handle pass:[*]_tep_); 18 | int *tep_get_sub_buffer_data_size*(struct tep_handle pass:[*]_tep_); 19 | int *tep_get_sub_buffer_commit_offset*(struct tep_handle pass:[*]_tep_); 20 | -- 21 | 22 | DESCRIPTION 23 | ----------- 24 | The *tep_get_page_size()* function returns the size of a memory page on 25 | the machine, where the trace is generated. The _tep_ argument is trace 26 | event parser context. 27 | 28 | The *tep_set_page_size()* function stores in the _tep_ context the size of a 29 | memory page on the machine, where the trace is generated. 30 | The _tep_ argument is trace event parser context. 31 | The _page_size_ argument is the size of a memory page, in bytes. 32 | 33 | The *tep_get_sub_buffer_size()* returns the size of each "sub buffer" of the 34 | ring buffer. The Linux kernel ring buffer is broken up into sections called 35 | sub buffers. This returns the size of those buffers. 36 | 37 | The *tep_get_sub_buffer_data_size()* returns the size of just the data portion 38 | of the sub buffers. 39 | 40 | The *tep_get_sub_buffer_commit_offset()* returns the offset on the sub buffer 41 | that holds the committed portion of data. This number contains the index from 42 | the data portion of the sub buffer that is the end of the last element on the 43 | sub buffer. 44 | 45 | RETURN VALUE 46 | ------------ 47 | The *tep_get_page_size()* function returns size of the memory page, in bytes. 48 | 49 | The *tep_get_sub_buffer_size()* function returns the number of bytes each sub 50 | buffer is made up of. 51 | 52 | The *tep_get_sub_buffer_commit_offset()* function returns the location on the 53 | sub buffer that contains the index of the last element. 54 | 55 | EXAMPLE 56 | ------- 57 | [source,c] 58 | -- 59 | #include 60 | #include 61 | ... 62 | struct tep_handle *tep = tep_alloc(); 63 | ... 64 | int page_size = getpagesize(); 65 | 66 | tep_set_page_size(tep, page_size); 67 | 68 | printf("The page size for this machine is %d\n", tep_get_page_size(tep)); 69 | 70 | -- 71 | 72 | FILES 73 | ----- 74 | [verse] 75 | -- 76 | *event-parse.h* 77 | Header file to include in order to have access to the library APIs. 78 | *-ltraceevent* 79 | Linker switch to add when building a program that uses the library. 80 | -- 81 | 82 | SEE ALSO 83 | -------- 84 | *libtraceevent*(3), *trace-cmd*(1) 85 | 86 | AUTHOR 87 | ------ 88 | [verse] 89 | -- 90 | *Steven Rostedt* , author of *libtraceevent*. 91 | *Tzvetomir Stoyanov* , author of this man page. 92 | -- 93 | REPORTING BUGS 94 | -------------- 95 | Report bugs to 96 | 97 | LICENSE 98 | ------- 99 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 100 | 101 | RESOURCES 102 | --------- 103 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 104 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-parse-files.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_parse_saved_cmdlines, tep_parse_printk_formats, tep_parse_kallsyms 7 | - Parsing functions to load mappings 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | int *tep_parse_saved_cmdlines*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_); 16 | int *tep_parse_printk_formats*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_); 17 | int *tep_parse_kallsyms*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_); 18 | -- 19 | 20 | DESCRIPTION 21 | ----------- 22 | *tep_parse_saved_cmdlines()* is a helper function to parse content in the tracefs 23 | file system of the "saved_cmdlines" file (stored in a string buffer passed in by _buf_) 24 | and loads the mapping of the process IDs (pid) to the comm names in the 25 | _tep_ handler. The events store the pid and this is used to be able to show the 26 | process names associated to those process ids. It parses the string _buf_ that 27 | holds the content of saved_cmdlines and ends with a nul character ('\0'). 28 | 29 | *tep_parse_printk_formats()* is a helper function to parse content in the tracefs 30 | file system of the "printk_formats" file (stored in a string buffer passed in by _buf_) 31 | and loads the mapping of addresses of strings that may be referenced by events. 32 | Events only store the address of constant strings in the kernel, and the mapping 33 | of their address to the string is exported to user space in the printk_formats 34 | file. It parses the string _buf_ that holds the content of printk_formats and 35 | ends with a nul character ('\0'). 36 | 37 | *tep_parse_kallsyms()* is a helper function to parse the Linux kernel /proc/kallsyms format 38 | (stored in a string buffer passed in by _buf_) and load the functions into the 39 | _tep_ handler such that function IP addresses can be mapped to their name when 40 | parsing events with %pS in the print format field. It parses the string _buf_ that 41 | holds the content of /proc/kallsyms and ends with a nul character ('\0'). 42 | 43 | RETURN VALUE 44 | ------------ 45 | The *tep_parse_saved_cmdlines*() function returns 0 in case of success, or -1 46 | in case of an error. 47 | 48 | The *tep_parse_printk_formats*() function returns 0 in case of success, or -1 49 | in case of an error. 50 | 51 | The *tep_parse_kallsyms*() function returns 0 in case of success, or -1 52 | in case of an error. 53 | 54 | EXAMPLE 55 | ------- 56 | [source,c] 57 | -- 58 | ... 59 | #include 60 | #include 61 | #include 62 | 63 | int load_cmdlines(struct tep_handle *tep) 64 | { 65 | char *buf = NULL; 66 | int r; 67 | 68 | buf = tracefs_instance_file_read(NULL, "saved_cmdlines", NULL); 69 | if (!buf) 70 | return -1; 71 | r = tep_parse_saved_cmdlines(tep, buf); 72 | free(buf); 73 | return r; 74 | } 75 | 76 | int load_print_strings(struct tep_handle *tep) 77 | { 78 | char *buf = NULL; 79 | int r; 80 | 81 | buf = tracefs_instance_file_read(NULL, "printk_formats", NULL); 82 | if (!buf) 83 | return -1; 84 | r = tep_parse_printk_formats(tep, buf); 85 | free(buf); 86 | return r; 87 | } 88 | 89 | int load_kallsyms(struct tep_handle *tep) 90 | { 91 | char *line = NULL; 92 | char *buf = NULL; 93 | size_t sz = 0; 94 | FILE *fp; 95 | int len = 0; 96 | int r; 97 | 98 | fp = fopen("/proc/kallsyms", "r"); 99 | while ((r = getline(&line, &sz, fp)) >= 0) { 100 | buf = realloc(buf, len + r + 1); 101 | memcpy(buf + len, line, r); 102 | len += r; 103 | } 104 | free(line); 105 | fclose(fp); 106 | if (!buf) 107 | return -1; 108 | buf[len] = 0; 109 | 110 | r = tep_parse_kallsyms(tep, buf); 111 | free(buf); 112 | return r; 113 | } 114 | ... 115 | -- 116 | 117 | FILES 118 | ----- 119 | [verse] 120 | -- 121 | *event-parse.h* 122 | Header file to include in order to have access to the library APIs. 123 | *-ltraceevent* 124 | Linker switch to add when building a program that uses the library. 125 | -- 126 | 127 | SEE ALSO 128 | -------- 129 | *libtraceevent*(3), *trace-cmd*(1), *tep_register_comm*(3), *tep_register_function*(3), 130 | *tep_register_print_string*(3) 131 | 132 | AUTHOR 133 | ------ 134 | [verse] 135 | -- 136 | *Steven Rostedt* , author of *libtraceevent*. 137 | *Tzvetomir Stoyanov* , coauthor of *libtraceevent*. 138 | -- 139 | REPORTING BUGS 140 | -------------- 141 | Report bugs to 142 | 143 | LICENSE 144 | ------- 145 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 146 | 147 | RESOURCES 148 | --------- 149 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 150 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-parse_event.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_parse_event, tep_parse_format - Parse the event format information 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | enum tep_errno *tep_parse_event*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); 15 | enum tep_errno *tep_parse_format*(struct tep_handle pass:[*]_tep_, struct tep_event pass:[*]pass:[*]_eventp_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); 16 | -- 17 | 18 | DESCRIPTION 19 | ----------- 20 | The *tep_parse_event()* function parses the event format and creates an event 21 | structure to quickly parse raw data for a given event. The _tep_ argument is 22 | the trace event parser context. The created event structure is stored in the 23 | _tep_ context. The _buf_ argument is a buffer with _size_, where the event 24 | format data is. The event format data can be taken from 25 | tracefs/events/.../.../format files. The _sys_ argument is the system of 26 | the event. 27 | 28 | The *tep_parse_format()* function does the same as *tep_parse_event()*. The only 29 | difference is in the extra _eventp_ argument, where the newly created event 30 | structure is returned. 31 | 32 | RETURN VALUE 33 | ------------ 34 | Both *tep_parse_event()* and *tep_parse_format()* functions return 0 on success, 35 | or TEP_ERRNO__... in case of an error. 36 | 37 | EXAMPLE 38 | ------- 39 | [source,c] 40 | -- 41 | #include 42 | ... 43 | struct tep_handle *tep = tep_alloc(); 44 | ... 45 | char *buf; 46 | int size; 47 | struct tep_event *event = NULL; 48 | buf = read_file("/sys/kernel/tracing/events/ftrace/print/format", &size); 49 | if (tep_parse_event(tep, buf, size, "ftrace") != 0) { 50 | /* Failed to parse the ftrace print format */ 51 | } 52 | 53 | if (tep_parse_format(tep, &event, buf, size, "ftrace") != 0) { 54 | /* Failed to parse the ftrace print format */ 55 | } 56 | ... 57 | -- 58 | 59 | FILES 60 | ----- 61 | [verse] 62 | -- 63 | *event-parse.h* 64 | Header file to include in order to have access to the library APIs. 65 | *-ltraceevent* 66 | Linker switch to add when building a program that uses the library. 67 | -- 68 | 69 | SEE ALSO 70 | -------- 71 | *libtraceevent*(3), *trace-cmd*(1) 72 | 73 | AUTHOR 74 | ------ 75 | [verse] 76 | -- 77 | *Steven Rostedt* , author of *libtraceevent*. 78 | *Tzvetomir Stoyanov* , author of this man page. 79 | -- 80 | REPORTING BUGS 81 | -------------- 82 | Report bugs to 83 | 84 | LICENSE 85 | ------- 86 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 87 | 88 | RESOURCES 89 | --------- 90 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 91 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-parse_head.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_parse_header_page - Parses the data stored in the header page. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | int *tep_parse_header_page*(struct tep_handle pass:[*]_tep_, char pass:[*]_buf_, unsigned long _size_, int _long_size_); 15 | -- 16 | 17 | DESCRIPTION 18 | ----------- 19 | The *tep_parse_header_page()* function parses the header page data from _buf_, 20 | and initializes the _tep_, trace event parser context, with it. The buffer 21 | _buf_ is with _size_, and is supposed to be copied from 22 | tracefs/events/header_page. 23 | 24 | Some old kernels do not have header page info, in this case the 25 | *tep_parse_header_page()* function can be called with _size_ equal to 0. The 26 | _tep_ context is initialized with default values. The _long_size_ can be used in 27 | this use case, to set the size of a long integer to be used. 28 | 29 | RETURN VALUE 30 | ------------ 31 | The *tep_parse_header_page()* function returns 0 in case of success, or -1 32 | in case of an error. 33 | 34 | EXAMPLE 35 | ------- 36 | [source,c] 37 | -- 38 | #include 39 | ... 40 | struct tep_handle *tep = tep_alloc(); 41 | ... 42 | char *buf; 43 | int size; 44 | buf = read_file("/sys/kernel/tracing/events/header_page", &size); 45 | if (tep_parse_header_page(tep, buf, size, sizeof(unsigned long)) != 0) { 46 | /* Failed to parse the header page */ 47 | } 48 | ... 49 | -- 50 | 51 | FILES 52 | ----- 53 | [verse] 54 | -- 55 | *event-parse.h* 56 | Header file to include in order to have access to the library APIs. 57 | *-ltraceevent* 58 | Linker switch to add when building a program that uses the library. 59 | -- 60 | 61 | SEE ALSO 62 | -------- 63 | *libtraceevent*(3), *trace-cmd*(1) 64 | 65 | AUTHOR 66 | ------ 67 | [verse] 68 | -- 69 | *Steven Rostedt* , author of *libtraceevent*. 70 | *Tzvetomir Stoyanov* , author of this man page. 71 | -- 72 | REPORTING BUGS 73 | -------------- 74 | Report bugs to 75 | 76 | LICENSE 77 | ------- 78 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 79 | 80 | RESOURCES 81 | --------- 82 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 83 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-plugins.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_load_plugins, tep_unload_plugins, tep_load_plugins_hook, tep_add_plugin_path, 7 | tep_plugin_add_option - Load / unload traceevent plugins. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | struct tep_plugin_list pass:[*]*tep_load_plugins*(struct tep_handle pass:[*]_tep_); 16 | void *tep_unload_plugins*(struct tep_plugin_list pass:[*]_plugin_list_, struct tep_handle pass:[*]_tep_); 17 | void *tep_load_plugins_hook*(struct tep_handle pass:[*]_tep_, const char pass:[*]_suffix_, 18 | void (pass:[*]_load_plugin_)(struct tep_handle pass:[*]tep, 19 | const char pass:[*]path, 20 | const char pass:[*]name, 21 | void pass:[*]data), 22 | void pass:[*]_data_); 23 | int *tep_add_plugin_path*(struct tep_handle pass:[*]tep, char pass:[*]path, 24 | enum tep_plugin_load_priority prio); 25 | int *tep_plugin_add_option*(const char pass:[*]_name_, const char pass:[*]_val_); 26 | -- 27 | 28 | DESCRIPTION 29 | ----------- 30 | The *tep_load_plugins()* function loads all plugins, located in the plugin 31 | directories. The _tep_ argument is trace event parser context. 32 | The plugin directories are : 33 | [verse] 34 | -- 35 | - Directories, specified in _tep_->plugins_dir with priority TEP_PLUGIN_FIRST 36 | - System's plugin directory, defined at the library compile time. It 37 | depends on the library installation prefix and usually is 38 | _(install_preffix)/lib/traceevent/plugins_ 39 | - Directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ 40 | - User's plugin directory, located at _~/.local/lib/traceevent/plugins_ 41 | - Directories, specified in _tep_->plugins_dir with priority TEP_PLUGIN_LAST 42 | -- 43 | Loading of plugins can be controlled by the _tep_flags_, using the 44 | *tep_set_flag()* API: 45 | [verse] 46 | -- 47 | _TEP_DISABLE_SYS_PLUGINS_ - do not load plugins, located in 48 | the system's plugin directory. 49 | _TEP_DISABLE_PLUGINS_ - do not load any plugins. 50 | -- 51 | The *tep_set_flag()* API needs to be called before *tep_load_plugins()*, if 52 | loading of all plugins is not the desired case. 53 | 54 | The *tep_unload_plugins()* function unloads the plugins, previously loaded by 55 | *tep_load_plugins()*. The _tep_ argument is trace event parser context. The 56 | _plugin_list_ is the list of loaded plugins, returned by 57 | the *tep_load_plugins()* function. 58 | 59 | The *tep_load_plugins_hook()* function walks through all directories with plugins 60 | and calls user specified *load_plugin()* hook for each plugin file. Only files 61 | with given _suffix_ are considered to be plugins. The _data_ is a user specified 62 | context, passed to *load_plugin()*. Directories and the walk order are the same 63 | as in *tep_load_plugins()* API. 64 | 65 | The *tep_add_plugin_path()* functions adds additional directories with plugins in 66 | the _tep_->plugins_dir list. It must be called before *tep_load_plugins()* in order 67 | for the plugins from the new directories to be loaded. The _tep_ argument is 68 | the trace event parser context. The _path_ is the full path to the new plugin 69 | directory. The _prio_ argument specifies the loading priority order for the 70 | new directory of plugins. The loading priority is important in case of different 71 | versions of the same plugin located in multiple plugin directories.The last loaded 72 | plugin wins. The priority can be: 73 | [verse] 74 | -- 75 | _TEP_PLUGIN_FIRST_ - Load plugins from this directory first 76 | _TEP_PLUGIN_LAST_ - Load plugins from this directory last 77 | -- 78 | Where the plugins in TEP_PLUGIN_LAST" will take precedence over the 79 | plugins in the other directories. 80 | 81 | The *tep_plugin_add_option()* sets options defined by a plugin. The _name_ is the 82 | name of the option to set to _val_. Plugins can add options to change its behavior 83 | and *tep_plugin_add_option()* is used by the application to make those modifications. 84 | 85 | 86 | RETURN VALUE 87 | ------------ 88 | The *tep_load_plugins()* function returns a list of successfully loaded plugins, 89 | or NULL in case no plugins are loaded. 90 | The *tep_add_plugin_path()* function returns -1 in case of an error, 0 otherwise. 91 | 92 | EXAMPLE 93 | ------- 94 | [source,c] 95 | -- 96 | #include 97 | ... 98 | struct tep_handle *tep = tep_alloc(); 99 | ... 100 | tep_add_plugin_path(tep, "~/dev_plugins", TEP_PLUGIN_LAST); 101 | ... 102 | struct tep_plugin_list *plugins = tep_load_plugins(tep); 103 | if (plugins == NULL) { 104 | /* no plugins are loaded */ 105 | } 106 | ... 107 | tep_unload_plugins(plugins, tep); 108 | ... 109 | void print_plugin(struct tep_handle *tep, const char *path, 110 | const char *name, void *data) 111 | { 112 | pritnf("Found libtraceevent plugin %s/%s\n", path, name); 113 | } 114 | ... 115 | tep_load_plugins_hook(tep, ".so", print_plugin, NULL); 116 | ... 117 | -- 118 | 119 | FILES 120 | ----- 121 | [verse] 122 | -- 123 | *event-parse.h* 124 | Header file to include in order to have access to the library APIs. 125 | *-ltraceevent* 126 | Linker switch to add when building a program that uses the library. 127 | -- 128 | 129 | SEE ALSO 130 | -------- 131 | *libtraceevent*(3), *trace-cmd*(1), *tep_set_flag*(3) 132 | 133 | AUTHOR 134 | ------ 135 | [verse] 136 | -- 137 | *Steven Rostedt* , author of *libtraceevent*. 138 | *Tzvetomir Stoyanov* , author of this man page. 139 | -- 140 | REPORTING BUGS 141 | -------------- 142 | Report bugs to 143 | 144 | LICENSE 145 | ------- 146 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 147 | 148 | RESOURCES 149 | --------- 150 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 151 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-record_parse.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_data_type, tep_data_pid,tep_data_preempt_count, tep_data_flags - 7 | Extract common fields from a record. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *trace_flag_type* { 16 | _TRACE_FLAG_IRQS_OFF_, 17 | _TRACE_FLAG_IRQS_NOSUPPORT_, 18 | _TRACE_FLAG_NEED_RESCHED_, 19 | _TRACE_FLAG_HARDIRQ_, 20 | _TRACE_FLAG_SOFTIRQ_, 21 | }; 22 | 23 | int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 24 | int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 25 | int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 26 | int *tep_data_flags*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 27 | -- 28 | 29 | DESCRIPTION 30 | ----------- 31 | This set of functions can be used to extract common fields from a record. 32 | 33 | The *tep_data_type()* function gets the event id from the record _rec_. 34 | It reads the "common_type" field. The _tep_ argument is the trace event parser 35 | context. 36 | 37 | The *tep_data_pid()* function gets the process id from the record _rec_. 38 | It reads the "common_pid" field. The _tep_ argument is the trace event parser 39 | context. 40 | 41 | The *tep_data_preempt_count()* function gets the preemption count from the 42 | record _rec_. It reads the "common_preempt_count" field. The _tep_ argument is 43 | the trace event parser context. 44 | 45 | The *tep_data_flags()* function gets the latency flags from the record _rec_. 46 | It reads the "common_flags" field. The _tep_ argument is the trace event parser 47 | context. Supported latency flags are: 48 | [verse] 49 | -- 50 | _TRACE_FLAG_IRQS_OFF_, Interrupts are disabled. 51 | _TRACE_FLAG_IRQS_NOSUPPORT_, Reading IRQ flag is not supported by the architecture. 52 | _TRACE_FLAG_NEED_RESCHED_, Task needs rescheduling. 53 | _TRACE_FLAG_HARDIRQ_, Hard IRQ is running. 54 | _TRACE_FLAG_SOFTIRQ_, Soft IRQ is running. 55 | -- 56 | 57 | RETURN VALUE 58 | ------------ 59 | The *tep_data_type()* function returns an integer, representing the event id. 60 | 61 | The *tep_data_pid()* function returns an integer, representing the process id 62 | 63 | The *tep_data_preempt_count()* function returns an integer, representing the 64 | preemption count. 65 | 66 | The *tep_data_flags()* function returns an integer, representing the latency 67 | flags. Look at the _trace_flag_type_ enum for supported flags. 68 | 69 | All these functions in case of an error return a negative integer. 70 | 71 | EXAMPLE 72 | ------- 73 | [source,c] 74 | -- 75 | #include 76 | ... 77 | struct tep_handle *tep = tep_alloc(); 78 | ... 79 | void process_record(struct tep_record *record) 80 | { 81 | int data; 82 | 83 | data = tep_data_type(tep, record); 84 | if (data >= 0) { 85 | /* Got the ID of the event */ 86 | } 87 | 88 | data = tep_data_pid(tep, record); 89 | if (data >= 0) { 90 | /* Got the process ID */ 91 | } 92 | 93 | data = tep_data_preempt_count(tep, record); 94 | if (data >= 0) { 95 | /* Got the preemption count */ 96 | } 97 | 98 | data = tep_data_flags(tep, record); 99 | if (data >= 0) { 100 | /* Got the latency flags */ 101 | } 102 | } 103 | ... 104 | -- 105 | 106 | FILES 107 | ----- 108 | [verse] 109 | -- 110 | *event-parse.h* 111 | Header file to include in order to have access to the library APIs. 112 | *-ltraceevent* 113 | Linker switch to add when building a program that uses the library. 114 | -- 115 | 116 | SEE ALSO 117 | -------- 118 | *libtraceevent*(3), *trace-cmd*(1) 119 | 120 | AUTHOR 121 | ------ 122 | [verse] 123 | -- 124 | *Steven Rostedt* , author of *libtraceevent*. 125 | *Tzvetomir Stoyanov* , author of this man page. 126 | -- 127 | REPORTING BUGS 128 | -------------- 129 | Report bugs to 130 | 131 | LICENSE 132 | ------- 133 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 134 | 135 | RESOURCES 136 | --------- 137 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 138 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-reg_event_handler.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_register_event_handler, tep_unregister_event_handler - Register / 7 | unregisters a callback function to parse an event information. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *tep_reg_handler* { 16 | _TEP_REGISTER_SUCCESS_, 17 | _TEP_REGISTER_SUCCESS_OVERWRITE_, 18 | }; 19 | 20 | int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_); 21 | int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); 22 | 23 | typedef int (*pass:[*]tep_event_handler_func*)(struct trace_seq pass:[*]s, struct tep_record pass:[*]record, struct tep_event pass:[*]event, void pass:[*]context); 24 | -- 25 | 26 | DESCRIPTION 27 | ----------- 28 | The *tep_register_event_handler()* function registers a handler function, 29 | which is going to be called to parse the information for a given event. 30 | The _tep_ argument is the trace event parser context. The _id_ argument is 31 | the id of the event. The _sys_name_ argument is the name of the system, 32 | the event belongs to. The _event_name_ argument is the name of the event. 33 | If _id_ is >= 0, it is used to find the event, otherwise _sys_name_ and 34 | _event_name_ are used. The _func_ is a pointer to the function, which is going 35 | to be called to parse the event information. The _context_ argument is a pointer 36 | to the context data, which will be passed to the _func_. If a handler function 37 | for the same event is already registered, it will be overridden with the new 38 | one. This mechanism allows a developer to override the parsing of a given event. 39 | If for some reason the default print format is not sufficient, the developer 40 | can register a function for an event to be used to parse the data instead. 41 | 42 | The *tep_unregister_event_handler()* function unregisters the handler function, 43 | previously registered with *tep_register_event_handler()*. The _tep_ argument 44 | is the trace event parser context. The _id_, _sys_name_, _event_name_, _func_, 45 | and _context_ are the same arguments, as when the callback function _func_ was 46 | registered. 47 | 48 | The _tep_event_handler_func_ is the type of the custom event handler 49 | function. The _s_ argument is the trace sequence, it can be used to create a 50 | custom string, describing the event. A _record_ to get the event from is passed 51 | as input parameter and also the _event_ - the handle to the record's event. The 52 | _context_ is custom context, set when the custom event handler is registered. 53 | 54 | RETURN VALUE 55 | ------------ 56 | The *tep_register_event_handler()* function returns _TEP_REGISTER_SUCCESS_ 57 | if the new handler is registered successfully or 58 | _TEP_REGISTER_SUCCESS_OVERWRITE_ if an existing handler is overwritten. 59 | If there is not enough memory to complete the registration, 60 | TEP_ERRNO__MEM_ALLOC_FAILED is returned. 61 | 62 | The *tep_unregister_event_handler()* function returns 0 if _func_ was removed 63 | successful or, -1 if the event was not found. 64 | 65 | The _tep_event_handler_func_ should return -1 in case of an error, 66 | or 0 otherwise. 67 | 68 | EXAMPLE 69 | ------- 70 | [source,c] 71 | -- 72 | #include 73 | #include 74 | ... 75 | struct tep_handle *tep = tep_alloc(); 76 | ... 77 | int timer_expire_handler(struct trace_seq *s, struct tep_record *record, 78 | struct tep_event *event, void *context) 79 | { 80 | trace_seq_printf(s, "hrtimer="); 81 | 82 | if (tep_print_num_field(s, "0x%llx", event, "timer", record, 0) == -1) 83 | tep_print_num_field(s, "0x%llx", event, "hrtimer", record, 1); 84 | 85 | trace_seq_printf(s, " now="); 86 | 87 | tep_print_num_field(s, "%llu", event, "now", record, 1); 88 | 89 | tep_print_func_field(s, " function=%s", event, "function", record, 0); 90 | 91 | return 0; 92 | } 93 | ... 94 | int ret; 95 | 96 | ret = tep_register_event_handler(tep, -1, "timer", "hrtimer_expire_entry", 97 | timer_expire_handler, NULL); 98 | if (ret < 0) { 99 | char buf[32]; 100 | 101 | tep_strerror(tep, ret, buf, 32) 102 | printf("Failed to register handler for hrtimer_expire_entry: %s\n", buf); 103 | } else { 104 | switch (ret) { 105 | case TEP_REGISTER_SUCCESS: 106 | printf ("Registered handler for hrtimer_expire_entry\n"); 107 | break; 108 | case TEP_REGISTER_SUCCESS_OVERWRITE: 109 | printf ("Overwrote handler for hrtimer_expire_entry\n"); 110 | break; 111 | } 112 | } 113 | ... 114 | ret = tep_unregister_event_handler(tep, -1, "timer", "hrtimer_expire_entry", 115 | timer_expire_handler, NULL); 116 | if ( ret ) 117 | printf ("Failed to unregister handler for hrtimer_expire_entry\n"); 118 | 119 | -- 120 | 121 | FILES 122 | ----- 123 | [verse] 124 | -- 125 | *event-parse.h* 126 | Header file to include in order to have access to the library APIs. 127 | *trace-seq.h* 128 | Header file to include in order to have access to trace sequences 129 | related APIs. Trace sequences are used to allow a function to call 130 | several other functions to create a string of data to use. 131 | *-ltraceevent* 132 | Linker switch to add when building a program that uses the library. 133 | -- 134 | 135 | SEE ALSO 136 | -------- 137 | *libtraceevent*(3), *trace-cmd*(1) 138 | 139 | AUTHOR 140 | ------ 141 | [verse] 142 | -- 143 | *Steven Rostedt* , author of *libtraceevent*. 144 | *Tzvetomir Stoyanov* , author of this man page. 145 | -- 146 | REPORTING BUGS 147 | -------------- 148 | Report bugs to 149 | 150 | LICENSE 151 | ------- 152 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 153 | 154 | RESOURCES 155 | --------- 156 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 157 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-reg_print_func.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_register_print_function,tep_unregister_print_function - 7 | Registers / Unregisters a helper function. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *tep_func_arg_type* { 16 | TEP_FUNC_ARG_VOID, 17 | TEP_FUNC_ARG_INT, 18 | TEP_FUNC_ARG_LONG, 19 | TEP_FUNC_ARG_STRING, 20 | TEP_FUNC_ARG_PTR, 21 | TEP_FUNC_ARG_MAX_TYPES 22 | }; 23 | 24 | typedef unsigned long long (*pass:[*]tep_func_handler*)(struct trace_seq pass:[*]s, unsigned long long pass:[*]args); 25 | 26 | int *tep_register_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, enum tep_func_arg_type _ret_type_, char pass:[*]_name_, _..._); 27 | int *tep_unregister_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, char pass:[*]_name_); 28 | -- 29 | 30 | DESCRIPTION 31 | ----------- 32 | Some events may have helper functions in the print format arguments. 33 | This allows a plugin to dynamically create a way to process one of 34 | these functions. 35 | 36 | The *tep_register_print_function()* registers such helper function. The _tep_ 37 | argument is the trace event parser context. The _func_ argument is a pointer 38 | to the helper function. The _ret_type_ argument is the return type of the 39 | helper function, value from the _tep_func_arg_type_ enum. The _name_ is the name 40 | of the helper function, as seen in the print format arguments. The _..._ is a 41 | variable list of _tep_func_arg_type_ enums, the _func_ function arguments. 42 | This list must end with _TEP_FUNC_ARG_VOID_. See 'EXAMPLE' section. 43 | 44 | The *tep_unregister_print_function()* unregisters a helper function, previously 45 | registered with *tep_register_print_function()*. The _tep_ argument is the 46 | trace event parser context. The _func_ and _name_ arguments are the same, used 47 | when the helper function was registered. 48 | 49 | The _tep_func_handler_ is the type of the helper function. The _s_ argument is 50 | the trace sequence, it can be used to create a custom string. 51 | The _args_ is a list of arguments, defined when the helper function was 52 | registered. 53 | 54 | RETURN VALUE 55 | ------------ 56 | The *tep_register_print_function()* function returns 0 in case of success. 57 | In case of an error, TEP_ERRNO_... code is returned. 58 | 59 | The *tep_unregister_print_function()* returns 0 in case of success, or -1 in 60 | case of an error. 61 | 62 | EXAMPLE 63 | ------- 64 | Some events have internal functions calls, that appear in the print format 65 | output. For example "tracefs/events/i915/g4x_wm/format" has: 66 | [source,c] 67 | -- 68 | print fmt: "pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s", 69 | ((REC->pipe) + 'A'), REC->frame, REC->scanline, REC->primary, 70 | REC->sprite, REC->cursor, yesno(REC->cxsr), REC->sr_plane, 71 | REC->sr_cursor, REC->sr_fbc, yesno(REC->hpll), REC->hpll_plane, 72 | REC->hpll_cursor, REC->hpll_fbc, yesno(REC->fbc) 73 | -- 74 | Notice the call to function *yesno()* in the print arguments. In the kernel 75 | context, this function has the following implementation: 76 | [source,c] 77 | -- 78 | static const char *yesno(int x) 79 | { 80 | static const char *yes = "yes"; 81 | static const char *no = "no"; 82 | 83 | return x ? yes : no; 84 | } 85 | -- 86 | The user space event parser has no idea how to handle this *yesno()* function. 87 | The *tep_register_print_function()* API can be used to register a user space 88 | helper function, mapped to the kernel's *yesno()*: 89 | [source,c] 90 | -- 91 | #include 92 | #include 93 | ... 94 | struct tep_handle *tep = tep_alloc(); 95 | ... 96 | static const char *yes_no_helper(int x) 97 | { 98 | return x ? "yes" : "no"; 99 | } 100 | ... 101 | if ( tep_register_print_function(tep, 102 | yes_no_helper, 103 | TEP_FUNC_ARG_STRING, 104 | "yesno", 105 | TEP_FUNC_ARG_INT, 106 | TEP_FUNC_ARG_VOID) != 0) { 107 | /* Failed to register yes_no_helper function */ 108 | } 109 | 110 | /* 111 | Now, when the event parser encounters this yesno() function, it will know 112 | how to handle it. 113 | */ 114 | ... 115 | if (tep_unregister_print_function(tep, yes_no_helper, "yesno") != 0) { 116 | /* Failed to unregister yes_no_helper function */ 117 | } 118 | -- 119 | 120 | FILES 121 | ----- 122 | [verse] 123 | -- 124 | *event-parse.h* 125 | Header file to include in order to have access to the library APIs. 126 | *trace-seq.h* 127 | Header file to include in order to have access to trace sequences 128 | related APIs. Trace sequences are used to allow a function to call 129 | several other functions to create a string of data to use. 130 | *-ltraceevent* 131 | Linker switch to add when building a program that uses the library. 132 | -- 133 | 134 | SEE ALSO 135 | -------- 136 | *libtraceevent*(3), *trace-cmd*(1) 137 | 138 | AUTHOR 139 | ------ 140 | [verse] 141 | -- 142 | *Steven Rostedt* , author of *libtraceevent*. 143 | *Tzvetomir Stoyanov* , author of this man page. 144 | -- 145 | REPORTING BUGS 146 | -------------- 147 | Report bugs to 148 | 149 | LICENSE 150 | ------- 151 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 152 | 153 | RESOURCES 154 | --------- 155 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 156 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-set_flag.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_set_flag, tep_clear_flag, tep_test_flag - 7 | Manage flags of trace event parser context. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | enum *tep_flag* { 16 | _TEP_NSEC_OUTPUT_, 17 | _TEP_DISABLE_SYS_PLUGINS_, 18 | _TEP_DISABLE_PLUGINS_ 19 | }; 20 | void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 21 | void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 22 | bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 23 | -- 24 | 25 | DESCRIPTION 26 | ----------- 27 | Trace event parser context flags are defined in *enum tep_flag*: 28 | [verse] 29 | -- 30 | _TEP_NSEC_OUTPUT_ - print event's timestamp in nano seconds, instead of micro seconds. 31 | _TEP_DISABLE_SYS_PLUGINS_ - disable plugins, located in system's plugin 32 | directory. This directory is defined at library compile 33 | time, and usually depends on library installation 34 | prefix: (install_preffix)/lib/traceevent/plugins 35 | _TEP_DISABLE_PLUGINS_ - disable all library plugins: 36 | - in system's plugin directory 37 | - in directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ 38 | - in user's home directory, _~/.traceevent/plugins_ 39 | -- 40 | Note: plugin related flags must me set before calling *tep_load_plugins()* API. 41 | 42 | The *tep_set_flag()* function sets _flag_ to _tep_ context. 43 | 44 | The *tep_clear_flag()* function clears _flag_ from _tep_ context. 45 | 46 | The *tep_test_flag()* function tests if _flag_ is set to _tep_ context. 47 | 48 | RETURN VALUE 49 | ------------ 50 | *tep_test_flag()* function returns true if _flag_ is set, false otherwise. 51 | 52 | EXAMPLE 53 | ------- 54 | [source,c] 55 | -- 56 | #include 57 | ... 58 | struct tep_handle *tep = tep_alloc(); 59 | ... 60 | /* Print timestamps in nanoseconds */ 61 | tep_set_flag(tep, TEP_NSEC_OUTPUT); 62 | ... 63 | if (tep_test_flag(tep, TEP_NSEC_OUTPUT)) { 64 | /* print timestamps in nanoseconds */ 65 | } else { 66 | /* print timestamps in microseconds */ 67 | } 68 | ... 69 | /* Print timestamps in microseconds */ 70 | tep_clear_flag(tep, TEP_NSEC_OUTPUT); 71 | ... 72 | -- 73 | FILES 74 | ----- 75 | [verse] 76 | -- 77 | *event-parse.h* 78 | Header file to include in order to have access to the library APIs. 79 | *-ltraceevent* 80 | Linker switch to add when building a program that uses the library. 81 | -- 82 | 83 | SEE ALSO 84 | -------- 85 | *libtraceevent*(3), *trace-cmd*(1) 86 | 87 | AUTHOR 88 | ------ 89 | [verse] 90 | -- 91 | *Steven Rostedt* , author of *libtraceevent*. 92 | *Tzvetomir Stoyanov* , author of this man page. 93 | -- 94 | REPORTING BUGS 95 | -------------- 96 | Report bugs to 97 | 98 | LICENSE 99 | ------- 100 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 101 | 102 | RESOURCES 103 | --------- 104 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 105 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-strerror.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | tep_strerror - Returns a string describing regular errno and tep error number. 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | int *tep_strerror*(struct tep_handle pass:[*]_tep_, enum tep_errno _errnum_, char pass:[*]_buf_, size_t _buflen_); 15 | 16 | -- 17 | DESCRIPTION 18 | ----------- 19 | The *tep_strerror()* function converts tep error number into a human 20 | readable string. 21 | The _tep_ argument is trace event parser context. The _errnum_ is a regular 22 | errno, defined in errno.h, or a tep error number. The string, describing this 23 | error number is copied in the _buf_ argument. The _buflen_ argument is 24 | the size of the _buf_. 25 | 26 | It as a thread safe wrapper around strerror_r(). The library function has two 27 | different behaviors - POSIX and GNU specific. The *tep_strerror()* API always 28 | behaves as the POSIX version - the error string is copied in the user supplied 29 | buffer. 30 | 31 | RETURN VALUE 32 | ------------ 33 | The *tep_strerror()* function returns 0, if a valid _errnum_ is passed and the 34 | string is copied into _buf_. If _errnum_ is not a valid error number, 35 | -1 is returned and _buf_ is not modified. 36 | 37 | EXAMPLE 38 | ------- 39 | [source,c] 40 | -- 41 | #include 42 | ... 43 | struct tep_handle *tep = tep_alloc(); 44 | ... 45 | char buf[32]; 46 | char *pool = calloc(1, 128); 47 | if (tep == NULL) { 48 | tep_strerror(tep, TEP_ERRNO__MEM_ALLOC_FAILED, buf, 32); 49 | printf ("The pool is not initialized, %s", buf); 50 | } 51 | ... 52 | -- 53 | 54 | FILES 55 | ----- 56 | [verse] 57 | -- 58 | *event-parse.h* 59 | Header file to include in order to have access to the library APIs. 60 | *-ltraceevent* 61 | Linker switch to add when building a program that uses the library. 62 | -- 63 | 64 | SEE ALSO 65 | -------- 66 | *libtraceevent*(3), *trace-cmd*(1) 67 | 68 | AUTHOR 69 | ------ 70 | [verse] 71 | -- 72 | *Steven Rostedt* , author of *libtraceevent*. 73 | *Tzvetomir Stoyanov* , author of this man page. 74 | -- 75 | REPORTING BUGS 76 | -------------- 77 | Report bugs to 78 | 79 | LICENSE 80 | ------- 81 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 82 | 83 | RESOURCES 84 | --------- 85 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 86 | -------------------------------------------------------------------------------- /Documentation/libtraceevent-tseq.txt: -------------------------------------------------------------------------------- 1 | libtraceevent(3) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | trace_seq_init, trace_seq_destroy, trace_seq_reset, trace_seq_terminate, 7 | trace_seq_putc, trace_seq_puts, trace_seq_printf, trace_seq_vprintf, 8 | trace_seq_do_fprintf, trace_seq_do_printf - 9 | Initialize / destroy a trace sequence. 10 | 11 | SYNOPSIS 12 | -------- 13 | [verse] 14 | -- 15 | *#include * 16 | *#include * 17 | 18 | void *trace_seq_init*(struct trace_seq pass:[*]_s_); 19 | void *trace_seq_destroy*(struct trace_seq pass:[*]_s_); 20 | void *trace_seq_reset*(struct trace_seq pass:[*]_s_); 21 | void *trace_seq_terminate*(struct trace_seq pass:[*]_s_); 22 | int *trace_seq_putc*(struct trace_seq pass:[*]_s_, unsigned char _c_); 23 | int *trace_seq_puts*(struct trace_seq pass:[*]_s_, const char pass:[*]_str_); 24 | int *trace_seq_printf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, _..._); 25 | int *trace_seq_vprintf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, va_list _args_); 26 | int *trace_seq_do_printf*(struct trace_seq pass:[*]_s_); 27 | int *trace_seq_do_fprintf*(struct trace_seq pass:[*]_s_, FILE pass:[*]_fp_); 28 | -- 29 | 30 | DESCRIPTION 31 | ----------- 32 | Trace sequences are used to allow a function to call several other functions 33 | to create a string of data to use. 34 | 35 | The *trace_seq_init()* function initializes the trace sequence _s_. 36 | 37 | The *trace_seq_destroy()* function destroys the trace sequence _s_ and frees 38 | all its resources that it had used. 39 | 40 | The *trace_seq_reset()* function re-initializes the trace sequence _s_. All 41 | characters already written in _s_ will be deleted. 42 | 43 | The *trace_seq_terminate()* function terminates the trace sequence _s_. It puts 44 | the null character pass:['\0'] at the end of the buffer. 45 | 46 | The *trace_seq_putc()* function puts a single character _c_ in the trace 47 | sequence _s_. 48 | 49 | The *trace_seq_puts()* function puts a NULL terminated string _str_ in the 50 | trace sequence _s_. 51 | 52 | The *trace_seq_printf()* function puts a formated string _fmt _with 53 | variable arguments _..._ in the trace sequence _s_. 54 | 55 | The *trace_seq_vprintf()* function puts a formated string _fmt _with 56 | list of arguments _args_ in the trace sequence _s_. 57 | 58 | The *trace_seq_do_printf()* function prints the buffer of trace sequence _s_ to 59 | the standard output stdout. 60 | 61 | The *trace_seq_do_fprintf()* function prints the buffer of trace sequence _s_ 62 | to the given file _fp_. 63 | 64 | RETURN VALUE 65 | ------------ 66 | Both *trace_seq_putc()* and *trace_seq_puts()* functions return the number of 67 | characters put in the trace sequence, or 0 in case of an error 68 | 69 | Both *trace_seq_printf()* and *trace_seq_vprintf()* functions return 0 if the 70 | trace oversizes the buffer's free space, the number of characters printed, or 71 | a negative value in case of an error. 72 | 73 | Both *trace_seq_do_printf()* and *trace_seq_do_fprintf()* functions return the 74 | number of printed characters, or -1 in case of an error. 75 | 76 | EXAMPLE 77 | ------- 78 | [source,c] 79 | -- 80 | #include 81 | #include 82 | ... 83 | struct trace_seq seq; 84 | trace_seq_init(&seq); 85 | ... 86 | void foo_seq_print(struct trace_seq *tseq, char *format, ...) 87 | { 88 | va_list ap; 89 | va_start(ap, format); 90 | if (trace_seq_vprintf(tseq, format, ap) <= 0) { 91 | /* Failed to print in the trace sequence */ 92 | } 93 | va_end(ap); 94 | } 95 | 96 | trace_seq_reset(&seq); 97 | 98 | char *str = " MAN page example"; 99 | if (trace_seq_puts(&seq, str) != strlen(str)) { 100 | /* Failed to put str in the trace sequence */ 101 | } 102 | if (trace_seq_putc(&seq, ':') != 1) { 103 | /* Failed to put ':' in the trace sequence */ 104 | } 105 | if (trace_seq_printf(&seq, " trace sequence: %d", 1) <= 0) { 106 | /* Failed to print in the trace sequence */ 107 | } 108 | foo_seq_print( &seq, " %d\n", 2); 109 | 110 | trace_seq_terminate(&seq); 111 | ... 112 | 113 | if (trace_seq_do_printf(&seq) < 0 ) { 114 | /* Failed to print the sequence buffer to the standard output */ 115 | } 116 | FILE *fp = fopen("trace.txt", "w"); 117 | if (trace_seq_do_fprintf(&seq, fp) < 0 ) [ 118 | /* Failed to print the sequence buffer to the trace.txt file */ 119 | } 120 | 121 | trace_seq_destroy(&seq); 122 | ... 123 | -- 124 | 125 | FILES 126 | ----- 127 | [verse] 128 | -- 129 | *event-parse.h* 130 | Header file to include in order to have access to the library APIs. 131 | *trace-seq.h* 132 | Header file to include in order to have access to trace sequences related APIs. 133 | *-ltraceevent* 134 | Linker switch to add when building a program that uses the library. 135 | -- 136 | 137 | SEE ALSO 138 | -------- 139 | *libtraceevent*(3), *trace-cmd*(1) 140 | 141 | AUTHOR 142 | ------ 143 | [verse] 144 | -- 145 | *Steven Rostedt* , author of *libtraceevent*. 146 | *Tzvetomir Stoyanov* , author of this man page. 147 | -- 148 | REPORTING BUGS 149 | -------------- 150 | Report bugs to 151 | 152 | LICENSE 153 | ------- 154 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 155 | 156 | RESOURCES 157 | --------- 158 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 159 | -------------------------------------------------------------------------------- /Documentation/manpage-1.72.xsl: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Documentation/manpage-base.xsl: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 18 | 19 | 20 | 21 | sp 22 | 23 | 24 | 25 | 26 | 30 | 31 | 32 | br 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Documentation/manpage-bold-literal.xsl: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 9 | 10 | 11 | fB 12 | 13 | 14 | fR 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Documentation/manpage-normal.xsl: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | 8 | 9 | 10 | \ 11 | . 12 | 13 | 14 | -------------------------------------------------------------------------------- /Documentation/manpage-suppress-sp.xsl: -------------------------------------------------------------------------------- 1 | 5 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Makefile.meson: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | undefine CFLAGS 4 | 5 | # Makefiles suck: This macro sets a default value of $(2) for the 6 | # variable named by $(1), unless the variable has been set by 7 | # environment or command line. This is necessary for CC and AR 8 | # because make sets default values, so the simpler ?= approach 9 | # won't work as expected. 10 | define allow-override 11 | $(if $(or $(findstring environment,$(origin $(1))),\ 12 | $(findstring command line,$(origin $(1)))),,\ 13 | $(eval $(1) = $(2))) 14 | endef 15 | 16 | $(call allow-override,MESON,meson) 17 | $(call allow-override,MESON_BUILD_DIR,build) 18 | 19 | 20 | all: compile 21 | 22 | PHONY += compile 23 | compile: $(MESON_BUILD_DIR) force 24 | $(MESON) compile -C $(MESON_BUILD_DIR) 25 | 26 | $(MESON_BUILD_DIR): 27 | $(MESON) setup --prefix=$(prefix) $(MESON_BUILD_DIR) 28 | 29 | install: compile 30 | $(MESON) install -C $(MESON_BUILD_DIR) 31 | 32 | docs: $(MESON_BUILD_DIR) 33 | $(MESON) compile -C build docs 34 | 35 | PHONY += clean_meson 36 | clean_meson: 37 | $(Q)$(RM) -rf $(MESON_BUILD_DIR) 38 | 39 | PHONY += force 40 | force: 41 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | The official repository is here: 3 | 4 | https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 5 | 6 | 7 | To build: 8 | 9 | make; 10 | sudo make install; 11 | 12 | To build in a specific directory outside of the source directory: 13 | 14 | make O=/path/to/build; sudo make O=/path/to/build 15 | 16 | Note that the path needs to exist before building. 17 | 18 | To set the install path (the expected final location): 19 | 20 | make prefix=/usr; sudo make O=/path/to/build 21 | 22 | To install in a directory not for the local system (for use to move 23 | to another machine): 24 | 25 | make DESTDIR=/path/to/dest/ install 26 | 27 | Note, if you have write permission to the DESTDIR, then there is 28 | no reason to use sudo or switch to root. 29 | 30 | Note, DESTDIR must end with '/', otherwise the files will be appended 31 | to the path, which will most likely have unwanted results. 32 | 33 | Contributions: 34 | 35 | For questions about the use of the library, please send email to: 36 | 37 | linux-trace-users@vger.kernel.org 38 | 39 | Subscribe: http://vger.kernel.org/vger-lists.html#linux-trace-users 40 | Archives: https://lore.kernel.org/linux-trace-users/ 41 | 42 | For contributions to development, please send patches to: 43 | 44 | linux-trace-devel@vger.kernel.org 45 | 46 | Subscribe: http://vger.kernel.org/vger-lists.html#linux-trace-devel 47 | Archives: https://lore.kernel.org/linux-trace-devel/ 48 | 49 | Note, this project follows the style of submitting patches as described 50 | by the Linux kernel. 51 | 52 | https://www.kernel.org/doc/html/v5.4/process/submitting-patches.html 53 | -------------------------------------------------------------------------------- /check-manpages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: LGPL-2.1 3 | # Copyright (C) 2022, Google Inc, Steven Rostedt 4 | # 5 | # This checks if any function is listed in a man page that is not listed 6 | # in the main man page. 7 | 8 | if [ $# -lt 1 ]; then 9 | echo "usage: check-manpages man-page-path" 10 | exit 1 11 | fi 12 | 13 | cd $1 14 | 15 | MAIN=libtraceevent 16 | MAIN_FILE=${MAIN}.txt 17 | 18 | PROCESSED="" 19 | 20 | # Ignore man pages that do not contain functions 21 | IGNORE="" 22 | 23 | for man in ${MAIN}-*.txt; do 24 | 25 | for a in `sed -ne '/^NAME/,/^SYNOP/{/^[a-z]/{s/, *$//;s/,/\n/g;s/ //g;s/-.*$/-/;/-/{s/-//p;q};p}}' $man`; do 26 | if [ "${PROCESSED/:${a} /}" != "${PROCESSED}" ]; then 27 | P="${PROCESSED/:${a} */}" 28 | echo "Found ${a} in ${man} and in ${P/* /}" 29 | fi 30 | PROCESSED="${man}:${a} ${PROCESSED}" 31 | if [ "${IGNORE/$man/}" != "${IGNORE}" ]; then 32 | continue 33 | fi 34 | if ! grep -q '\*'${a}'\*' $MAIN_FILE; then 35 | if [ "$last" == "" ]; then 36 | echo 37 | fi 38 | if [ "$last" != "$man" ]; then 39 | echo "Missing functions from $MAIN_FILE that are in $man" 40 | last=$man 41 | fi 42 | echo " ${a}" 43 | fi 44 | done 45 | done 46 | 47 | DEPRECATED="*tep_print_field*" 48 | 49 | # Should not be used by applications, only internal use by trace-cmd 50 | IGNORE="*kbuffer_set_old_format* *kbuffer_raw_get* *kbuffer_ptr_delta* *kbuffer_translate_data*" 51 | 52 | HEADER=event-parse.h 53 | 54 | sed -ne 's/^[a-z].*[ \*]\([a-z_][a-z_]*\)(.*/\1/p' -e 's/^\([a-z_][a-z_]*\)(.*/\1/p' ../include/traceevent/{event-parse,trace-seq,kbuffer}.h | while read f; do 55 | if ! grep -q '\*'${f}'\*' $MAIN_FILE; then 56 | if [ "${DEPRECATED/\*$f\*/}" != "${DEPRECATED}" ]; then 57 | continue; 58 | fi 59 | if [ "${IGNORE/\*$f\*/}" != "${IGNORE}" ]; then 60 | continue; 61 | fi 62 | for head in event-parse.h trace-seq.h kbuffer.h; do 63 | if grep -q $f ../include/traceevent/$head; then 64 | if [ "$HEADER" != "$head" ]; then 65 | last="" 66 | HEADER=$head 67 | break 68 | fi 69 | fi 70 | done 71 | if [ "$last" == "" ]; then 72 | echo 73 | echo "Missing functions from $MAIN_FILE that are in $HEADER" 74 | last=$f 75 | fi 76 | echo " ${f}" 77 | fi 78 | done 79 | -------------------------------------------------------------------------------- /include/asm/bug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_ASM_BUG_H 3 | #define _TOOLS_ASM_BUG_H 4 | 5 | #include 6 | #include 7 | 8 | #define __WARN_printf(arg...) do { fprintf(stderr, arg); fprintf(stderr, "\n");} while (0) 9 | 10 | #define WARN(condition, format...) ({ \ 11 | int __ret_warn_on = !!(condition); \ 12 | if (unlikely(__ret_warn_on)) \ 13 | __WARN_printf(format); \ 14 | unlikely(__ret_warn_on); \ 15 | }) 16 | 17 | #define WARN_ON(condition) ({ \ 18 | int __ret_warn_on = !!(condition); \ 19 | if (unlikely(__ret_warn_on)) \ 20 | __WARN_printf("assertion failed at %s:%d\n", \ 21 | __FILE__, __LINE__); \ 22 | unlikely(__ret_warn_on); \ 23 | }) 24 | 25 | #define WARN_ON_ONCE(condition) ({ \ 26 | static int __warned; \ 27 | int __ret_warn_once = !!(condition); \ 28 | \ 29 | if (unlikely(__ret_warn_once && !__warned)) { \ 30 | __warned = true; \ 31 | WARN_ON(1); \ 32 | } \ 33 | unlikely(__ret_warn_once); \ 34 | }) 35 | 36 | #define WARN_ONCE(condition, format...) ({ \ 37 | static int __warned; \ 38 | int __ret_warn_once = !!(condition); \ 39 | \ 40 | if (unlikely(__ret_warn_once)) \ 41 | if (WARN(!__warned, format)) \ 42 | __warned = 1; \ 43 | unlikely(__ret_warn_once); \ 44 | }) 45 | 46 | #endif /* _TOOLS_ASM_BUG_H */ 47 | -------------------------------------------------------------------------------- /include/linux/compiler-gcc.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_LINUX_COMPILER_H_ 3 | #error "Please don't include directly, include instead." 4 | #endif 5 | 6 | /* 7 | * Common definitions for all gcc versions go here. 8 | */ 9 | #ifndef GCC_VERSION 10 | #define GCC_VERSION (__GNUC__ * 10000 \ 11 | + __GNUC_MINOR__ * 100 \ 12 | + __GNUC_PATCHLEVEL__) 13 | #endif 14 | 15 | #if GCC_VERSION >= 70000 && !defined(__CHECKER__) 16 | # define __fallthrough __attribute__ ((fallthrough)) 17 | #endif 18 | 19 | #if GCC_VERSION >= 40300 20 | # define __compiletime_error(message) __attribute__((error(message))) 21 | #endif /* GCC_VERSION >= 40300 */ 22 | 23 | /* &a[0] degrades to a pointer: a different type from an array */ 24 | #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) 25 | 26 | #ifndef __pure 27 | #define __pure __attribute__((pure)) 28 | #endif 29 | #define noinline __attribute__((noinline)) 30 | #ifdef __has_attribute 31 | #if __has_attribute(disable_tail_calls) 32 | #define __no_tail_call __attribute__((disable_tail_calls)) 33 | #endif 34 | #endif 35 | #ifndef __no_tail_call 36 | #if GCC_VERSION > 40201 37 | #define __no_tail_call __attribute__((optimize("no-optimize-sibling-calls"))) 38 | #else 39 | #define __no_tail_call 40 | #endif 41 | #endif 42 | #ifndef __packed 43 | #define __packed __attribute__((packed)) 44 | #endif 45 | #ifndef __noreturn 46 | #define __noreturn __attribute__((noreturn)) 47 | #endif 48 | #ifndef __aligned 49 | #define __aligned(x) __attribute__((aligned(x))) 50 | #endif 51 | #define __printf(a, b) __attribute__((format(printf, a, b))) 52 | #define __scanf(a, b) __attribute__((format(scanf, a, b))) 53 | 54 | #if GCC_VERSION >= 50100 55 | #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 56 | #endif 57 | -------------------------------------------------------------------------------- /include/linux/time64.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_LINUX_TIME64_H 3 | #define _TOOLS_LINUX_TIME64_H 4 | 5 | #define MSEC_PER_SEC 1000L 6 | #define USEC_PER_MSEC 1000L 7 | #define NSEC_PER_USEC 1000L 8 | #define NSEC_PER_MSEC 1000000L 9 | #define USEC_PER_SEC 1000000L 10 | #define NSEC_PER_SEC 1000000000L 11 | #define FSEC_PER_SEC 1000000000000000LL 12 | 13 | #endif /* _LINUX_TIME64_H */ 14 | -------------------------------------------------------------------------------- /include/traceevent/event-utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef __TEP_EVENT_UTIL_H 7 | #define __TEP_EVENT_UTIL_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "event-parse.h" 14 | 15 | void tep_warning(const char *fmt, ...); 16 | void tep_info(const char *fmt, ...); 17 | 18 | /* Can be overridden */ 19 | int tep_vprint(const char *name, enum tep_loglevel level, 20 | bool print_err, const char *fmt, va_list ap); 21 | 22 | /* The actual call of tep_vprint() for overrides to use */ 23 | int __tep_vprint(const char *name, enum tep_loglevel level, 24 | bool print_err, const char *fmt, va_list ap); 25 | 26 | 27 | #define __deprecated(msg) __attribute__((deprecated("msg"))) 28 | 29 | /* For backward compatibilty, do not use */ 30 | int tep_vwarning(const char *name, const char *fmt, va_list ap) __deprecated(Use tep_vprint instead); 31 | void pr_stat(const char *fmt, ...) __deprecated(Use tep_info instead); 32 | void vpr_stat(const char *fmt, va_list ap) __deprecated(Use tep_vprint instead); 33 | void __pr_stat(const char *fmt, ...) __deprecated(Use tep_info instead);; 34 | void __vpr_stat(const char *fmt, va_list ap) __deprecated(Use tep_vprint instead);; 35 | 36 | #define min(x, y) ({ \ 37 | typeof(x) _min1 = (x); \ 38 | typeof(y) _min2 = (y); \ 39 | (void) (&_min1 == &_min2); \ 40 | _min1 < _min2 ? _min1 : _min2; }) 41 | 42 | static inline char *strim(char *string) 43 | { 44 | char *ret; 45 | 46 | if (!string) 47 | return NULL; 48 | while (*string) { 49 | if (!isspace(*string)) 50 | break; 51 | string++; 52 | } 53 | ret = string; 54 | 55 | string = ret + strlen(ret) - 1; 56 | while (string > ret) { 57 | if (!isspace(*string)) 58 | break; 59 | string--; 60 | } 61 | string[1] = 0; 62 | 63 | return ret; 64 | } 65 | 66 | static inline int has_text(const char *text) 67 | { 68 | if (!text) 69 | return 0; 70 | 71 | while (*text) { 72 | if (!isspace(*text)) 73 | return 1; 74 | text++; 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/traceevent/kbuffer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2012 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _KBUFFER_H 7 | #define _KBUFFER_H 8 | 9 | #ifndef TS_SHIFT 10 | #define TS_SHIFT 27 11 | #endif 12 | 13 | enum kbuffer_endian { 14 | KBUFFER_ENDIAN_BIG, 15 | KBUFFER_ENDIAN_LITTLE, 16 | KBUFFER_ENDIAN_SAME_AS_HOST, 17 | }; 18 | 19 | enum kbuffer_long_size { 20 | KBUFFER_LSIZE_4, 21 | KBUFFER_LSIZE_8, 22 | KBUFFER_LSIZE_SAME_AS_HOST, 23 | }; 24 | 25 | enum { 26 | KBUFFER_TYPE_PADDING = 29, 27 | KBUFFER_TYPE_TIME_EXTEND = 30, 28 | KBUFFER_TYPE_TIME_STAMP = 31, 29 | }; 30 | 31 | struct kbuffer; 32 | 33 | struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian); 34 | struct kbuffer *kbuffer_dup(struct kbuffer *kbuf); 35 | void kbuffer_free(struct kbuffer *kbuf); 36 | int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer); 37 | int kbuffer_refresh(struct kbuffer *kbuf); 38 | void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts); 39 | void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts); 40 | unsigned long long kbuffer_timestamp(struct kbuffer *kbuf); 41 | unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf); 42 | unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr); 43 | 44 | void *kbuffer_translate_data(int swap, void *data, unsigned int *size); 45 | 46 | void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts); 47 | int kbuffer_read_buffer(struct kbuffer *kbuf, void *buffer, int len); 48 | 49 | int kbuffer_curr_index(struct kbuffer *kbuf); 50 | 51 | int kbuffer_curr_offset(struct kbuffer *kbuf); 52 | int kbuffer_curr_size(struct kbuffer *kbuf); 53 | int kbuffer_event_size(struct kbuffer *kbuf); 54 | int kbuffer_missed_events(struct kbuffer *kbuf); 55 | int kbuffer_subbuffer_size(struct kbuffer *kbuf); 56 | void *kbuffer_subbuffer(struct kbuffer *kbuf); 57 | 58 | void kbuffer_set_old_format(struct kbuffer *kbuf); 59 | int kbuffer_start_of_data(struct kbuffer *kbuf); 60 | 61 | /* Debugging */ 62 | 63 | struct kbuffer_raw_info { 64 | int type; 65 | int length; 66 | unsigned long long delta; 67 | void *next; 68 | }; 69 | 70 | /* Read raw data */ 71 | struct kbuffer_raw_info *kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, 72 | struct kbuffer_raw_info *info); 73 | 74 | #endif /* _K_BUFFER_H */ 75 | -------------------------------------------------------------------------------- /include/traceevent/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | headers = [ 6 | 'event-parse.h', 7 | 'event-utils.h', 8 | 'kbuffer.h', 9 | 'trace-seq.h', 10 | ] 11 | 12 | foreach h : headers 13 | install_headers(h, subdir : 'traceevent') 14 | endforeach 15 | -------------------------------------------------------------------------------- /include/traceevent/trace-seq.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | 7 | #ifndef _TRACE_SEQ_H 8 | #define _TRACE_SEQ_H 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /* ----------------------- trace_seq ----------------------- */ 18 | 19 | #ifndef TRACE_SEQ_BUF_SIZE 20 | #define TRACE_SEQ_BUF_SIZE 4096 21 | #endif 22 | 23 | enum trace_seq_fail { 24 | TRACE_SEQ__GOOD, 25 | TRACE_SEQ__BUFFER_POISONED, 26 | TRACE_SEQ__MEM_ALLOC_FAILED, 27 | }; 28 | 29 | /* 30 | * Trace sequences are used to allow a function to call several other functions 31 | * to create a string of data to use (up to a max of PAGE_SIZE). 32 | */ 33 | 34 | struct trace_seq { 35 | char *buffer; 36 | unsigned int buffer_size; 37 | unsigned int len; 38 | unsigned int readpos; 39 | enum trace_seq_fail state; 40 | }; 41 | 42 | void trace_seq_init(struct trace_seq *s); 43 | void trace_seq_reset(struct trace_seq *s); 44 | void trace_seq_destroy(struct trace_seq *s); 45 | 46 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 47 | __attribute__ ((format (printf, 2, 3))); 48 | extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 49 | __attribute__ ((format (printf, 2, 0))); 50 | 51 | extern int trace_seq_puts(struct trace_seq *s, const char *str); 52 | extern int trace_seq_putc(struct trace_seq *s, unsigned char c); 53 | 54 | extern void trace_seq_terminate(struct trace_seq *s); 55 | 56 | extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp); 57 | extern int trace_seq_do_printf(struct trace_seq *s); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* _TRACE_SEQ_H */ 64 | -------------------------------------------------------------------------------- /libtraceevent.pc.template: -------------------------------------------------------------------------------- 1 | prefix=INSTALL_PREFIX 2 | libdir=${prefix}/LIB_DIR 3 | includedir=${prefix}/HEADER_DIR 4 | 5 | Name: libtraceevent 6 | URL: https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 7 | Description: Linux kernel trace event library 8 | Version: LIB_VERSION 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -ltraceevent 11 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | project( 6 | 'libtraceevent', ['c'], 7 | meson_version: '>= 0.58.0', 8 | license: 'LGPL-2.1', 9 | version: '1.8.4', 10 | default_options: [ 11 | 'c_std=gnu99', 12 | 'buildtype=debug', 13 | 'default_library=both', 14 | 'prefix=/usr/local', 15 | 'warning_level=1', 16 | ]) 17 | 18 | library_version = meson.project_version() 19 | 20 | cunit_dep = dependency('cunit', required : false) 21 | 22 | prefixdir = get_option('prefix') 23 | mandir = join_paths(prefixdir, get_option('mandir')) 24 | htmldir = join_paths(prefixdir, get_option('htmldir')) 25 | libdir = join_paths(prefixdir, get_option('libdir')) 26 | plugindir = get_option('plugindir') 27 | if plugindir == '' 28 | plugindir = join_paths(libdir, 'traceevent/plugins') 29 | endif 30 | 31 | add_project_arguments( 32 | [ 33 | '-D_GNU_SOURCE', 34 | '-DPLUGIN_DIR="@0@"'.format(plugindir), 35 | ], 36 | language : 'c', 37 | ) 38 | 39 | incdir = include_directories(['include', 'include/traceevent']) 40 | 41 | subdir('src') 42 | subdir('include/traceevent') 43 | subdir('plugins') 44 | if cunit_dep.found() 45 | subdir('utest') 46 | endif 47 | subdir('samples') 48 | 49 | if get_option('doc') 50 | subdir('Documentation') 51 | 52 | custom_target( 53 | 'docs', 54 | output: 'docs', 55 | depends: [html, man], 56 | command: ['echo']) 57 | endif 58 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | option('plugindir', type : 'string', 6 | description : 'set the plugin dir') 7 | option('htmldir', type : 'string', value : 'share/doc/libtraceevent-doc', 8 | description : 'directory for HTML documentation') 9 | option('asciidoctor', type : 'boolean', value: false, 10 | description : 'use asciidoctor instead of asciidoc') 11 | option('docbook-xls-172', type : 'boolean', value : false, 12 | description : 'enable docbook XLS 172 workaround') 13 | option('asciidoc-no-roff', type : 'boolean', value : false, 14 | description : 'enable no roff workaround') 15 | option('man-bold-literal', type : 'boolean', value : false, 16 | description : 'enable bold literals') 17 | option('docbook-suppress-sp', type : 'boolean', value : false, 18 | description : 'docbook suppress sp') 19 | option('doc', type : 'boolean', value: true, 20 | description : 'produce documentation') 21 | -------------------------------------------------------------------------------- /plugins/Build: -------------------------------------------------------------------------------- 1 | plugin_jbd2-y += plugin_jbd2.o 2 | plugin_hrtimer-y += plugin_hrtimer.o 3 | plugin_kmem-y += plugin_kmem.o 4 | plugin_kvm-y += plugin_kvm.o 5 | plugin_mac80211-y += plugin_mac80211.o 6 | plugin_sched_switch-y += plugin_sched_switch.o 7 | plugin_function-y += plugin_function.o 8 | plugin_futex-y += plugin_futex.o 9 | plugin_xen-y += plugin_xen.o 10 | plugin_scsi-y += plugin_scsi.o 11 | plugin_cfg80211-y += plugin_cfg80211.o 12 | plugin_tlb-y += plugin_tlb.o -------------------------------------------------------------------------------- /plugins/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | #MAKEFLAGS += --no-print-directory 4 | 5 | 6 | # Makefiles suck: This macro sets a default value of $(2) for the 7 | # variable named by $(1), unless the variable has been set by 8 | # environment or command line. This is necessary for CC and AR 9 | # because make sets default values, so the simpler ?= approach 10 | # won't work as expected. 11 | define allow-override 12 | $(if $(or $(findstring environment,$(origin $(1))),\ 13 | $(findstring command line,$(origin $(1)))),,\ 14 | $(eval $(1) = $(2))) 15 | endef 16 | 17 | # Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. 18 | $(call allow-override,CC,$(CROSS_COMPILE)gcc) 19 | $(call allow-override,AR,$(CROSS_COMPILE)ar) 20 | $(call allow-override,NM,$(CROSS_COMPILE)nm) 21 | $(call allow-override,PKG_CONFIG,pkg-config) 22 | 23 | EXT = -std=gnu99 24 | INSTALL = install 25 | 26 | # Use DESTDIR for installing into a different root directory. 27 | # This is useful for building a package. The program will be 28 | # installed in this directory as if it was the root directory. 29 | # Then the build tool can move it later. 30 | DESTDIR ?= 31 | DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' 32 | 33 | LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 34 | ifeq ($(LP64), 1) 35 | libdir_relative_tmp = lib64 36 | else 37 | libdir_relative_tmp = lib 38 | endif 39 | 40 | libdir_relative ?= $(libdir_relative_tmp) 41 | prefix ?= /usr/local 42 | libdir = $(prefix)/$(libdir_relative) 43 | 44 | include ../scripts/utils.mk 45 | 46 | # copy a bit from Linux kbuild 47 | 48 | ifeq ("$(origin V)", "command line") 49 | VERBOSE = $(V) 50 | endif 51 | ifndef VERBOSE 52 | VERBOSE = 0 53 | endif 54 | 55 | # Shell quotes 56 | plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) 57 | 58 | CONFIG_INCLUDES = 59 | CONFIG_LIBS = 60 | CONFIG_FLAGS = 61 | 62 | OBJ = $@ 63 | N = 64 | 65 | INCLUDES = -I. -I.. -I../src -I $(srctree)/include -I $(EP_HEADERS_DIR) $(CONFIG_INCLUDES) 66 | 67 | # Set compile option CFLAGS 68 | ifdef EXTRA_CFLAGS 69 | CFLAGS := $(EXTRA_CFLAGS) 70 | else 71 | CFLAGS := -g -Wall 72 | endif 73 | 74 | # Append required CFLAGS 75 | override CFLAGS += -fPIC 76 | override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 77 | override CFLAGS += $(udis86-flags) -D_GNU_SOURCE 78 | 79 | ifeq ($(VERBOSE),1) 80 | Q = 81 | else 82 | Q = @ 83 | endif 84 | 85 | export srctree OUTPUT CC LD CFLAGS V 86 | 87 | DYNAMIC_LIST_FILE := $(bdir)/libtraceevent-dynamic-list 88 | 89 | PLUGINS = plugin_jbd2.so 90 | PLUGINS += plugin_hrtimer.so 91 | PLUGINS += plugin_kmem.so 92 | PLUGINS += plugin_kvm.so 93 | PLUGINS += plugin_mac80211.so 94 | PLUGINS += plugin_net.so 95 | PLUGINS += plugin_sched_switch.so 96 | PLUGINS += plugin_function.so 97 | PLUGINS += plugin_futex.so 98 | PLUGINS += plugin_xen.so 99 | PLUGINS += plugin_scsi.so 100 | PLUGINS += plugin_cfg80211.so 101 | PLUGINS += plugin_tlb.so 102 | 103 | PLUGINS := $(PLUGINS:%.so=$(bdir)/%.so) 104 | DEPS := $(PLUGINS:$(bdir)/%.so=$(bdir)/.%.d) 105 | 106 | plugins: $(PLUGINS) $(DYNAMIC_LIST_FILE) 107 | 108 | $(PLUGINS): | $(bdir) 109 | $(DEPS): | $(bdir) 110 | 111 | $(bdir)/%.so: $(srctree)/plugins/%.c 112 | $(Q)$(call do_plugin_build) 113 | 114 | define update_dir 115 | (echo $1 > $@.tmp; \ 116 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 117 | rm -f $@.tmp; \ 118 | else \ 119 | echo ' UPDATE $@'; \ 120 | mv -f $@.tmp $@; \ 121 | fi); 122 | endef 123 | 124 | tags: force 125 | $(RM) tags 126 | find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 127 | --regex-c++='/_PE\(([^,)]*).*/TEP_ERRNO__\1/' 128 | 129 | TAGS: force 130 | $(RM) TAGS 131 | find . -name '*.[ch]' | xargs etags \ 132 | --regex='/_PE(\([^,)]*\).*/TEP_ERRNO__\1/' 133 | 134 | define do_install_plugins 135 | for plugin in $1; do \ 136 | $(call do_install,$$plugin,$(plugin_dir_SQ)); \ 137 | done 138 | endef 139 | 140 | define do_generate_dynamic_list_file 141 | symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \ 142 | xargs echo "U w W" | tr 'w ' 'W\n' | sort -u | xargs echo`;\ 143 | if [ "$$symbol_type" = "U W" ];then \ 144 | (echo '{'; \ 145 | $(NM) -u -D $1 | awk 'NF>1 {sub("@.*", "", $$2); print "\t"$$2";"}' | sort -u;\ 146 | echo '};'; \ 147 | ) > $2; \ 148 | else \ 149 | (echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\ 150 | fi 151 | endef 152 | 153 | $(DYNAMIC_LIST_FILE): $(PLUGINS) 154 | $(Q)($(print_gen)$(call do_generate_dynamic_list_file, $(PLUGINS), $@)) 155 | 156 | install: $(PLUGINS) 157 | $(Q)$(call do_install_plugins, $(PLUGINS)) 158 | 159 | clean: 160 | $(Q)$(call do_clean, $(DYNAMIC_LIST_FILE) $(PLUGINS)) 161 | 162 | PHONY += force plugins $(DYNAMIC_LIST_FILE) 163 | force: 164 | 165 | # Declare the contents of the .PHONY variable as phony. We keep that 166 | # information in a variable so we can use it in if_changed and friends. 167 | .PHONY: $(PHONY) 168 | -------------------------------------------------------------------------------- /plugins/dynamic_list.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: LGPL-2.1 3 | 4 | symbol_type=$(nm -u -D $@ | awk 'NF>1 {print $1}' | xargs echo "U w W" | 5 | tr 'w ' 'W\n' | sort -u | xargs echo) 6 | 7 | if [ "$symbol_type" = "U W" ]; then 8 | echo '{' 9 | nm -u -D $@ | awk 'NF>1 {sub("@.*", "", $2); print "\t"$2";"}' | sort -u 10 | echo '};' 11 | fi 12 | -------------------------------------------------------------------------------- /plugins/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | plugins = [ 6 | 'plugin_cfg80211.c', 7 | 'plugin_function.c', 8 | 'plugin_futex.c', 9 | 'plugin_hrtimer.c', 10 | 'plugin_jbd2.c', 11 | 'plugin_kmem.c', 12 | 'plugin_kvm.c', 13 | 'plugin_mac80211.c', 14 | 'plugin_sched_switch.c', 15 | 'plugin_scsi.c', 16 | 'plugin_tlb.c', 17 | 'plugin_xen.c', 18 | ] 19 | 20 | pdeps = [] 21 | foreach plugin : plugins 22 | pdeps += shared_module( 23 | plugin.replace('.c', ''), 24 | plugin, 25 | name_prefix: '', 26 | dependencies: [libtraceevent_dep], 27 | include_directories: [incdir], 28 | install: true, 29 | install_dir: plugindir) 30 | endforeach 31 | 32 | # perf needs the exported symbol list 33 | dynamic_list_file = find_program('dynamic_list.sh') 34 | custom_target( 35 | 'dynamic_list', 36 | depends: pdeps, 37 | input: pdeps, 38 | output: 'libtraceevent-dynamic-list', 39 | command: [dynamic_list_file, '@INPUT@'], 40 | capture: true, 41 | build_by_default: true, 42 | install: true, 43 | install_dir: plugindir) 44 | -------------------------------------------------------------------------------- /plugins/plugin_cfg80211.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "event-parse.h" 7 | 8 | /* 9 | * From glibc endian.h, for older systems where it is not present, e.g.: RHEL5, 10 | * Fedora6. 11 | */ 12 | #ifndef le16toh 13 | # if __BYTE_ORDER == __LITTLE_ENDIAN 14 | # define le16toh(x) (x) 15 | # else 16 | # define le16toh(x) __bswap_16 (x) 17 | # endif 18 | #endif 19 | 20 | 21 | static unsigned long long 22 | process___le16_to_cpup(struct trace_seq *s, unsigned long long *args) 23 | { 24 | uint16_t *val = (uint16_t *) (unsigned long) args[0]; 25 | return val ? (long long) le16toh(*val) : 0; 26 | } 27 | 28 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 29 | { 30 | tep_register_print_function(tep, 31 | process___le16_to_cpup, 32 | TEP_FUNC_ARG_INT, 33 | "__le16_to_cpup", 34 | TEP_FUNC_ARG_PTR, 35 | TEP_FUNC_ARG_VOID); 36 | return 0; 37 | } 38 | 39 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 40 | { 41 | tep_unregister_print_function(tep, process___le16_to_cpup, 42 | "__le16_to_cpup"); 43 | } 44 | -------------------------------------------------------------------------------- /plugins/plugin_futex.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2017 National Instruments Corp. 4 | * 5 | * Author: Julia Cartwright 6 | * 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "event-parse.h" 14 | 15 | #define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0])) 16 | 17 | struct futex_args { 18 | unsigned long long uaddr; 19 | unsigned long long op; 20 | unsigned long long val; 21 | unsigned long long utime; /* or val2 */ 22 | unsigned long long uaddr2; 23 | unsigned long long val3; 24 | }; 25 | 26 | struct futex_op { 27 | const char *name; 28 | const char *fmt_val; 29 | const char *fmt_utime; 30 | const char *fmt_uaddr2; 31 | const char *fmt_val3; 32 | }; 33 | 34 | static const struct futex_op futex_op_tbl[] = { 35 | { "FUTEX_WAIT", " val=0x%08llx", " utime=0x%08llx", NULL, NULL }, 36 | { "FUTEX_WAKE", " val=%llu", NULL, NULL, NULL }, 37 | { "FUTEX_FD", " val=%llu", NULL, NULL, NULL }, 38 | { "FUTEX_REQUEUE", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", NULL }, 39 | { "FUTEX_CMP_REQUEUE", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" }, 40 | { "FUTEX_WAKE_OP", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" }, 41 | { "FUTEX_LOCK_PI", NULL, " utime=0x%08llx", NULL, NULL }, 42 | { "FUTEX_UNLOCK_PI", NULL, NULL, NULL, NULL }, 43 | { "FUTEX_TRYLOCK_PI", NULL, NULL, NULL, NULL }, 44 | { "FUTEX_WAIT_BITSET", " val=0x%08llx", " utime=0x%08llx", NULL, " val3=0x%08llx" }, 45 | { "FUTEX_WAKE_BITSET", " val=%llu", NULL, NULL, " val3=0x%08llx" }, 46 | { "FUTEX_WAIT_REQUEUE_PI", " val=0x%08llx", " utime=0x%08llx", " uaddr2=0x%08llx", " val3=0x%08llx" }, 47 | { "FUTEX_CMP_REQUEUE_PI", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" }, 48 | }; 49 | 50 | 51 | static void futex_print(struct trace_seq *s, const struct futex_args *args, 52 | const struct futex_op *fop) 53 | { 54 | trace_seq_printf(s, " uaddr=0x%08llx", args->uaddr); 55 | 56 | if (fop->fmt_val) 57 | trace_seq_printf(s, fop->fmt_val, args->val); 58 | 59 | if (fop->fmt_utime) 60 | trace_seq_printf(s,fop->fmt_utime, args->utime); 61 | 62 | if (fop->fmt_uaddr2) 63 | trace_seq_printf(s, fop->fmt_uaddr2, args->uaddr2); 64 | 65 | if (fop->fmt_val3) 66 | trace_seq_printf(s, fop->fmt_val3, args->val3); 67 | } 68 | 69 | static int futex_handler(struct trace_seq *s, struct tep_record *record, 70 | struct tep_event *event, void *context) 71 | { 72 | const struct futex_op *fop; 73 | struct futex_args args; 74 | unsigned long long cmd; 75 | 76 | if (tep_get_field_val(s, event, "uaddr", record, &args.uaddr, 1)) 77 | return 1; 78 | 79 | if (tep_get_field_val(s, event, "op", record, &args.op, 1)) 80 | return 1; 81 | 82 | if (tep_get_field_val(s, event, "val", record, &args.val, 1)) 83 | return 1; 84 | 85 | if (tep_get_field_val(s, event, "utime", record, &args.utime, 1)) 86 | return 1; 87 | 88 | if (tep_get_field_val(s, event, "uaddr2", record, &args.uaddr2, 1)) 89 | return 1; 90 | 91 | if (tep_get_field_val(s, event, "val3", record, &args.val3, 1)) 92 | return 1; 93 | 94 | cmd = args.op & FUTEX_CMD_MASK; 95 | if (cmd >= ARRAY_SIZE(futex_op_tbl)) 96 | return 1; 97 | 98 | fop = &futex_op_tbl[cmd]; 99 | 100 | trace_seq_printf(s, "op=%s", fop->name); 101 | 102 | if (args.op & FUTEX_PRIVATE_FLAG) 103 | trace_seq_puts(s, "|FUTEX_PRIVATE_FLAG"); 104 | 105 | if (args.op & FUTEX_CLOCK_REALTIME) 106 | trace_seq_puts(s, "|FUTEX_CLOCK_REALTIME"); 107 | 108 | futex_print(s, &args, fop); 109 | return 0; 110 | } 111 | 112 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 113 | { 114 | tep_register_event_handler(tep, -1, "syscalls", "sys_enter_futex", 115 | futex_handler, NULL); 116 | return 0; 117 | } 118 | 119 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 120 | { 121 | tep_unregister_event_handler(tep, -1, "syscalls", "sys_enter_futex", 122 | futex_handler, NULL); 123 | } 124 | -------------------------------------------------------------------------------- /plugins/plugin_hrtimer.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt 4 | * Copyright (C) 2009 Johannes Berg 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #include "event-parse.h" 11 | #include "trace-seq.h" 12 | 13 | static int timer_expire_handler(struct trace_seq *s, 14 | struct tep_record *record, 15 | struct tep_event *event, void *context) 16 | { 17 | trace_seq_printf(s, "hrtimer="); 18 | 19 | if (tep_print_num_field(s, "0x%llx", event, "timer", 20 | record, 0) == -1) 21 | tep_print_num_field(s, "0x%llx", event, "hrtimer", 22 | record, 1); 23 | 24 | trace_seq_printf(s, " now="); 25 | 26 | tep_print_num_field(s, "%llu", event, "now", record, 1); 27 | 28 | tep_print_func_field(s, " function=%s", event, "function", 29 | record, 0); 30 | return 0; 31 | } 32 | 33 | static int timer_start_handler(struct trace_seq *s, 34 | struct tep_record *record, 35 | struct tep_event *event, void *context) 36 | { 37 | trace_seq_printf(s, "hrtimer="); 38 | 39 | if (tep_print_num_field(s, "0x%llx", event, "timer", 40 | record, 0) == -1) 41 | tep_print_num_field(s, "0x%llx", event, "hrtimer", 42 | record, 1); 43 | 44 | tep_print_func_field(s, " function=%s", event, "function", 45 | record, 0); 46 | 47 | trace_seq_printf(s, " expires="); 48 | tep_print_num_field(s, "%llu", event, "expires", record, 1); 49 | 50 | trace_seq_printf(s, " softexpires="); 51 | tep_print_num_field(s, "%llu", event, "softexpires", record, 1); 52 | return 0; 53 | } 54 | 55 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 56 | { 57 | tep_register_event_handler(tep, -1, 58 | "timer", "hrtimer_expire_entry", 59 | timer_expire_handler, NULL); 60 | 61 | tep_register_event_handler(tep, -1, "timer", "hrtimer_start", 62 | timer_start_handler, NULL); 63 | return 0; 64 | } 65 | 66 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 67 | { 68 | tep_unregister_event_handler(tep, -1, 69 | "timer", "hrtimer_expire_entry", 70 | timer_expire_handler, NULL); 71 | 72 | tep_unregister_event_handler(tep, -1, "timer", "hrtimer_start", 73 | timer_start_handler, NULL); 74 | } 75 | -------------------------------------------------------------------------------- /plugins/plugin_jbd2.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include "event-parse.h" 10 | #include "trace-seq.h" 11 | 12 | #define MINORBITS 20 13 | #define MINORMASK ((1U << MINORBITS) - 1) 14 | 15 | #define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) 16 | #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) 17 | 18 | static unsigned long long 19 | process_jbd2_dev_to_name(struct trace_seq *s, unsigned long long *args) 20 | { 21 | unsigned int dev = args[0]; 22 | 23 | trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev)); 24 | return 0; 25 | } 26 | 27 | static unsigned long long 28 | process_jiffies_to_msecs(struct trace_seq *s, unsigned long long *args) 29 | { 30 | unsigned long long jiffies = args[0]; 31 | 32 | trace_seq_printf(s, "%lld", jiffies); 33 | return jiffies; 34 | } 35 | 36 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 37 | { 38 | tep_register_print_function(tep, 39 | process_jbd2_dev_to_name, 40 | TEP_FUNC_ARG_STRING, 41 | "jbd2_dev_to_name", 42 | TEP_FUNC_ARG_INT, 43 | TEP_FUNC_ARG_VOID); 44 | 45 | tep_register_print_function(tep, 46 | process_jiffies_to_msecs, 47 | TEP_FUNC_ARG_LONG, 48 | "jiffies_to_msecs", 49 | TEP_FUNC_ARG_LONG, 50 | TEP_FUNC_ARG_VOID); 51 | return 0; 52 | } 53 | 54 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 55 | { 56 | tep_unregister_print_function(tep, process_jbd2_dev_to_name, 57 | "jbd2_dev_to_name"); 58 | 59 | tep_unregister_print_function(tep, process_jiffies_to_msecs, 60 | "jiffies_to_msecs"); 61 | } 62 | -------------------------------------------------------------------------------- /plugins/plugin_kmem.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include "event-parse.h" 10 | #include "trace-seq.h" 11 | 12 | static int call_site_handler(struct trace_seq *s, struct tep_record *record, 13 | struct tep_event *event, void *context) 14 | { 15 | struct tep_format_field *field; 16 | unsigned long long val, addr; 17 | void *data = record->data; 18 | const char *func; 19 | 20 | field = tep_find_field(event, "call_site"); 21 | if (!field) 22 | return 1; 23 | 24 | if (tep_read_number_field(field, data, &val)) 25 | return 1; 26 | 27 | func = tep_find_function(event->tep, val); 28 | if (!func) 29 | return 1; 30 | 31 | addr = tep_find_function_address(event->tep, val); 32 | 33 | trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr)); 34 | return 1; 35 | } 36 | 37 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 38 | { 39 | tep_register_event_handler(tep, -1, "kmem", "kfree", 40 | call_site_handler, NULL); 41 | 42 | tep_register_event_handler(tep, -1, "kmem", "kmalloc", 43 | call_site_handler, NULL); 44 | 45 | tep_register_event_handler(tep, -1, "kmem", "kmalloc_node", 46 | call_site_handler, NULL); 47 | 48 | tep_register_event_handler(tep, -1, "kmem", "kmem_cache_alloc", 49 | call_site_handler, NULL); 50 | 51 | tep_register_event_handler(tep, -1, "kmem", 52 | "kmem_cache_alloc_node", 53 | call_site_handler, NULL); 54 | 55 | tep_register_event_handler(tep, -1, "kmem", "kmem_cache_free", 56 | call_site_handler, NULL); 57 | return 0; 58 | } 59 | 60 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 61 | { 62 | tep_unregister_event_handler(tep, -1, "kmem", "kfree", 63 | call_site_handler, NULL); 64 | 65 | tep_unregister_event_handler(tep, -1, "kmem", "kmalloc", 66 | call_site_handler, NULL); 67 | 68 | tep_unregister_event_handler(tep, -1, "kmem", "kmalloc_node", 69 | call_site_handler, NULL); 70 | 71 | tep_unregister_event_handler(tep, -1, "kmem", "kmem_cache_alloc", 72 | call_site_handler, NULL); 73 | 74 | tep_unregister_event_handler(tep, -1, "kmem", 75 | "kmem_cache_alloc_node", 76 | call_site_handler, NULL); 77 | 78 | tep_unregister_event_handler(tep, -1, "kmem", "kmem_cache_free", 79 | call_site_handler, NULL); 80 | } 81 | -------------------------------------------------------------------------------- /plugins/plugin_mac80211.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009 Johannes Berg 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include "event-parse.h" 10 | #include "trace-seq.h" 11 | 12 | #define INDENT 65 13 | 14 | static void print_string(struct trace_seq *s, struct tep_event *event, 15 | const char *name, const void *data) 16 | { 17 | struct tep_format_field *f = tep_find_field(event, name); 18 | int offset; 19 | int length; 20 | 21 | if (!f) { 22 | trace_seq_printf(s, "NOTFOUND:%s", name); 23 | return; 24 | } 25 | 26 | offset = f->offset; 27 | length = f->size; 28 | 29 | if (!strncmp(f->type, "__data_loc", 10)) { 30 | unsigned long long v; 31 | if (tep_read_number_field(f, data, &v)) { 32 | trace_seq_printf(s, "invalid_data_loc"); 33 | return; 34 | } 35 | offset = v & 0xffff; 36 | length = v >> 16; 37 | } 38 | 39 | trace_seq_printf(s, "%.*s", length, (char *)data + offset); 40 | } 41 | 42 | #define SF(fn) tep_print_num_field(s, fn ":%d", event, fn, record, 0) 43 | #define SFX(fn) tep_print_num_field(s, fn ":%#x", event, fn, record, 0) 44 | #define SP() trace_seq_putc(s, ' ') 45 | 46 | static int drv_bss_info_changed(struct trace_seq *s, 47 | struct tep_record *record, 48 | struct tep_event *event, void *context) 49 | { 50 | void *data = record->data; 51 | 52 | print_string(s, event, "wiphy_name", data); 53 | trace_seq_printf(s, " vif:"); 54 | print_string(s, event, "vif_name", data); 55 | tep_print_num_field(s, "(%d)", event, "vif_type", record, 1); 56 | 57 | trace_seq_printf(s, "\n%*s", INDENT, ""); 58 | SF("assoc"); SP(); 59 | SF("aid"); SP(); 60 | SF("cts"); SP(); 61 | SF("shortpre"); SP(); 62 | SF("shortslot"); SP(); 63 | SF("dtimper"); SP(); 64 | trace_seq_printf(s, "\n%*s", INDENT, ""); 65 | SF("bcnint"); SP(); 66 | SFX("assoc_cap"); SP(); 67 | SFX("basic_rates"); SP(); 68 | SF("enable_beacon"); 69 | trace_seq_printf(s, "\n%*s", INDENT, ""); 70 | SF("ht_operation_mode"); 71 | 72 | return 0; 73 | } 74 | 75 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 76 | { 77 | tep_register_event_handler(tep, -1, "mac80211", 78 | "drv_bss_info_changed", 79 | drv_bss_info_changed, NULL); 80 | return 0; 81 | } 82 | 83 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 84 | { 85 | tep_unregister_event_handler(tep, -1, "mac80211", 86 | "drv_bss_info_changed", 87 | drv_bss_info_changed, NULL); 88 | } 89 | -------------------------------------------------------------------------------- /plugins/plugin_net.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | #include 3 | 4 | #include "event-parse.h" 5 | #include "trace-seq.h" 6 | 7 | static unsigned long long 8 | process_builtin_constant_p(struct trace_seq *s, unsigned long long *args) 9 | { 10 | return 0; 11 | } 12 | 13 | static unsigned long long 14 | process_builtin_bswap16(struct trace_seq *s, unsigned long long *args) 15 | { 16 | return __builtin_bswap16((uint16_t)args[0]); 17 | } 18 | 19 | static unsigned long long 20 | process_builtin_bswap32(struct trace_seq *s, unsigned long long *args) 21 | { 22 | return __builtin_bswap32((uint32_t)args[0]); 23 | } 24 | 25 | static unsigned long long 26 | process_builtin_bswap64(struct trace_seq *s, unsigned long long *args) 27 | { 28 | return __builtin_bswap64(args[0]); 29 | } 30 | 31 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 32 | { 33 | tep_register_print_function(tep, 34 | process_builtin_constant_p, 35 | TEP_FUNC_ARG_INT, 36 | "__builtin_constant_p", 37 | TEP_FUNC_ARG_INT, 38 | TEP_FUNC_ARG_VOID); 39 | tep_register_print_function(tep, 40 | process_builtin_bswap16, 41 | TEP_FUNC_ARG_INT, 42 | "__fswab16", 43 | TEP_FUNC_ARG_INT, 44 | TEP_FUNC_ARG_VOID); 45 | tep_register_print_function(tep, 46 | process_builtin_bswap16, 47 | TEP_FUNC_ARG_INT, 48 | "__builtin_bswap16", 49 | TEP_FUNC_ARG_INT, 50 | TEP_FUNC_ARG_VOID); 51 | tep_register_print_function(tep, 52 | process_builtin_bswap32, 53 | TEP_FUNC_ARG_INT, 54 | "__fswab32", 55 | TEP_FUNC_ARG_INT, 56 | TEP_FUNC_ARG_VOID); 57 | tep_register_print_function(tep, 58 | process_builtin_bswap32, 59 | TEP_FUNC_ARG_INT, 60 | "__builtin_bswap32", 61 | TEP_FUNC_ARG_INT, 62 | TEP_FUNC_ARG_VOID); 63 | tep_register_print_function(tep, 64 | process_builtin_bswap64, 65 | TEP_FUNC_ARG_LONG, 66 | "__fswab64", 67 | TEP_FUNC_ARG_LONG, 68 | TEP_FUNC_ARG_VOID); 69 | tep_register_print_function(tep, 70 | process_builtin_bswap64, 71 | TEP_FUNC_ARG_LONG, 72 | "__builtin_bswap64", 73 | TEP_FUNC_ARG_LONG, 74 | TEP_FUNC_ARG_VOID); 75 | return 0; 76 | } 77 | 78 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 79 | { 80 | tep_unregister_print_function(tep, process_builtin_constant_p, 81 | "__builtin_constant_p"); 82 | tep_unregister_print_function(tep, process_builtin_bswap16, 83 | "__fswab16"); 84 | tep_unregister_print_function(tep, process_builtin_bswap16, 85 | "__builtin_bswap16"); 86 | tep_unregister_print_function(tep, process_builtin_bswap32, 87 | "__fswab32"); 88 | tep_unregister_print_function(tep, process_builtin_bswap32, 89 | "__builtin_bswap32"); 90 | tep_unregister_print_function(tep, process_builtin_bswap64, 91 | "__fswab64"); 92 | tep_unregister_print_function(tep, process_builtin_bswap64, 93 | "__builtin_bswap64"); 94 | } 95 | -------------------------------------------------------------------------------- /plugins/plugin_tlb.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2015 Red Hat Inc, Steven Rostedt 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include "event-parse.h" 10 | 11 | enum tlb_flush_reason { 12 | TLB_FLUSH_ON_TASK_SWITCH, 13 | TLB_REMOTE_SHOOTDOWN, 14 | TLB_LOCAL_SHOOTDOWN, 15 | TLB_LOCAL_MM_SHOOTDOWN, 16 | NR_TLB_FLUSH_REASONS, 17 | }; 18 | 19 | static int tlb_flush_handler(struct trace_seq *s, struct tep_record *record, 20 | struct tep_event *event, void *context) 21 | { 22 | unsigned long long val; 23 | 24 | trace_seq_printf(s, "pages="); 25 | 26 | tep_print_num_field(s, "%ld", event, "pages", record, 1); 27 | 28 | if (tep_get_field_val(s, event, "reason", record, &val, 1) < 0) 29 | return -1; 30 | 31 | trace_seq_puts(s, " reason="); 32 | 33 | switch (val) { 34 | case TLB_FLUSH_ON_TASK_SWITCH: 35 | trace_seq_puts(s, "flush on task switch"); 36 | break; 37 | case TLB_REMOTE_SHOOTDOWN: 38 | trace_seq_puts(s, "remote shootdown"); 39 | break; 40 | case TLB_LOCAL_SHOOTDOWN: 41 | trace_seq_puts(s, "local shootdown"); 42 | break; 43 | case TLB_LOCAL_MM_SHOOTDOWN: 44 | trace_seq_puts(s, "local mm shootdown"); 45 | break; 46 | } 47 | 48 | trace_seq_printf(s, " (%lld)", val); 49 | 50 | return 0; 51 | } 52 | 53 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 54 | { 55 | tep_register_event_handler(tep, -1, "tlb", "tlb_flush", 56 | tlb_flush_handler, NULL); 57 | 58 | return 0; 59 | } 60 | 61 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 62 | { 63 | tep_unregister_event_handler(tep, -1, 64 | "tlb", "tlb_flush", 65 | tlb_flush_handler, NULL); 66 | } 67 | -------------------------------------------------------------------------------- /plugins/plugin_xen.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | #include 3 | #include 4 | #include 5 | #include "event-parse.h" 6 | #include "trace-seq.h" 7 | 8 | #define __HYPERVISOR_set_trap_table 0 9 | #define __HYPERVISOR_mmu_update 1 10 | #define __HYPERVISOR_set_gdt 2 11 | #define __HYPERVISOR_stack_switch 3 12 | #define __HYPERVISOR_set_callbacks 4 13 | #define __HYPERVISOR_fpu_taskswitch 5 14 | #define __HYPERVISOR_sched_op_compat 6 15 | #define __HYPERVISOR_dom0_op 7 16 | #define __HYPERVISOR_set_debugreg 8 17 | #define __HYPERVISOR_get_debugreg 9 18 | #define __HYPERVISOR_update_descriptor 10 19 | #define __HYPERVISOR_memory_op 12 20 | #define __HYPERVISOR_multicall 13 21 | #define __HYPERVISOR_update_va_mapping 14 22 | #define __HYPERVISOR_set_timer_op 15 23 | #define __HYPERVISOR_event_channel_op_compat 16 24 | #define __HYPERVISOR_xen_version 17 25 | #define __HYPERVISOR_console_io 18 26 | #define __HYPERVISOR_physdev_op_compat 19 27 | #define __HYPERVISOR_grant_table_op 20 28 | #define __HYPERVISOR_vm_assist 21 29 | #define __HYPERVISOR_update_va_mapping_otherdomain 22 30 | #define __HYPERVISOR_iret 23 /* x86 only */ 31 | #define __HYPERVISOR_vcpu_op 24 32 | #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ 33 | #define __HYPERVISOR_mmuext_op 26 34 | #define __HYPERVISOR_acm_op 27 35 | #define __HYPERVISOR_nmi_op 28 36 | #define __HYPERVISOR_sched_op 29 37 | #define __HYPERVISOR_callback_op 30 38 | #define __HYPERVISOR_xenoprof_op 31 39 | #define __HYPERVISOR_event_channel_op 32 40 | #define __HYPERVISOR_physdev_op 33 41 | #define __HYPERVISOR_hvm_op 34 42 | #define __HYPERVISOR_tmem_op 38 43 | 44 | /* Architecture-specific hypercall definitions. */ 45 | #define __HYPERVISOR_arch_0 48 46 | #define __HYPERVISOR_arch_1 49 47 | #define __HYPERVISOR_arch_2 50 48 | #define __HYPERVISOR_arch_3 51 49 | #define __HYPERVISOR_arch_4 52 50 | #define __HYPERVISOR_arch_5 53 51 | #define __HYPERVISOR_arch_6 54 52 | #define __HYPERVISOR_arch_7 55 53 | 54 | #define N(x) [__HYPERVISOR_##x] = "("#x")" 55 | static const char *xen_hypercall_names[] = { 56 | N(set_trap_table), 57 | N(mmu_update), 58 | N(set_gdt), 59 | N(stack_switch), 60 | N(set_callbacks), 61 | N(fpu_taskswitch), 62 | N(sched_op_compat), 63 | N(dom0_op), 64 | N(set_debugreg), 65 | N(get_debugreg), 66 | N(update_descriptor), 67 | N(memory_op), 68 | N(multicall), 69 | N(update_va_mapping), 70 | N(set_timer_op), 71 | N(event_channel_op_compat), 72 | N(xen_version), 73 | N(console_io), 74 | N(physdev_op_compat), 75 | N(grant_table_op), 76 | N(vm_assist), 77 | N(update_va_mapping_otherdomain), 78 | N(iret), 79 | N(vcpu_op), 80 | N(set_segment_base), 81 | N(mmuext_op), 82 | N(acm_op), 83 | N(nmi_op), 84 | N(sched_op), 85 | N(callback_op), 86 | N(xenoprof_op), 87 | N(event_channel_op), 88 | N(physdev_op), 89 | N(hvm_op), 90 | 91 | /* Architecture-specific hypercall definitions. */ 92 | N(arch_0), 93 | N(arch_1), 94 | N(arch_2), 95 | N(arch_3), 96 | N(arch_4), 97 | N(arch_5), 98 | N(arch_6), 99 | N(arch_7), 100 | }; 101 | #undef N 102 | 103 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 104 | 105 | static const char *xen_hypercall_name(unsigned op) 106 | { 107 | if (op < ARRAY_SIZE(xen_hypercall_names) && 108 | xen_hypercall_names[op] != NULL) 109 | return xen_hypercall_names[op]; 110 | 111 | return ""; 112 | } 113 | 114 | unsigned long long process_xen_hypercall_name(struct trace_seq *s, 115 | unsigned long long *args) 116 | { 117 | unsigned int op = args[0]; 118 | 119 | trace_seq_printf(s, "%s", xen_hypercall_name(op)); 120 | return 0; 121 | } 122 | 123 | int TEP_PLUGIN_LOADER(struct tep_handle *tep) 124 | { 125 | tep_register_print_function(tep, 126 | process_xen_hypercall_name, 127 | TEP_FUNC_ARG_STRING, 128 | "xen_hypercall_name", 129 | TEP_FUNC_ARG_INT, 130 | TEP_FUNC_ARG_VOID); 131 | return 0; 132 | } 133 | 134 | void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 135 | { 136 | tep_unregister_print_function(tep, process_xen_hypercall_name, 137 | "xen_hypercall_name"); 138 | } 139 | -------------------------------------------------------------------------------- /samples/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | 3 | include $(src)/scripts/utils.mk 4 | 5 | TARGETS := 6 | TARGETS += test-event 7 | 8 | sdir := $(obj)/samples 9 | 10 | TARGETS := $(patsubst %,$(sdir)/%,$(TARGETS)) 11 | 12 | all: $(TARGETS) 13 | 14 | $(sdir): 15 | @mkdir -p $(sdir) 16 | 17 | $(TARGETS): $(sdir) $(LIBTRACEEVENT_STATIC) 18 | 19 | $(sdir)/%: $(bdir)/%.o 20 | $(call do_sample_build,$@,$<) 21 | 22 | $(bdir)/%.o: $(bdir)/%.c 23 | $(Q)$(CC) -o $@ -c $< $(CFLAGS) $(INCLUDES) 24 | 25 | clean: 26 | $(Q)$(call do_clean,$(sdir)/*) 27 | -------------------------------------------------------------------------------- /samples/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | executable( 6 | 'test-event', 7 | ['test-event.c'], 8 | dependencies: libtraceevent_dep, 9 | include_directories: [incdir]) 10 | -------------------------------------------------------------------------------- /samples/test-event.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2022 Google Inc, Steven Rostedt 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static char *argv0; 14 | 15 | static char *get_this_name(void) 16 | { 17 | static char *this_name; 18 | char *arg; 19 | char *p; 20 | 21 | if (this_name) 22 | return this_name; 23 | 24 | arg = argv0; 25 | p = arg+strlen(arg); 26 | 27 | while (p >= arg && *p != '/') 28 | p--; 29 | p++; 30 | 31 | this_name = p; 32 | return p; 33 | } 34 | 35 | static void usage(void) 36 | { 37 | char *p = get_this_name(); 38 | 39 | printf("usage: %s [options]\n" 40 | " -h : this message\n" 41 | " -s system : the system for the event\n" 42 | " -e format : the event format file\n" 43 | " -f file : file to read the event from\n" 44 | " otherwise, reads from stdin\n" 45 | "\n",p); 46 | exit(-1); 47 | } 48 | 49 | static void __vdie(const char *fmt, va_list ap, int err) 50 | { 51 | int ret = errno; 52 | char *p = get_this_name(); 53 | 54 | if (err && errno) 55 | perror(p); 56 | else 57 | ret = -1; 58 | 59 | fprintf(stderr, " "); 60 | vfprintf(stderr, fmt, ap); 61 | 62 | fprintf(stderr, "\n"); 63 | exit(ret); 64 | } 65 | 66 | void die(const char *fmt, ...) 67 | { 68 | va_list ap; 69 | 70 | va_start(ap, fmt); 71 | __vdie(fmt, ap, 0); 72 | va_end(ap); 73 | } 74 | 75 | void pdie(const char *fmt, ...) 76 | { 77 | va_list ap; 78 | 79 | va_start(ap, fmt); 80 | __vdie(fmt, ap, 1); 81 | va_end(ap); 82 | } 83 | 84 | /* Must be a power of two */ 85 | #define BUFALLOC 1024 86 | #define BUFMASK (~(BUFALLOC - 1)) 87 | 88 | int main(int argc, char **argv) 89 | { 90 | struct tep_handle *tep; 91 | struct tep_event *event; 92 | FILE *file = stdin; 93 | FILE *fp = NULL; 94 | char *system = NULL; 95 | char *event_buf = NULL; 96 | int esize = 0; 97 | int c; 98 | 99 | argv0 = argv[0]; 100 | 101 | while ((c = getopt(argc, argv, "hs:e:f:")) >= 0) { 102 | switch (c) { 103 | case 's': 104 | system = optarg; 105 | break; 106 | case 'e': 107 | event_buf = optarg; 108 | file = NULL; 109 | break; 110 | case 'f': 111 | fp = fopen(optarg, "r"); 112 | if (!fp) 113 | pdie("%s", optarg); 114 | file = fp; 115 | break; 116 | case 'h': 117 | usage(); 118 | } 119 | } 120 | if (file) { 121 | char *line = NULL; 122 | size_t n = 0; 123 | int len; 124 | 125 | while (getline(&line, &n, file) > 0) { 126 | len = strlen(line) + 1; 127 | 128 | if (((esize - 1) & BUFMASK) < ((esize + len) & BUFMASK)) { 129 | int a; 130 | 131 | a = (esize + len + BUFALLOC - 1) & BUFMASK; 132 | event_buf = realloc(event_buf, a); 133 | if (!event_buf) 134 | pdie("allocating event"); 135 | } 136 | strcpy(event_buf + esize, line); 137 | esize += len - 1; 138 | } 139 | free(line); 140 | } 141 | 142 | tep = tep_alloc(); 143 | if (!tep) 144 | pdie("Allocating tep handle"); 145 | 146 | tep_set_loglevel(TEP_LOG_ALL); 147 | 148 | if (!system) 149 | system = "test"; 150 | 151 | if (tep_parse_format(tep, &event, event_buf, esize, system)) 152 | die("Failed to parse event"); 153 | 154 | } 155 | -------------------------------------------------------------------------------- /scripts/features.mk: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | # taken from perf which was based on Linux Kbuild 4 | # try-cc 5 | # Usage: option = $(call try-cc, source-to-build, cc-options) 6 | try-cc = $(shell sh -c \ 7 | 'TMP="$(BUILD_OUTPUT)$(TMPOUT).$$$$"; \ 8 | echo "$(1)" | \ 9 | $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \ 10 | rm -f "$$TMP"') 11 | 12 | define SOURCE_PTRACE 13 | #include 14 | #include 15 | 16 | int main (void) 17 | { 18 | int ret; 19 | ret = ptrace(PTRACE_ATTACH, 0, NULL, 0); 20 | ptrace(PTRACE_TRACEME, 0, NULL, 0); 21 | ptrace(PTRACE_GETSIGINFO, 0, NULL, NULL); 22 | ptrace(PTRACE_GETEVENTMSG, 0, NULL, NULL); 23 | ptrace(PTRACE_SETOPTIONS, NULL, NULL, 24 | PTRACE_O_TRACEFORK | 25 | PTRACE_O_TRACEVFORK | 26 | PTRACE_O_TRACECLONE | 27 | PTRACE_O_TRACEEXIT); 28 | ptrace(PTRACE_CONT, NULL, NULL, 0); 29 | ptrace(PTRACE_DETACH, 0, NULL, NULL); 30 | ptrace(PTRACE_SETOPTIONS, 0, NULL, 31 | PTRACE_O_TRACEFORK | 32 | PTRACE_O_TRACEVFORK | 33 | PTRACE_O_TRACECLONE | 34 | PTRACE_O_TRACEEXIT); 35 | return ret; 36 | } 37 | endef 38 | -------------------------------------------------------------------------------- /scripts/utilities.mak: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # This allows us to work with the newline character: 3 | define newline 4 | 5 | 6 | endef 7 | newline := $(newline) 8 | 9 | # nl-escape 10 | # 11 | # Usage: escape = $(call nl-escape[,escape]) 12 | # 13 | # This is used as the common way to specify 14 | # what should replace a newline when escaping 15 | # newlines; the default is a bizarre string. 16 | # 17 | nl-escape = $(if $(1),$(1),m822df3020w6a44id34bt574ctac44eb9f4n) 18 | 19 | # escape-nl 20 | # 21 | # Usage: escaped-text = $(call escape-nl,text[,escape]) 22 | # 23 | # GNU make's $(shell ...) function converts to a 24 | # single space each newline character in the output 25 | # produced during the expansion; this may not be 26 | # desirable. 27 | # 28 | # The only solution is to change each newline into 29 | # something that won't be converted, so that the 30 | # information can be recovered later with 31 | # $(call unescape-nl...) 32 | # 33 | escape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1)) 34 | 35 | # unescape-nl 36 | # 37 | # Usage: text = $(call unescape-nl,escaped-text[,escape]) 38 | # 39 | # See escape-nl. 40 | # 41 | unescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1)) 42 | 43 | # shell-escape-nl 44 | # 45 | # Usage: $(shell some-command | $(call shell-escape-nl[,escape])) 46 | # 47 | # Use this to escape newlines from within a shell call; 48 | # the default escape is a bizarre string. 49 | # 50 | # NOTE: The escape is used directly as a string constant 51 | # in an `awk' program that is delimited by shell 52 | # single-quotes, so be wary of the characters 53 | # that are chosen. 54 | # 55 | define shell-escape-nl 56 | awk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}' 57 | endef 58 | 59 | # shell-unescape-nl 60 | # 61 | # Usage: $(shell some-command | $(call shell-unescape-nl[,escape])) 62 | # 63 | # Use this to unescape newlines from within a shell call; 64 | # the default escape is a bizarre string. 65 | # 66 | # NOTE: The escape is used directly as an extended regular 67 | # expression constant in an `awk' program that is 68 | # delimited by shell single-quotes, so be wary 69 | # of the characters that are chosen. 70 | # 71 | # (The bash shell has a bug where `{gsub(...),...}' is 72 | # misinterpreted as a brace expansion; this can be 73 | # overcome by putting a space between `{' and `gsub'). 74 | # 75 | define shell-unescape-nl 76 | awk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }' 77 | endef 78 | 79 | # escape-for-shell-sq 80 | # 81 | # Usage: embeddable-text = $(call escape-for-shell-sq,text) 82 | # 83 | # This function produces text that is suitable for 84 | # embedding in a shell string that is delimited by 85 | # single-quotes. 86 | # 87 | escape-for-shell-sq = $(subst ','\'',$(1)) 88 | 89 | # shell-sq 90 | # 91 | # Usage: single-quoted-and-escaped-text = $(call shell-sq,text) 92 | # 93 | shell-sq = '$(escape-for-shell-sq)' 94 | 95 | # shell-wordify 96 | # 97 | # Usage: wordified-text = $(call shell-wordify,text) 98 | # 99 | # For instance: 100 | # 101 | # |define text 102 | # |hello 103 | # |world 104 | # |endef 105 | # | 106 | # |target: 107 | # | echo $(call shell-wordify,$(text)) 108 | # 109 | # At least GNU make gets confused by expanding a newline 110 | # within the context of a command line of a makefile rule 111 | # (this is in constrast to a `$(shell ...)' function call, 112 | # which can handle it just fine). 113 | # 114 | # This function avoids the problem by producing a string 115 | # that works as a shell word, regardless of whether or 116 | # not it contains a newline. 117 | # 118 | # If the text to be wordified contains a newline, then 119 | # an intrictate shell command substitution is constructed 120 | # to render the text as a single line; when the shell 121 | # processes the resulting escaped text, it transforms 122 | # it into the original unescaped text. 123 | # 124 | # If the text does not contain a newline, then this function 125 | # produces the same results as the `$(shell-sq)' function. 126 | # 127 | shell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq)) 128 | define _sw-esc-nl 129 | "$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))" 130 | endef 131 | 132 | # is-absolute 133 | # 134 | # Usage: bool-value = $(call is-absolute,path) 135 | # 136 | is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y) 137 | 138 | # lookup 139 | # 140 | # Usage: absolute-executable-path-or-empty = $(call lookup,path) 141 | # 142 | # (It's necessary to use `sh -c' because GNU make messes up by 143 | # trying too hard and getting things wrong). 144 | # 145 | lookup = $(call unescape-nl,$(shell sh -c $(_l-sh))) 146 | _l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,)) 147 | 148 | # is-executable 149 | # 150 | # Usage: bool-value = $(call is-executable,path) 151 | # 152 | # (It's necessary to use `sh -c' because GNU make messes up by 153 | # trying too hard and getting things wrong). 154 | # 155 | is-executable = $(call _is-executable-helper,$(shell-sq)) 156 | _is-executable-helper = $(shell sh -c $(_is-executable-sh)) 157 | _is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y) 158 | 159 | # get-executable 160 | # 161 | # Usage: absolute-executable-path-or-empty = $(call get-executable,path) 162 | # 163 | # The goal is to get an absolute path for an executable; 164 | # the `command -v' is defined by POSIX, but it's not 165 | # necessarily very portable, so it's only used if 166 | # relative path resolution is requested, as determined 167 | # by the presence of a leading `/'. 168 | # 169 | get-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup))) 170 | _ge-abspath = $(if $(is-executable),$(1)) 171 | 172 | # get-supplied-or-default-executable 173 | # 174 | # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default) 175 | # 176 | define get-executable-or-default 177 | $(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) 178 | endef 179 | _ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2))) 180 | _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 181 | -------------------------------------------------------------------------------- /scripts/utils.mk: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | 3 | # Utils 4 | 5 | PWD := $(shell /bin/pwd) 6 | GOBJ = $(notdir $(strip $@)) 7 | BASE1 = $(notdir $(strip $1)) 8 | BASE2 = $(notdir $(strip $2)) 9 | BASEPWD = $(notdir $(strip $(PWD))) 10 | 11 | 12 | ifeq ($(VERBOSE),1) 13 | Q = 14 | S = 15 | else 16 | Q = @ 17 | S = -s 18 | endif 19 | 20 | # Use empty print_* macros if either SILENT or VERBOSE. 21 | ifeq ($(findstring 1,$(SILENT)$(VERBOSE)),1) 22 | print_compile = 23 | print_app_build = 24 | print_fpic_compile = 25 | print_shared_lib_compile = 26 | print_plugin_obj_compile = 27 | print_plugin_build = 28 | print_install = 29 | print_uninstall = 30 | print_gen = 31 | print_update = 32 | print_descend = 33 | print_clean = 34 | else 35 | print_compile = echo ' COMPILE '$(GOBJ); 36 | print_app_build = echo ' BUILD '$(GOBJ); 37 | print_fpic_compile = echo ' COMPILE FPIC '$(GOBJ); 38 | print_shared_lib_compile = echo ' COMPILE SHARED LIB '$(GOBJ); 39 | print_plugin_obj_compile = echo ' COMPILE PLUGIN OBJ '$(GOBJ); 40 | print_plugin_build = echo ' BUILD PLUGIN '$(GOBJ); 41 | print_static_lib_build = echo ' BUILD STATIC LIB '$(GOBJ); 42 | print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; 43 | print_uninstall = echo ' UNINSTALL $(DESTDIR_SQ)$1'; 44 | print_gen = echo ' GEN '$(GOBJ); 45 | print_update = echo ' UPDATE '$(GOBJ); 46 | print_descend = echo ' DESCEND '$(BASE1) $(BASE2); 47 | print_clean = echo ' CLEAN '$(BASEPWD); 48 | endif 49 | 50 | do_fpic_compile = \ 51 | ($(print_fpic_compile) \ 52 | $(CC) -c $(CPPFLAGS) $(CFLAGS) $(EXT) -fPIC $< -o $@) 53 | 54 | do_compile = \ 55 | ($(if $(GENERATE_PIC), $(do_fpic_compile), \ 56 | $(print_compile) \ 57 | $(CC) -c $(CPPFLAGS) $(CFLAGS) $(EXT) $< -o $@)) 58 | 59 | do_app_build = \ 60 | ($(print_app_build) \ 61 | $(CC) $^ -rdynamic -o $@ $(LDFLAGS) $(CONFIG_LIBS) $(LIBS)) 62 | 63 | do_build_static_lib = \ 64 | ($(print_static_lib_build) \ 65 | if [ -f $@ ]; then \ 66 | mv $@ $@.rm; $(RM) $@.rm; \ 67 | fi; \ 68 | $(AR) rcs $@ $^) 69 | 70 | do_compile_shared_library = \ 71 | ($(print_shared_lib_compile) \ 72 | $(CC) --shared $^ '-Wl,-soname,$(1),-rpath=$$ORIGIN' -o $@ $(LDFLAGS) $(LIBS)) 73 | 74 | do_compile_plugin_obj = \ 75 | ($(print_plugin_obj_compile) \ 76 | $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ $<) 77 | 78 | do_plugin_build = \ 79 | ($(print_plugin_build) \ 80 | $(CC) $(CFLAGS) $(LDFLAGS) -shared -nostartfiles -o $@ $<) 81 | 82 | do_compile_python_plugin_obj = \ 83 | ($(print_plugin_obj_compile) \ 84 | $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PYTHON_DIR_SQ) $(PYTHON_INCLUDES) -fPIC -o $@ $<) 85 | 86 | do_python_plugin_build = \ 87 | ($(print_plugin_build) \ 88 | $(CC) $< -shared $(LDFLAGS) $(PYTHON_LDFLAGS) -o $@) 89 | 90 | do_clean = \ 91 | ($(print_clean) \ 92 | $(RM) $1) 93 | 94 | do_sample_build = \ 95 | $(Q)($(print_sample_build) \ 96 | $(CC) -o $1 $2 $(CFLAGS) $(LIBTRACEEVENT_STATIC) -ldl) 97 | 98 | do_sample_obj = \ 99 | $(Q)($(print_sample_obj) \ 100 | $(CC) -g -Wall -c $(CFLAGS) -o $1 $2 -I../include/) 101 | 102 | # 103 | # Define a callable command for descending to a new directory 104 | # 105 | # Call by doing: $(call descend,directory[,target]) 106 | # 107 | descend = \ 108 | ($(print_descend) \ 109 | mkdir -p $(obj)/$(BASE1); \ 110 | $(MAKE) $(PRINT_DIR) bdir=$(obj)/$(BASE1) -C $(1) $(2)) 111 | 112 | descend_clean = \ 113 | $(MAKE) $(PRINT_DIR) bdir=$(obj)/$(BASE1) -C $(1) clean 114 | 115 | define make_version.h 116 | (echo '/* This file is automatically generated. Do not modify. */'; \ 117 | echo \#define VERSION_CODE $(shell \ 118 | expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ 119 | echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ 120 | echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ 121 | echo '#define FILE_VERSION '$(FILE_VERSION); \ 122 | if [ -d $(src)/.git ]; then \ 123 | d=`git diff`; \ 124 | x=""; \ 125 | if [ ! -z "$$d" ]; then x="+"; fi; \ 126 | echo '#define VERSION_GIT "'$(shell \ 127 | git log -1 --pretty=format:"%H" 2>/dev/null)$$x'"'; \ 128 | else \ 129 | echo '#define VERSION_GIT "not-a-git-repo"'; \ 130 | fi \ 131 | ) > $1 132 | endef 133 | 134 | define update_version.h 135 | ($(call make_version.h, $@.tmp); \ 136 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 137 | rm -f $@.tmp; \ 138 | else \ 139 | $(print_update) \ 140 | mv -f $@.tmp $@; \ 141 | fi); 142 | endef 143 | 144 | define update_dir 145 | (echo $1 > $@.tmp; \ 146 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 147 | rm -f $@.tmp; \ 148 | else \ 149 | $(print_update) \ 150 | mv -f $@.tmp $@; \ 151 | fi); 152 | endef 153 | 154 | define build_prefix 155 | (echo $1 > $@.tmp; \ 156 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 157 | rm -f $@.tmp; \ 158 | else \ 159 | $(print_update) \ 160 | mv -f $@.tmp $@; \ 161 | fi); 162 | endef 163 | 164 | define do_install_mkdir 165 | if [ ! -d '$(DESTDIR_SQ)$1' ]; then \ 166 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ 167 | fi 168 | endef 169 | 170 | define do_install 171 | $(print_install) \ 172 | $(call do_install_mkdir,$2); \ 173 | $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' 174 | endef 175 | 176 | define do_install_pkgconfig_file 177 | if [ -n "${pkgconfig_dir}" ]; then \ 178 | $(call do_install,$(PKG_CONFIG_FILE),$(pkgconfig_dir),644); \ 179 | else \ 180 | (echo Failed to locate pkg-config directory) 1>&2; \ 181 | fi 182 | endef 183 | -------------------------------------------------------------------------------- /src/Build: -------------------------------------------------------------------------------- 1 | libtraceevent-y += event-parse.o 2 | libtraceevent-y += event-plugin.o 3 | libtraceevent-y += trace-seq.o 4 | libtraceevent-y += parse-filter.o 5 | libtraceevent-y += parse-utils.o 6 | libtraceevent-y += kbuffer-parse.o 7 | libtraceevent-y += tep_strerror.o 8 | libtraceevent-y += event-parse-api.o 9 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | 3 | include $(src)/scripts/utils.mk 4 | 5 | OBJS = 6 | OBJS += event-parse-api.o 7 | OBJS += event-parse.o 8 | OBJS += event-plugin.o 9 | OBJS += kbuffer-parse.o 10 | OBJS += parse-filter.o 11 | OBJS += parse-utils.o 12 | OBJS += tep_strerror.o 13 | OBJS += trace-seq.o 14 | 15 | OBJS := $(OBJS:%.o=$(bdir)/%.o) 16 | DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) 17 | 18 | $(bdir)/%.o: %.c 19 | $(Q)$(call do_fpic_compile) 20 | 21 | $(LIBTRACEEVENT_STATIC): $(OBJS) 22 | $(Q)$(call do_build_static_lib) 23 | 24 | $(LIBTRACEEVENT_SHARED): $(OBJS) 25 | $(Q)$(call do_compile_shared_library,$(notdir $(LIBTRACEEVENT_SHARED_VERSION))) 26 | 27 | $(LIBTRACEEVENT_SHARED_VERSION): $(LIBTRACEEVENT_SHARED) 28 | @ln -sf $( $@ 40 | 41 | $(OBJS): $(bdir)/%.o : $(bdir)/.%.d 42 | 43 | $(OBJS): | $(bdir) 44 | $(DEPS): | $(bdir) 45 | 46 | clean: 47 | $(Q)$(call do_clean,$(OBJS) $(DEPS)) 48 | 49 | dep_includes := $(wildcard $(DEPS)) 50 | 51 | ifneq ($(dep_includes),) 52 | include $(dep_includes) 53 | endif 54 | 55 | .PHONY: $(LIBTRACEEVENT_SHARED_SO) $(LIBTRACEEVENT_STATIC) 56 | -------------------------------------------------------------------------------- /src/event-parse-local.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | 7 | #ifndef _PARSE_EVENTS_INT_H 8 | #define _PARSE_EVENTS_INT_H 9 | 10 | struct tep_cmdline; 11 | struct cmdline_list; 12 | struct func_map; 13 | struct func_list; 14 | struct event_handler; 15 | struct func_resolver; 16 | struct tep_plugins_dir; 17 | 18 | #define __hidden __attribute__((visibility ("hidden"))) 19 | 20 | struct tep_handle { 21 | int ref_count; 22 | 23 | int header_page_ts_offset; 24 | int header_page_ts_size; 25 | int header_page_size_offset; 26 | int header_page_size_size; 27 | int header_page_data_offset; 28 | int header_page_data_size; 29 | int header_page_overwrite; 30 | 31 | enum tep_endian file_bigendian; 32 | enum tep_endian host_bigendian; 33 | 34 | int old_format; 35 | 36 | int cpus; 37 | int long_size; 38 | int page_size; 39 | 40 | struct tep_cmdline *cmdlines; 41 | struct cmdline_list *cmdlist; 42 | int cmdline_count; 43 | 44 | struct func_map *func_map; 45 | struct func_resolver *func_resolver; 46 | struct func_list *funclist; 47 | unsigned int func_count; 48 | 49 | struct printk_map *printk_map; 50 | struct printk_list *printklist; 51 | unsigned int printk_count; 52 | 53 | struct tep_event **events; 54 | int nr_events; 55 | struct tep_event **sort_events; 56 | enum tep_event_sort_type last_type; 57 | 58 | int type_offset; 59 | int type_size; 60 | 61 | int pid_offset; 62 | int pid_size; 63 | 64 | int pc_offset; 65 | int pc_size; 66 | 67 | int flags_offset; 68 | int flags_size; 69 | 70 | int ld_offset; 71 | int ld_size; 72 | 73 | int test_filters; 74 | 75 | int flags; 76 | 77 | struct tep_format_field *bprint_ip_field; 78 | struct tep_format_field *bprint_fmt_field; 79 | struct tep_format_field *bprint_buf_field; 80 | 81 | struct event_handler *handlers; 82 | struct tep_function_handler *func_handlers; 83 | 84 | /* cache */ 85 | struct tep_event *last_event; 86 | 87 | struct tep_plugins_dir *plugins_dir; 88 | 89 | const char *input_buf; 90 | unsigned long long input_buf_ptr; 91 | unsigned long long input_buf_siz; 92 | }; 93 | 94 | enum tep_print_parse_type { 95 | PRINT_FMT_STRING, 96 | PRINT_FMT_ARG_DIGIT, 97 | PRINT_FMT_ARG_POINTER, 98 | PRINT_FMT_ARG_STRING, 99 | }; 100 | 101 | struct tep_print_parse { 102 | struct tep_print_parse *next; 103 | 104 | char *format; 105 | int ls; 106 | enum tep_print_parse_type type; 107 | struct tep_print_arg *arg; 108 | struct tep_print_arg *len_as_arg; 109 | }; 110 | 111 | void tep_free_event(struct tep_event *event); 112 | void tep_free_format_field(struct tep_format_field *field); 113 | void tep_free_plugin_paths(struct tep_handle *tep); 114 | 115 | unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data); 116 | unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data); 117 | unsigned long long tep_data2host8(struct tep_handle *tep, unsigned long long data); 118 | 119 | /* access to the internal parser */ 120 | int tep_peek_char(struct tep_handle *tep); 121 | void tep_init_input_buf(struct tep_handle *tep, const char *buf, unsigned long long size); 122 | unsigned long long tep_get_input_buf_ptr(struct tep_handle *tep); 123 | const char *tep_get_input_buf(struct tep_handle *tep); 124 | enum tep_event_type tep_read_token(struct tep_handle *tep, char **tok); 125 | void tep_free_token(char *tok); 126 | 127 | #endif /* _PARSE_EVENTS_INT_H */ 128 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | sources= [ 6 | 'event-parse-api.c', 7 | 'event-parse.c', 8 | 'event-plugin.c', 9 | 'kbuffer-parse.c', 10 | 'parse-filter.c', 11 | 'parse-utils.c', 12 | 'tep_strerror.c', 13 | 'trace-seq.c', 14 | ] 15 | 16 | cc = meson.get_compiler('c') 17 | dl_dep = cc.find_library('dl') 18 | 19 | libtraceevent = library( 20 | 'traceevent', 21 | sources, 22 | version: library_version, 23 | dependencies: [dl_dep], 24 | include_directories: [incdir], 25 | install: true) 26 | 27 | pkg = import('pkgconfig') 28 | pkg.generate( 29 | libtraceevent, 30 | subdirs: 'traceevent', 31 | filebase: meson.project_name(), 32 | name: meson.project_name(), 33 | version: meson.project_version(), 34 | description: 'Manage trace event', 35 | url: 'https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/') 36 | 37 | libtraceevent_dep = declare_dependency( 38 | include_directories: ['.'], 39 | link_with: libtraceevent) 40 | -------------------------------------------------------------------------------- /src/parse-utils.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "event-utils.h" 13 | #include "event-parse.h" 14 | #include "kbuffer.h" 15 | 16 | #define __weak __attribute__((weak)) 17 | 18 | static int log_level = TEP_LOG_CRITICAL; 19 | 20 | /** 21 | * tep_set_loglevel - set log level of the library 22 | * @level: desired level of the library messages 23 | */ 24 | void tep_set_loglevel(enum tep_loglevel level) 25 | { 26 | log_level = level; 27 | } 28 | 29 | /** 30 | * tep_vprint - print library log messages 31 | * @name: name of the library. 32 | * @level: severity of the log message. This parameter is not used in this implementation, but as 33 | * the function is weak and can be overridden, having the log level could be useful 34 | * for other implementations. 35 | * @print_err: whether to print the errno, if non zero. 36 | * @fmt: printf format string of the message. 37 | * @ap: list of printf parameters. 38 | * 39 | * This function is used to print all messages from traceevent, tracefs and trace-cmd libraries. 40 | * It is defined as weak, so the application that uses those libraries can override it in order 41 | * to implement its own logic for printing library logs. 42 | * 43 | * Return the value of errno at the function enter. 44 | */ 45 | int __weak tep_vprint(const char *name, enum tep_loglevel level, 46 | bool print_err, const char *fmt, va_list ap) 47 | { 48 | return __tep_vprint(name, level, print_err, fmt, ap); 49 | } 50 | 51 | /** 52 | * __tep_vprint - print library log messages 53 | * @name: name of the library. 54 | * @level: severity of the log message. This parameter is not used in this implementation, but as 55 | * the function is weak and can be overridden, having the log level could be useful 56 | * for other implementations. 57 | * @print_err: whether to print the errno, if non zero. 58 | * @fmt: printf format string of the message. 59 | * @ap: list of printf parameters. 60 | * 61 | * This function is used to print all messages from traceevent, tracefs and trace-cmd libraries. 62 | * It is defined as weak, so the application that uses those libraries can override it in order 63 | * to implement its own logic for printing library logs. 64 | * 65 | * Return the value of errno at the function enter. 66 | */ 67 | int __tep_vprint(const char *name, enum tep_loglevel level, 68 | bool print_err, const char *fmt, va_list ap) 69 | { 70 | int ret = errno; 71 | FILE *fp = stdout; 72 | 73 | if (level <= TEP_LOG_WARNING) { 74 | fp = stderr; 75 | if (errno && print_err) { 76 | perror(name); 77 | fprintf(stderr, " "); 78 | } 79 | } 80 | vfprintf(fp, fmt, ap); 81 | fprintf(fp, "\n"); 82 | 83 | return ret; 84 | } 85 | 86 | void tep_warning(const char *fmt, ...) 87 | { 88 | va_list ap; 89 | 90 | if (log_level < TEP_LOG_WARNING) 91 | return; 92 | 93 | va_start(ap, fmt); 94 | tep_vprint("libtraceevent", TEP_LOG_WARNING, true, fmt, ap); 95 | va_end(ap); 96 | } 97 | 98 | 99 | void tep_info(const char *fmt, ...) 100 | { 101 | va_list ap; 102 | 103 | if (log_level < TEP_LOG_INFO) 104 | return; 105 | 106 | va_start(ap, fmt); 107 | tep_vprint("libtraceevent", TEP_LOG_INFO, false, fmt, ap); 108 | va_end(ap); 109 | } 110 | 111 | /* The below is for backward compatibility */ 112 | int __weak tep_vwarning(const char *name, const char *fmt, va_list ap) 113 | { 114 | return tep_vprint(name, TEP_LOG_WARNING, true, fmt, ap); 115 | } 116 | 117 | void pr_stat(const char *fmt, ...) __attribute__((weak, alias("tep_info"))); 118 | void __pr_stat(const char *fmt, ...) __attribute__((weak, alias("tep_info"))); 119 | 120 | void __weak __vpr_stat(const char *fmt, va_list ap) 121 | { 122 | tep_vprint("libtraceevent", TEP_LOG_INFO, false, fmt, ap); 123 | } 124 | 125 | void vpr_stat(const char *fmt, va_list ap) __attribute__((weak, alias("__vpr_stat"))); 126 | 127 | /** 128 | * tep_kbuffer - return an allocated kbuffer that can be used for the tep handle 129 | * @tep: the handle that will work with the kbuffer descriptor 130 | * 131 | * Allocates and returns a new kbuffer. 132 | * The return must be freed by kbuffer_free(); 133 | */ 134 | struct kbuffer *tep_kbuffer(struct tep_handle *tep) 135 | { 136 | enum kbuffer_endian endian; 137 | int long_size; 138 | 139 | long_size = tep_get_long_size(tep); 140 | 141 | /* If the long_size is not set, then use the commit size */ 142 | if (!long_size) 143 | long_size = tep_get_header_page_size(tep); 144 | 145 | if (long_size == 8) 146 | long_size = KBUFFER_LSIZE_8; 147 | else 148 | long_size = KBUFFER_LSIZE_4; 149 | 150 | if (tep_is_file_bigendian(tep)) 151 | endian = KBUFFER_ENDIAN_BIG; 152 | else 153 | endian = KBUFFER_ENDIAN_LITTLE; 154 | 155 | return kbuffer_alloc(long_size, endian); 156 | } 157 | -------------------------------------------------------------------------------- /src/tep_strerror.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | #undef _GNU_SOURCE 3 | #include 4 | #include 5 | 6 | #include "event-parse.h" 7 | 8 | #undef _PE 9 | #define _PE(code, str) str 10 | static const char * const tep_error_str[] = { 11 | TEP_ERRORS 12 | }; 13 | #undef _PE 14 | 15 | /* 16 | * The tools so far have been using the strerror_r() GNU variant, that returns 17 | * a string, be it the buffer passed or something else. 18 | * 19 | * But that, besides being tricky in cases where we expect that the function 20 | * using strerror_r() returns the error formatted in a provided buffer (we have 21 | * to check if it returned something else and copy that instead), breaks the 22 | * build on systems not using glibc, like Alpine Linux, where musl libc is 23 | * used. 24 | * 25 | * So, introduce yet another wrapper, str_error_r(), that has the GNU 26 | * interface, but uses the portable XSI variant of strerror_r(), so that users 27 | * rest asured that the provided buffer is used and it is what is returned. 28 | */ 29 | int tep_strerror(struct tep_handle *tep __maybe_unused, 30 | enum tep_errno errnum, char *buf, size_t buflen) 31 | { 32 | const char *msg; 33 | int idx; 34 | 35 | if (!buflen) 36 | return 0; 37 | 38 | if (errnum >= 0) { 39 | int err = strerror_r(errnum, buf, buflen); 40 | buf[buflen - 1] = 0; 41 | return err; 42 | } 43 | 44 | if (errnum <= __TEP_ERRNO__START || 45 | errnum >= __TEP_ERRNO__END) 46 | return -1; 47 | 48 | idx = errnum - __TEP_ERRNO__START - 1; 49 | msg = tep_error_str[idx]; 50 | snprintf(buf, buflen, "%s", msg); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main () 4 | { 5 | tep_load_plugins(NULL); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /utest/.gitignore: -------------------------------------------------------------------------------- 1 | trace-utest 2 | -------------------------------------------------------------------------------- /utest/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | 3 | include $(src)/scripts/utils.mk 4 | 5 | TARGETS = $(bdir)/trace-utest 6 | 7 | OBJS = 8 | OBJS += trace-utest.o 9 | OBJS += traceevent-utest.o 10 | 11 | LIBS += -lcunit \ 12 | -ldl \ 13 | $(LIBTRACEEVENT_STATIC) 14 | 15 | OBJS := $(OBJS:%.o=$(bdir)/%.o) 16 | DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) 17 | 18 | $(OBJS): | $(bdir) 19 | $(DEPS): | $(bdir) 20 | 21 | $(bdir)/trace-utest: $(OBJS) $(LIBTRACEEVENT_STATIC) 22 | $(Q)$(do_app_build) 23 | 24 | $(bdir)/%.o: %.c 25 | $(Q)$(call do_fpic_compile) 26 | 27 | $(DEPS): $(bdir)/.%.d: %.c 28 | $(Q)$(CC) -M $(CPPFLAGS) $(CFLAGS) $< > $@ 29 | $(Q)$(CC) -M -MT $(bdir)/$*.o $(CPPFLAGS) $(CFLAGS) $< > $@ 30 | 31 | $(OBJS): $(bdir)/%.o : $(bdir)/.%.d 32 | 33 | dep_includes := $(wildcard $(DEPS)) 34 | 35 | test: $(TARGETS) 36 | 37 | clean: 38 | $(Q)$(call do_clean,$(TARGETS) $(bdir)/*.o $(bdir)/.*.d) 39 | -------------------------------------------------------------------------------- /utest/README: -------------------------------------------------------------------------------- 1 | 2 | Unit tests for libtraceevent library. The tests use CUnit framework: 3 | 4 | http://cunit.sourceforge.net/ 5 | 6 | which must be pre installed on the system, before building the unit tests. 7 | The framework can be downloaded, compiled and installed manually, or 8 | using a precompiled distro package: 9 | 10 | Fedora: 11 | CUnit 12 | CUnit-devel 13 | 14 | Ubuntu and Debian: 15 | libcunit1 16 | libcunit1-doc 17 | libcunit1-dev 18 | -------------------------------------------------------------------------------- /utest/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | source = [ 6 | 'trace-utest.c', 7 | 'traceevent-utest.c', 8 | ] 9 | 10 | e = executable( 11 | 'trace-utest', 12 | source, 13 | include_directories: [incdir], 14 | dependencies: [libtraceevent_dep, cunit_dep]) 15 | 16 | test('trace-utest', e) 17 | -------------------------------------------------------------------------------- /utest/trace-utest.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2020, VMware, Tzvetomir Stoyanov 4 | * 5 | * Modified from libtracefs to libtraceevent: 6 | * Copyright (C) 2021, VMware, Steven Rostedt 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include "trace-utest.h" 19 | 20 | enum unit_tests { 21 | RUN_NONE = 0, 22 | RUN_TRACEEVENT = (1 << 0), 23 | RUN_ALL = 0xFFFF 24 | }; 25 | 26 | static void print_help(char **argv) 27 | { 28 | printf("Usage: %s [OPTIONS]\n", basename(argv[0])); 29 | printf("\t-s, --silent\tPrint test summary\n"); 30 | printf("\t-r, --run test\tRun specific test:\n"); 31 | printf("\t\t traceevent run libtraceevent tests\n"); 32 | printf("\t-h, --help\tPrint usage information\n"); 33 | exit(0); 34 | } 35 | 36 | int main(int argc, char **argv) 37 | { 38 | CU_BasicRunMode verbose = CU_BRM_VERBOSE; 39 | enum unit_tests tests = RUN_NONE; 40 | int failed_tests; 41 | 42 | for (;;) { 43 | int c; 44 | int index = 0; 45 | const char *opts = "+hsr:"; 46 | static struct option long_options[] = { 47 | {"silent", no_argument, NULL, 's'}, 48 | {"run", required_argument, NULL, 'r'}, 49 | {"help", no_argument, NULL, 'h'}, 50 | {NULL, 0, NULL, 0} 51 | }; 52 | 53 | c = getopt_long (argc, argv, opts, long_options, &index); 54 | if (c == -1) 55 | break; 56 | switch (c) { 57 | case 'r': 58 | if (strcmp(optarg, "traceevent") == 0) 59 | tests |= RUN_TRACEEVENT; 60 | else 61 | print_help(argv); 62 | break; 63 | case 's': 64 | verbose = CU_BRM_SILENT; 65 | break; 66 | case 'h': 67 | default: 68 | print_help(argv); 69 | break; 70 | } 71 | } 72 | 73 | if (tests == RUN_NONE) 74 | tests = RUN_ALL; 75 | 76 | if (CU_initialize_registry() != CUE_SUCCESS) { 77 | printf("Test registry cannot be initialized\n"); 78 | return -1; 79 | } 80 | 81 | if (tests & RUN_TRACEEVENT) 82 | test_traceevent_lib(); 83 | 84 | CU_basic_set_mode(verbose); 85 | CU_basic_run_tests(); 86 | failed_tests = CU_get_number_of_tests_failed(); 87 | CU_cleanup_registry(); 88 | return failed_tests != 0; 89 | } 90 | -------------------------------------------------------------------------------- /utest/trace-utest.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2020, VMware, Tzvetomir Stoyanov 4 | * 5 | * Modified from libtracefs to libtraceevent: 6 | * Copyright (C) 2021, VMware, Steven Rostedt 7 | * 8 | */ 9 | #ifndef _TRACE_UTEST_H_ 10 | #define _TRACE_UTEST_H_ 11 | 12 | void test_traceevent_lib(void); 13 | 14 | #endif /* _TRACE_UTEST_H_ */ 15 | --------------------------------------------------------------------------------