├── CODING_STYLE ├── CONTRIBUTE ├── COPYING ├── COPYING.LIB ├── DCO ├── Documentation ├── Makefile ├── README.PythonPlugin ├── asciidoc.conf ├── libtracecmd │ ├── Makefile │ ├── install-docs.sh.in │ ├── libtracecmd-files.txt │ ├── libtracecmd-instances.txt │ ├── libtracecmd-iterate.txt │ ├── libtracecmd-log.txt │ ├── libtracecmd-maps.txt │ ├── libtracecmd-peer.txt │ ├── libtracecmd-record.txt │ ├── libtracecmd-timestamp.txt │ ├── libtracecmd.txt │ └── meson.build ├── manpage-1.72.xsl ├── manpage-base.xsl ├── manpage-bold-literal.xsl ├── manpage-normal.xsl ├── manpage-suppress-sp.xsl └── trace-cmd │ ├── Makefile │ ├── install-docs.sh.in │ ├── meson.build │ ├── trace-cmd-agent.1.txt │ ├── trace-cmd-attach.1.txt │ ├── trace-cmd-check-events.1.txt │ ├── trace-cmd-clear.1.txt │ ├── trace-cmd-convert.1.txt │ ├── trace-cmd-dump.1.txt │ ├── trace-cmd-extract.1.txt │ ├── trace-cmd-hist.1.txt │ ├── trace-cmd-list.1.txt │ ├── trace-cmd-listen.1.txt │ ├── trace-cmd-mem.1.txt │ ├── trace-cmd-options.1.txt │ ├── trace-cmd-profile.1.txt │ ├── trace-cmd-record.1.txt │ ├── trace-cmd-report.1.txt │ ├── trace-cmd-reset.1.txt │ ├── trace-cmd-restore.1.txt │ ├── trace-cmd-set.1.txt │ ├── trace-cmd-show.1.txt │ ├── trace-cmd-snapshot.1.txt │ ├── trace-cmd-split.1.txt │ ├── trace-cmd-sqlhist.1.txt │ ├── trace-cmd-stack.1.txt │ ├── trace-cmd-start.1.txt │ ├── trace-cmd-stat.1.txt │ ├── trace-cmd-stop.1.txt │ ├── trace-cmd-stream.1.txt │ ├── trace-cmd.1.txt │ ├── trace-cmd.dat.v6.5.txt │ └── trace-cmd.dat.v7.5.txt ├── LICENSES ├── GPL-2.0 └── LGPL-2.1 ├── Makefile ├── Makefile.meson ├── PACKAGING ├── README ├── check-manpages.sh ├── features.mk ├── include ├── linux │ └── time64.h ├── trace-cmd │ └── trace-cmd.h └── version.h ├── lib ├── Documentation ├── check-manpages.sh ├── meson.build ├── meson_options.txt └── trace-cmd │ ├── Makefile │ ├── include │ ├── meson.build │ ├── private │ │ ├── meson.build │ │ ├── trace-cmd-private-python.h │ │ ├── trace-cmd-private.h │ │ ├── trace-filter-hash.h │ │ ├── trace-hash.h │ │ ├── trace-msg.h │ │ └── trace-rbtree.h │ ├── trace-cmd-local.h │ ├── trace-hash-local.h │ ├── trace-tsync-local.h │ └── trace-write-local.h │ ├── meson.build │ ├── plugins │ └── Makefile │ ├── test.c │ ├── trace-blk-hack.c │ ├── trace-compress-zlib.c │ ├── trace-compress-zstd.c │ ├── trace-compress.c │ ├── trace-filter-hash.c │ ├── trace-filter.c │ ├── trace-ftrace.c │ ├── trace-hash.c │ ├── trace-hooks.c │ ├── trace-input.c │ ├── trace-maps.c │ ├── trace-msg.c │ ├── trace-output.c │ ├── trace-perf.c │ ├── trace-plugin.c │ ├── trace-rbtree.c │ ├── trace-recorder.c │ ├── trace-timesync-kvm.c │ ├── trace-timesync-ptp.c │ ├── trace-timesync.c │ └── trace-util.c ├── libtracecmd.pc.template ├── make-trace-cmd.sh ├── meson-vcs-tag.sh ├── meson.build ├── meson_options.txt ├── python ├── Makefile ├── ctracecmd.i ├── event-viewer.py ├── meson.build ├── tracecmd.py └── tracecmdgui.py ├── scripts ├── debug │ ├── tsync_hist.py │ ├── tsync_readme │ └── tsync_res.py └── utils.mk ├── tracecmd ├── Makefile ├── include │ ├── bug.h │ ├── list.h │ └── trace-local.h ├── meson.build ├── trace-agent.c ├── trace-attach.c ├── trace-check-events.c ├── trace-clear.c ├── trace-cmd.bash ├── trace-cmd.c ├── trace-convert.c ├── trace-dump.c ├── trace-hist.c ├── trace-list.c ├── trace-listen.c ├── trace-mem.c ├── trace-profile.c ├── trace-read.c ├── trace-record.c ├── trace-restore.c ├── trace-setup-guest.c ├── trace-show.c ├── trace-snapshot.c ├── trace-split.c ├── trace-sqlhist.c ├── trace-stack.c ├── trace-stat.c ├── trace-stream.c ├── trace-tsync.c ├── trace-usage.c ├── trace-vm.c └── trace-vsock.c └── utest ├── Makefile ├── README ├── meson.build ├── trace-utest.c ├── trace-utest.h └── tracecmd-utest.c /CONTRIBUTE: -------------------------------------------------------------------------------- 1 | If you like to become part of the community and submit patches, here's how 2 | to do so for trace-cmd. 3 | 4 | If you only want to report a bug, or suggest an enhancement, you may do 5 | so at: 6 | 7 | https://bugzilla.kernel.org/buglist.cgi?component=Trace-cmd%2FKernelshark 8 | 9 | All development is done via a mailing list: 10 | 11 | http://vger.kernel.org/vger-lists.html#linux-trace-devel 12 | 13 | Patches should be sent to linux-trace-devel@vger.kernel.org 14 | 15 | Start by cloning the official repository: 16 | 17 | git clone git://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git 18 | 19 | Make your changes. When you are satisfied with them, commit them into git. 20 | Here's some helpful hints for your git commits. 21 | 22 | 1) When making changes, please follow the coding style defined by the file 23 | called CODING_STYLE in this directory. 24 | 25 | 2) Every commit should only do one thing. 26 | That is, if your work requires some cleaning up of code, do that 27 | clean up as a separate commit and not with your functional changes. 28 | Find ways to take "steps" in modifying code. If you can break up 29 | your changes in a series of steps, do so. 30 | 31 | 3) The commit log should start with a title. Like the below 32 | 33 | trace-cmd: Add CONTRIBUTE file 34 | 35 | Even though this repo is for trace-cmd, start the topic with 36 | "trace-cmd:" because the commits will end up as patches to a mailing 37 | list that handles other tracing repos, differentiating them with the subject 38 | is useful. You can be more specific as well. If the change only affects the 39 | "record" command, you may start the title with "trace-cmd record:". 40 | 41 | 4) The body of the commit (with a blank line from the title), should be self 42 | contained, and explain why you are making the change. The title should hold 43 | the "what" is changing, but the body contains the rationale for the change. 44 | It should be a stand alone, and not state things like "See the next patch", 45 | because when it is in git history, there's no knowing what the next patch 46 | is. You can make statements like "This is needed for a 47 | that will come later". Where "" is something that you are 48 | working on and the current commit is one of the steps required to get there. 49 | 50 | 5) Add your Developer Certificate of Origin (DCO) at the bottom of the commit 51 | log. That is "Signed-off-by: Full Name " where your full name is your 52 | real name (no pseudonyms). Optionally, if you are making the change on 53 | behalf of your company, you may also add your company name, if you are not 54 | using your company's email. "Signed-off-by: Full Name (Company) ". 55 | Please note, the DCO is your statement that you have the legal right to 56 | make these changes for the project you are submitting to. 57 | 58 | You can use the Linux kernel "checkpatch.pl" script to help verify the formatting 59 | of your patch: 60 | 61 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/checkpatch.pl 62 | 63 | Please note that checkpatch.pl is a guide and not a hard rule. If it reports a 64 | fix that makes the code harder to read, that fix can probably be ignored. 65 | 66 | git format-patch --stdout HEAD~1..HEAD | ./checkpatch.pl 67 | 68 | Finally, you can use the git "send-email" functionality: 69 | 70 | git send-email --from=' --to='linux-trace-devel@vger.kernel.org' HEAD~1..HEAD 71 | 72 | If you are sending one patch, if you are adding more than one patch, also include 73 | a cover letter: 74 | 75 | git send-email --cover-letter --annotate --from=' --to='linux-trace-devel@vger.kernel.org' ~1..HEAD 76 | 77 | If you receive feedback on your patches, and plan on sending another version, 78 | please use the '-v' option to mark your patches that they are a new version. 79 | For example, if you add "-v2" to the above commands, instead of having: 80 | "[PATCH]" in the subject, it will have "[PATCH v2]", letting the reviewers know 81 | that this is a new version. If you send another version, use "-v3" and so on. 82 | 83 | For more information about git send-email: 84 | 85 | https://git-scm.com/docs/git-send-email 86 | 87 | To keep track of the status of patches that have been submitted, check out: 88 | 89 | https://patchwork.kernel.org/project/linux-trace-devel/list/ 90 | 91 | If you would like to apply patches from the mailing list, you can use 92 | the "b4" utility. 93 | 94 | $ pip install b4 95 | 96 | Then from the mailing list archive, find a message id from a patch or patch 97 | series. For example, to get the patch from: 98 | 99 | https://lore.kernel.org/linux-trace-devel/20210205173713.132051-1-tz.stoyanov@gmail.com/ 100 | 101 | $ b4 am -o - 20210205173713.132051-1-tz.stoyanov@gmail.com > /tmp/p.mbox 102 | $ git am /tmp/p.mbox 103 | 104 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | There are two main licenses that the tools in this directory are covered 2 | under. For the applications themselves, they are covered under GPL-2.0 (see 3 | LICENSES/GPL-2.0). As for the exported headers and libraries, they are covered 4 | under LPGL-2.1 (see LICENSES/LGPL-2.1). 5 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | 2 | (Copied from the Linux Kernel's Documentation/process/submitting-patches.rst) 3 | 4 | Sign your work - the Developer's Certificate of Origin 5 | ------------------------------------------------------ 6 | 7 | The sign-off is a simple line at the end of the explanation for the 8 | patch, which certifies that you wrote it or otherwise have the right to 9 | pass it on as an open-source patch. The rules are pretty simple: if you 10 | can certify the below: 11 | 12 | Developer's Certificate of Origin 1.1 13 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 14 | 15 | By making a contribution to this project, I certify that: 16 | 17 | (a) The contribution was created in whole or in part by me and I 18 | have the right to submit it under the open source license 19 | indicated in the file; or 20 | 21 | (b) The contribution is based upon previous work that, to the best 22 | of my knowledge, is covered under an appropriate open source 23 | license and I have the right under that license to submit that 24 | work with modifications, whether created in whole or in part 25 | by me, under the same open source license (unless I am 26 | permitted to submit under a different license), as indicated 27 | in the file; or 28 | 29 | (c) The contribution was provided directly to me by some other 30 | person who certified (a), (b) or (c) and I have not modified 31 | it. 32 | 33 | (d) I understand and agree that this project and the contribution 34 | are public and that a record of the contribution (including all 35 | personal information I submit with it, including my sign-off) is 36 | maintained indefinitely and may be redistributed consistent with 37 | this project or the open source license(s) involved. 38 | 39 | then you just add a line saying:: 40 | 41 | Signed-off-by: Random J Developer 42 | 43 | using your real name (sorry, no pseudonyms or anonymous contributions.) 44 | 45 | Some people also put extra tags at the end. They'll just be ignored for 46 | now, but you can do this to mark internal company procedures or just 47 | point out some special detail about the sign-off. 48 | -------------------------------------------------------------------------------- /Documentation/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | doc_dir:=$(src)/Documentation 4 | 5 | export doc_dir 6 | 7 | SUBDIR += trace-cmd 8 | SUBDIR += libtracecmd 9 | 10 | .PHONY: $(SUBDIR) 11 | 12 | DOCDIR = $(src)/Documentation 13 | ASCIIDOC=asciidoc 14 | ASCIIDOC_CONF = $(DOCDIR)/asciidoc.conf 15 | ASCIIDOC_EXTRA = --unsafe -f $(ASCIIDOC_CONF) 16 | ASCIIDOC_HTML = xhtml11 17 | MANPAGE_XSL = $(DOCDIR)/manpage-normal.xsl 18 | XMLTO_EXTRA = 19 | INSTALL?=install 20 | RM ?= rm -f 21 | 22 | ASCIIDOC_INSTALLED := $(shell command -v $(ASCIIDOC) 2> /dev/null) 23 | ifndef ASCIIDOC_INSTALLED 24 | missing_tools += $(ASCIIDOC) 25 | endif 26 | 27 | XMLTO=xmlto 28 | XMLTO_INSTALLED := $(shell command -v $(XMLTO) 2> /dev/null) 29 | ifndef XMLTO_INSTALLED 30 | missing_tools += $(XMLTO) 31 | endif 32 | 33 | # 34 | # For asciidoc ... 35 | # -7.1.2, no extra settings are needed. 36 | # 8.0-, set ASCIIDOC8. 37 | # 38 | 39 | # 40 | # For docbook-xsl ... 41 | # -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) 42 | # 1.69.0, no extra settings are needed? 43 | # 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? 44 | # 1.71.1, no extra settings are needed? 45 | # 1.72.0, set DOCBOOK_XSL_172. 46 | # 1.73.0-, set ASCIIDOC_NO_ROFF 47 | # 48 | 49 | # 50 | # If you had been using DOCBOOK_XSL_172 in an attempt to get rid 51 | # of 'the ".ft C" problem' in your generated manpages, and you 52 | # instead ended up with weird characters around callouts, try 53 | # using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). 54 | # 55 | 56 | ifdef ASCIIDOC8 57 | ASCIIDOC_EXTRA += -a asciidoc7compatible 58 | endif 59 | ifdef DOCBOOK_XSL_172 60 | ASCIIDOC_EXTRA += -a libtracecmd-asciidoc-no-roff 61 | MANPAGE_XSL = $(DOCDIR)/manpage-1.72.xsl 62 | else 63 | ifdef ASCIIDOC_NO_ROFF 64 | # docbook-xsl after 1.72 needs the regular XSL, but will not 65 | # pass-thru raw roff codes from asciidoc.conf, so turn them off. 66 | ASCIIDOC_EXTRA += -a libtracecmd-asciidoc-no-roff 67 | endif 68 | endif 69 | ifdef MAN_BOLD_LITERAL 70 | XMLTO_EXTRA += -m $(DOCDIR)/manpage-bold-literal.xsl 71 | endif 72 | ifdef DOCBOOK_SUPPRESS_SP 73 | XMLTO_EXTRA += -m $(DOCDIR)/manpage-suppress-sp.xsl 74 | endif 75 | 76 | ifdef USE_ASCIIDOCTOR 77 | ASCIIDOC = asciidoctor 78 | ASCIIDOC_EXTRA = -a compat-mode 79 | ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions 80 | ASCIIDOC_HTML = xhtml5 81 | endif 82 | 83 | ifneq ($(findstring $(MAKEFLAGS),w),w) 84 | PRINT_DIR = --no-print-directory 85 | else # "make -w" 86 | NO_SUBDIR = : 87 | endif 88 | 89 | export ASCIIDOC ASCIIDOC_CONF ASCIIDOC_EXTRA ASCIIDOC_HTML 90 | export MANPAGE_XSL 91 | export XMLTO XMLTO_INSTALLED XMLTO_EXTRA 92 | export missing_tools 93 | export RM 94 | 95 | all: $(SUBDIR) 96 | clean: $(SUBDIR) 97 | install: $(SUBDIR) 98 | 99 | $(SUBDIR): 100 | make -C $@ $(MAKECMDGOALS) 101 | 102 | -------------------------------------------------------------------------------- /Documentation/README.PythonPlugin: -------------------------------------------------------------------------------- 1 | PYTHON PLUGIN DOCUMENTATION 2 | ============================= 3 | 4 | With the python plugin (make python-plugin) you can now 5 | write plugins in python. The API exported by the python 6 | plugin itself (written in C) allows you to access most 7 | information about a record from python. 8 | 9 | To write a python plugin, put a new .py file into a new 10 | ~/.trace-cmd/python/ directory. 11 | 12 | The most basic python plugin is this: 13 | 14 | --- %< --- 15 | def register(pevent): 16 | pass 17 | --- >% --- 18 | 19 | which obviously does nothing at all. 20 | 21 | To register a callback, use the pevent.register_event_handler 22 | function: 23 | 24 | --- %< --- 25 | import tracecmd 26 | 27 | def my_event_handler(trace_seq, event): 28 | pass 29 | 30 | def register(pevent): 31 | pevent.register_event_handler("subsys", "event_name", 32 | my_event_handler) 33 | --- >% --- 34 | 35 | 36 | There are four object types that you get, described below. 37 | 38 | tracecmd.PEvent 39 | ----------------- 40 | 41 | This is the class of the 'pevent' object above, 42 | you get one of those via your register callback. 43 | It has one method and one property: 44 | * register_event_handler() - example above, to register 45 | an event handler function 46 | * file_endian - either '<' or '>' indicating 47 | which endianness the file has, 48 | to be used with struct.unpack() 49 | 50 | tracecmd.TraceSeq 51 | ------------------- 52 | 53 | This is the class of the 'trace_seq' parameter to your callback 54 | function. It has only one method, puts(), to put data into the 55 | buffer. Formatting must be done in python. 56 | 57 | tracecmd.Event 58 | ---------------------- 59 | 60 | This is the class of the 'event' parameter to your callback 61 | function. Note that it doesn't just contain the format, but 62 | also the event data. As such, you can do much with this, and 63 | this is what you'll usually use. Each instance of this allows 64 | access to record items via the dict protocol, and you can get 65 | the items via its keys() methods. So for example, your 66 | callback could be 67 | 68 | --- %< --- 69 | def my_callback(trace_seq, event): 70 | for fieldname in event.keys(): 71 | field = event[fieldname] 72 | --- >% --- 73 | 74 | Each field returned from the dict protocol is an instance of 75 | the next (and last) class: 76 | 77 | tracecmd.Field 78 | ---------------------- 79 | 80 | This is an instance of a field, including its data. It affords 81 | numerous use cases and is what you'll be using most. 82 | 83 | * If this is an integer field, i.e. 1, 2, 4 or 8 bytes long, 84 | you can convert it to the number contained, according to 85 | the file's endianness, by simply casting it to a long: 86 | 87 | field = event['myint'] 88 | value = long(field) 89 | 90 | * You can access the field's data, as field.data, and if the 91 | data is really a "__data_loc" type that will be resolved 92 | automatically. (If you don't know what this means, don't 93 | worry about it and just use field.data) 94 | 95 | 96 | This is it. It's pretty simple. A fully-featured plugin could 97 | look like this: 98 | 99 | --- %< --- 100 | def my_event_handler(trace_seq, event): 101 | trace_seq.puts("myev: %u", long(event['myfield'])) 102 | 103 | def register(pevent): 104 | pevent.register_event_handler("subsys", "event_name", 105 | my_event_handler) 106 | --- >% --- 107 | 108 | 109 | Tips and tricks 110 | ----------------- 111 | 112 | Be familiar with the struct module and use it, always 113 | checking endianness and potentially using pevent.file_endian. 114 | 115 | 116 | If you need access to pevent in your callbacks, simply 117 | pass it in yourself: 118 | 119 | --- %< --- 120 | def my_event_handler(pevent, trace_seq, event): 121 | pass 122 | 123 | def register(pevent): 124 | pevent.register_event_handler("subsys", "event_name", 125 | lambda *args: my_event_handler(pevent, *args) 126 | ) 127 | --- >% --- 128 | -------------------------------------------------------------------------------- /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 | libtracefs 78 | {libtracefs_version} 79 | libtracefs 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/libtracecmd/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | # Include the utils 4 | include $(src)/scripts/utils.mk 5 | 6 | # This Makefile and manpage XSL files were taken from libtracefs 7 | # and modified for libtracecmd 8 | 9 | MAN3_TXT= \ 10 | $(wildcard libtracecmd-*.txt) \ 11 | libtracecmd.txt 12 | 13 | MAN_TXT = $(MAN3_TXT) 14 | _MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) 15 | _MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) 16 | _DOC_MAN3=$(patsubst %.txt,%.m,$(MAN3_TXT)) 17 | 18 | MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML)) 19 | MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML)) 20 | DOC_MAN3=$(addprefix $(OUTPUT),$(_DOC_MAN3)) 21 | 22 | # Make the path relative to DESTDIR, not prefix 23 | ifndef DESTDIR 24 | prefix?=$(HOME) 25 | endif 26 | bindir?=$(prefix)/bin 27 | htmldir?=$(prefix)/share/doc/libtracecmd-doc 28 | pdfdir?=$(prefix)/share/doc/libtracecmd-doc 29 | mandir?=$(prefix)/share/man 30 | man3dir=$(mandir)/man3 31 | 32 | ifdef USE_ASCIIDOCTOR 33 | ASCIIDOC_EXTRA += -a mansource="libtracecmd" -a manmanual="libtracecmd Manual" 34 | endif 35 | 36 | all: check-man-tools html man 37 | 38 | man: man3 39 | man3: $(DOC_MAN3) 40 | 41 | html: $(MAN_HTML) 42 | 43 | $(MAN_HTML) $(DOC_MAN3): $(ASCIIDOC_CONF) 44 | 45 | install: check-man-tools install-man install-html 46 | 47 | check-man-tools: 48 | ifdef missing_tools 49 | $(error "You need to install $(missing_tools) for man pages") 50 | endif 51 | 52 | install-%.3: $(OUTPUT)%.3 53 | $(Q)$(call do_install_docs,$<,$(man3dir),644); 54 | 55 | do-install-man: man $(addprefix install-,$(wildcard $(OUTPUT)*.3)) 56 | 57 | install-man: man 58 | $(Q)$(MAKE) -C . do-install-man 59 | 60 | install-%.txt: $(OUTPUT)%.html 61 | $(Q)$(call do_install_docs,$<,$(htmldir),644); 62 | 63 | do-install-html: html $(addprefix install-,$(wildcard *.txt)) 64 | 65 | install-html: html do-install-html 66 | 67 | uninstall: uninstall-man uninstall-html 68 | 69 | uninstall-man: 70 | $(Q)$(RM) $(addprefix $(DESTDIR)$(man3dir)/,$(DOC_MAN3)) 71 | 72 | uninstall-html: 73 | $(Q)$(RM) $(addprefix $(DESTDIR)$(htmldir)/,$(MAN_HTML)) 74 | 75 | ifdef missing_tools 76 | DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed) 77 | else 78 | DO_INSTALL_MAN = do-install-man 79 | endif 80 | 81 | CLEAN_FILES = \ 82 | $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ 83 | $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ 84 | $(DOC_MAN3) *.3 *.m 85 | 86 | clean: 87 | $(Q) $(RM) $(CLEAN_FILES) 88 | 89 | ifdef USE_ASCIIDOCTOR 90 | $(OUTPUT)%.m : $(OUTPUT)%.txt 91 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 92 | $(ASCIIDOC) -b manpage -d manpage \ 93 | $(ASCIIDOC_EXTRA) -alibtracecmd_version=$(LIBTRACECMD_VERSION) -o $@+ $< && \ 94 | mv $@+ $@ 95 | endif 96 | 97 | $(OUTPUT)%.m : $(OUTPUT)%.xml 98 | $(QUIET_XMLTO)$(RM) $@ && \ 99 | $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<; \ 100 | touch $@ 101 | 102 | $(OUTPUT)%.xml : %.txt 103 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 104 | $(ASCIIDOC) -b docbook -d manpage \ 105 | $(ASCIIDOC_EXTRA) -alibtracecmd_version=$(LIBTRACECMD_VERSION) -o $@+ $< && \ 106 | mv $@+ $@ 107 | 108 | $(MAN_HTML): $(OUTPUT)%.html : %.txt 109 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 110 | $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ 111 | $(ASCIIDOC_EXTRA) -alibtracecmd_version=$(LIBTRACECMD_VERSION) -o $@+ $< && \ 112 | mv $@+ $@ 113 | -------------------------------------------------------------------------------- /Documentation/libtracecmd/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/libtracecmd/libtracecmd-instances.txt: -------------------------------------------------------------------------------- 1 | libtracecmd(3) 2 | ============= 3 | 4 | NAME 5 | ---- 6 | tracecmd_buffer_instances, tracecmd_buffer_instance_name, tracecmd_buffer_instance_handle 7 | - Read tracing instances from a trace file. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | int *tracecmd_buffer_instances*(struct tracecmd_input pass:[*]_handle_); 16 | const char pass:[*]*tracecmd_buffer_instance_name*(struct tracecmd_input pass:[*]_handle_, int _indx_); 17 | struct tracecmd_input pass:[*]*tracecmd_buffer_instance_handle*(struct tracecmd_input pass:[*]_handle_, int _indx_); 18 | -- 19 | 20 | DESCRIPTION 21 | ----------- 22 | This set of APIs can be used to get information and read tracing data 23 | from tracing instances stored in a trace file. 24 | 25 | The *tracecmd_buffer_instances()* function gets the number of tracing 26 | instances recorded in a trace file. The top instance is not counted. 27 | The _handle_ is a tracecmd_input handler returned by 28 | *tracecmd_open_head()*. 29 | 30 | The *tracecmd_buffer_instance_name()* function gets the name of the 31 | tracing instance with given index _indx_, recorded in a trace file. 32 | The _indx_ is a number in the interval [0 .. count-1], where count 33 | is the number returned by *tracecmd_buffer_instances()*. The _handle_ 34 | is a tracecmd_input handler returned by *tracecmd_open_head()*. 35 | 36 | The *tracecmd_buffer_instance_handle()* allocates and initializes a 37 | tracecmd_input handle, associated with trace instance with index 38 | _indx_ from a trace file. The _handle_ is a tracecmd_input handler 39 | returned by *tracecmd_open_head()*. The _indx_ is a number in the 40 | interval [0 .. count-1], where count is the number returned by 41 | *tracecmd_buffer_instances()*. 42 | 43 | RETURN VALUE 44 | ------------ 45 | The *tracecmd_buffer_instances()* function returns the number of tracing 46 | instances recorded in a trace file. 47 | 48 | The *tracecmd_buffer_instance_name()* function returns a string, the name 49 | of a tracing instance, or NULL in case of an error The string must *not* 50 | be freed. 51 | 52 | The *tracecmd_buffer_instance_handle()* function returns a pointer to 53 | newly allocated tracecmd_input handler or NULL in case if an error. The 54 | returned handler must be closed by *tracecmd_close()(3)* 55 | 56 | EXAMPLE 57 | ------- 58 | [source,c] 59 | -- 60 | #include 61 | ... 62 | struct tracecmd_input *handle = tracecmd_open_head("trace.dat"); 63 | if (!handle) { 64 | /* Failed to open trace.dat file */ 65 | } 66 | ... 67 | int num = tracecmd_buffer_instances(handle); 68 | 69 | while(num) { 70 | struct tracecmd_input *h; 71 | char *name; 72 | 73 | name = tracecmd_buffer_instance_name(handle, num); 74 | if (!name) { 75 | /* Failed to get name of instance num */ 76 | } 77 | h = tracecmd_buffer_instance_handle(handle, num); 78 | if (!h) { 79 | /* Failed to initialize handler for instance num */ 80 | } 81 | 82 | ... 83 | tracecmd_close(h); 84 | num--; 85 | } 86 | ... 87 | tracecmd_close(handle); 88 | 89 | -- 90 | FILES 91 | ----- 92 | [verse] 93 | -- 94 | *trace-cmd.h* 95 | Header file to include in order to have access to the library APIs. 96 | *-ltracecmd* 97 | Linker switch to add when building a program that uses the library. 98 | -- 99 | 100 | SEE ALSO 101 | -------- 102 | *libtracefs(3)*, 103 | *libtraceevent(3)*, 104 | *trace-cmd(1)* 105 | *trace-cmd.dat(5)* 106 | 107 | AUTHOR 108 | ------ 109 | [verse] 110 | -- 111 | *Steven Rostedt* 112 | *Tzvetomir Stoyanov* 113 | -- 114 | REPORTING BUGS 115 | -------------- 116 | Report bugs to 117 | 118 | LICENSE 119 | ------- 120 | libtracecmd is Free Software licensed under the GNU LGPL 2.1 121 | 122 | RESOURCES 123 | --------- 124 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 125 | 126 | COPYING 127 | ------- 128 | Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under 129 | the terms of the GNU Public License (GPL). 130 | -------------------------------------------------------------------------------- /Documentation/libtracecmd/libtracecmd-log.txt: -------------------------------------------------------------------------------- 1 | libtracecmd(3) 2 | ============= 3 | 4 | NAME 5 | ---- 6 | tracecmd_set_loglevel - Set log level of the library 7 | 8 | SYNOPSIS 9 | -------- 10 | [verse] 11 | -- 12 | *#include * 13 | 14 | int *tracecmd_set_loglevel*(enum tep_loglevel _level_); 15 | -- 16 | 17 | DESCRIPTION 18 | ----------- 19 | The *tracecmd_set_loglevel()* function sets the level of the library logs that will be printed on 20 | the console. See *libtraceevent(3)* for detailed desciription of the log levels. Setting the log 21 | level to specific value means that logs from the previous levels will be printed too. For example 22 | _TEP_LOG_WARNING_ will print any logs with severity _TEP_LOG_WARNING_, _TEP_LOG_ERROR_ and 23 | _TEP_LOG_CRITICAL_. The default log level is _TEP_LOG_CRITICAL_. When a new level is set, it is 24 | also propagated to the libtracefs and libtraceevent. 25 | 26 | EXAMPLE 27 | ------- 28 | [source,c] 29 | -- 30 | #include 31 | ... 32 | tracecmd_set_loglevel(TEP_LOG_ALL); 33 | ... 34 | /* call libtracecmd, libtracefs or libtraceevent APIs and observe any logs they produce */ 35 | ... 36 | tracecmd_set_loglevel(TEP_LOG_CRITICAL); 37 | -- 38 | 39 | FILES 40 | ----- 41 | [verse] 42 | -- 43 | *trace-cmd.h* 44 | Header file to include in order to have access to the library APIs. 45 | *-ltracecmd* 46 | Linker switch to add when building a program that uses the library. 47 | -- 48 | 49 | SEE ALSO 50 | -------- 51 | *libtracefs(3)*, 52 | *libtraceevent(3)*, 53 | *trace-cmd(1)* 54 | *trace-cmd.dat(5)* 55 | 56 | AUTHOR 57 | ------ 58 | [verse] 59 | -- 60 | *Steven Rostedt* 61 | *Tzvetomir Stoyanov* 62 | -- 63 | REPORTING BUGS 64 | -------------- 65 | Report bugs to 66 | 67 | LICENSE 68 | ------- 69 | libtracecmd is Free Software licensed under the GNU LGPL 2.1 70 | 71 | RESOURCES 72 | --------- 73 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 74 | 75 | COPYING 76 | ------- 77 | Copyright \(C) 2021 VMware, Inc. Free use of this software is granted under 78 | the terms of the GNU Public License (GPL). 79 | -------------------------------------------------------------------------------- /Documentation/libtracecmd/libtracecmd-record.txt: -------------------------------------------------------------------------------- 1 | libtracecmd(3) 2 | ============= 3 | 4 | NAME 5 | ---- 6 | tracecmd_read_cpu_first, tracecmd_read_data, tracecmd_read_at, 7 | tracecmd_free_record, tracecmd_get_tep - Read recorded events from a trace file. 8 | 9 | SYNOPSIS 10 | -------- 11 | [verse] 12 | -- 13 | *#include * 14 | 15 | struct tep_record pass:[*]*tracecmd_read_cpu_first*(struct tracecmd_input pass:[*]_handle_, int _cpu_); 16 | struct tep_record pass:[*]*tracecmd_read_data*(struct tracecmd_input pass:[*]_handle_, int _cpu_); 17 | struct tep_record pass:[*]*tracecmd_read_at*(struct tracecmd_input pass:[*]_handle_, unsigned long long _offset_, int pass:[*]_cpu_); 18 | void *tracecmd_free_record*(struct tep_record pass:[*]_record_); 19 | struct tep_handle pass:[*]*tracecmd_get_tep*(struct tracecmd_input pass:[*]_handle_); 20 | -- 21 | 22 | DESCRIPTION 23 | ----------- 24 | This set of APIs can be used to read tracing data from a trace file opened 25 | with *tracecmd_open()(3)*, *tracecmd_open_fd()(3)* or *tracecmd_open_head()(3)*. 26 | 27 | The *tracecmd_read_cpu_first()* function reads the first trace record 28 | for a given _cpu_ from a trace file associated with _handle_. The returned 29 | record must be freed with *tracecmd_free_record()*. 30 | 31 | The *tracecmd_read_data()* function reads the next trace record for 32 | a given _cpu_ from a trace file associated with _handle_ and increments 33 | the read location pointer, so that the next call to *tracecmd_read_data()* 34 | will not read the same record again. The returned record must be freed 35 | with *tracecmd_free_record()*. 36 | 37 | The *tracecmd_read_at()* function reads a trace record from a specific 38 | _offset_ within the file associated with _handle_. The CPU on which the 39 | recorded event occurred is stored in the _cpu_. The function does not 40 | change the current read location pointer. The returned record must be 41 | freed with *tracecmd_free_record()*. 42 | 43 | The *tracecmd_free_record()* function frees a _record_ returned by any 44 | of the _tracecmd_read__ APIs. 45 | 46 | The *tracecmd_get_tep()* function returns a tep context for a given 47 | _handle_. 48 | 49 | RETURN VALUE 50 | ------------ 51 | The *tracecmd_read_cpu_first()*, *tracecmd_read_data()* and 52 | *tracecmd_read_at()* functions return a pointer to struct tep_record or 53 | NULL in case of an error.The returned record must be freed with 54 | *tracecmd_free_record()*. 55 | 56 | The *tracecmd_get_tep()* function returns a pointer to tep context or 57 | NULL if there is no tep context for the given _handle_. The returned 58 | tep pointer must *not* be freed. 59 | 60 | EXAMPLE 61 | ------- 62 | [source,c] 63 | -- 64 | #include 65 | ... 66 | struct tracecmd_input *handle = tracecmd_open("trace.dat"); 67 | if (!handle) { 68 | /* Failed to open trace.dat file */ 69 | } 70 | ... 71 | unsigned long long offset = 0; 72 | struct tep_record *rec; 73 | int cpu = 0; 74 | rec = tracecmd_read_cpu_first(handle, cpu); 75 | while (rec) { 76 | ... 77 | if ( /* some interesting record noticed */) { 78 | /* store the offset of the interesting record */ 79 | offset = rec->offset; 80 | } 81 | ... 82 | tracecmd_free_record(rec); 83 | rec = tracecmd_read_data(handle, cpu); 84 | } 85 | ... 86 | if (offset) { 87 | rec = tracecmd_read_at(handle, offset, &cpu); 88 | if (rec) { 89 | /* Got record at offset on cpu */ 90 | ... 91 | tracecmd_free_record(rec); 92 | } 93 | } 94 | 95 | ... 96 | tracecmd_close(hadle); 97 | 98 | -- 99 | FILES 100 | ----- 101 | [verse] 102 | -- 103 | *trace-cmd.h* 104 | Header file to include in order to have access to the library APIs. 105 | *-ltracecmd* 106 | Linker switch to add when building a program that uses the library. 107 | -- 108 | 109 | SEE ALSO 110 | -------- 111 | *libtracefs(3)*, 112 | *libtraceevent(3)*, 113 | *trace-cmd(1)* 114 | *trace-cmd.dat(5)* 115 | 116 | AUTHOR 117 | ------ 118 | [verse] 119 | -- 120 | *Steven Rostedt* 121 | *Tzvetomir Stoyanov* 122 | -- 123 | REPORTING BUGS 124 | -------------- 125 | Report bugs to 126 | 127 | LICENSE 128 | ------- 129 | libtracecmd is Free Software licensed under the GNU LGPL 2.1 130 | 131 | RESOURCES 132 | --------- 133 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 134 | 135 | COPYING 136 | ------- 137 | Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under 138 | the terms of the GNU Public License (GPL). 139 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | # Include the utils 4 | include $(src)/scripts/utils.mk 5 | 6 | # This Makefile and manpage XSL files were taken from libtracefs 7 | # and modified for libtracecmd 8 | 9 | MAN1_TXT= \ 10 | $(wildcard trace-cmd*.1.txt) 11 | 12 | MAN5_TXT= \ 13 | $(wildcard trace-cmd*.5.txt) 14 | 15 | MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) 16 | _MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) 17 | _MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) 18 | _DOC_MAN1=$(patsubst %.1.txt,%.1,$(MAN1_TXT)) 19 | _DOC_MAN5=$(patsubst %.5.txt,%.5,$(MAN5_TXT)) 20 | 21 | MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML)) 22 | MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML)) 23 | DOC_MAN1=$(addprefix $(OUTPUT),$(_DOC_MAN1)) 24 | DOC_MAN5=$(addprefix $(OUTPUT),$(_DOC_MAN5)) 25 | 26 | # Make the path relative to DESTDIR, not prefix 27 | ifndef DESTDIR 28 | prefix?=$(HOME) 29 | endif 30 | bindir?=$(prefix)/bin 31 | htmldir?=$(prefix)/share/doc/trace-cmd 32 | pdfdir?=$(prefix)/share/doc/trace-cmd 33 | mandir?=$(prefix)/share/man 34 | man1dir=$(mandir)/man1 35 | man5dir=$(mandir)/man5 36 | 37 | ifdef USE_ASCIIDOCTOR 38 | ASCIIDOC_EXTRA += -a mansource="libtracecmd" -a manmanual="libtracecmd Manual" 39 | endif 40 | 41 | all: check-man-tools html man 42 | 43 | man: man1 man5 44 | man1: $(DOC_MAN1) 45 | man5: $(DOC_MAN5) 46 | 47 | html: $(MAN_HTML) 48 | 49 | $(MAN_HTML) $(DOC_MAN1) $(DOC_MAN5): $(ASCIIDOC_CONF) 50 | 51 | install: check-man-tools install-man install-html 52 | 53 | check-man-tools: 54 | ifdef missing_tools 55 | $(error "You need to install $(missing_tools) for man pages") 56 | endif 57 | 58 | install-%.1: $(OUTPUT)%.1 59 | $(Q)$(call do_install_docs,$<,$(man1dir),644); 60 | 61 | install-%.5: $(OUTPUT)%.5 62 | $(Q)$(call do_install_docs,$<,$(man5dir),644); 63 | 64 | do-install-man: man $(addprefix install-,$(wildcard $(OUTPUT)*.1)) \ 65 | $(addprefix install-,$(wildcard $(OUTPUT)*.5)) 66 | 67 | install-man: man 68 | $(Q)$(MAKE) -C . do-install-man 69 | 70 | install-%.txt: $(OUTPUT)%.html 71 | $(Q)$(call do_install_docs,$<,$(htmldir),644); 72 | 73 | do-install-html: html $(addprefix install-,$(wildcard *.txt)) 74 | 75 | install-html: html do-install-html 76 | 77 | uninstall: uninstall-man uninstall-html 78 | 79 | uninstall-man: 80 | $(Q)$(RM) $(addprefix $(DESTDIR)$(man1dir)/,$(DOC_MAN1)) 81 | $(Q)$(RM) $(addprefix $(DESTDIR)$(man5dir)/,$(DOC_MAN5)) 82 | 83 | uninstall-html: 84 | $(Q)$(RM) $(addprefix $(DESTDIR)$(htmldir)/,$(MAN_HTML)) 85 | 86 | ifdef missing_tools 87 | DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed) 88 | else 89 | DO_INSTALL_MAN = do-install-man 90 | endif 91 | 92 | CLEAN_FILES = \ 93 | $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ 94 | $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ 95 | $(DOC_MAN1) $(DOC_MAN5) *.1 *.5 96 | 97 | clean: 98 | $(Q) $(RM) $(CLEAN_FILES) 99 | 100 | ifdef USE_ASCIIDOCTOR 101 | $(OUTPUT)%.1 : $(OUTPUT)%.1.txt 102 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 103 | $(ASCIIDOC) -b manpage -d manpage \ 104 | $(ASCIIDOC_EXTRA) -atracecmd_version=$(TRACECMD_VERSION) -o $@+ $< && \ 105 | mv $@+ $@ 106 | 107 | $(OUTPUT)%.5 : $(OUTPUT)%.5.txt 108 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 109 | $(ASCIIDOC) -b manpage -d manpage \ 110 | $(ASCIIDOC_EXTRA) -atracecmd_version=$(TRACECMD_VERSION) -o $@+ $< && \ 111 | mv $@+ $@ 112 | endif 113 | 114 | $(OUTPUT)%.1 : $(OUTPUT)%.1.xml 115 | $(QUIET_XMLTO)$(RM) $@ && \ 116 | $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<; \ 117 | 118 | $(OUTPUT)%.5 : $(OUTPUT)%.5.xml 119 | $(QUIET_XMLTO)$(RM) $@ && \ 120 | $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<; \ 121 | 122 | $(OUTPUT)%.xml : %.txt 123 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 124 | $(ASCIIDOC) -b docbook -d manpage \ 125 | $(ASCIIDOC_EXTRA) -atracecmd_version=$(TRACECMD_VERSION) -o $@+ $< && \ 126 | mv $@+ $@ 127 | 128 | $(MAN_HTML): $(OUTPUT)%.html : %.txt 129 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 130 | $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ 131 | $(ASCIIDOC_EXTRA) -atracecmd_version=$(TRACECMD_VERSION) -o $@+ $< && \ 132 | mv $@+ $@ 133 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/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/trace-cmd/trace-cmd-agent.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-AGENT(1) 2 | ================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-agent - Run as an agent on a machine (to be controlled by another machine) 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd agent* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) agent listens over a vsocket (for virtual machines) or a TCP port 15 | for connections to control the tracing of the machine. The agent will then start 16 | tracing on the local machine and pass the data to the controlling connection. 17 | 18 | OPTIONS 19 | ------- 20 | *-N* 'client':: 21 | Listen over TCP instead of a vsocket. Must pass in a client host name or IP address 22 | to allow connection to. It will only connect to the specified client. Note, any process 23 | on that client can control the agent. 24 | 25 | *This is a very insecure setting. Only use on a trusted network* 26 | *Only use if the client machine is totally trusted* 27 | 28 | *-p* 'port':: 29 | This option will specify the port to listen to. 30 | 31 | *-D*:: 32 | This options causes trace-cmd agent to go into a daemon mode and run in 33 | the background. 34 | 35 | *-P* 'cid':: 36 | Allow an agent to also act as a proxy server, where it can be run on a host 37 | and connect with a guest. 'cid' is the context ID (see *vsock*(7)) of the 38 | client (e.g., guest VM) it will allow to connect. 39 | 40 | *--verbose*[='level']:: 41 | Set the log level. Supported log levels are "none", "critical", "error", "warning", 42 | "info", "debug", "all" or their identifiers "0", "1", "2", "3", "4", "5", "6". Setting the log 43 | level to specific value enables all logs from that and all previous levels. 44 | The level will default to "info" if one is not specified. 45 | 46 | Example: enable all critical, error and warning logs 47 | 48 | trace-cmd listen --verbose=warning 49 | 50 | SEE ALSO 51 | -------- 52 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 53 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 54 | trace-cmd-split(1), trace-cmd-list(1) 55 | 56 | AUTHOR 57 | ------ 58 | Written by Steven Rostedt, 59 | 60 | RESOURCES 61 | --------- 62 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 63 | 64 | COPYING 65 | ------- 66 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 67 | the terms of the GNU Public License (GPL). 68 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-attach.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-ATTACH(1) 2 | =================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-attach - attach a guest trace.dat file to a host trace.dat file 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd attach* ['OPTIONS'] host-trace-file guest-trace-file guest-pid [guest-pid ...] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) attach is used to take a trace.dat file created on a guest and 15 | attach it to a trace.dat file that was created on the host. In most cases, 16 | trace-cmd-agent(1) can be used to automate this, but if for some reason, the 17 | agent isn't appropriate, it may be required to start trace-cmd recording on 18 | the guest with trace-cmd-record(1). If the host recording is activated at the 19 | same time, one can use trace-cmd attach(1) to connect the guest and host files 20 | as if they were created by the trace-cmd agent. 21 | 22 | *host-trace-file*:: 23 | The trace.dat file created by the host. Must have kvm_exit and kvm_entry 24 | events, and use the "tsc2nsec" clock. 25 | 26 | *guest-trace-file*:: 27 | The trace.dat file created by the guest. Must use the "x86-tsc" clock. 28 | For now, this is only supported on x86, it may support other achitectures 29 | later. 30 | 31 | *guest-pid*:: 32 | The process ID of the host thread that represents the guests threads. 33 | Each process ID that represents all of the guest vCPUs should be listed. 34 | Note, you can add more than just the threads that represent the guest 35 | vCPUs, as the tool will search the *host-trace-file* for kvm_exit and 36 | kvm_entry events to match these PIDs with the vCPUs that they represent. 37 | 38 | OPTIONS 39 | ------- 40 | *-c* 'cpus':: 41 | Specify a the number of CPUS the guest has. 42 | 43 | *-s* 'timeshift':: 44 | A comma separated list of the format _offset_,_scale_,_frac_,_timestamp_ 45 | These values map to what are given in /sys/kernel/kvm//vcpu/* 46 | 47 | *offset*: Is the offset of the guest. "tsc-offest" in the directory. Note 48 | that the value listed here is the negative of what is listed in 49 | the directory. 50 | 51 | *scale*: The scaling factor. "tsc-scaling-ratio" 52 | 53 | *frac*: The fraction bits. "tsc-scaling-ratio-frac-bits" 54 | 55 | *timestamp*: The timestamp to start using the above. In some cases, the 56 | values may change over time. By adding a timestamp, it will 57 | take effect after the timestamp has been hit. Normally 58 | this would be zero. 59 | 60 | Currently, only one timeshift is given per CPU. One *-s* option should be 61 | given for each CPU. If there are less options than CPUs, then the last option 62 | given will be used for the rest of the CPUs. If only one option is given, then 63 | the values for that option will be used for all CPUs. 64 | 65 | EXAMPLES 66 | -------- 67 | 68 | Enable all events for tracing: 69 | 70 | [source,shell] 71 | ---- 72 | $ # find the process for a given guest 73 | $ ps aux |grep qemu 74 | libvirt+ 63170 5.6 1.6 13994848 4257540 ? Sl May02 2884:49 /usr/bin/qemu-system-x86_64... 75 | 76 | $ # Use 63170 to find all the PIDs for the give guest 77 | $ ls /proc/63170/task 78 | 1541591 63170 63198 63209 63211 63213 63214 63215 63216 63217 63218 63219 63234 79 | 80 | $ # Find the tsc offset 81 | $ su 82 | # cat /sys/kernel/debug/kvm/63170-15/vcpu0/tsc-offset 83 | -27950965013436847 84 | 85 | # trace-cmd record -C tsc2nsec -e kvm -e sched -e irq -e timer 86 | 87 | # on guest: 88 | 89 | # trace-cmd record -C x86-tsc -e sched -e irq -e timer sleep 10 90 | 91 | # back on host, hit Ctrl^C to stop tracing after the guest is done 92 | 93 | # # Make the trace.dat user owned by your user account. 94 | # chown user.user trace.dat 95 | # exit 96 | 97 | $ scp root@guest:trace.dat trace-guest.dat 98 | 99 | $ # now attach the two files (guest has 8 CPUs) 100 | $ trace-cmd attach -c 8 -s 27950965013436847 trace.dat trace-guest.dat 1541591 63170 63198 63209 63211 63213 63214 63215 63216 63217 63218 63219 63234 101 | 102 | $ trace-cmd report -i trace.dat -i trace-guest.dat 103 | $ # now you should see the guest trace interleaved within the host trace. 104 | ---- 105 | 106 | 107 | SEE ALSO 108 | -------- 109 | trace-cmd(1), trace-cmd-report(1), trace-cmd-start(1), trace-cmd-stop(1), 110 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 111 | trace-cmd-list(1), trace-cmd-listen(1), trace-cmd-profile(1) 112 | 113 | AUTHOR 114 | ------ 115 | Written by Steven Rostedt (Google) 116 | 117 | RESOURCES 118 | --------- 119 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 120 | 121 | COPYING 122 | ------- 123 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 124 | the terms of the GNU Public License (GPL). 125 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-check-events.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-CHECK_EVENTS(1) 2 | ========================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-check-events - parse the event formats on local system 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd check-events* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) check-events parses format strings for all the events on the 15 | local system. It returns whether all the format strings can be parsed 16 | correctly. It will load plugins unless specified otherwise. 17 | 18 | This is useful to check for any trace event format strings which may contain 19 | some internal kernel function references which cannot be decoded outside of 20 | the kernel. This may mean that either the unparsed format strings of the trace 21 | events need to be changed or that a plugin needs to be created to parse them. 22 | 23 | OPTIONS 24 | ------- 25 | *-N* - Don't load plugins 26 | 27 | *--verbose*[='level']:: 28 | Set the log level. Supported log levels are "none", "critical", "error", "warning", 29 | "info", "debug", "all" or their identifiers "0", "1", "2", "3", "4", "5", "6". Setting the log 30 | level to specific value enables all logs from that and all previous levels. 31 | The level will default to "info" if one is not specified. 32 | 33 | Example: enable all critical, error and warning logs 34 | 35 | trace-cmd check-events --verbose=warning 36 | 37 | SEE ALSO 38 | -------- 39 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-stop(1), 40 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 41 | trace-cmd-list(1), trace-cmd-listen(1), trace-cmd-start(1) 42 | 43 | AUTHOR 44 | ------ 45 | Written by Vaibhav Nagarnaik, 46 | 47 | RESOURCES 48 | --------- 49 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 50 | 51 | COPYING 52 | ------- 53 | Copyright \(C) 2011 Google, Inc. Free use of this software is granted under 54 | the terms of the GNU Public License (GPL). 55 | 56 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-clear.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-CLEAR(1) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-clear - clear the Ftrace buffer. 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd clear* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The *trace-cmd(1) clear* clears the content of the Ftrace ring buffer. 15 | 16 | OPTIONS 17 | ------- 18 | *-B* 'buffer-name':: 19 | If the kernel supports multiple buffers, this will clear only the given 20 | buffer. It does not affect any other buffers. This may be used multiple 21 | times to specify different buffers. The top level buffer will not be 22 | clearded if this option is given. 23 | 24 | *-a*:: 25 | Clear all existing buffers, including the top level one. 26 | 27 | SEE ALSO 28 | -------- 29 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 30 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 31 | trace-cmd-list(1), trace-cmd-listen(1) 32 | 33 | AUTHOR 34 | ------ 35 | [verse] 36 | -- 37 | *Steven Rostedt* , author of *trace-cmd*. 38 | *Tzvetomir Stoyanov* , author of this man page. 39 | -- 40 | REPORTING BUGS 41 | -------------- 42 | Report bugs to 43 | 44 | LICENSE 45 | ------- 46 | trace-cmd is Free Software licensed under the terms of the 47 | GNU Public License (GPL). 48 | 49 | RESOURCES 50 | --------- 51 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-convert.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-CONVERT(1) 2 | =================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-convert - convert trace files 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd convert* ['OPTIONS'] ['output-file'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) convert command converts trace file. It reads the input file and copies the data 15 | into an output file. The output file may be in different format, depending on the command line 16 | arguments. The default output is in version 7 and compressed (if 17 | compiled with compression support). 18 | 19 | OPTIONS 20 | ------- 21 | *-i* 'input-file':: 22 | By default, trace-cmd convert will read the file 'trace.dat'. But the *-i* 23 | option open up the given 'input-file' instead. 24 | 25 | *-o* 'out-file':: 26 | The name of the output file, this parameter is mandatory. Note, the output file may also be 27 | specified as the last item on the command line. 28 | 29 | *--file-version*:: 30 | Desired version of the output file. Supported versions are 6 or 7. 31 | 32 | *--compression*:: 33 | Compression of the trace output file, one of these strings can be passed: 34 | 35 | 'any' - auto select the best available compression algorithm 36 | 37 | 'none' - do not compress the trace file 38 | 39 | 'name' - the name of the desired compression algorithms. Available algorithms can be listed with 40 | trace-cmd list -c 41 | 42 | *--help*:: 43 | Print usage information. 44 | 45 | EXAMPLES 46 | -------- 47 | 48 | # trace-cmd convert --compression any trace_compress.dat 49 | 50 | SEE ALSO 51 | -------- 52 | trace-cmd(1), trace-cmd.dat(1) 53 | 54 | AUTHOR 55 | ------ 56 | *Steven Rostedt* , author of *trace-cmd*. 57 | *Tzvetomir Stoyanov* , author of this man page. 58 | 59 | RESOURCES 60 | --------- 61 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 62 | 63 | COPYING 64 | ------- 65 | Copyright \(C) 2021 VMware. Free use of this software is granted under 66 | the terms of the GNU Public License (GPL). 67 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-extract.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-EXTRACT(1) 2 | ==================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-extract - extract out the data from the Ftrace Linux tracer. 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd extract ['OPTIONS']* 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) extract is usually used after 'trace-cmd-start(1)' and 15 | 'trace-cmd-stop(1)'. It can be used after the Ftrace tracer has been started 16 | manually through the Ftrace pseudo file system. 17 | 18 | The extract command creates a trace.dat file that can be used by 19 | 'trace-cmd-report(1)' to read from. It reads the kernel internal ring buffer 20 | to produce the trace.dat file. 21 | 22 | OPTIONS 23 | ------- 24 | *-p* 'plugin':: 25 | Although *extract* does not start any traces, some of the plugins require 26 | just reading the output in ASCII format. These are the latency tracers, 27 | since the latency tracers have a separate internal buffer. The plugin 28 | option is therefore only necessary for the 'wakeup', 'wakeup-rt', 29 | 'irqsoff', 'preemptoff' and 'preemptirqsoff' plugins. 30 | 31 | With out this option, the extract command will extract from the internal 32 | Ftrace buffers. 33 | 34 | *-O* 'option':: 35 | If a latency tracer is being extracted, and the *-p* option is used, then 36 | there are some Ftrace options that can change the format. This will update 37 | those options before extracting. To see the list of options see 38 | 'trace-cmd-list'. To enable an option, write its name, to disable the 39 | option append the characters 'no' to it. For example: 'noprint-parent' 40 | will disable the 'print-parent' option that prints the parent function in 41 | printing a function event. 42 | 43 | *-o* 'outputfile':: 44 | By default, the extract command will create a 'trace.dat' file. This 45 | option will change where the file is written to. 46 | 47 | *-s*:: 48 | Extract from the snapshot buffer (if the kernel supports it). 49 | 50 | *--date*:: 51 | This is the same as the trace-cmd-record(1) --date option, but it 52 | does cause the extract routine to disable all tracing. That is, 53 | the end of the extract will perform something similar to trace-cmd-reset(1). 54 | 55 | *-B* 'buffer-name':: 56 | If the kernel supports multiple buffers, this will extract the trace for 57 | only the given buffer. It does not affect any other buffer. This may be 58 | used multiple times to specify different buffers. When this option is 59 | used, the top level instance will not be extracted unless *-t* is given. 60 | 61 | *-a*:: 62 | Extract all existing buffer instances. When this option is used, the 63 | top level instance will not be extracted unless *-t* is given. 64 | 65 | *-t*:: 66 | Extracts the top level instance buffer. Without the *-B* or *-a* option 67 | this is the same as the default. But if *-B* or *-a* is used, this is 68 | required if the top level instance buffer should also be extracted. 69 | 70 | *--verbose*[='level']:: 71 | Set the log level. Supported log levels are "none", "critical", "error", "warning", 72 | "info", "debug", "all" or their identifiers "0", "1", "2", "3", "4", "5", "6". Setting the log 73 | level to specific value enables all logs from that and all previous levels. 74 | The level will default to "info" if one is not specified. 75 | 76 | Example: enable all critical, error and warning logs 77 | 78 | trace-cmd extract --verbose=warning 79 | 80 | SEE ALSO 81 | -------- 82 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 83 | trace-cmd-stop(1), trace-cmd-reset(1), trace-cmd-split(1), 84 | trace-cmd-list(1), trace-cmd-listen(1) 85 | 86 | AUTHOR 87 | ------ 88 | Written by Steven Rostedt, 89 | 90 | RESOURCES 91 | --------- 92 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 93 | 94 | COPYING 95 | ------- 96 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 97 | the terms of the GNU Public License (GPL). 98 | 99 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-hist.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-HIST(1) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-hist - show histogram of events in trace.dat file 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd hist* ['OPTIONS']['input-file'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) hist displays a histogram form from the trace.dat file. 15 | Instead of showing the events as they were ordered, it creates a histogram 16 | that can be displayed per task or for all tasks where the most common 17 | events appear first. It uses the function tracer and call stacks that it 18 | finds to try to put together a call graph of the events. 19 | 20 | OPTIONS 21 | ------- 22 | *-i* 'input-file':: 23 | By default, trace-cmd hist will read the file 'trace.dat'. But the *-i* 24 | option open up the given 'input-file' instead. Note, the input file may 25 | also be specified as the last item on the command line. 26 | 27 | *-P*:: 28 | To compact all events and show the call graphs by ignoring tasks 29 | and different PIDs, add the *-P* to do so. Instead of showing the 30 | task name, it will group all chains together and show "". 31 | 32 | SEE ALSO 33 | -------- 34 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 35 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 36 | trace-cmd-split(1), trace-cmd-listen(1) 37 | 38 | AUTHOR 39 | ------ 40 | Written by Steven Rostedt, 41 | 42 | RESOURCES 43 | --------- 44 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 45 | 46 | COPYING 47 | ------- 48 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 49 | the terms of the GNU Public License (GPL). 50 | 51 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-list.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-LIST(1) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-list - list available plugins, events or options for Ftrace. 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd list* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) list displays the available plugins, events or Ftrace options 15 | that are configured on the current machine. If no option is given, then it 16 | lists all plugins, event systems, events and Ftrace options to standard output. 17 | 18 | OPTIONS 19 | ------- 20 | *-e* ['regex']:: 21 | This option will list the available events that are enabled on the 22 | local system. 23 | 24 | It takes an optional argument that uses 'regcomp(3)' expressions to seach. 25 | 26 | trace-cmd list -e '^sys.*' 27 | 28 | *-F*:: 29 | Used with *-e* 'regex' to show the fields of the event. 30 | 31 | *--full*:: 32 | Used with *-F* which will show the "print fmt" of the event along with the fields. 33 | 34 | *-l*:: 35 | Used with *-e* 'regex' to show those events filters. 36 | 37 | *-R*:: 38 | Used with *-e* 'regex' to show those events triggers. 39 | 40 | *-s*:: 41 | This option will list the available event systems. 42 | 43 | *-t*:: 44 | This option will list the available tracers that are enabled on the 45 | local system. 46 | 47 | *-p*:: 48 | Same as *-t* and only for legacy purposes. 49 | 50 | *-o*:: 51 | This option will list the available Ftrace options that are configured on 52 | the local system. 53 | 54 | *-f* ['regex']:: 55 | This option will list the available filter functions. These are the list of 56 | functions on the system that you can trace, or filter on. 57 | It takes an optional argument that uses 'regcomp(3)' expressions to seach. 58 | 59 | trace-cmd list -f '^sched.*' 60 | 61 | *-P*:: 62 | List the plugin files that get loaded on trace-cmd report. 63 | 64 | *-O*:: 65 | List plugin options that can be used by trace-cmd report *-O* option. 66 | 67 | *-B*:: 68 | List defined buffer instances (sub buffers). 69 | 70 | *-C*:: 71 | List defined clocks that can be used with trace-cmd record -C. 72 | The one in brackets ([]) is the active clock. 73 | 74 | *-c*:: 75 | List the available trace file compression algorithms. 76 | 77 | SEE ALSO 78 | -------- 79 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 80 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 81 | trace-cmd-split(1), trace-cmd-listen(1) 82 | 83 | AUTHOR 84 | ------ 85 | Written by Steven Rostedt, 86 | 87 | RESOURCES 88 | --------- 89 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 90 | 91 | COPYING 92 | ------- 93 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 94 | the terms of the GNU Public License (GPL). 95 | 96 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-listen.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-LISTEN(1) 2 | =================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-listen - listen for incoming connection to record tracing. 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd listen* -p 'port' ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) listen sets up a port to listen to waiting for connections 15 | from other hosts that run 'trace-cmd-record(1)' with the *-N* option. When a 16 | connection is made, and the remote host sends data, it will create a file 17 | called 'trace.HOST:PORT.dat'. Where HOST is the name of the remote host, and 18 | PORT is the port that the remote host used to connect with. 19 | 20 | OPTIONS 21 | ------- 22 | *-p* 'port':: 23 | This option will specify the port to listen to. 24 | 25 | *-D*:: 26 | This options causes trace-cmd listen to go into a daemon mode and run in 27 | the background. 28 | 29 | *-V*:: 30 | Listen on a vsocket instead. This is useful for tracing between host and 31 | guest VMs. 32 | 33 | *-d* 'dir':: 34 | This option specifies a directory to write the data files into. 35 | 36 | *-o* 'filename':: 37 | This option overrides the default 'trace' in the 'trace.HOST:PORT.dat' that 38 | is created when a remote host connects. 39 | 40 | *-l* 'filename':: 41 | This option writes the output messages to a log file instead of standard output. 42 | 43 | *--verbose*[='level']:: 44 | Set the log level. Supported log levels are "none", "critical", "error", "warning", 45 | "info", "debug", "all" or their identifiers "0", "1", "2", "3", "4", "5", "6". Setting the log 46 | level to specific value enables all logs from that and all previous levels. 47 | The level will default to "info" if one is not specified. 48 | 49 | Example: enable all critical, error and warning logs 50 | 51 | trace-cmd listen --verbose=warning 52 | 53 | SEE ALSO 54 | -------- 55 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 56 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 57 | trace-cmd-split(1), trace-cmd-list(1) 58 | 59 | AUTHOR 60 | ------ 61 | Written by Steven Rostedt, 62 | 63 | RESOURCES 64 | --------- 65 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 66 | 67 | COPYING 68 | ------- 69 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 70 | the terms of the GNU Public License (GPL). 71 | 72 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-mem.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-MEM(1) 2 | ================ 3 | 4 | NAME 5 | ---- 6 | trace-cmd-mem - show memory usage of certain kmem events 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd mem* ['OPTIONS']['input-file'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) mem requires a trace-cmd record that enabled the following 15 | events: 16 | 17 | kmalloc 18 | kmalloc_node 19 | kfree 20 | kmem_cache_alloc 21 | kmem_cache_alloc_node 22 | kmem_cache_alloc_free 23 | 24 | It then reads the amount requested and the ammount freed as well as the 25 | functions that called the allocation. It then reports the final amount 26 | of bytes requested and allocated, along with the total amount allocated 27 | and requested, as well as the max allocation and requested during the run. 28 | It reports the amount of wasted bytes (allocated - requested) that was 29 | not freed, as well as the max wasted amount during the run. The list is 30 | sorted by descending order of wasted bytes after the run. 31 | 32 | Function Waste Alloc req TotAlloc TotReq MaxAlloc MaxReq MaxWaste 33 | -------- ----- ----- --- -------- ------ -------- ------ -------- 34 | rb_allocate_cpu_buffer 768 2304 1536 2304 1536 2304 1536 768 35 | alloc_pipe_info 400 1152 752 1152 752 1152 752 400 36 | instance_mkdir 252 544 292 544 292 544 292 252 37 | __d_alloc 215 1086560 1086345 1087208 1086993 1086560 1086345 215 38 | get_empty_filp 72 2304 2232 4864 4712 4864 4712 152 39 | mm_alloc 40 960 920 960 920 960 920 40 40 | prepare_creds 32 192 160 1728 1440 1728 1440 288 41 | tracing_buffers_open 8 32 24 32 24 32 24 8 42 | do_brk 0 0 0 368 368 368 368 0 43 | journal_add_journal_head 0 6048 6048 6048 6048 6048 6048 0 44 | journal_start 0 0 0 1224 1224 48 48 0 45 | __rb_allocate_pages 0 3289856 3289856 3289856 3289856 3289856 3289856 0 46 | anon_vma_alloc 0 0 0 936 936 864 864 0 47 | [...] 48 | 49 | OPTIONS 50 | ------- 51 | *-i* 'input-file':: 52 | By default, trace-cmd hist will read the file 'trace.dat'. But the *-i* 53 | option open up the given 'input-file' instead. Note, the input file may 54 | also be specified as the last item on the command line. 55 | 56 | SEE ALSO 57 | -------- 58 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 59 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-hist(1), 60 | trace-cmd-split(1), trace-cmd-listen(1) 61 | 62 | AUTHOR 63 | ------ 64 | Written by Steven Rostedt, 65 | 66 | RESOURCES 67 | --------- 68 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 69 | 70 | COPYING 71 | ------- 72 | Copyright \(C) 2013 Red Hat, Inc. Free use of this software is granted under 73 | the terms of the GNU Public License (GPL). 74 | 75 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-options.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-OPTIONS(1) 2 | ==================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-options - list available options from trace-cmd plugins 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd options* 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) options command will examine all the trace-cmd plugins 15 | that are used by *trace-cmd report(1)* and list them. 16 | 17 | SEE ALSO 18 | -------- 19 | trace-cmd(1), trace-cmd-record(1), trace-cmd-start(1), trace-cmd-stop(1), 20 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 21 | trace-cmd-list(1), trace-cmd-listen(1) 22 | 23 | AUTHOR 24 | ------ 25 | Written by Steven Rostedt, 26 | 27 | RESOURCES 28 | --------- 29 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 30 | 31 | COPYING 32 | ------- 33 | Copyright \(C) 2011 Red Hat, Inc. Free use of this software is granted under 34 | the terms of the GNU Public License (GPL). 35 | 36 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-reset.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-RESET(1) 2 | ================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-reset - turn off all Ftrace tracing to bring back full performance 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd reset* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) reset command turns off all tracing of Ftrace. This will 15 | bring back the performance of the system before tracing was enabled. This is 16 | necessary since 'trace-cmd-record(1)', 'trace-cmd-stop(1)' and 17 | 'trace-cmd-extract(1)' do not disable the tracer, event after the data has 18 | been pulled from the buffers. The rational is that the user may want to 19 | manually enable the tracer with the Ftrace pseudo file system, or examine other 20 | parts of Ftrace to see what trace-cmd did. After the reset command happens, 21 | the data in the ring buffer, and the options that were used are all lost. 22 | 23 | OPTIONS 24 | ------- 25 | Please note that the order that options are specified on the command line is 26 | significant. See EXAMPLES. 27 | 28 | *-b* 'buffer_size':: 29 | When the kernel boots, the Ftrace ring buffer is of a minimal size (3 30 | pages per CPU). The first time the tracer is used, the ring buffer size 31 | expands to what it was set for (default 1.4 Megs per CPU). 32 | 33 | If no more tracing is to be done, this option allows you to shrink the 34 | ring buffer down to free up available memory. 35 | 36 | trace-cmd reset -b 1 37 | 38 | The buffer instance affected is the one (or ones) specified by the most 39 | recently preceding *-B*, *-t*, or *-a* option: 40 | 41 | When used after *-B*, resizes the buffer instance that precedes it on 42 | the command line. 43 | 44 | When used after *-a*, resizes all buffer instances except the top one. 45 | 46 | When used after *-t* or before any *-B* or *-a*, resizes the top 47 | instance. 48 | 49 | *-B* 'buffer-name':: 50 | If the kernel supports multiple buffers, this will reset the trace for 51 | only the given buffer. It does not affect any other buffer. This may be 52 | used multiple times to specify different buffers. The top level buffer 53 | will not be reset if this option is given (unless the *-t* option is 54 | also supplied). 55 | 56 | *-a*:: 57 | Reset the trace for all existing buffer instances. When this option 58 | is used, the top level instance will not be reset unless *-t* is given. 59 | 60 | *-d*:: 61 | This option deletes the instance buffer(s) specified by the most recently 62 | preceding *-B* or *-a* option. Because the top-level instance buffer 63 | cannot be deleted, it is invalid to use this immediately following *-t* or 64 | prior to any *-B* or *-a* option on the command line. 65 | 66 | *-t*:: 67 | Resets the top level instance buffer. Without the *-B* or *-a* option 68 | this is the same as the default. But if *-B* or *-a* is used, this is 69 | required if the top level instance buffer should also be reset. 70 | 71 | *-k* 'dynevent-name':: 72 | This option allows preserving specified dynamic event during reset. Valid 73 | parameters are *kprobe*, *kretprobe*, *uprobe*, *uretprobe*, *eprobe*, 74 | *synth* and *all* (for keeping all dynamic events). This may be used 75 | multiple times to specify different dynamic event types. 76 | 77 | EXAMPLES 78 | -------- 79 | 80 | Reset tracing for instance-one and set its per-cpu buffer size to 4096kb. 81 | Also deletes instance-two. The top level instance and any other instances 82 | remain unaffected: 83 | 84 | trace-cmd reset -B instance-one -b 4096 -B instance-two -d 85 | 86 | Delete all instance buffers. Top level instance remains unaffected: 87 | 88 | trace-cmd reset -a -d 89 | 90 | Delete all instance buffers and also reset the top instance: 91 | 92 | trace-cmd reset -t -a -d 93 | 94 | Invalid. This command implies an attempt to delete the top instance: 95 | 96 | trace-cmd reset -a -t -d 97 | 98 | Reset the top instance and set its per-cpu buffer size to 1024kb. If any 99 | instance buffers exist, they will be unaffected: 100 | 101 | trace-cmd reset -b 1024 102 | 103 | Prevent *kprobes* and *kretprobes* from being destroyed during reset: 104 | 105 | trace-cmd reset -k kprobe -k kretprobe 106 | 107 | 108 | SEE ALSO 109 | -------- 110 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 111 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-split(1), 112 | trace-cmd-list(1), trace-cmd-listen(1) 113 | 114 | AUTHOR 115 | ------ 116 | Written by Steven Rostedt, 117 | 118 | RESOURCES 119 | --------- 120 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 121 | 122 | COPYING 123 | ------- 124 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 125 | the terms of the GNU Public License (GPL). 126 | 127 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-restore.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-RESTORE(1) 2 | ==================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-restore - restore a failed trace record 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd restore* ['OPTIONS'] ['command'] cpu-file [cpu-file ...] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) restore command will restore a crashed trace-cmd-record(1) 15 | file. If for some reason a trace-cmd record fails, it will leave a the 16 | per-cpu data files and not create the final trace.dat file. The trace-cmd 17 | restore will append the files to create a working trace.dat file that can 18 | be read with trace-cmd-report(1). 19 | 20 | When trace-cmd record runs, it spawns off a process per CPU and writes 21 | to a per cpu file usually called 'trace.dat.cpuX', where X represents the 22 | CPU number that it is tracing. If the -o option was used in the trace-cmd 23 | record, then the CPU data files will have that name instead of the 24 | 'trace.dat' name. If a unexpected crash occurs before the tracing 25 | is finished, then the per CPU files will still exist but there will 26 | not be any trace.dat file to read from. trace-cmd restore will allow you 27 | to create a trace.dat file with the existing data files. 28 | 29 | OPTIONS 30 | ------- 31 | *-c*:: 32 | Create a partial trace.dat file from the machine, to be used with 33 | a full trace-cmd restore at another time. This option is useful for 34 | embedded devices. If a server contains the cpu files of a crashed 35 | trace-cmd record (or trace-cmd listen), trace-cmd restore can be 36 | executed on the embedded device with the -c option to get all the 37 | stored information of that embedded device. Then the file created 38 | could be copied to the server to run the trace-cmd restore there 39 | with the cpu files. 40 | 41 | If *-o* is not specified, then the file created will be called 42 | 'trace-partial.dat'. This is because the file is not a full version 43 | of something that trace-cmd-report(1) could use. 44 | 45 | *-t* tracing_dir:: 46 | Used with *-c*, it overrides the location to read the events from. 47 | By default, tracing information is read from the debugfs/tracing 48 | directory. *-t* will use that location instead. This can be useful 49 | if the trace.dat file to create is from another machine. 50 | Just tar -cvf events.tar debugfs/tracing and copy and untar that 51 | file locally, and use that directory instead. 52 | 53 | *-k* kallsyms:: 54 | Used with *-c*, it overrides where to read the kallsyms file from. 55 | By default, /proc/kallsyms is used. *-k* will override the file to 56 | read the kallsyms from. This can be useful if the trace.dat file 57 | to create is from another machine. Just copy the /proc/kallsyms 58 | file locally, and use *-k* to point to that file. 59 | 60 | *-o* output':: 61 | By default, trace-cmd restore will create a 'trace.dat' file 62 | (or 'trace-partial.dat' if *-c* is specified). You can 63 | specify a different file to write to with the *-o* option. 64 | 65 | *-i* input:: 66 | By default, trace-cmd restore will read the information of the 67 | current system to create the initial data stored in the 'trace.dat' 68 | file. If the crash was on another machine, then that machine should 69 | have the trace-cmd restore run with the *-c* option to create the 70 | trace.dat partial file. Then that file can be copied to the current 71 | machine where trace-cmd restore will use *-i* to load that file 72 | instead of reading from the current system. 73 | 74 | EXAMPLES 75 | -------- 76 | 77 | If a crash happened on another box, you could run: 78 | 79 | $ trace-cmd restore -c -o box-partial.dat 80 | 81 | Then on the server that has the cpu files: 82 | 83 | $ trace-cmd restore -i box-partial.dat trace.dat.cpu0 trace.dat.cpu1 84 | 85 | This would create a trace.dat file for the embedded box. 86 | 87 | SEE ALSO 88 | -------- 89 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 90 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 91 | trace-cmd-list(1), trace-cmd-listen(1) 92 | 93 | AUTHOR 94 | ------ 95 | Written by Steven Rostedt, 96 | 97 | RESOURCES 98 | --------- 99 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 100 | 101 | COPYING 102 | ------- 103 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 104 | the terms of the GNU Public License (GPL). 105 | 106 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-show.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-SHOW(1) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-show - show the contents of the Ftrace Linux kernel tracing buffer. 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd show* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) show displays the contents of one of the Ftrace Linux 15 | kernel tracing files: trace, snapshot, or trace_pipe. It is basically 16 | the equivalent of doing: 17 | 18 | cat /sys/kernel/debug/tracing/trace 19 | 20 | OPTIONS 21 | ------- 22 | *-p*:: 23 | Instead of displaying the contents of the "trace" file, use the 24 | "trace_pipe" file. The difference between the two is that the "trace" 25 | file is static. That is, if tracing is stopped, the "trace" file 26 | will show the same contents each time. 27 | 28 | The "trace_pipe" file is a consuming read, where a read of the file 29 | will consume the output of what was read and it will not read the 30 | same thing a second time even if tracing is stopped. This file 31 | als will block. If no data is available, trace-cmd show will stop 32 | and wait for data to appear. 33 | 34 | *-s*:: 35 | Instead of reading the "trace" file, read the snapshot file. The snapshot 36 | is made by an application writing into it and the kernel will perform 37 | as swap between the currently active buffer and the current snapshot 38 | buffer. If no more swaps are made, the snapshot will remain static. 39 | This is not a consuming read. 40 | 41 | *-c* 'cpu':: 42 | Read only the trace file for a specified CPU. 43 | 44 | *-f*:: 45 | Display the full path name of the file that is being displayed. 46 | 47 | *-B* 'buf':: 48 | If a buffer instance was created, then the *-B* option will access the 49 | files associated with the given buffer. 50 | 51 | *--tracing_on*:: 52 | Show if tracing is on for the given instance. 53 | 54 | *--current_tracer*:: 55 | Show what the current tracer is. 56 | 57 | *--buffer_size*:: 58 | Show the current buffer size (per-cpu) 59 | 60 | *--buffer_total_size*:: 61 | Show the total size of all buffers. 62 | 63 | *--buffer_subbuf_size*:: 64 | Show the size in kilobytes of the sub-buffers of the ring buffer. 65 | The ring buffer is broken up into equal size sub-buffers were an event can only 66 | be as big as the sub-buffer data section (the size minus its meta data). 67 | 68 | *--buffer_percent*:: 69 | Show the percentage the buffer must be filled before a reader that is blocked 70 | on the trace_pipe_raw file will be woken up. 71 | 72 | 0 : wake up immediately on any new data 73 | 1 - 99 : wake up on this percentage of the sub-buffers being full 74 | 100 : wake up after the buffer is full and the writer is on the last sub-buffer 75 | 76 | *--ftrace_filter*:: 77 | Show what function filters are set. 78 | 79 | *--ftrace_notrace*:: 80 | Show what function disabled filters are set. 81 | 82 | *--ftrace_pid*:: 83 | Show the PIDs the function tracer is limited to (if any). 84 | 85 | *--graph_function*:: 86 | Show the functions that will be graphed. 87 | 88 | *--graph_notrace*:: 89 | Show the functions that will not be graphed. 90 | 91 | *--hist* '[system:]event':: 92 | Show the content of a histogram "hist" file for a given event 93 | 94 | *--trigger* '[system:]event':: 95 | Show the content of the "trigger" file for a given event 96 | 97 | *--cpumask*:: 98 | Show the mask of CPUs that tracing will trace. 99 | 100 | 101 | SEE ALSO 102 | -------- 103 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 104 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 105 | trace-cmd-list(1), trace-cmd-listen(1) 106 | 107 | AUTHOR 108 | ------ 109 | Written by Steven Rostedt, 110 | 111 | RESOURCES 112 | --------- 113 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 114 | 115 | COPYING 116 | ------- 117 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 118 | the terms of the GNU Public License (GPL). 119 | 120 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-snapshot.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-SNAPSHOT(1) 2 | ===================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-snapshot - take, reset, free, or show a Ftrace kernel snapshot 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd snapshot* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) snapshot controls or displays the Ftrace Linux kernel 15 | snapshot feature (if the kernel supports it). This is useful to "freeze" 16 | an instance of a live trace but without stopping the trace. 17 | 18 | trace-cmd start -p function 19 | trace-cmd snapshot -s 20 | trace-cmd snapshot 21 | [ dumps the content of buffer at 'trace-cmd snapshot -s' ] 22 | trace-cmd snapshot -s 23 | trace-cmd snapshot 24 | [ dumps the new content of the buffer at the last -s operation ] 25 | 26 | OPTIONS 27 | ------- 28 | *-s*:: 29 | Take a snapshot of the currently running buffer. 30 | 31 | *-r*:: 32 | Clear out the buffer. 33 | 34 | *-f*:: 35 | Free the snapshot buffer. The buffer takes up memory inside the 36 | kernel. It is best to free it when not in use. The first -s 37 | operation will allocate it if it is not already allocated. 38 | 39 | *-c* 'cpu':: 40 | Operate on a per cpu snapshot (may not be fully supported by all kernels) 41 | 42 | *-B* 'buf':: 43 | If a buffer instance was created, then the *-B* option will operate on 44 | the snapshot within the buffer. 45 | 46 | 47 | SEE ALSO 48 | -------- 49 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 50 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 51 | trace-cmd-list(1), trace-cmd-listen(1) 52 | 53 | AUTHOR 54 | ------ 55 | Written by Steven Rostedt, 56 | 57 | RESOURCES 58 | --------- 59 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 60 | 61 | COPYING 62 | ------- 63 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 64 | the terms of the GNU Public License (GPL). 65 | 66 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-split.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-SPLIT(1) 2 | ================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-split - split a trace.dat file into smaller files 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd split* ['OPTIONS'] ['start-time' ['end-time']] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) split is used to break up a trace.dat into small files. 15 | The 'start-time' specifies where the new file will start at. Using 16 | 'trace-cmd-report(1)' and copying the time stamp given at a particular event, 17 | can be used as input for either 'start-time' or 'end-time'. The split will 18 | stop creating files when it reaches an event after 'end-time'. If only the 19 | end-time is needed, use 0.0 as the start-time. 20 | 21 | If start-time is left out, then the split will start at the beginning of the 22 | file. If end-time is left out, then split will continue to the end unless it 23 | meets one of the requirements specified by the options. 24 | 25 | OPTIONS 26 | ------- 27 | *-i* 'file':: 28 | If this option is not specified, then the split command will look for the 29 | file named 'trace.dat'. This options will allow the reading of another 30 | file other than 'trace.dat'. 31 | 32 | *-o* 'file':: 33 | By default, the split command will use the input file name as a basis of 34 | where to write the split files. The output file will be the input file 35 | with an attached \'.#\' to the end: trace.dat.1, trace.dat.2, etc. 36 | 37 | This option will change the name of the base file used. 38 | 39 | -o file will create file.1, file.2, etc. 40 | 41 | *-s* 'seconds':: 42 | This specifies how many seconds should be recorded before the new file 43 | should stop. 44 | 45 | *-m* 'milliseconds':: 46 | This specifies how many milliseconds should be recorded before the new 47 | file should stop. 48 | 49 | *-u* 'microseconds':: 50 | This specifies how many microseconds should be recorded before the new 51 | file should stop. 52 | 53 | *-e* 'events':: 54 | This specifies how many events should be recorded before the new file 55 | should stop. 56 | 57 | *-p* 'pages':: 58 | This specifies the number of pages that should be recorded before the new 59 | file should stop. 60 | 61 | Note: only one of *-p*, *-e*, *-u*, *-m*, *-s* may be specified at a time. 62 | 63 | If *-p* is specified, then *-c* is automatically set. 64 | 65 | *-r*:: 66 | This option causes the break up to repeat until end-time is reached (or 67 | end of the input if end-time is not specified). 68 | 69 | trace-cmd split -r -e 10000 70 | 71 | This will break up trace.dat into several smaller files, each with at most 72 | 10,000 events in it. 73 | 74 | *-c*:: 75 | This option causes the above break up to be per CPU. 76 | 77 | trace-cmd split -c -p 10 78 | 79 | This will create a file that has 10 pages per each CPU from the input. 80 | 81 | *-C* 'cpu':: 82 | This option will split for a single CPU. Only the cpu named will be extracted 83 | from the file. 84 | 85 | trace-cmd split -C 1 86 | 87 | This will split out all the events for cpu 1 in the file. 88 | 89 | *--top*:: 90 | This allows to keep the top buffer. 91 | The top buffer can be renamed using the '-b' option. 92 | 93 | trace-cmd split --top 94 | 95 | This will keep only the top buffer. 96 | 97 | trace-cmd split --top -b old_top 98 | 99 | This will keep only the top buffer and rename it 'old_top'. 100 | 101 | *-B* 'buffer':: 102 | This allows to keep the selected buffer. 103 | A buffer can be promoted to the top buffer using the '-t' option. 104 | 105 | trace-cmd split -B timer -B sched 106 | 107 | This will keep the 'timer' and 'sched' buffers. 108 | 109 | trace-cmd split -B timer -t -B sched 110 | 111 | This will keep the 'timer' and 'sched' buffers, with the events 112 | from the 'timer' buffer promoted to the top instance. 113 | 114 | SEE ALSO 115 | -------- 116 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 117 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 118 | trace-cmd-list(1), trace-cmd-listen(1) 119 | 120 | AUTHOR 121 | ------ 122 | Written by Steven Rostedt, 123 | 124 | RESOURCES 125 | --------- 126 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 127 | 128 | COPYING 129 | ------- 130 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 131 | the terms of the GNU Public License (GPL). 132 | 133 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-stack.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-STACK(1) 2 | ================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-stack - read, enable or disable Ftrace Linux kernel stack tracing. 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd stack* 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) stack enables the Ftrace stack tracer within the kernel. 15 | The stack tracer enables the function tracer and at each function call 16 | within the kernel, the stack is checked. When a new maximum usage stack 17 | is discovered, it is recorded. 18 | 19 | When no option is used, the current stack is displayed. 20 | 21 | To enable the stack tracer, use the option *--start*, and to disable 22 | the stack tracer, use the option *--stop*. The output will be the maximum 23 | stack found since the start was enabled. 24 | 25 | Use *--reset* to reset the stack counter to zero. 26 | 27 | User *--verbose*[='level'] to set the log level. Supported log levels are "none", "critical", "error", 28 | "warning", "info", "debug", "all" or their identifiers "0", "1", "2", "3", "4", "5", "6". Setting 29 | the log level to specific value enables all logs from that and all previous levels. The level will 30 | default to "info" if one is not specified. 31 | 32 | SEE ALSO 33 | -------- 34 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 35 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 36 | trace-cmd-list(1), trace-cmd-listen(1) 37 | 38 | AUTHOR 39 | ------ 40 | Written by Steven Rostedt, 41 | 42 | RESOURCES 43 | --------- 44 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 45 | 46 | COPYING 47 | ------- 48 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 49 | the terms of the GNU Public License (GPL). 50 | 51 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-start.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-START(1) 2 | ================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-start - start the Ftrace Linux kernel tracer without recording 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd start* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) start enables all the Ftrace tracing the same way 15 | trace-cmd-record(1) does. The difference is that it does not run threads to 16 | create a trace.dat file. This is useful just to enable Ftrace and you are only 17 | interested in the trace after some event has occurred and the trace is 18 | stopped. Then the trace can be read straight from the Ftrace pseudo file 19 | system or can be extracted with trace-cmd-extract(1). 20 | 21 | OPTIONS 22 | ------- 23 | The options are the same as 'trace-cmd-record(1)', except that it does not 24 | take options specific to recording (*-s*, *-o*, *-N*, and *-t*). 25 | 26 | *--fork* :: 27 | This option is only available for trace-cmd start. It tells trace-cmd 28 | to not wait for the process to finish before returning. 29 | With this option, trace-cmd start will return right after it forks 30 | the process on the command line. This option only has an effect if 31 | trace-cmd start also executes a command. 32 | 33 | SEE ALSO 34 | -------- 35 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-stop(1), 36 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 37 | trace-cmd-list(1), trace-cmd-listen(1) 38 | 39 | AUTHOR 40 | ------ 41 | Written by Steven Rostedt, 42 | 43 | RESOURCES 44 | --------- 45 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 46 | 47 | COPYING 48 | ------- 49 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 50 | the terms of the GNU Public License (GPL). 51 | 52 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-stat.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-STAT(1) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-stat - show the status of the tracing (ftrace) system 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd stat* ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) stat displays the various status of the tracing (ftrace) 15 | system. The status that it shows is: 16 | 17 | *Instances:* List all configured ftrace instances. 18 | 19 | *Tracer:* if one of the tracers (like function_graph) is active. Otherwise 20 | nothing is displayed. 21 | 22 | *Events:* Lists the events that are enable. 23 | 24 | *Event filters:* Shows any filters that are set for any events 25 | 26 | *Function filters:* Shows any filters for the function tracers 27 | 28 | *Graph functions:* Shows any functions that the function graph tracer should graph 29 | 30 | *Buffers:* Shows the trace buffer size if they have been expanded. 31 | By default, tracing buffers are in a compressed format until they are used. 32 | If they are compressed, the buffer display will not be shown. 33 | 34 | *Trace clock:* If the tracing clock is anything other than the default "local" 35 | it will be displayed. 36 | 37 | *Trace CPU mask:* If not all available CPUs are in the tracing CPU mask, then 38 | the tracing CPU mask will be displayed. 39 | 40 | *Trace max latency:* Shows the value of the trace max latency if it is other than zero. 41 | 42 | *Kprobes:* Shows any kprobes that are defined for tracing. 43 | 44 | *Uprobes:* Shows any uprobes that are defined for tracing. 45 | 46 | *Error log:* Dump the content of ftrace error_log file. 47 | 48 | OPTIONS 49 | ------- 50 | *-B* 'buffer-name':: 51 | Display the status of a given buffer instance. May be specified more than once 52 | to display the status of multiple instances. 53 | 54 | *-t*:: 55 | If *-B* is also specified, show the status of the top level tracing directory 56 | as well as the instance(s). 57 | 58 | *-o*:: 59 | Display the all the options along with their values. If they start with "no", then 60 | the option is disabled. 61 | 62 | SEE ALSO 63 | -------- 64 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 65 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 66 | trace-cmd-split(1), trace-cmd-listen(1) 67 | 68 | AUTHOR 69 | ------ 70 | Written by Steven Rostedt, 71 | 72 | RESOURCES 73 | --------- 74 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 75 | 76 | COPYING 77 | ------- 78 | Copyright \(C) 2014 Red Hat, Inc. Free use of this software is granted under 79 | the terms of the GNU Public License (GPL). 80 | 81 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-stop.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-STOP(1) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | trace-cmd-stop - stop the Ftrace Linux kernel tracer from writing to the ring 7 | buffer. 8 | 9 | SYNOPSIS 10 | -------- 11 | *trace-cmd stop* ['OPTIONS'] 12 | 13 | DESCRIPTION 14 | ----------- 15 | The trace-cmd(1) stop is a complement to 'trace-cmd-start(1)'. This will 16 | disable Ftrace from writing to the ring buffer. This does not stop the 17 | overhead that the tracing may incur. Only the updating of the ring buffer is 18 | disabled, the Ftrace tracing may still be inducing overhead. 19 | 20 | After stopping the trace, the 'trace-cmd-extract(1)' may strip out the data 21 | from the ring buffer and create a trace.dat file. The Ftrace pseudo file 22 | system may also be examined. 23 | 24 | To disable the tracing completely to remove the overhead it causes, use 25 | 'trace-cmd-reset(1)'. But after a reset is performed, the data that has been 26 | recorded is lost. 27 | 28 | OPTIONS 29 | ------- 30 | *-B* 'buffer-name':: 31 | If the kernel supports multiple buffers, this will stop the trace for 32 | only the given buffer. It does not affect any other buffer. This may be 33 | used multiple times to specify different buffers. When this option is 34 | used, the top level instance will not be stopped unless *-t* is given. 35 | 36 | *-a*:: 37 | Stop the trace for all existing buffer instances. When this option 38 | is used, the top level instance will not be stopped unless *-t* is given. 39 | 40 | *-t*:: 41 | Stops the top level instance buffer. Without the *-B* or *-a* option this 42 | is the same as the default. But if *-B* or *-a* is used, this is 43 | required if the top level instance buffer should also be stopped. 44 | 45 | SEE ALSO 46 | -------- 47 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 48 | trace-cmd-extract(1), trace-cmd-reset(1), trace-cmd-split(1), 49 | trace-cmd-list(1), trace-cmd-listen(1) 50 | 51 | AUTHOR 52 | ------ 53 | Written by Steven Rostedt, 54 | 55 | RESOURCES 56 | --------- 57 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 58 | 59 | COPYING 60 | ------- 61 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 62 | the terms of the GNU Public License (GPL). 63 | 64 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd-stream.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD-STREAM(1) 2 | =================== 3 | 4 | NAME 5 | ---- 6 | trace-cmd-stream - stream a trace to stdout as it is happening 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd stream ['OPTIONS']* ['command'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) stream will start tracing just like trace-cmd-record(1), except 15 | it will not record to a file and instead it will read the binary buffer 16 | as it is happening, convert it to a human readable format and write it to 17 | stdout. 18 | 19 | This is basically the same as trace-cmd-start(1) and then doing a trace-cmd-show(1) 20 | with the *-p* option. trace-cmd-stream is not as efficient as reading from the 21 | pipe file as most of the stream work is done in userspace. This is useful if 22 | it is needed to do the work mostly in userspace instead of the kernel, and stream 23 | also helps to debug trace-cmd-profile(1) which uses the stream code to perform 24 | the live data analysis for the profile. 25 | 26 | 27 | OPTIONS 28 | ------- 29 | These are the same as trace-cmd-record(1), except that it does not take 30 | the *-o* option. 31 | 32 | SEE ALSO 33 | -------- 34 | trace-cmd(1), trace-cmd-record(1), trace-cmd-report(1), trace-cmd-start(1), 35 | trace-cmd-stop(1), trace-cmd-reset(1), trace-cmd-split(1), 36 | trace-cmd-list(1), trace-cmd-listen(1) 37 | 38 | AUTHOR 39 | ------ 40 | Written by Steven Rostedt, 41 | 42 | RESOURCES 43 | --------- 44 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 45 | 46 | COPYING 47 | ------- 48 | Copyright \(C) 2014 Red Hat, Inc. Free use of this software is granted under 49 | the terms of the GNU Public License (GPL). 50 | 51 | -------------------------------------------------------------------------------- /Documentation/trace-cmd/trace-cmd.1.txt: -------------------------------------------------------------------------------- 1 | TRACE-CMD(1) 2 | ============ 3 | 4 | NAME 5 | ---- 6 | trace-cmd - interacts with Ftrace Linux kernel internal tracer 7 | 8 | SYNOPSIS 9 | -------- 10 | *trace-cmd* 'COMMAND' ['OPTIONS'] 11 | 12 | DESCRIPTION 13 | ----------- 14 | The trace-cmd(1) command interacts with the Ftrace tracer that is built inside 15 | the Linux kernel. It interfaces with the Ftrace specific files found in the 16 | debugfs file system under the tracing directory. A 'COMMAND' must be 17 | specified to tell trace-cmd what to do. 18 | 19 | 20 | COMMANDS 21 | -------- 22 | 23 | record - record a live trace and write a trace.dat file to the 24 | local disk or to the network. 25 | 26 | set - set a ftrace configuration parameter. 27 | 28 | report - reads a trace.dat file and converts the binary data to a 29 | ASCII text readable format. 30 | 31 | stream - Start tracing and read the output directly 32 | 33 | profile - Start profiling and read the output directly 34 | 35 | hist - show a histogram of the events. 36 | 37 | stat - show tracing (ftrace) status of the running system 38 | 39 | options - list the plugin options that are available to *report* 40 | 41 | start - start the tracing without recording to a trace.dat file. 42 | 43 | stop - stop tracing (only disables recording, overhead of tracer 44 | is still in effect) 45 | 46 | restart - restart tracing from a previous stop (only effects recording) 47 | 48 | extract - extract the data from the kernel buffer and create a trace.dat 49 | file. 50 | 51 | show - display the contents of one of the Ftrace Linux kernel tracing files 52 | 53 | reset - disables all tracing and gives back the system performance. 54 | (clears all data from the kernel buffers) 55 | 56 | clear - clear the content of the Ftrace ring buffers. 57 | 58 | split - splits a trace.dat file into smaller files. 59 | 60 | list - list the available plugins or events that can be recorded. 61 | 62 | listen - open up a port to listen for remote tracing connections. 63 | 64 | agent - listen on a vsocket for trace clients 65 | 66 | setup-guest - create FIFOs for tracing guest VMs 67 | 68 | restore - restore the data files of a crashed run of trace-cmd record 69 | 70 | snapshot- take snapshot of running trace 71 | 72 | stack - run and display the stack tracer 73 | 74 | check-events - parse format strings for all trace events and return 75 | whether all formats are parseable 76 | 77 | convert - convert trace files 78 | 79 | attach - attach a host trace.dat file to a guest trace.dat file 80 | 81 | dump - read out the meta data from a trace file 82 | 83 | OPTIONS 84 | ------- 85 | 86 | *-h*, --help:: 87 | Display the help text. 88 | 89 | Other options see the man page for the corresponding command. 90 | 91 | SEE ALSO 92 | -------- 93 | trace-cmd-record(1), trace-cmd-report(1), trace-cmd-hist(1), trace-cmd-start(1), 94 | trace-cmd-stop(1), trace-cmd-extract(1), trace-cmd-reset(1), 95 | trace-cmd-restore(1), trace-cmd-stack(1), trace-cmd-convert(1), 96 | trace-cmd-split(1), trace-cmd-list(1), trace-cmd-listen(1), 97 | trace-cmd.dat(5), trace-cmd-check-events(1), trace-cmd-stat(1), 98 | trace-cmd-attach(1) 99 | 100 | AUTHOR 101 | ------ 102 | Written by Steven Rostedt, 103 | 104 | RESOURCES 105 | --------- 106 | https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 107 | 108 | COPYING 109 | ------- 110 | Copyright \(C) 2010 Red Hat, Inc. Free use of this software is granted under 111 | the terms of the GNU Public License (GPL). 112 | 113 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /PACKAGING: -------------------------------------------------------------------------------- 1 | The libtracefs and libtraceevent packages are required for trace-cmd 2 | and libtracecmd.so 3 | 4 | In order to create a package directory with libtraceevent, libtracefs 5 | and libtracecmd and trace-cmd, you can follow these steps: 6 | 7 | git clone git://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git 8 | git clone git://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git 9 | git clone git://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git 10 | 11 | cd libtraceevent 12 | INSTALL_PATH=/tmp/install ../trace-cmd/make-trace-cmd.sh install 13 | 14 | cd ../libtracefs 15 | INSTALL_PATH=/tmp/install ../trace-cmd/make-trace-cmd.sh install 16 | 17 | cd ../trace-cmd 18 | INSTALL_PATH=/tmp/install ./make-trace-cmd.sh install install_libs 19 | 20 | cd /tmp/install 21 | tar cvjf /tmp/trace-cmd-files.tar.bz2 . 22 | 23 | And then the tarball of /tmp/trace-cmd-files.tar.bz2 will can be extracted 24 | on another machine at the root directory, and trace-cmd will be installed there. 25 | 26 | Note, to define a prefix, add a PREFIX variable before calling make-trace-cmd.sh 27 | 28 | For example: 29 | 30 | PREFIX=/usr/local INSTALL_PATH=/tmp/install ./make-trace-cmd.sh install 31 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | 3 | For more information on contributing please see: https://www.trace-cmd.org 4 | 5 | Note: The official repositiory for trace-cmd and KernelShark is here: 6 | 7 | git://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git 8 | 9 | For bug reports and issues, please file it here: 10 | 11 | https://bugzilla.kernel.org/buglist.cgi?component=Trace-cmd%2FKernelshark&product=Tools&resolution=--- 12 | 13 | These files make up the code that create the trace-cmd programs. 14 | This includes the GUI interface application kernelshark as well 15 | as trace-graph and trace-view. 16 | 17 | These files also make up the code to create the libtracecmd library. 18 | 19 | The applications are licensed under the GNU General Public License 2.0 20 | (see COPYING) and the libraries are licensed under the GNU 21 | Lesser General Public License 2.1 (See COPYING.LIB). 22 | 23 | BUILDING: 24 | 25 | In order to install build dependencies on Debian / Ubuntu do the following: 26 | sudo apt-get install build-essential git pkg-config -y 27 | sudo apt-get install libtracefs-dev libtraceevent-dev -y 28 | 29 | In order to install build dependencies on Fedora, as root do the following: 30 | dnf install gcc make git pkg-config -y 31 | dnf install libtracefs-devel libtraceevent-devel -y 32 | 33 | In case your distribution does not have the required libtracefs and 34 | libtraceevent libraries, build and install them manually: 35 | 36 | git clone https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 37 | cd libtraceevent 38 | make 39 | sudo make install 40 | 41 | git clone https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 42 | cd libtracefs 43 | make 44 | sudo make install 45 | 46 | To make trace-cmd 47 | make 48 | 49 | To make the gui 50 | make gui 51 | 52 | INSTALL: 53 | 54 | To install trace-cmd 55 | make install 56 | 57 | To install the gui 58 | make install_gui 59 | 60 | To install libtracecmd libraries 61 | make install_libs 62 | 63 | Note: The default install is relative to /usr/local 64 | The default install directory is /usr/local/bin 65 | The default plugin directory is /usr/local/lib/trace-cmd/plugins 66 | 67 | To change the default, you can set 'prefix', eg 68 | mkdir $HOME/test-trace 69 | make prefix=$HOME/test-trace 70 | make prefix=$HOME/test-trace install 71 | 72 | -------------------------------------------------------------------------------- /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=libtracecmd 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="" 48 | 49 | sed -ne 's/^[a-z].*[ \*]\([a-z_][a-z_]*\)(.*/\1/p' -e 's/^\([a-z_][a-z_]*\)(.*/\1/p' ../../include/trace-cmd/trace-cmd.h | while read f; do 50 | if ! grep -q '\*'${f}'\*' $MAIN_FILE; then 51 | if [ "${DEPRECATED/\*$f\*/}" != "${DEPRECATED}" ]; then 52 | continue; 53 | fi 54 | if [ "$last" == "" ]; then 55 | echo 56 | echo "Missing functions from $MAIN_FILE that are in tracefs.h" 57 | last=$f 58 | fi 59 | echo " ${f}" 60 | fi 61 | done 62 | -------------------------------------------------------------------------------- /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 | 39 | define SOURCE_AUDIT 40 | #include 41 | #include 42 | 43 | int main (void) 44 | { 45 | char *name; 46 | int ret; 47 | ret = audit_detect_machine(); 48 | if (ret < 0) 49 | return ret; 50 | name = audit_syscall_to_name(1, ret); 51 | if (!name) 52 | return -1; 53 | return ret; 54 | } 55 | endef 56 | -------------------------------------------------------------------------------- /include/linux/time64.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #ifndef _TOOLS_LINUX_TIME64_H 4 | #define _TOOLS_LINUX_TIME64_H 5 | 6 | #define MSEC_PER_SEC 1000L 7 | #define USEC_PER_MSEC 1000L 8 | #define NSEC_PER_USEC 1000L 9 | #define NSEC_PER_MSEC 1000000L 10 | #define USEC_PER_SEC 1000000L 11 | #define NSEC_PER_SEC 1000000000L 12 | #define FSEC_PER_SEC 1000000000000000LL 13 | 14 | #endif /* _LINUX_TIME64_H */ 15 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | #ifndef _VERSION_H 2 | #define _VERSION_H 3 | 4 | #define VERSION(a, b) (((a) << 8) + (b)) 5 | 6 | #ifdef BUILDGUI 7 | #include "ks_version.h" 8 | #else 9 | #include "tc_version.h" 10 | #endif 11 | 12 | #endif /* _VERSION_H */ 13 | -------------------------------------------------------------------------------- /lib/Documentation: -------------------------------------------------------------------------------- 1 | ../Documentation -------------------------------------------------------------------------------- /lib/check-manpages.sh: -------------------------------------------------------------------------------- 1 | ../check-manpages.sh -------------------------------------------------------------------------------- /lib/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | project( 6 | 'libtracecmd', ['c'], 7 | meson_version: '>= 0.50.0', 8 | license: 'GPL-2.0', 9 | version: '1.5.3', 10 | default_options: [ 11 | 'c_std=gnu99', 12 | 'buildtype=debug', 13 | 'default_library=both', 14 | 'prefix=/usr/local', 15 | 'warning_level=1']) 16 | 17 | cc = meson.get_compiler('c') 18 | 19 | prefixdir = get_option('prefix') 20 | mandir = join_paths(prefixdir, get_option('mandir')) 21 | htmldir = join_paths(prefixdir, get_option('htmldir')) 22 | 23 | libtracecmd_standalone_build = true 24 | 25 | library_version = meson.project_version() 26 | 27 | conf = configuration_data() 28 | 29 | libtraceevent_dep = dependency('libtraceevent', version: '>= 1.5.0', required: true) 30 | libtracefs_dep = dependency('libtracefs', version: '>= 1.6.0', required: true) 31 | 32 | threads_dep = dependency('threads', required: true) 33 | dl_dep = cc.find_library('dl', required : false) 34 | 35 | zlib_dep = dependency('zlib', required: false) 36 | conf.set('HAVE_ZLIB', zlib_dep.found(), description: 'Is zlib avialable?') 37 | 38 | libzstd_dep = dependency('libzstd', version: '>= 1.4.0', required: false) 39 | conf.set('HAVE_ZSTD', libzstd_dep.found(), description: 'Is libzstd available?') 40 | 41 | cunit_dep = dependency('cunit', required : false) 42 | 43 | vsock_defined = get_option('vsock') and cc.has_header('linux/vm_sockets.h') 44 | conf.set('VSOCK', vsock_defined, description: 'Is vsock available?') 45 | 46 | perf_defined = cc.has_header('linux/perf_event.h') 47 | conf.set('PERF', perf_defined, description: 'Is perf available?') 48 | 49 | have_ptrace = get_option('ptrace') and cc.compiles( 50 | ''' 51 | #include 52 | #include 53 | 54 | int main (void) 55 | { 56 | int ret; 57 | ret = ptrace(PTRACE_ATTACH, 0, NULL, 0); 58 | ptrace(PTRACE_TRACEME, 0, NULL, 0); 59 | ptrace(PTRACE_GETSIGINFO, 0, NULL, NULL); 60 | ptrace(PTRACE_GETEVENTMSG, 0, NULL, NULL); 61 | ptrace(PTRACE_SETOPTIONS, NULL, NULL, 62 | PTRACE_O_TRACEFORK | 63 | PTRACE_O_TRACEVFORK | 64 | PTRACE_O_TRACECLONE | 65 | PTRACE_O_TRACEEXIT); 66 | ptrace(PTRACE_CONT, NULL, NULL, 0); 67 | ptrace(PTRACE_DETACH, 0, NULL, NULL); 68 | ptrace(PTRACE_SETOPTIONS, 0, NULL, 69 | PTRACE_O_TRACEFORK | 70 | PTRACE_O_TRACEVFORK | 71 | PTRACE_O_TRACECLONE | 72 | PTRACE_O_TRACEEXIT); 73 | return ret; 74 | } 75 | ''', 76 | name: 'ptrace') 77 | if not have_ptrace 78 | conf.set10('NO_PTRACE', true, description: 'Is ptrace missing?') 79 | conf.set('WARN_NO_PTRACE', true, description: 'Issue no ptrace warning?') 80 | endif 81 | 82 | audit_dep = dependency('audit', required: false) 83 | if not audit_dep.found() 84 | conf.set10('NO_AUDIT', true, description: 'Is audit missing?') 85 | conf.set('WARN_NO_AUDIT', true, description: 'Issue no audit warning?') 86 | endif 87 | 88 | add_project_arguments( 89 | [ 90 | '-D_GNU_SOURCE', 91 | '-include', 'trace-cmd/include/private/config.h', 92 | ], 93 | language : 'c') 94 | 95 | libtracecmd_ext_incdir = include_directories( 96 | [ 97 | '../include', 98 | '../include/trace-cmd', 99 | '../tracecmd/include' 100 | ]) 101 | 102 | subdir('trace-cmd/include') 103 | subdir('trace-cmd/include/private') 104 | subdir('trace-cmd') 105 | if libtracecmd_standalone_build 106 | subdir('Documentation/libtracecmd') 107 | 108 | custom_target( 109 | 'docs', 110 | output: 'docs', 111 | depends: [html, man], 112 | command: ['echo']) 113 | endif 114 | 115 | install_headers( 116 | '../include/trace-cmd/trace-cmd.h', 117 | subdir: 'trace-cmd') 118 | -------------------------------------------------------------------------------- /lib/meson_options.txt: -------------------------------------------------------------------------------- 1 | # -*- mode: meson -*- 2 | # SPDX-License-Identifier: LGPL-2.1 3 | 4 | option('vsock', type : 'boolean', value : true, 5 | description : 'build with vsock support') 6 | option('ptrace', type : 'boolean', value : true, 7 | description : 'build with ptrace support') 8 | option('htmldir', type : 'string', value : 'share/doc/libtracecmd-doc', 9 | description : 'directory for HTML documentation') 10 | option('asciidoctor', type : 'boolean', value: false, 11 | description : 'use asciidoctor instead of asciidoc') 12 | option('docbook-xls-172', type : 'boolean', value : false, 13 | description : 'enable docbook XLS 172 workaround') 14 | option('asciidoc-no-roff', type : 'boolean', value : false, 15 | description : 'enable no roff workaround') 16 | option('man-bold-literal', type : 'boolean', value : false, 17 | description : 'enable bold literals') 18 | option('docbook-suppress-sp', type : 'boolean', value : false, 19 | description : 'docbook suppress sp') 20 | -------------------------------------------------------------------------------- /lib/trace-cmd/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | include $(src)/scripts/utils.mk 4 | 5 | bdir:=$(obj)/lib/trace-cmd 6 | ldir:=$(src)/lib/trace-cmd 7 | 8 | DEFAULT_TARGET = $(LIBTRACECMD_STATIC) 9 | 10 | OBJS = 11 | OBJS += trace-hash.o 12 | OBJS += trace-rbtree.o 13 | OBJS += trace-hooks.o 14 | OBJS += trace-input.o 15 | OBJS += trace-output.o 16 | OBJS += trace-recorder.o 17 | OBJS += trace-util.o 18 | OBJS += trace-filter-hash.o 19 | OBJS += trace-filter.o 20 | OBJS += trace-msg.o 21 | OBJS += trace-plugin.o 22 | OBJS += trace-maps.o 23 | ifeq ($(PERF_DEFINED), 1) 24 | OBJS += trace-perf.o 25 | endif 26 | OBJS += trace-timesync.o 27 | OBJS += trace-timesync-ptp.o 28 | ifeq ($(VSOCK_DEFINED), 1) 29 | OBJS += trace-timesync-kvm.o 30 | endif 31 | OBJS += trace-compress.o 32 | ifeq ($(ZLIB_INSTALLED), 1) 33 | OBJS += trace-compress-zlib.o 34 | endif 35 | ifeq ($(ZSTD_INSTALLED), 1) 36 | OBJS += trace-compress-zstd.o 37 | endif 38 | 39 | # Additional util objects 40 | OBJS += trace-blk-hack.o 41 | OBJS += trace-ftrace.o 42 | 43 | OBJS := $(OBJS:%.o=$(bdir)/%.o) 44 | DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) 45 | 46 | all: $(DEFAULT_TARGET) 47 | 48 | $(bdir): 49 | @mkdir -p $(bdir) 50 | 51 | $(OBJS): | $(bdir) 52 | $(DEPS): | $(bdir) 53 | 54 | $(LIBTRACECMD_STATIC): $(OBJS) 55 | $(Q)$(call do_build_static_lib) 56 | 57 | LPTHREAD ?= -lpthread 58 | 59 | LIBS = $(LIBTRACEEVENT_LDLAGS) $(LIBTRACEFS_LDLAGS) $(ZLIB_LDLAGS) $(LIBZSTD_LDLAGS) $(LPTHREAD) 60 | 61 | $(LIBTRACECMD_SHARED_VERSION): $(LIBTRACECMD_SHARED) 62 | @ln -sf $( $@ 77 | 78 | $(OBJS): $(bdir)/%.o : $(bdir)/.%.d 79 | 80 | ifeq ("$(DESTDIR)", "") 81 | # If DESTDIR is not defined, then test if after installing the library 82 | # and running ldconfig, if the library is visible by ld.so. 83 | # If not, add the path to /etc/ld.so.conf.d/trace.conf and run ldconfig again. 84 | define install_ld_config 85 | if $(LDCONFIG); then \ 86 | if ! grep -q "^$(libdir)$$" $(LD_SO_CONF_PATH)/* ; then \ 87 | echo here;\ 88 | $(CC) -o $(bdir)/test $(ldir)/test.c -I $(includedir_SQ) \ 89 | -L $(libdir_SQ) -ltracecmd &> /dev/null; \ 90 | if ! $(bdir)/test &> /dev/null; then \ 91 | $(call print_install,trace.conf,$(LD_SO_CONF_PATH)) \ 92 | echo $(libdir_SQ) >> $(LD_SO_CONF_PATH)/trace.conf; \ 93 | $(LDCONFIG); \ 94 | fi; \ 95 | $(RM) $(bdir)/test; \ 96 | fi; \ 97 | fi 98 | endef 99 | else 100 | # If installing to a location for another machine or package, do not bother 101 | # with running ldconfig. 102 | define install_ld_config 103 | endef 104 | endif # DESTDIR = "" 105 | 106 | install_pkgconfig: $(PKG_CONFIG_FILE) 107 | $(Q)$(call do_install_pkgconfig_file,$(prefix)) 108 | 109 | install_libs: install_pkgconfig 110 | $(Q)$(call do_install,$(LIBTRACECMD_SHARED),$(libdir_SQ)) 111 | $(Q)$(call print_install,$(LIBTRACECMD_SHARED_VERSION),$(DESTDIR)$(libdir_SQ)) 112 | $(Q)cp -fpR $(LIBTRACECMD_SHARED_VERSION) $(DESTDIR)$(libdir_SQ) 113 | $(Q)$(call print_install,$(LIBTRACECMD_SHARED_SO),$(DESTDIR)$(libdir_SQ)) 114 | $(Q)cp -fpR $(LIBTRACECMD_SHARED_SO) $(DESTDIR)$(libdir_SQ) 115 | $(Q)$(call do_install,$(src)/include/trace-cmd/trace-cmd.h,$(includedir_SQ)/trace-cmd,644) 116 | $(Q)$(call install_ld_config) 117 | 118 | dep_includes := $(wildcard $(DEPS)) 119 | 120 | ifneq ($(dep_includes),) 121 | include $(dep_includes) 122 | endif 123 | 124 | clean: 125 | $(RM) $(bdir)/*.a $(bdir)/*.so $(bdir)/*.so.* $(bdir)/*.o $(bdir)/.*.d 126 | 127 | .PHONY: clean 128 | 129 | PHONY += force 130 | force: 131 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | libtracecmd_incdir = include_directories(['.']) 6 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/private/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | config_h = configure_file( 6 | output: 'config.h', 7 | configuration: conf 8 | ) 9 | 10 | libtracecmd_private_incdir = include_directories(['.']) 11 | 12 | config_dep = declare_dependency( 13 | include_directories : libtracecmd_private_incdir, 14 | sources: config_h) 15 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/private/trace-cmd-private-python.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Private interface exposed to the python module. See python/ctracecmd.i and 4 | * python/tracecmd.py. 5 | */ 6 | #ifndef _TRACE_CMD_PRIVATE_PYTHON_H 7 | #define _TRACE_CMD_PRIVATE_PYTHON_H 8 | 9 | int tracecmd_long_size(struct tracecmd_input *handle); 10 | int tracecmd_cpus(struct tracecmd_input *handle); 11 | 12 | struct tep_record * 13 | tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu); 14 | 15 | struct tep_record * 16 | tracecmd_peek_data(struct tracecmd_input *handle, int cpu); 17 | 18 | static inline struct tep_record * 19 | tracecmd_peek_data_ref(struct tracecmd_input *handle, int cpu) 20 | { 21 | struct tep_record *rec = tracecmd_peek_data(handle, cpu); 22 | if (rec) 23 | rec->ref_count++; 24 | return rec; 25 | } 26 | 27 | #endif /* _TRACE_CMD_PRIVATE_PYTHON_H */ 28 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/private/trace-filter-hash.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * Copyright (C) 2018 VMware Inc, Steven Rostedt 5 | * 6 | */ 7 | #ifndef _TRACE_FILTER_HASH_H 8 | #define _TRACE_FILTER_HASH_H 9 | 10 | #include 11 | 12 | struct tracecmd_filter_id_item { 13 | struct tracecmd_filter_id_item *next; 14 | int id; 15 | }; 16 | 17 | struct tracecmd_filter_id { 18 | struct tracecmd_filter_id_item **hash; 19 | int count; 20 | }; 21 | 22 | /** 23 | * tracecmd_quick_hash - A quick (non secured) hash alogirthm 24 | * @val: The value to perform the hash on 25 | * @bits: The size in bits you need to return 26 | * 27 | * This is a quick hashing function adapted from Donald E. Knuth's 32 28 | * bit multiplicative hash. See The Art of Computer Programming (TAOCP). 29 | * Multiplication by the Prime number, closest to the golden ratio of 30 | * 2^32. 31 | * 32 | * @bits is used to max the result for use cases that require 33 | * a power of 2 return value that is less than 32 bits. Any value 34 | * of @bits greater than 31 (or zero), will simply return the full hash on @val. 35 | */ 36 | static inline uint32_t tracecmd_quick_hash(uint32_t val, unsigned int bits) 37 | { 38 | val *= UINT32_C(2654435761); 39 | 40 | if (!bits || bits > 31) 41 | return val; 42 | 43 | return val & ((1 << bits) - 1); 44 | } 45 | 46 | struct tracecmd_filter_id_item * 47 | tracecmd_filter_id_find(struct tracecmd_filter_id *hash, int id); 48 | void tracecmd_filter_id_add(struct tracecmd_filter_id *hash, int id); 49 | void tracecmd_filter_id_remove(struct tracecmd_filter_id *hash, int id); 50 | void tracecmd_filter_id_clear(struct tracecmd_filter_id *hash); 51 | struct tracecmd_filter_id *tracecmd_filter_id_hash_alloc(void); 52 | void tracecmd_filter_id_hash_free(struct tracecmd_filter_id *hash); 53 | struct tracecmd_filter_id * 54 | tracecmd_filter_id_hash_copy(struct tracecmd_filter_id *hash); 55 | int *tracecmd_filter_ids(struct tracecmd_filter_id *hash); 56 | int tracecmd_filter_id_compare(struct tracecmd_filter_id *hash1, 57 | struct tracecmd_filter_id *hash2); 58 | 59 | static inline int tracecmd_filter_task_count(struct tracecmd_filter_id *hash) 60 | { 61 | return hash->count; 62 | } 63 | 64 | #endif /* _TRACE_FILTER_HASH_H */ 65 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/private/trace-hash.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (C) 2014 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _TRACE_HASH_H 7 | #define _TRACE_HASH_H 8 | 9 | struct trace_hash_item { 10 | struct trace_hash_item *next; 11 | struct trace_hash_item *prev; 12 | unsigned long long key; 13 | }; 14 | 15 | struct trace_hash { 16 | struct trace_hash_item **buckets; 17 | int nr_buckets; 18 | int power; 19 | }; 20 | 21 | int tcmd_hash_init(struct trace_hash *hash, int buckets); 22 | void tcmd_hash_free(struct trace_hash *hash); 23 | int tcmd_hash_add(struct trace_hash *hash, struct trace_hash_item *item); 24 | int tcmd_hash_empty(struct trace_hash *hash); 25 | 26 | static inline void trace_hash_del(struct trace_hash_item *item) 27 | { 28 | struct trace_hash_item *prev = item->prev; 29 | 30 | prev->next = item->next; 31 | if (item->next) 32 | item->next->prev = prev; 33 | } 34 | 35 | #define trace_hash_for_each_bucket(bucket, hash) \ 36 | for (bucket = (hash)->buckets; \ 37 | (bucket) < (hash)->buckets + (hash)->nr_buckets; (bucket)++) 38 | 39 | #define trace_hash_for_each_item(item, bucket) \ 40 | for ((item = *(bucket)); item; item = (item)->next) 41 | 42 | #define trace_hash_for_each_item_safe(item, n, bucket) \ 43 | for ((item = *(bucket)), n = item ? item->next : NULL; item; \ 44 | item = n, n = item ? (item)->next : NULL) 45 | 46 | #define trace_hash_while_item(item, bucket) \ 47 | while ((item = *(bucket))) 48 | 49 | typedef int (*trace_hash_func)(struct trace_hash_item *item, void *data); 50 | 51 | struct trace_hash_item * 52 | tcmd_hash_find(struct trace_hash *hash, unsigned long long key, 53 | trace_hash_func match, void *data); 54 | 55 | #endif /* _TRACE_HASH_H */ 56 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/private/trace-msg.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | #ifndef _TRACE_MSG_H_ 3 | #define _TRACE_MSG_H_ 4 | 5 | #include 6 | 7 | #define UDP_MAX_PACKET (65536 - 20) 8 | #define V3_MAGIC "766679\0" 9 | #define V3_CPU "-1V3" 10 | 11 | #define V1_PROTOCOL 1 12 | #define V3_PROTOCOL 3 13 | 14 | extern unsigned int page_size; 15 | 16 | #endif /* _TRACE_MSG_H_ */ 17 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/private/trace-rbtree.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2023 Google, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _TRACE_RBTREE_H 7 | #define _TRACE_RBTREE_H 8 | 9 | struct trace_rbtree_node { 10 | struct trace_rbtree_node *parent; 11 | struct trace_rbtree_node *left; 12 | struct trace_rbtree_node *right; 13 | int color; 14 | }; 15 | 16 | typedef int (*trace_rbtree_cmp_fn)(const struct trace_rbtree_node *A, const struct trace_rbtree_node *B); 17 | 18 | typedef int (*trace_rbtree_search_fn)(const struct trace_rbtree_node *n, const void *data); 19 | 20 | struct trace_rbtree { 21 | struct trace_rbtree_node *node; 22 | trace_rbtree_search_fn search; 23 | trace_rbtree_cmp_fn cmp; 24 | size_t nr_nodes; 25 | }; 26 | 27 | void tcmd_rbtree_init(struct trace_rbtree *tree, trace_rbtree_cmp_fn cmp_fn, 28 | trace_rbtree_search_fn search_fn); 29 | struct trace_rbtree_node *trace_rbtree_find(struct trace_rbtree *tree, const void *data); 30 | void trace_rbtree_delete(struct trace_rbtree *tree, struct trace_rbtree_node *node); 31 | int tcmd_rbtree_insert(struct trace_rbtree *tree, struct trace_rbtree_node *node); 32 | struct trace_rbtree_node *trace_rbtree_pop_nobalance(struct trace_rbtree *tree); 33 | 34 | #endif /* _TRACE_RBTREE_H */ 35 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/trace-cmd-local.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _TRACE_CMD_LOCAL_H 7 | #define _TRACE_CMD_LOCAL_H 8 | 9 | #include 10 | #include "trace-cmd-private.h" 11 | 12 | #define FILE_VERSION_DEFAULT 7 13 | 14 | /* Can be overridden */ 15 | void tracecmd_warning(const char *fmt, ...); 16 | void tracecmd_critical(const char *fmt, ...); 17 | void tracecmd_info(const char *fmt, ...); 18 | 19 | #ifndef htonll 20 | # if __BYTE_ORDER == __LITTLE_ENDIAN 21 | #define htonll(x) __bswap_64(x) 22 | #define ntohll(x) __bswap_64(x) 23 | #else 24 | #define htonll(x) (x) 25 | #define ntohll(x) (x) 26 | #endif 27 | #endif 28 | 29 | #ifdef HAVE_ZLIB 30 | int tracecmd_zlib_init(void); 31 | #endif 32 | 33 | #ifdef HAVE_ZSTD 34 | int tracecmd_zstd_init(void); 35 | #else 36 | static inline int tracecmd_zstd_init(void) 37 | { 38 | return 0; 39 | } 40 | #endif 41 | 42 | struct data_file_write { 43 | unsigned long long file_size; 44 | unsigned long long write_size; 45 | /* offset in the trace file, where write_size is stored */ 46 | unsigned long long file_write_size; 47 | unsigned long long data_offset; 48 | /* offset in the trace file, where data_offset is stored */ 49 | unsigned long long file_data_offset; 50 | }; 51 | 52 | enum tracecmd_filters tcmd_filter_match(struct tracecmd_filter *filter, 53 | struct tep_record *record); 54 | 55 | void tcmd_set_guest_map(struct tracecmd_input *handle, struct tracecmd_cpu_map *map); 56 | struct tracecmd_cpu_map *tcmd_get_guest_map(struct tracecmd_input *handle); 57 | void tcmd_set_guest_map_cnt(struct tracecmd_input *handle, int count); 58 | int tcmd_get_guest_map_cnt(struct tracecmd_input *handle); 59 | void tcmd_guest_map_free(struct tracecmd_cpu_map *map); 60 | 61 | void tracecmd_compress_init(void); 62 | void tracecmd_compress_free(void); 63 | 64 | bool tcmd_check_file_state(unsigned long file_version, int current_state, int new_state); 65 | bool tcmd_check_out_state(struct tracecmd_output *handle, int new_state); 66 | 67 | int tcmd_out_uncompress_block(struct tracecmd_output *handle); 68 | int tcmd_out_compression_start(struct tracecmd_output *handle, bool compress); 69 | int tcmd_out_compression_end(struct tracecmd_output *handle, bool compress); 70 | void tcmd_out_compression_reset(struct tracecmd_output *handle, bool compress); 71 | bool tcmd_out_check_compression(struct tracecmd_output *handle); 72 | 73 | void tcmd_out_set_file_state(struct tracecmd_output *handle, int new_state); 74 | int tcmd_out_save_options_offset(struct tracecmd_output *handle, 75 | unsigned long long start); 76 | unsigned long long tcmd_out_copy_fd_compress(struct tracecmd_output *handle, 77 | int fd, unsigned long long max, 78 | unsigned long long *write_size, int page); 79 | void tcmd_in_uncompress_reset(struct tracecmd_input *handle); 80 | int tcmd_in_uncompress_block(struct tracecmd_input *handle); 81 | 82 | unsigned long long 83 | tcmd_out_write_section_header(struct tracecmd_output *handle, unsigned short header_id, 84 | char *description, int flags, bool option); 85 | int tcmd_out_update_section_header(struct tracecmd_output *handle, unsigned long long offset); 86 | 87 | long long tcmd_do_write_check(struct tracecmd_output *handle, const void *data, long long size); 88 | 89 | struct tracecmd_option * 90 | tcmd_out_add_buffer_option(struct tracecmd_output *handle, const char *name, 91 | unsigned short id, unsigned long long data_offset, 92 | int cpus, struct data_file_write *cpu_data, int page_size); 93 | 94 | struct cpu_data_source { 95 | int fd; 96 | ssize_t size; 97 | off_t offset; 98 | }; 99 | 100 | int tcmd_out_write_cpu_data(struct tracecmd_output *handle, int cpus, 101 | struct cpu_data_source *data, const char *buff_name); 102 | int tcmd_out_write_emty_cpu_data(struct tracecmd_output *handle, int cpus); 103 | off_t tcmd_msg_lseek(struct tracecmd_msg_handle *msg_handle, off_t offset, int whence); 104 | unsigned long long tcmd_get_last_option_offset(struct tracecmd_input *handle); 105 | unsigned int tcmd_get_meta_strings_size(struct tracecmd_input *handle); 106 | int tcmd_append_options(struct tracecmd_output *handle, void *buf, size_t len); 107 | void *tcmd_get_options(struct tracecmd_output *handle, size_t *len); 108 | 109 | /* filters */ 110 | struct tracecmd_filter *tcmd_filter_get(struct tracecmd_input *handle); 111 | void tcmd_filter_set(struct tracecmd_input *handle, struct tracecmd_filter *filter); 112 | void tcmd_filter_free(struct tracecmd_filter *filter); 113 | 114 | #endif /* _TRACE_CMD_LOCAL_H */ 115 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/trace-hash-local.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (C) 2009, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _TRACE_HASH_LOCAL_H 7 | #define _TRACE_HASH_LOCAL_H 8 | 9 | static inline unsigned int trace_hash(unsigned int val) 10 | { 11 | unsigned int hash, tmp; 12 | 13 | hash = 12546869; /* random prime */ 14 | 15 | /* 16 | * The following hash is based off of Paul Hsieh's super fast hash: 17 | * http://www.azillionmonkeys.com/qed/hash.html 18 | * Note, he released this code unde the GPL 2.0 license, which 19 | * is the same as the license for the programs that use it here. 20 | */ 21 | 22 | hash += (val & 0xffff); 23 | tmp = (val >> 16) ^ hash; 24 | hash = (hash << 16) ^ tmp; 25 | hash += hash >> 11; 26 | 27 | hash ^= hash << 3; 28 | hash += hash >> 5; 29 | hash ^= hash << 4; 30 | hash += hash >> 17; 31 | hash ^= hash << 25; 32 | hash += hash >> 6; 33 | 34 | return hash; 35 | } 36 | 37 | static inline unsigned int trace_hash_str(char *str) 38 | { 39 | int val = 0; 40 | int i; 41 | 42 | for (i = 0; str[i]; i++) 43 | val += ((int)str[i]) << (i & 0xf); 44 | return trace_hash(val); 45 | } 46 | #endif /* _TRACE_HASH_LOCAL_H */ 47 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/trace-tsync-local.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2019, VMware, Tzvetomir Stoyanov 4 | * 5 | */ 6 | #ifndef _TRACE_TSYNC_LOCAL_H 7 | #define _TRACE_TSYNC_LOCAL_H 8 | 9 | #include 10 | 11 | struct tsync_proto; 12 | 13 | struct tracecmd_time_sync { 14 | pthread_t thread; 15 | bool thread_running; 16 | unsigned long long trace_id; 17 | char *proto_name; 18 | int loop_interval; 19 | pthread_mutex_t lock; 20 | pthread_cond_t cond; 21 | pthread_barrier_t first_sync; 22 | char *clock_str; 23 | struct tracecmd_msg_handle *msg_handle; 24 | struct tsync_proto *proto; 25 | void *context; 26 | int guest_pid; 27 | int vcpu_count; 28 | int remote_id; 29 | int local_id; 30 | }; 31 | 32 | struct clock_sync_offsets { 33 | /* Arrays with calculated time offsets at given time */ 34 | int sync_size; /* Allocated size of sync_ts, 35 | * sync_offsets, sync_scalings and sync_frac 36 | */ 37 | int sync_count; /* Number of elements in sync_ts, 38 | * sync_offsets, sync_scalings and sync_frac 39 | */ 40 | long long *sync_ts; 41 | long long *sync_offsets; 42 | long long *sync_scalings; 43 | long long *sync_frac; 44 | }; 45 | 46 | struct clock_sync_context { 47 | void *proto_data; /* time sync protocol specific data */ 48 | bool is_server; /* server side time sync role */ 49 | bool is_guest; /* guest or host time sync role */ 50 | struct tracefs_instance *instance; /* ftrace buffer, used for time sync events */ 51 | 52 | int cpu_count; 53 | struct clock_sync_offsets *offsets; /* Array of size cpu_count 54 | * calculated offsets per CPU 55 | */ 56 | 57 | /* Identifiers of local and remote time sync peers */ 58 | unsigned int local_id; 59 | unsigned int remote_id; 60 | }; 61 | 62 | int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, 63 | int supported_clocks, unsigned int flags, 64 | int (*init)(struct tracecmd_time_sync *), 65 | int (*free)(struct tracecmd_time_sync *), 66 | int (*calc)(struct tracecmd_time_sync *, 67 | long long *, long long *, long long*, 68 | long long *, unsigned int)); 69 | int tracecmd_tsync_proto_unregister(char *proto_name); 70 | int ptp_clock_sync_register(void); 71 | 72 | #ifdef VSOCK 73 | int kvm_clock_sync_register(void); 74 | #else 75 | static inline int kvm_clock_sync_register(void) 76 | { 77 | return 0; 78 | } 79 | #endif 80 | 81 | #endif /* _TRACE_TSYNC_LOCAL_H */ 82 | -------------------------------------------------------------------------------- /lib/trace-cmd/include/trace-write-local.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _TRACE_WRITE_LOCAL_H 7 | #define _TRACE_WRITE_LOCAL_H 8 | 9 | /* Local for trace-input.c, trace-output.c and trace-msg.c */ 10 | 11 | static inline ssize_t __do_write(int fd, const void *data, size_t size) 12 | { 13 | ssize_t tot = 0; 14 | ssize_t w; 15 | 16 | do { 17 | w = write(fd, data + tot, size - tot); 18 | tot += w; 19 | 20 | if (!w) 21 | break; 22 | if (w < 0) 23 | return w; 24 | } while (tot != size); 25 | 26 | return tot; 27 | } 28 | 29 | static inline ssize_t 30 | __do_write_check(int fd, const void *data, size_t size) 31 | { 32 | ssize_t ret; 33 | 34 | ret = __do_write(fd, data, size); 35 | if (ret < 0) 36 | return ret; 37 | if (ret != size) 38 | return -1; 39 | 40 | return 0; 41 | } 42 | 43 | #endif /* _TRACE_WRITE_LOCAL_H */ 44 | -------------------------------------------------------------------------------- /lib/trace-cmd/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: LGPL-2.1 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | sources = [ 6 | 'trace-hash.c', 7 | 'trace-rbtree.c', 8 | 'trace-hooks.c', 9 | 'trace-input.c', 10 | 'trace-output.c', 11 | 'trace-recorder.c', 12 | 'trace-util.c', 13 | 'trace-filter-hash.c', 14 | 'trace-filter.c', 15 | 'trace-msg.c', 16 | 'trace-plugin.c', 17 | 'trace-maps.c', 18 | 'trace-timesync.c', 19 | 'trace-timesync-ptp.c', 20 | 'trace-compress.c', 21 | 'trace-blk-hack.c', 22 | 'trace-ftrace.c', 23 | ] 24 | 25 | if perf_defined 26 | sources += 'trace-perf.c' 27 | endif 28 | 29 | if vsock_defined 30 | sources += 'trace-timesync-kvm.c' 31 | endif 32 | 33 | if zlib_dep.found() 34 | sources += 'trace-compress-zlib.c' 35 | endif 36 | 37 | if libzstd_dep.found() 38 | sources += 'trace-compress-zstd.c' 39 | endif 40 | 41 | if libtracecmd_standalone_build 42 | libtracecmd = library( 43 | 'tracecmd', 44 | sources, 45 | version: library_version, 46 | dependencies: [ 47 | libtraceevent_dep, 48 | libtracefs_dep, 49 | threads_dep, 50 | dl_dep, 51 | zlib_dep, 52 | libzstd_dep, 53 | audit_dep], 54 | include_directories: [ 55 | libtracecmd_incdir, 56 | libtracecmd_private_incdir, 57 | libtracecmd_ext_incdir], 58 | install: true) 59 | 60 | pkg = import('pkgconfig') 61 | pkg.generate( 62 | libtracecmd, 63 | subdirs: 'trace-cmd', 64 | libraries: [ 65 | libtracefs_dep, 66 | libtraceevent_dep], 67 | filebase: meson.project_name(), 68 | name: meson.project_name(), 69 | version: meson.project_version(), 70 | description: 'Library for creating and reading trace-cmd data files', 71 | url: 'https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/') 72 | 73 | libtracecmd_dep = declare_dependency( 74 | include_directories: ['.'], 75 | link_with: libtracecmd) 76 | else 77 | static_libtracecmd = static_library( 78 | 'tracecmd', 79 | sources, 80 | dependencies: [ 81 | libtraceevent_dep, 82 | libtracefs_dep, 83 | threads_dep, 84 | dl_dep, 85 | zlib_dep, 86 | libzstd_dep, 87 | audit_dep], 88 | include_directories: [ 89 | libtracecmd_incdir, 90 | libtracecmd_private_incdir, 91 | libtracecmd_ext_incdir], 92 | install: false) 93 | endif 94 | -------------------------------------------------------------------------------- /lib/trace-cmd/plugins/Makefile: -------------------------------------------------------------------------------- 1 | include $(src)/scripts/utils.mk 2 | 3 | bdir:=$(obj)/lib/trace-cmd/plugins 4 | 5 | PLUGIN_OBJS = 6 | 7 | PLUGIN_OBJS := $(PLUGIN_OBJS:%.o=$(bdir)/%.o) 8 | PLUGIN_BUILD := $(PLUGIN_OBJS:$(bdir)/%.o=$(bdir)/%.so) 9 | 10 | PLUGINS := $(PLUGIN_BUILD) 11 | 12 | DEPS := $(PLUGIN_OBJS:$(bdir)/%.o=$(bdir)/.%.d) 13 | 14 | all: $(PLUGINS) 15 | 16 | $(bdir): 17 | @mkdir -p $(bdir) 18 | 19 | $(PLUGIN_OBJS): | $(bdir) 20 | $(DEPS): | $(bdir) 21 | 22 | $(PLUGIN_OBJS): $(bdir)/%.o : %.c 23 | $(Q)$(do_compile_plugin_obj) 24 | 25 | $(PLUGIN_BUILD): $(bdir)/%.so: $(bdir)/%.o 26 | $(Q)$(do_plugin_build) 27 | 28 | $(DEPS): $(bdir)/.%.d: %.c 29 | $(Q)$(CC) -M -MT $(bdir)/$*.o $(CPPFLAGS) $(CFLAGS) $< > $@ 30 | 31 | $(PLUGIN_OBJS): $(bdir)/%.o : $(bdir)/.%.d 32 | 33 | PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS)) 34 | 35 | $(PLUGINS_INSTALL): $(bdir)/%.install : $(bdir)/%.so force 36 | $(Q)$(call do_install_data,$<,$(plugin_tracecmd_dir_SQ)) 37 | 38 | install_plugins: $(PLUGINS_INSTALL) 39 | 40 | # The following targets are necessary to trigger a rebuild when 41 | # $(PLUGIN_DIR_TRACECMD) change. Without them, a full clean build would 42 | # necessary in order to get the binaries updated. 43 | 44 | $(bdir)/tracecmd_plugin_dir: $(bdir) force 45 | $(Q)$(N)$(call update_dir, 'PLUGIN_DIR_TRACECMD=$(PLUGIN_DIR_TRACECMD)') 46 | 47 | dep_includes := $(wildcard $(DEPS)) 48 | 49 | ifneq ($(dep_includes),) 50 | include $(dep_includes) 51 | endif 52 | 53 | clean: 54 | $(RM) -f $(bdir)/*.a $(bdir)/*.so $(bdir)/*.o $(bdir)/.*.d\ 55 | $(bdir)/tracecmd_plugin_dir 56 | 57 | force: 58 | .PHONY: clean force 59 | -------------------------------------------------------------------------------- /lib/trace-cmd/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | tracecmd_open_head("trace.dat", 0); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /lib/trace-cmd/trace-blk-hack.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include "trace-cmd.h" 8 | #include "trace-local.h" 9 | 10 | static const char blk_event_start[] = 11 | "name: blktrace\n" 12 | "ID: %d\n" 13 | "format:\n" 14 | "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\n" 15 | "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\n" 16 | "\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\n" 17 | "\tfield:int common_pid;\toffset:4;\tsize:4;\n"; 18 | 19 | static const char blk_body[] = "\n" 20 | "\tfield:u64 sector;\toffset:16;\tsize:8;\n" 21 | "\tfield:int bytes;\toffset:24;\tsize:4;\n" 22 | "\tfield:int action;\toffset:28;\tsize:4;\n" 23 | "\tfield:int pid;\toffset:32;\tsize:4;\n" 24 | "\tfield:int device;\toffset:36;\tsize:4;\n" 25 | "\tfield:int cpu;\toffset:40;\tsize:4;\n" 26 | "\tfield:short error;\toffset:44;\tsize:2;\n" 27 | "\tfield:short pdu_len;\toffset:46;\tsize:2;\n" 28 | "\tfield:void data;\toffset:48;\tsize:0;\n" 29 | "\n" 30 | "print fmt: \"%%d\", REC->pid\n"; 31 | 32 | int tracecmd_blk_hack(struct tracecmd_input *handle) 33 | { 34 | struct tep_handle *pevent; 35 | struct tep_event *event; 36 | struct tep_format_field *field; 37 | char buf[4096]; /* way more than enough! */ 38 | int id; 39 | int l; 40 | int r; 41 | 42 | pevent = tracecmd_get_tep(handle); 43 | 44 | /* 45 | * Unfortunately, the TRACE_BLK has changed a bit. 46 | * We need to test if various events exist to try 47 | * to guess what event id TRACE_BLK would be. 48 | */ 49 | 50 | /* It was originally behind the "power" event */ 51 | event = tep_find_event_by_name(pevent, "ftrace", "power"); 52 | if (event) { 53 | id = event->id + 1; 54 | goto found; 55 | } 56 | 57 | /* 58 | * But the power tracer is now in perf. 59 | * Then it was after kmem_free 60 | */ 61 | event = tep_find_event_by_name(pevent, "ftrace", "kmem_free"); 62 | if (event) { 63 | id = event->id + 1; 64 | goto found; 65 | } 66 | 67 | /* 68 | * But that then went away. 69 | * Currently it should be behind the user stack. 70 | */ 71 | event = tep_find_event_by_name(pevent, "ftrace", "user_stack"); 72 | if (event) { 73 | id = event->id + 1; 74 | goto found; 75 | } 76 | /* Give up :( */ 77 | return -1; 78 | 79 | found: 80 | /* 81 | * Blk events are not exported in the events directory. 82 | * This is a hack to attempt to create a block event 83 | * that we can read. 84 | * 85 | * We'll make a format file to look like this: 86 | * 87 | * name: blktrace 88 | * ID: 13 89 | * format: 90 | * field:unsigned short common_type; offset:0; size:2; 91 | * field:unsigned char common_flags; offset:2; size:1; 92 | * field:unsigned char common_preempt_count; offset:3; size:1; 93 | * field:int common_pid; offset:4; size:4; 94 | * field:int common_lock_depth; offset:8; size:4; 95 | * 96 | * field:u64 sector; offset:16; size:8; 97 | * field:int bytes; offset:32; size:4; 98 | * field:int action; offset:36; size:4; 99 | * field:int pid; offset:40; size:4; 100 | * field:int device; offset:44; size:4; 101 | * field:int cpu; offset:48; size:4; 102 | * field:short error; offset:52; size:2; 103 | * field:short pdu_len; offset:54; size:2; 104 | * field:void data; offset:60; size:0; 105 | * 106 | * print fmt: "%d", REC->pid 107 | * 108 | * Note: the struct blk_io_trace is used directly and 109 | * just the first parts of the struct are not used in order 110 | * to not write over the ftrace data. 111 | */ 112 | 113 | /* Make sure the common fields exist */ 114 | field = tep_find_common_field(event, "common_type"); 115 | if (!field || field->offset != 0 || field->size != 2) 116 | goto fail; 117 | field = tep_find_common_field(event, "common_flags"); 118 | if (!field || field->offset != 2 || field->size != 1) 119 | goto fail; 120 | field = tep_find_common_field(event, "common_preempt_count"); 121 | if (!field || field->offset != 3 || field->size != 1) 122 | goto fail; 123 | field = tep_find_common_field(event, "common_pid"); 124 | if (!field || field->offset != 4 || field->size != 4) 125 | goto fail; 126 | r = sprintf(buf, blk_event_start, id); 127 | l = r; 128 | 129 | /* lock depth is optional */ 130 | field = tep_find_common_field(event, "common_lock_depth"); 131 | if (field) { 132 | if (field->offset != 8 || field->size != 4) 133 | return -1; 134 | r = sprintf(buf+l, "\tfield:int common_lock_depth;\toffset:8;\tsize:4;\n"); 135 | l += r; 136 | } 137 | 138 | r = sprintf(buf+l, blk_body); 139 | 140 | /* Parse this event */ 141 | l += r; 142 | tep_parse_event(pevent, buf, l, "ftrace"); 143 | 144 | return 0; 145 | 146 | fail: 147 | return -1; 148 | } 149 | -------------------------------------------------------------------------------- /lib/trace-cmd/trace-compress-zlib.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2021, VMware, Tzvetomir Stoyanov tz.stoyanov@gmail.com> 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "trace-cmd-private.h" 12 | 13 | #define __ZLIB_NAME "zlib" 14 | #define __ZLIB_WEIGTH 10 15 | 16 | static int zlib_compress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes) 17 | { 18 | unsigned long obytes = out_bytes; 19 | int ret; 20 | 21 | ret = compress2((unsigned char *)out, &obytes, 22 | (unsigned char *)in, (unsigned long)in_bytes, Z_BEST_COMPRESSION); 23 | switch (ret) { 24 | case Z_OK: 25 | return obytes; 26 | case Z_BUF_ERROR: 27 | errno = -ENOBUFS; 28 | break; 29 | case Z_MEM_ERROR: 30 | errno = -ENOMEM; 31 | break; 32 | case Z_STREAM_ERROR: 33 | errno = -EINVAL; 34 | break; 35 | case Z_ERRNO: 36 | break; 37 | default: 38 | errno = -EFAULT; 39 | break; 40 | } 41 | 42 | return -1; 43 | } 44 | 45 | static int zlib_decompress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes) 46 | { 47 | unsigned long obytes = out_bytes; 48 | int ret; 49 | 50 | ret = uncompress((unsigned char *)out, &obytes, 51 | (unsigned char *)in, (unsigned long)in_bytes); 52 | switch (ret) { 53 | case Z_OK: 54 | return obytes; 55 | case Z_BUF_ERROR: 56 | errno = -ENOBUFS; 57 | break; 58 | case Z_MEM_ERROR: 59 | errno = -ENOMEM; 60 | break; 61 | case Z_DATA_ERROR: 62 | errno = -EINVAL; 63 | break; 64 | case Z_ERRNO: 65 | break; 66 | default: 67 | errno = -EFAULT; 68 | break; 69 | } 70 | 71 | return -1; 72 | } 73 | 74 | static unsigned int zlib_compress_bound(void *ctx, unsigned int in_bytes) 75 | { 76 | return compressBound(in_bytes); 77 | } 78 | 79 | static bool zlib_is_supported(const char *name, const char *version) 80 | { 81 | const char *zver; 82 | 83 | if (!name) 84 | return false; 85 | if (strlen(name) != strlen(__ZLIB_NAME) || strcmp(name, __ZLIB_NAME)) 86 | return false; 87 | 88 | if (!version) 89 | return true; 90 | 91 | zver = zlibVersion(); 92 | if (!zver) 93 | return false; 94 | 95 | /* Compare the major version number */ 96 | if (atoi(version) <= atoi(zver)) 97 | return true; 98 | 99 | return false; 100 | } 101 | 102 | int tracecmd_zlib_init(void) 103 | { 104 | struct tracecmd_compression_proto proto; 105 | 106 | memset(&proto, 0, sizeof(proto)); 107 | proto.name = __ZLIB_NAME; 108 | proto.version = zlibVersion(); 109 | proto.weight = __ZLIB_WEIGTH; 110 | proto.compress = zlib_compress; 111 | proto.uncompress = zlib_decompress; 112 | proto.is_supported = zlib_is_supported; 113 | proto.compress_size = zlib_compress_bound; 114 | 115 | return tracecmd_compress_proto_register(&proto); 116 | } 117 | -------------------------------------------------------------------------------- /lib/trace-cmd/trace-compress-zstd.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2022, Sebastian Andrzej Siewior 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #include "trace-cmd-private.h" 11 | 12 | #define __ZSTD_NAME "zstd" 13 | #define __ZSTD_WEIGTH 5 14 | 15 | struct zstd_context { 16 | ZSTD_CCtx *ctx_c; 17 | ZSTD_DCtx *ctx_d; 18 | }; 19 | 20 | static int zstd_compress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes) 21 | { 22 | struct zstd_context *context = ctx; 23 | size_t ret; 24 | 25 | if (!ctx) 26 | return -1; 27 | 28 | ret = ZSTD_compress2(context->ctx_c, out, out_bytes, in, in_bytes); 29 | if (ZSTD_isError(ret)) 30 | return -1; 31 | 32 | return ret; 33 | } 34 | 35 | static int zstd_decompress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes) 36 | { 37 | struct zstd_context *context = ctx; 38 | size_t ret; 39 | 40 | if (!ctx) 41 | return -1; 42 | 43 | ret = ZSTD_decompressDCtx(context->ctx_d, out, out_bytes, in, in_bytes); 44 | if (ZSTD_isError(ret)) { 45 | errno = -EINVAL; 46 | return -1; 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | static unsigned int zstd_compress_bound(void *ctx, unsigned int in_bytes) 53 | { 54 | return ZSTD_compressBound(in_bytes); 55 | } 56 | 57 | static bool zstd_is_supported(const char *name, const char *version) 58 | { 59 | if (!name) 60 | return false; 61 | if (strcmp(name, __ZSTD_NAME)) 62 | return false; 63 | 64 | return true; 65 | } 66 | 67 | static void *new_zstd_context(void) 68 | { 69 | struct zstd_context *context; 70 | size_t r; 71 | 72 | context = calloc(1, sizeof(*context)); 73 | if (!context) 74 | return NULL; 75 | 76 | context->ctx_c = ZSTD_createCCtx(); 77 | context->ctx_d = ZSTD_createDCtx(); 78 | if (!context->ctx_c || !context->ctx_d) 79 | goto err; 80 | 81 | r = ZSTD_CCtx_setParameter(context->ctx_c, ZSTD_c_contentSizeFlag, 0); 82 | if (ZSTD_isError(r)) 83 | goto err; 84 | 85 | return context; 86 | err: 87 | ZSTD_freeCCtx(context->ctx_c); 88 | ZSTD_freeDCtx(context->ctx_d); 89 | free(context); 90 | return NULL; 91 | } 92 | static void free_zstd_context(void *ctx) 93 | { 94 | struct zstd_context *context = ctx; 95 | 96 | if (!ctx) 97 | return; 98 | 99 | ZSTD_freeCCtx(context->ctx_c); 100 | ZSTD_freeDCtx(context->ctx_d); 101 | free(context); 102 | } 103 | 104 | int tracecmd_zstd_init(void) 105 | { 106 | struct tracecmd_compression_proto proto; 107 | 108 | memset(&proto, 0, sizeof(proto)); 109 | proto.name = __ZSTD_NAME; 110 | proto.version = ZSTD_versionString(); 111 | proto.weight = __ZSTD_WEIGTH; 112 | proto.compress = zstd_compress; 113 | proto.uncompress = zstd_decompress; 114 | proto.is_supported = zstd_is_supported; 115 | proto.compress_size = zstd_compress_bound; 116 | proto.new_context = new_zstd_context; 117 | proto.free_context = free_zstd_context; 118 | 119 | return tracecmd_compress_proto_register(&proto); 120 | } 121 | -------------------------------------------------------------------------------- /lib/trace-cmd/trace-hash.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2014, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "trace-cmd-private.h" 13 | #include "trace-hash.h" 14 | 15 | int __hidden tcmd_hash_init(struct trace_hash *hash, int buckets) 16 | { 17 | memset(hash, 0, sizeof(*hash)); 18 | 19 | hash->buckets = calloc(sizeof(*hash->buckets), buckets); 20 | if (!hash->buckets) 21 | return -ENOMEM; 22 | hash->nr_buckets = buckets; 23 | 24 | /* If a power of two then we can shortcut */ 25 | if (!(buckets & (buckets - 1))) 26 | hash->power = buckets - 1; 27 | 28 | return 0; 29 | } 30 | 31 | void __hidden tcmd_hash_free(struct trace_hash *hash) 32 | { 33 | free(hash->buckets); 34 | } 35 | 36 | int __hidden tcmd_hash_empty(struct trace_hash *hash) 37 | { 38 | struct trace_hash_item **bucket; 39 | 40 | trace_hash_for_each_bucket(bucket, hash) 41 | if (*bucket) 42 | return 0; 43 | return 1; 44 | } 45 | 46 | int __hidden tcmd_hash_add(struct trace_hash *hash, struct trace_hash_item *item) 47 | { 48 | struct trace_hash_item *next; 49 | int bucket = hash->power ? item->key & hash->power : 50 | item->key % hash->nr_buckets; 51 | 52 | if (hash->buckets[bucket]) { 53 | next = hash->buckets[bucket]; 54 | next->prev = item; 55 | } else 56 | next = NULL; 57 | 58 | item->next = next; 59 | item->prev = (struct trace_hash_item *)&hash->buckets[bucket]; 60 | 61 | hash->buckets[bucket] = item; 62 | 63 | return 1; 64 | } 65 | 66 | __hidden struct trace_hash_item * 67 | tcmd_hash_find(struct trace_hash *hash, unsigned long long key, 68 | trace_hash_func match, void *data) 69 | { 70 | struct trace_hash_item *item; 71 | int bucket = hash->power ? key & hash->power : 72 | key % hash->nr_buckets; 73 | 74 | for (item = hash->buckets[bucket]; item; item = item->next) { 75 | if (item->key == key) { 76 | if (!match) 77 | return item; 78 | if (match(item, data)) 79 | return item; 80 | } 81 | } 82 | 83 | return NULL; 84 | } 85 | -------------------------------------------------------------------------------- /lib/trace-cmd/trace-hooks.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2015 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "trace-cmd-private.h" 12 | #include "trace-cmd-local.h" 13 | #include "event-utils.h" 14 | 15 | struct hook_list *tracecmd_create_event_hook(const char *arg) 16 | { 17 | struct hook_list *hook; 18 | char *system = NULL; 19 | char *event; 20 | char *match; 21 | char *flags = NULL; 22 | char *pid = NULL; 23 | char *str; 24 | char *tok; 25 | int index; 26 | int ch; 27 | int i; 28 | 29 | hook = malloc(sizeof(*hook)); 30 | if (!hook) 31 | return NULL; 32 | memset(hook, 0, sizeof(*hook)); 33 | 34 | str = strdup(arg); 35 | if (!str) { 36 | free(hook); 37 | return NULL; 38 | } 39 | 40 | hook->str = str; 41 | hook->hook = arg; 42 | 43 | /* 44 | * Hooks are in the form of: 45 | * [:],[,]/ 46 | * [:],[,] 47 | * 48 | * Where start_system, start_pid, end_system, and flags are all 49 | * optional. 50 | * 51 | * Flags are (case insensitive): 52 | * P - pinned to cpu (wont migrate) 53 | * G - global, not hooked to task - currently ignored. 54 | * S - save stacks for this event. 55 | */ 56 | tok = strtok(str, ":,"); 57 | if (!tok) 58 | goto invalid_tok; 59 | 60 | /* See what the token was from the original arg */ 61 | index = strlen(tok); 62 | if (arg[index] == ':') { 63 | /* this is a system, the next token must be ',' */ 64 | system = tok; 65 | tok = strtok(NULL, ","); 66 | if (!tok) 67 | goto invalid_tok; 68 | } 69 | event = tok; 70 | 71 | tok = strtok(NULL, ",/"); 72 | if (!tok) 73 | goto invalid_tok; 74 | match = tok; 75 | index = strlen(tok) + tok - str; 76 | if (arg[index] == ',') { 77 | tok = strtok(NULL, "/"); 78 | if (!tok) 79 | goto invalid_tok; 80 | pid = tok; 81 | } 82 | 83 | hook->start_system = system; 84 | hook->start_event = event; 85 | hook->start_match = match; 86 | hook->pid = pid; 87 | 88 | /* Now process the end event */ 89 | system = NULL; 90 | 91 | tok = strtok(NULL, ":,"); 92 | if (!tok) 93 | goto invalid_tok; 94 | 95 | /* See what the token was from the original arg */ 96 | index = tok - str + strlen(tok); 97 | if (arg[index] == ':') { 98 | /* this is a system, the next token must be ',' */ 99 | system = tok; 100 | tok = strtok(NULL, ","); 101 | if (!tok) 102 | goto invalid_tok; 103 | } 104 | event = tok; 105 | 106 | tok = strtok(NULL, ","); 107 | if (!tok) 108 | goto invalid_tok; 109 | match = tok; 110 | index = strlen(tok) + tok - str; 111 | if (arg[index] == ',') { 112 | tok = strtok(NULL, ""); 113 | if (!tok) 114 | goto invalid_tok; 115 | flags = tok; 116 | } 117 | 118 | hook->end_system = system; 119 | hook->end_event = event; 120 | hook->end_match = match; 121 | hook->migrate = 1; 122 | if (flags) { 123 | for (i = 0; flags[i]; i++) { 124 | ch = tolower(flags[i]); 125 | switch (ch) { 126 | case 'p': 127 | hook->migrate = 0; 128 | break; 129 | case 'g': 130 | hook->global = 1; 131 | break; 132 | case 's': 133 | hook->stack = 1; 134 | break; 135 | default: 136 | tracecmd_warning("unknown flag %c", flags[i]); 137 | } 138 | } 139 | } 140 | 141 | printf("start %s:%s:%s (%s) end %s:%s:%s (%s)\n", 142 | hook->start_system, 143 | hook->start_event, 144 | hook->start_match, 145 | hook->pid, 146 | hook->end_system, 147 | hook->end_event, 148 | hook->end_match, 149 | flags); 150 | return hook; 151 | 152 | invalid_tok: 153 | tracecmd_warning("Invalid hook format '%s'", arg); 154 | free(hook->str); 155 | free(hook); 156 | return NULL; 157 | } 158 | 159 | void tracecmd_free_hooks(struct hook_list *hooks) 160 | { 161 | struct hook_list *hook; 162 | 163 | while (hooks) { 164 | hook = hooks; 165 | hooks = hooks->next; 166 | 167 | free(hook->str); 168 | free(hook); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /lib/trace-cmd/trace-perf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2021, VMware, Tzvetomir Stoyanov 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #include "trace-cmd-private.h" 11 | 12 | static void default_perf_init_pe(struct perf_event_attr *pe) 13 | { 14 | pe->type = PERF_TYPE_SOFTWARE; 15 | pe->sample_type = PERF_SAMPLE_CPU; 16 | pe->size = sizeof(struct perf_event_attr); 17 | pe->config = PERF_COUNT_HW_CPU_CYCLES; 18 | pe->disabled = 1; 19 | pe->exclude_kernel = 1; 20 | pe->freq = 1; 21 | pe->sample_freq = 1000; 22 | pe->inherit = 1; 23 | pe->mmap = 1; 24 | pe->comm = 1; 25 | pe->task = 1; 26 | pe->precise_ip = 1; 27 | pe->sample_id_all = 1; 28 | pe->read_format = PERF_FORMAT_ID | 29 | PERF_FORMAT_TOTAL_TIME_ENABLED | 30 | PERF_FORMAT_TOTAL_TIME_RUNNING; 31 | } 32 | 33 | /** 34 | * tcmd_perf_init - Initialize perf context 35 | * 36 | * @perf: structure, representing perf context, that will be initialized. 37 | * @pages: Number of perf memory mapped pages. 38 | * @cpu: CPU number, associated with this perf context. 39 | * @pid: PID, associated with this perf context. 40 | * 41 | * The perf context in initialized with default values. The caller can set 42 | * custom perf parameters in perf->pe, before calling tcmd_perf_open() API. 43 | * 44 | * Returns 0 on success, or -1 in case of an error. 45 | * 46 | */ 47 | int __hidden tcmd_perf_init(struct trace_perf *perf, int pages, int cpu, int pid) 48 | { 49 | if (!perf) 50 | return -1; 51 | 52 | memset(perf, 0, sizeof(struct trace_perf)); 53 | default_perf_init_pe(&perf->pe); 54 | perf->cpu = cpu; 55 | perf->pages = pages; 56 | perf->pid = pid; 57 | perf->fd = -1; 58 | 59 | return 0; 60 | } 61 | 62 | /** 63 | * tcmd_perf_close - Close perf session 64 | * 65 | * @perf: structure, representing context of a running perf session, opened 66 | * with tcmd_perf_open() 67 | * 68 | */ 69 | void __hidden tcmd_perf_close(struct trace_perf *perf) 70 | { 71 | if (perf->fd >= 0) 72 | close(perf->fd); 73 | perf->fd = -1; 74 | if (perf->mmap && perf->mmap != MAP_FAILED) 75 | munmap(perf->mmap, (perf->pages + 1) * getpagesize()); 76 | perf->mmap = NULL; 77 | } 78 | 79 | /** 80 | * tcmd_perf_open - Open perf session 81 | * 82 | * @perf: structure, representing perf context that will be opened. It must be 83 | * initialized with tcmd_perf_init(). 84 | * 85 | * Returns 0 on success, or -1 in case of an error. In case of success, the 86 | * session must be closed with tcmd_perf_close() 87 | */ 88 | int __hidden tcmd_perf_open(struct trace_perf *perf) 89 | { 90 | perf->fd = syscall(__NR_perf_event_open, &perf->pe, perf->pid, perf->cpu, -1, 0); 91 | if (perf->fd < 0) 92 | return -1; 93 | fcntl(perf->fd, F_SETFL, O_NONBLOCK); 94 | 95 | perf->mmap = mmap(NULL, (perf->pages + 1) * getpagesize(), 96 | PROT_READ | PROT_WRITE, MAP_SHARED, perf->fd, 0); 97 | if (perf->mmap == MAP_FAILED) 98 | goto error; 99 | 100 | return 0; 101 | 102 | error: 103 | tcmd_perf_close(perf); 104 | return -1; 105 | } 106 | -------------------------------------------------------------------------------- /libtracecmd.pc.template: -------------------------------------------------------------------------------- 1 | prefix=INSTALL_PREFIX 2 | libdir=LIB_DIR 3 | includedir=HEADER_DIR 4 | 5 | Name: libtracecmd 6 | URL: https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/ 7 | Description: Library for creating and reading trace-cmd data files 8 | Version: LIB_VERSION 9 | Requires: libtracefs >= LIBTRACEFS_MIN_VERSION 10 | Cflags: -I${includedir} 11 | Libs: -L${libdir} -ltracecmd 12 | -------------------------------------------------------------------------------- /make-trace-cmd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$INSTALL_PATH" ]; then 4 | echo 5 | echo 'Error: No $INSTALL_PATH defined' 6 | echo 7 | echo " usage: [PREFIX=prefix][BUILD_PATH=/path/to/build][CFLAGS=custom-cflags] INSTALL_PATH=/path/to/install make-trace-cmd.sh install|install_libs|clean|uninstall" 8 | echo 9 | echo " Used to create a self contained directory to copy to other machines." 10 | echo 11 | echo " Please read PACKAGING for more information." 12 | echo 13 | exit 14 | fi 15 | 16 | if [ ! -d $INSTALL_PATH ]; then 17 | mkdir $INSTALL_PATH 18 | fi 19 | 20 | if [ ! -z "$BUILD_PATH" ]; then 21 | if [ ! -d $BUILD_PATH ]; then 22 | mkdir $BUILD_PATH 23 | fi 24 | O_PATH="O=$BUILD_PATH" 25 | fi 26 | 27 | if [ -z "$PREFIX" ]; then 28 | PREFIX="/usr" 29 | fi 30 | 31 | PKG_PATH=`pkg-config --variable pc_path pkg-config | tr ":" " " | cut -d' ' -f1` 32 | 33 | WITH_PATH="" 34 | # If pkg-config supports --with-path, use that as well 35 | if pkg-config --with-path=/tmp --variable pc_path pkg-config &> /dev/null ; then 36 | WITH_PATH="--with-path=$INSTALL_PATH$PKG_PATH" 37 | fi 38 | 39 | if [ -z "$CFLAGS" ]; then 40 | CFLAGS="-g -Wall" 41 | fi 42 | 43 | PKG_CONFIG_PATH="$INSTALL_PATH/$PKG_PATH" PKG_CONFIG="pkg-config $WITH_PATH --define-variable=prefix=$INSTALL_PATH/$PREFIX" CFLAGS="-I$INSTALL_PATH/$PREFIX/include $CFLAGS" make DESTDIR=$INSTALL_PATH $O_PATH prefix=$PREFIX $@ 44 | -------------------------------------------------------------------------------- /meson-vcs-tag.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: LGPL-2.1-or-later 3 | 4 | set -eu 5 | set -o pipefail 6 | 7 | dir="${1:?}" 8 | fallback="${2:?}" 9 | 10 | # Apparently git describe has a bug where it always considers the work-tree 11 | # dirty when invoked with --git-dir (even though 'git status' is happy). Work 12 | # around this issue by cd-ing to the source directory. 13 | cd "$dir" 14 | # Check that we have either .git/ (a normal clone) or a .git file (a work-tree) 15 | # and that we don't get confused if a tarball is extracted in a higher-level 16 | # git repository. 17 | [ -e .git ] && git describe --abbrev=7 --dirty=+ 2>/dev/null | sed 's/^v//' || echo "$fallback" 18 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | # -*- mode: meson -*- 2 | # SPDX-License-Identifier: GPL-2.0 3 | 4 | option('version-tag', type : 'string', 5 | description : 'override the git version string') 6 | option('vsock', type : 'boolean', value : true, 7 | description : 'build with vsock support') 8 | option('ptrace', type : 'boolean', value : true, 9 | description : 'build with ptrace support') 10 | option('htmldir', type : 'string', value : 'share/doc/trace-cmd-doc', 11 | description : 'directory for HTML documentation') 12 | option('asciidoctor', type : 'boolean', value: false, 13 | description : 'use asciidoctor instead of asciidoc') 14 | option('docbook-xls-172', type : 'boolean', value : false, 15 | description : 'enable docbook XLS 172 workaround') 16 | option('asciidoc-no-roff', type : 'boolean', value : false, 17 | description : 'enable no roff workaround') 18 | option('man-bold-literal', type : 'boolean', value : false, 19 | description : 'enable bold literals') 20 | option('docbook-suppress-sp', type : 'boolean', value : false, 21 | description : 'docbook suppress sp') 22 | option('python', type : 'combo', choices : ['auto', 'true', 'false'], 23 | description : 'Generate trac-cmd Python bindings') 24 | option('doc', type : 'boolean', value: true, 25 | description : 'produce documentation') 26 | option('utest', type : 'boolean', value: true, 27 | description : 'build utest') 28 | -------------------------------------------------------------------------------- /python/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | include $(src)/scripts/utils.mk 4 | 5 | ifdef BUILD_PYTHON_WORKS 6 | PYTHON_SO_INSTALL := ctracecmd.install 7 | PYTHON_PY_PROGS := event-viewer.install 8 | PYTHON_PY_LIBS := tracecmd.install 9 | endif 10 | 11 | ctracecmd.so: ctracecmd.i $(LIBTRACECMD_STATIC) 12 | swig -Wall -python -noproxy \ 13 | -I$(src)/include/trace-cmd -I$(src)/lib/trace-cmd/include/private \ 14 | $(LIBTRACEEVENT_CFLAGS) ctracecmd.i 15 | $(CC) -fpic -c $(CPPFLAGS) $(CFLAGS) $(PYTHON_INCLUDES) ctracecmd_wrap.c 16 | $(CC) --shared $(LIBTRACECMD_STATIC) $(LDFLAGS) $(LIBZSTD_LDLAGS) $(ZLIB_LDLAGS) \ 17 | ctracecmd_wrap.o -o ctracecmd.so $(TRACE_LIBS) 18 | 19 | $(PYTHON_SO_INSTALL): %.install : %.so force 20 | $(Q)$(call do_install_data,$<,$(python_dir_SQ)) 21 | 22 | $(PYTHON_PY_PROGS): %.install : %.py force 23 | $(Q)$(call do_install,$<,$(python_dir_SQ)) 24 | 25 | $(PYTHON_PY_LIBS): %.install : %.py force 26 | $(Q)$(call do_install_data,$<,$(python_dir_SQ)) 27 | 28 | install_python: $(PYTHON_SO_INSTALL) $(PYTHON_PY_PROGS) $(PYTHON_PY_LIBS) 29 | 30 | 31 | clean: 32 | $(RM) *.a *.so *.o .*.d ctracecmd_wrap.* 33 | 34 | force: 35 | .PHONY: clean force 36 | -------------------------------------------------------------------------------- /python/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | want_python = get_option('python') 6 | if want_python != 'false' 7 | python3 = import('python').find_installation('python3') 8 | py3_dep = python3.dependency(required: want_python == 'true') 9 | swig = find_program('swig', required: want_python == 'true') 10 | header_found = cc.has_header('Python.h', dependencies: py3_dep) 11 | have_python_support = py3_dep.found() and swig.found() and header_found 12 | else 13 | have_python_support = false 14 | endif 15 | 16 | if have_python_support 17 | pymod_swig = custom_target( 18 | 'ctracecmd.py', 19 | input: ['ctracecmd.i'], 20 | output: ['ctracecmd.py', 'ctracecmd_wrap.c'], 21 | command: [ 22 | swig, 23 | '-python', 24 | '-I' + meson.current_source_dir() + '/../include/trace-cmd', 25 | '-I' + meson.current_source_dir() + '/../lib/trace-cmd/include/private', 26 | '-I' + libtraceevent_dep.get_pkgconfig_variable('prefix') + '/include/traceevent', 27 | '-o', '@OUTPUT1@', 28 | '@INPUT0@'], 29 | install: true, 30 | install_dir: [ python3.get_install_dir(pure: false, subdir: 'trace-cmd'), false]) 31 | 32 | incdir_py = include_directories(['.', '../include/trace-cmd', '../lib/trace-cmd/include/private']) 33 | 34 | pyctracecmd_clib = python3.extension_module( 35 | '_ctracecmd', 36 | pymod_swig[1], 37 | dependencies : [libtraceevent_dep, libtracefs_dep, py3_dep], 38 | include_directories: [incdir, incdir_py], 39 | install: true, 40 | subdir: 'trace-cmd') 41 | endif 42 | -------------------------------------------------------------------------------- /scripts/debug/tsync_hist.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright (C) 2019, VMware Inc, Tzvetomir Stoyanov 4 | # Copyright (C) 2019, VMware Inc, Yordan Karadzhov 5 | 6 | 7 | import matplotlib.pyplot as plt 8 | import matplotlib.lines as mlines 9 | import numpy as np 10 | import sys 11 | 12 | def newline(p1, p2): 13 | ax = plt.gca() 14 | xmin, xmax = ax.get_xbound() 15 | 16 | if(p2[0] == p1[0]): 17 | xmin = xmax = p1[0] 18 | ymin, ymax = ax.get_ybound() 19 | else: 20 | ymax = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmax-p1[0]) 21 | ymin = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmin-p1[0]) 22 | 23 | l = mlines.Line2D([xmin,xmax], [ymin,ymax], color='red') 24 | ax.add_line(l) 25 | return l 26 | 27 | 28 | data = np.loadtxt(fname = sys.argv[1]) 29 | selected_ts = data[-1, 1] 30 | selected_ofs = data[-1, 0] 31 | data = data[:-1,:] 32 | 33 | x = data[:, 1] - data[:, 0] 34 | 35 | mean = x.mean() 36 | std = x.std() 37 | 38 | num_bins = 500 39 | min = x.min() #+ .4 * (x.max() - x.min()) 40 | max = x.max() #- .4 * (x.max() - x.min()) 41 | bins = np.linspace(min, max, num_bins, endpoint = False, dtype=int) 42 | 43 | fig, ax = plt.subplots() 44 | 45 | # the histogram of the data 46 | n, bins, patches = ax.hist(x, bins, histtype=u'step'); 47 | 48 | ax.set_xlabel('clock offset [$\mu$s]') 49 | ax.set_ylabel('entries') 50 | ax.set_title("$\sigma$=%i" % std) 51 | 52 | x1, y1 = [selected_ofs, min], [selected_ofs, max] 53 | newline(x1, y1) 54 | 55 | # Tweak spacing to prevent clipping of ylabel 56 | fig.tight_layout() 57 | plt.show() 58 | -------------------------------------------------------------------------------- /scripts/debug/tsync_readme: -------------------------------------------------------------------------------- 1 | PTP-like algorithm debug 2 | ======================== 3 | 4 | tsync_*.py scripts can be used to visualise debug files, written when the PTP-like algorithm 5 | is compiled with TSYNC_DEBUG defined. The files are located in the guest machine: 6 | s-cid*.txt - For each offset calculation: host and guest clocks and calculated offset. 7 | res-cid*.txt - For each tracing session: all calculated clock offsets. 8 | 9 | tsync_hist.py plots a histogram, using data from a s-cid*.txt file: 10 | "python tsync_hist.py s-cid2_1.txt" 11 | tsync_res.py plots a line, using data from res-cid*.txt file: 12 | "python tsync_res.py res-cid2.txt" 13 | -------------------------------------------------------------------------------- /scripts/debug/tsync_res.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright (C) 2019, VMware Inc, Tzvetomir Stoyanov 4 | # Copyright (C) 2019, VMware Inc, Yordan Karadzhov 5 | 6 | 7 | import matplotlib.pyplot as plt 8 | import matplotlib.lines as mlines 9 | import numpy as np 10 | import sys 11 | 12 | def newline(p1, p2): 13 | ax = plt.gca() 14 | xmin, xmax = ax.get_xbound() 15 | 16 | if(p2[0] == p1[0]): 17 | xmin = xmax = p1[0] 18 | ymin, ymax = ax.get_ybound() 19 | else: 20 | ymax = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmax-p1[0]) 21 | ymin = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmin-p1[0]) 22 | 23 | l = mlines.Line2D([xmin,xmax], [ymin,ymax], color='red') 24 | ax.add_line(l) 25 | return l 26 | 27 | data = np.loadtxt(fname = sys.argv[1]) 28 | x = data[:, 0] 29 | y = data[:, 1] 30 | 31 | fig, ax = plt.subplots() 32 | 33 | ax.set_xlabel('samples (t)') 34 | ax.set_ylabel('clock offset') 35 | ax.set_title("$\delta$=%i ns" % (max(y) - min(y))) 36 | 37 | l = mlines.Line2D(x, y) 38 | ax.add_line(l) 39 | ax.set_xlim(min(x), max(x)) 40 | ax.set_ylim(min(y), max(y) ) 41 | 42 | print(min(y), max(y), max(y) - min(y)) 43 | 44 | # Tweak spacing to prevent clipping of ylabel 45 | fig.tight_layout() 46 | plt.show() 47 | -------------------------------------------------------------------------------- /tracecmd/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | VERSION := $(TC_VERSION) 4 | PATCHLEVEL := $(TC_PATCHLEVEL) 5 | EXTRAVERSION := $(TC_EXTRAVERSION) 6 | 7 | bdir:=$(obj)/tracecmd 8 | 9 | TC_VERSION := $(bdir)/include/tc_version.h 10 | TARGETS = $(bdir)/trace-cmd $(TC_VERSION) 11 | 12 | BUILDGUI := 0 13 | include $(src)/scripts/utils.mk 14 | 15 | CFLAGS += -I$(bdir)/include 16 | 17 | TRACE_CMD_OBJS = 18 | TRACE_CMD_OBJS += trace-cmd.o 19 | TRACE_CMD_OBJS += trace-record.o 20 | TRACE_CMD_OBJS += trace-read.o 21 | TRACE_CMD_OBJS += trace-split.o 22 | TRACE_CMD_OBJS += trace-listen.o 23 | TRACE_CMD_OBJS += trace-stack.o 24 | TRACE_CMD_OBJS += trace-hist.o 25 | TRACE_CMD_OBJS += trace-mem.o 26 | TRACE_CMD_OBJS += trace-snapshot.o 27 | TRACE_CMD_OBJS += trace-stat.o 28 | TRACE_CMD_OBJS += trace-profile.o 29 | TRACE_CMD_OBJS += trace-stream.o 30 | TRACE_CMD_OBJS += trace-record.o 31 | TRACE_CMD_OBJS += trace-restore.o 32 | TRACE_CMD_OBJS += trace-check-events.o 33 | TRACE_CMD_OBJS += trace-show.o 34 | TRACE_CMD_OBJS += trace-list.o 35 | TRACE_CMD_OBJS += trace-usage.o 36 | TRACE_CMD_OBJS += trace-dump.o 37 | TRACE_CMD_OBJS += trace-clear.o 38 | TRACE_CMD_OBJS += trace-vm.o 39 | TRACE_CMD_OBJS += trace-convert.o 40 | TRACE_CMD_OBJS += trace-attach.o 41 | TRACE_CMD_OBJS += trace-agent.o 42 | TRACE_CMD_OBJS += trace-tsync.o 43 | TRACE_CMD_OBJS += trace-setup-guest.o 44 | TRACE_CMD_OBJS += trace-sqlhist.o 45 | ifeq ($(VSOCK_DEFINED), 1) 46 | TRACE_CMD_OBJS += trace-vsock.o 47 | endif 48 | 49 | ALL_OBJS := $(TRACE_CMD_OBJS:%.o=$(bdir)/%.o) 50 | 51 | all_objs := $(sort $(ALL_OBJS)) 52 | all_deps := $(all_objs:$(bdir)/%.o=$(bdir)/.%.d) 53 | 54 | LPTHREAD ?= -lpthread 55 | LRT ?= -lrt 56 | 57 | CONFIG_INCLUDES = 58 | CONFIG_LIBS = $(LRT) $(LPTHREAD) $(TRACE_LIBS) $(ZLIB_LDLAGS) $(LIBZSTD_LDLAGS) 59 | CONFIG_FLAGS = 60 | 61 | all: $(TARGETS) 62 | 63 | $(bdir): 64 | @mkdir -p $(bdir) 65 | 66 | $(bdir)/include: | $(bdir) 67 | @mkdir -p $(bdir)/include 68 | 69 | $(TC_VERSION): force | $(bdir)/include 70 | $(Q)$(call update_version.h) 71 | 72 | $(all_deps): | $(bdir) 73 | $(all_objs): | $(bdir) 74 | 75 | $(bdir)/trace-cmd: $(ALL_OBJS) 76 | $(Q)$(do_app_build) 77 | 78 | $(bdir)/trace-cmd: $(LIBTRACECMD_STATIC) 79 | 80 | $(bdir)/%.o: %.c 81 | $(Q)$(call do_compile) 82 | 83 | $(all_deps): $(bdir)/.%.d: %.c 84 | $(Q)$(CC) -M -MT $(bdir)/$*.o $(CPPFLAGS) $(CFLAGS) $< > $@ 85 | 86 | $(all_deps): $(TC_VERSION) 87 | 88 | $(all_objs): $(bdir)/%.o : $(bdir)/.%.d 89 | 90 | dep_includes := $(wildcard $(DEPS)) 91 | 92 | ifneq ($(dep_includes),) 93 | include $(dep_includes) 94 | endif 95 | 96 | clean: 97 | $(RM) $(bdir)/*.a $(bdir)/*.so $(bdir)/*.o $(bdir)/.*.d $(TARGETS) 98 | 99 | force: 100 | .PHONY: clean 101 | -------------------------------------------------------------------------------- /tracecmd/include/bug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | #ifndef __TRACE_CMD_BUG 3 | #define __TRACE_CMD_BUG 4 | 5 | #define unlikely(cond) __builtin_expect(!!(cond), 0) 6 | 7 | #define WARN_ONCE(cond, fmt, ...) \ 8 | ({ \ 9 | int __c__ = cond; \ 10 | if (unlikely(__c__)) { \ 11 | warning(fmt, ##__VA_ARGS__); \ 12 | } \ 13 | __c__; \ 14 | }) 15 | #endif /* __TRACE_CMD_BUG */ 16 | -------------------------------------------------------------------------------- /tracecmd/include/list.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef __LIST_H 7 | #define __LIST_H 8 | 9 | #define offset_of(type, field) __builtin_offsetof(type, field) 10 | #define container_of(p, type, field) (type *)((long)p - offset_of(type, field)) 11 | 12 | struct list_head { 13 | struct list_head *next; 14 | struct list_head *prev; 15 | }; 16 | 17 | static inline void list_head_init(struct list_head *list) 18 | { 19 | list->next = list; 20 | list->prev = list; 21 | } 22 | 23 | static inline void list_add(struct list_head *p, struct list_head *head) 24 | { 25 | struct list_head *next = head->next; 26 | 27 | p->prev = head; 28 | p->next = next; 29 | next->prev = p; 30 | head->next = p; 31 | } 32 | 33 | static inline void list_add_tail(struct list_head *p, struct list_head *head) 34 | { 35 | struct list_head *prev = head->prev; 36 | 37 | p->prev = prev; 38 | p->next = head; 39 | prev->next = p; 40 | head->prev = p; 41 | } 42 | 43 | static inline void list_del(struct list_head *p) 44 | { 45 | struct list_head *next = p->next; 46 | struct list_head *prev = p->prev; 47 | 48 | next->prev = prev; 49 | prev->next = next; 50 | } 51 | 52 | static inline int list_empty(struct list_head *list) 53 | { 54 | return list->next == list; 55 | } 56 | 57 | #define list_for_each_entry(p, list, field) \ 58 | for (p = container_of((list)->next, typeof(*p), field); \ 59 | &(p)->field != list; \ 60 | p = container_of((p)->field.next, typeof(*p), field)) 61 | 62 | #define list_for_each_entry_safe(p, n, list, field) \ 63 | for (p = container_of((list)->next, typeof(*p), field), \ 64 | n = container_of((p)->field.next, typeof(*p), field); \ 65 | &(p)->field != list; \ 66 | p = n, n = container_of((p)->field.next, typeof(*p), field)) 67 | 68 | #endif /* __LIST_H */ 69 | -------------------------------------------------------------------------------- /tracecmd/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | sources = [ 6 | 'trace-agent.c', 7 | 'trace-attach.c', 8 | 'trace-check-events.c', 9 | 'trace-clear.c', 10 | 'trace-cmd.c', 11 | 'trace-convert.c', 12 | 'trace-dump.c', 13 | 'trace-hist.c', 14 | 'trace-list.c', 15 | 'trace-listen.c', 16 | 'trace-mem.c', 17 | 'trace-profile.c', 18 | 'trace-read.c', 19 | 'trace-record.c', 20 | 'trace-restore.c', 21 | 'trace-setup-guest.c', 22 | 'trace-show.c', 23 | 'trace-snapshot.c', 24 | 'trace-split.c', 25 | 'trace-stack.c', 26 | 'trace-stat.c', 27 | 'trace-stream.c', 28 | 'trace-tsync.c', 29 | 'trace-usage.c', 30 | 'trace-vm.c', 31 | 'trace-sqlhist.c', 32 | ] 33 | 34 | if vsock_defined 35 | sources += 'trace-vsock.c' 36 | endif 37 | 38 | trace_cmd_incdir = include_directories(['.', 'include']) 39 | 40 | executable( 41 | 'trace-cmd', 42 | sources, 43 | dependencies: [ 44 | libtraceevent_dep, 45 | libtracefs_dep, 46 | zlib_dep, 47 | libzstd_dep, 48 | audit_dep], 49 | include_directories: [ 50 | incdir, 51 | trace_cmd_incdir, 52 | libtracecmd_incdir, 53 | libtracecmd_private_incdir, 54 | libtracecmd_ext_incdir], 55 | link_with: [static_libtracecmd], 56 | install: true, 57 | install_dir: bindir) 58 | 59 | install_data( 60 | 'trace-cmd.bash', 61 | install_dir: datadir + '/bash-completion/completions') 62 | -------------------------------------------------------------------------------- /tracecmd/trace-check-events.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #include "tracefs.h" 11 | #include "trace-local.h" 12 | 13 | enum { 14 | OPT_verbose = 255, 15 | }; 16 | 17 | void trace_check_events(int argc, char **argv) 18 | { 19 | const char *tracing; 20 | int ret, c; 21 | int parsing_failures = 0; 22 | struct tep_handle *pevent = NULL; 23 | struct tep_plugin_list *list = NULL; 24 | int open_flags = 0; 25 | int option_index = 0; 26 | static struct option long_options[] = { 27 | {"verbose", optional_argument, NULL, OPT_verbose}, 28 | {NULL, 0, NULL, 0} 29 | }; 30 | 31 | 32 | while ((c = getopt_long(argc-1, argv+1, "+hN", long_options, &option_index)) >= 0) { 33 | switch (c) { 34 | case 'h': 35 | default: 36 | usage(argv); 37 | break; 38 | case 'N': 39 | open_flags |= TRACECMD_FL_LOAD_NO_PLUGINS; 40 | break; 41 | case OPT_verbose: 42 | if (trace_set_verbose(optarg) < 0) 43 | die("invalid verbose level %s", optarg); 44 | break; 45 | } 46 | } 47 | tracing = tracefs_tracing_dir(); 48 | 49 | if (!tracing) { 50 | printf("Can not find or mount tracing directory!\n" 51 | "Either tracing is not configured for this " 52 | "kernel\n" 53 | "or you do not have the proper permissions to " 54 | "mount the directory"); 55 | exit(EINVAL); 56 | } 57 | 58 | pevent = tep_alloc(); 59 | if (!pevent) 60 | exit(EINVAL); 61 | 62 | list = tcmd_load_plugins(pevent, open_flags); 63 | ret = tracefs_fill_local_events(tracing, pevent, &parsing_failures); 64 | if (ret || parsing_failures) 65 | ret = EINVAL; 66 | tep_unload_plugins(list, pevent); 67 | tep_free(pevent); 68 | 69 | return; 70 | } 71 | -------------------------------------------------------------------------------- /tracecmd/trace-clear.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | * Updates: 6 | * Copyright (C) 2020, VMware, Tzvetomir Stoyanov 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | #include "tracefs.h" 14 | #include "trace-local.h" 15 | 16 | struct instances_list { 17 | struct instances_list *next; 18 | struct tracefs_instance *instance; 19 | }; 20 | 21 | static int add_new_instance(struct instances_list **list, char *name) 22 | { 23 | struct instances_list *new; 24 | 25 | if (!tracefs_instance_exists(name)) 26 | return -1; 27 | new = calloc(1, sizeof(*new)); 28 | if (!new) 29 | return -1; 30 | new->instance = tracefs_instance_create(name); 31 | if (!new->instance) { 32 | free(new); 33 | return -1; 34 | } 35 | 36 | new->next = *list; 37 | *list = new; 38 | return 0; 39 | } 40 | 41 | static int add_instance_walk(const char *name, void *data) 42 | { 43 | return add_new_instance((struct instances_list **)data, (char *)name); 44 | } 45 | 46 | static void clear_list(struct instances_list *list) 47 | { 48 | struct instances_list *del; 49 | 50 | while (list) { 51 | del = list; 52 | list = list->next; 53 | tracefs_instance_free(del->instance); 54 | free(del); 55 | } 56 | } 57 | 58 | static void clear_instance_trace(struct tracefs_instance *instance) 59 | { 60 | FILE *fp; 61 | char *path; 62 | 63 | /* reset the trace */ 64 | path = tracefs_instance_get_file(instance, "trace"); 65 | fp = fopen(path, "w"); 66 | if (!fp) 67 | die("writing to '%s'", path); 68 | tracefs_put_tracing_file(path); 69 | fwrite("0", 1, 1, fp); 70 | fclose(fp); 71 | } 72 | 73 | static void clear_trace(struct instances_list *instances) 74 | { 75 | if (instances) { 76 | while (instances) { 77 | clear_instance_trace(instances->instance); 78 | instances = instances->next; 79 | } 80 | } else 81 | clear_instance_trace(NULL); 82 | } 83 | 84 | void trace_clear(int argc, char **argv) 85 | { 86 | struct instances_list *instances = NULL; 87 | bool all = false; 88 | int c; 89 | 90 | for (;;) { 91 | int option_index = 0; 92 | static struct option long_options[] = { 93 | {"all", no_argument, NULL, 'a'}, 94 | {"help", no_argument, NULL, '?'}, 95 | {NULL, 0, NULL, 0} 96 | }; 97 | 98 | c = getopt_long (argc-1, argv+1, "+haB:", 99 | long_options, &option_index); 100 | if (c == -1) 101 | break; 102 | switch (c) { 103 | case 'B': 104 | if (add_new_instance(&instances, optarg)) 105 | die("Failed to allocate instance %s", optarg); 106 | break; 107 | case 'a': 108 | all = true; 109 | if (tracefs_instances_walk(add_instance_walk, &instances)) 110 | die("Failed to add all instances"); 111 | break; 112 | case 'h': 113 | case '?': 114 | default: 115 | usage(argv); 116 | break; 117 | } 118 | } 119 | 120 | clear_trace(instances); 121 | if (all) 122 | clear_trace(NULL); 123 | clear_list(instances); 124 | exit(0); 125 | } 126 | -------------------------------------------------------------------------------- /tracecmd/trace-cmd.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "trace-local.h" 16 | 17 | int silence_warnings; 18 | int show_status; 19 | 20 | #ifndef gettid 21 | #define gettid() syscall(__NR_gettid) 22 | #endif 23 | 24 | void warning(const char *fmt, ...) 25 | { 26 | va_list ap; 27 | 28 | if (silence_warnings) 29 | return; 30 | 31 | if (errno) 32 | perror("trace-cmd"); 33 | errno = 0; 34 | 35 | va_start(ap, fmt); 36 | fprintf(stderr, " "); 37 | vfprintf(stderr, fmt, ap); 38 | va_end(ap); 39 | 40 | fprintf(stderr, "\n"); 41 | } 42 | 43 | void *malloc_or_die(unsigned int size) 44 | { 45 | void *data; 46 | 47 | data = malloc(size); 48 | if (!data) 49 | die("malloc"); 50 | return data; 51 | } 52 | 53 | /* Same as strtok_r(), but allows empty tokens */ 54 | char *strparse(char *str, char delim, char **save) 55 | { 56 | char *next; 57 | 58 | if (!str) { 59 | str = *save; 60 | if ((*save)[0] == '\0') 61 | return NULL; 62 | } 63 | 64 | next = strchr(str, delim); 65 | if (next) { 66 | *next = '\0'; 67 | *save = next + 1; 68 | } else { 69 | *save = str + strlen(str); 70 | } 71 | return str; 72 | } 73 | 74 | void tracecmd_debug(const char *fmt, ...) 75 | { 76 | va_list ap; 77 | 78 | if (!tracecmd_get_debug()) 79 | return; 80 | 81 | va_start(ap, fmt); 82 | printf("[%d] ", (int)gettid()); 83 | vprintf(fmt, ap); 84 | va_end(ap); 85 | } 86 | 87 | static struct trace_log_severity { 88 | int id; 89 | const char *name; 90 | } log_severity[] = { 91 | { .id = TEP_LOG_NONE, .name = "none" }, 92 | { .id = TEP_LOG_CRITICAL, .name = "crit" }, 93 | { .id = TEP_LOG_ERROR, .name = "err" }, 94 | { .id = TEP_LOG_WARNING, .name = "warn" }, 95 | { .id = TEP_LOG_INFO, .name = "info" }, 96 | { .id = TEP_LOG_DEBUG, .name = "debug" }, 97 | { .id = TEP_LOG_ALL, .name = "all" }, 98 | }; 99 | 100 | void trace_set_loglevel(int level) 101 | { 102 | tracecmd_set_loglevel(level); 103 | tracefs_set_loglevel(level); 104 | tep_set_loglevel(level); 105 | } 106 | 107 | int trace_set_verbose(char *level) 108 | { 109 | int id; 110 | 111 | /* Default level is info */ 112 | if (!level) 113 | level = "info"; 114 | 115 | if (isdigit(level[0])) { 116 | id = atoi(level); 117 | if (id >= TEP_LOG_NONE) { 118 | if (id > TEP_LOG_ALL) 119 | id = TEP_LOG_ALL; 120 | trace_set_loglevel(id); 121 | return 0; 122 | } 123 | } else { 124 | int size = ARRAY_SIZE(log_severity); 125 | int i; 126 | 127 | for (i = 0; i < size; i++) { 128 | if (!strncmp(level, log_severity[i].name, strlen(log_severity[i].name))) { 129 | trace_set_loglevel(log_severity[i].id); 130 | return 0; 131 | } 132 | } 133 | } 134 | 135 | return -1; 136 | } 137 | 138 | /** 139 | * struct command 140 | * @name command name 141 | * @run function to execute on command `name` 142 | */ 143 | struct command { 144 | char *name; 145 | void (*run)(int argc, char **argv); 146 | }; 147 | 148 | 149 | /** 150 | * Lookup table that maps command names to functions 151 | */ 152 | struct command commands[] = { 153 | {"report", trace_report}, 154 | {"snapshot", trace_snapshot}, 155 | {"hist", trace_hist}, 156 | {"mem", trace_mem}, 157 | {"listen", trace_listen}, 158 | {"agent", trace_agent}, 159 | {"setup-guest", trace_setup_guest}, 160 | {"split", trace_split}, 161 | {"restore", trace_restore}, 162 | {"stack", trace_stack}, 163 | {"check-events", trace_check_events}, 164 | {"record", trace_record}, 165 | {"start", trace_start}, 166 | {"set", trace_set}, 167 | {"extract", trace_extract}, 168 | {"stop", trace_stop}, 169 | {"stream", trace_stream}, 170 | {"profile", trace_profile}, 171 | {"restart", trace_restart}, 172 | {"clear", trace_clear}, 173 | {"reset", trace_reset}, 174 | {"stat", trace_stat}, 175 | {"options", trace_option}, 176 | {"show", trace_show}, 177 | {"list", trace_list}, 178 | {"help", trace_usage}, 179 | {"dump", trace_dump}, 180 | {"attach", trace_attach}, 181 | {"convert", trace_convert}, 182 | {"sqlhist", trace_sqlhist}, 183 | {"-h", trace_usage}, 184 | }; 185 | 186 | int main (int argc, char **argv) 187 | { 188 | int i; 189 | 190 | errno = 0; 191 | 192 | if (argc < 2) 193 | trace_usage(argc, argv); 194 | 195 | for (i = 0; i < ARRAY_SIZE(commands); ++i) { 196 | if (strcmp(argv[1], commands[i].name) == 0 ){ 197 | commands[i].run(argc, argv); 198 | goto out; 199 | } 200 | } 201 | 202 | /* No valid command found, show help */ 203 | trace_usage(argc, argv); 204 | out: 205 | exit(0); 206 | } 207 | -------------------------------------------------------------------------------- /tracecmd/trace-convert.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2021, VMware, Tzvetomir Stoyanov 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "trace-local.h" 12 | #include "trace-cmd.h" 13 | #include "trace-cmd-private.h" 14 | 15 | static void convert_file(const char *in, const char *out, int file_version, char *compr) 16 | { 17 | struct tracecmd_input *ihandle; 18 | struct tracecmd_output *ohandle; 19 | 20 | ihandle = tracecmd_open_head(in, 0); 21 | if (!ihandle) 22 | die("error reading %s", in); 23 | 24 | ohandle = tracecmd_copy(ihandle, out, TRACECMD_FILE_CPU_FLYRECORD, file_version, compr); 25 | if (!ohandle) 26 | die("error writing %s", out); 27 | 28 | tracecmd_output_close(ohandle); 29 | tracecmd_close(ihandle); 30 | } 31 | 32 | enum { 33 | OPT_file_version = 254, 34 | OPT_compression = 255, 35 | }; 36 | 37 | void trace_convert(int argc, char **argv) 38 | { 39 | char *input_file = NULL; 40 | char *output_file = NULL; 41 | char *compression = NULL; 42 | int file_version = tracecmd_default_file_version(); 43 | int c; 44 | 45 | if (argc < 2) 46 | usage(argv); 47 | 48 | if (strcmp(argv[1], "convert") != 0) 49 | usage(argv); 50 | 51 | for (;;) { 52 | int option_index = 0; 53 | static struct option long_options[] = { 54 | {"compression", required_argument, NULL, OPT_compression}, 55 | {"file-version", required_argument, NULL, OPT_file_version}, 56 | {"help", no_argument, NULL, '?'}, 57 | {NULL, 0, NULL, 0} 58 | }; 59 | 60 | c = getopt_long (argc-1, argv+1, "+hi:o:", long_options, &option_index); 61 | if (c == -1) 62 | break; 63 | switch (c) { 64 | case 'i': 65 | if (input_file) 66 | die("Only one input file is supported, %s already set", 67 | input_file); 68 | input_file = optarg; 69 | break; 70 | case 'o': 71 | if (output_file) 72 | die("Only one output file is supported, %s already set", 73 | output_file); 74 | output_file = optarg; 75 | break; 76 | case OPT_compression: 77 | if (strcmp(optarg, "any") && strcmp(optarg, "none") && 78 | !tracecmd_compress_is_supported(optarg, NULL)) 79 | die("Compression algorithm %s is not supported", optarg); 80 | compression = optarg; 81 | break; 82 | case OPT_file_version: 83 | file_version = atoi(optarg); 84 | if (file_version < FILE_VERSION_MIN || file_version > FILE_VERSION_MAX) 85 | die("Unsupported file version %d, " 86 | "supported versions are from %d to %d", 87 | file_version, FILE_VERSION_MIN, FILE_VERSION_MAX); 88 | 89 | break; 90 | case 'h': 91 | case '?': 92 | default: 93 | usage(argv); 94 | } 95 | } 96 | 97 | if ((argc - optind) >= 2) { 98 | if (output_file) 99 | usage(argv); 100 | output_file = argv[optind + 1]; 101 | } 102 | 103 | if (!input_file) 104 | input_file = DEFAULT_INPUT_FILE; 105 | if (!output_file) 106 | usage(argv); 107 | if (file_version >= FILE_VERSION_COMPRESSION && !compression) 108 | compression = "any"; 109 | 110 | convert_file(input_file, output_file, file_version, compression); 111 | } 112 | -------------------------------------------------------------------------------- /tracecmd/trace-restore.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "trace-local.h" 23 | 24 | static struct tracecmd_output *create_output(const char *file, 25 | const char *tracing_dir, const char *kallsyms) 26 | { 27 | struct tracecmd_output *out; 28 | 29 | out = tracecmd_output_create(file); 30 | if (!out) 31 | goto error; 32 | 33 | if (tracing_dir && tracecmd_output_set_trace_dir(out, tracing_dir)) 34 | goto error; 35 | if (kallsyms && tracecmd_output_set_kallsyms(out, kallsyms)) 36 | goto error; 37 | if (tracecmd_output_write_headers(out, NULL)) 38 | goto error; 39 | return out; 40 | error: 41 | if (out) 42 | tracecmd_output_close(out); 43 | unlink(file); 44 | return NULL; 45 | } 46 | 47 | void trace_restore (int argc, char **argv) 48 | { 49 | struct tracecmd_output *handle; 50 | const char *output_file = DEFAULT_INPUT_FILE; 51 | const char *output = NULL; 52 | const char *input = NULL; 53 | const char *tracing_dir = NULL; 54 | const char *kallsyms = NULL; 55 | struct stat st1; 56 | struct stat st2; 57 | int first_arg; 58 | int create_only = 0; 59 | int args; 60 | int c; 61 | 62 | if (argc < 2) 63 | usage(argv); 64 | 65 | if (strcmp(argv[1], "restore") != 0) 66 | usage(argv); 67 | 68 | while ((c = getopt(argc-1, argv+1, "+hco:i:t:k:")) >= 0) { 69 | switch (c) { 70 | case 'h': 71 | usage(argv); 72 | break; 73 | case 'c': 74 | if (input) 75 | die("-c and -i are incompatible"); 76 | create_only = 1; 77 | /* make output default to partial */ 78 | output_file = "trace-partial.dat"; 79 | break; 80 | 81 | case 't': 82 | tracing_dir = optarg; 83 | break; 84 | case 'k': 85 | kallsyms = optarg; 86 | break; 87 | case 'o': 88 | if (output) 89 | die("only one output file allowed"); 90 | output = optarg; 91 | break; 92 | 93 | case 'i': 94 | if (input) 95 | die("only one input file allowed"); 96 | if (create_only) 97 | die("-c and -i are incompatible"); 98 | input = optarg; 99 | break; 100 | 101 | default: 102 | usage(argv); 103 | } 104 | } 105 | 106 | if (!output) 107 | output = output_file; 108 | 109 | if ((argc - optind) <= 1) { 110 | if (!create_only) { 111 | warning("No data files found"); 112 | usage(argv); 113 | } 114 | 115 | handle = create_output(output, tracing_dir, kallsyms); 116 | if (!handle) 117 | die("Unabled to create output file %s", output); 118 | if (tracecmd_write_cmdlines(handle) < 0) 119 | die("Failed to write command lines"); 120 | tracecmd_output_close(handle); 121 | exit(0); 122 | } 123 | first_arg = optind + 1; 124 | args = argc - first_arg; 125 | printf("first = %d %s args=%d\n", first_arg, argv[first_arg], args); 126 | 127 | /* Make sure input and output are not the same file */ 128 | if (input && output) { 129 | if (stat(input, &st1) < 0) 130 | die("%s:", input); 131 | /* output exists? otherwise we don't care */ 132 | if (stat(output, &st2) == 0) { 133 | if (st1.st_ino == st2.st_ino && 134 | st1.st_dev == st2.st_dev) 135 | die("input and output file are the same"); 136 | } 137 | } 138 | 139 | if (input) { 140 | struct tracecmd_input *ihandle; 141 | 142 | ihandle = tracecmd_alloc(input, 0); 143 | if (!ihandle) 144 | die("error reading file %s", input); 145 | /* make sure headers are ok */ 146 | if (tracecmd_read_headers(ihandle, TRACECMD_FILE_CMD_LINES) < 0) 147 | die("error reading file %s headers", input); 148 | 149 | handle = tracecmd_copy(ihandle, output, TRACECMD_FILE_CMD_LINES, 0, NULL); 150 | tracecmd_close(ihandle); 151 | } else { 152 | handle = tracecmd_output_create(output); 153 | tracecmd_output_write_headers(handle, NULL); 154 | } 155 | 156 | if (!handle) 157 | die("error writing to %s", output); 158 | 159 | if (tracecmd_append_cpu_data(handle, args, &argv[first_arg]) < 0) 160 | die("failed to append data"); 161 | 162 | return; 163 | } 164 | -------------------------------------------------------------------------------- /tracecmd/trace-snapshot.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2013 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "tracefs.h" 16 | #include "trace-local.h" 17 | 18 | static void write_file(const char *name, char *val) 19 | { 20 | char *path; 21 | int fd; 22 | ssize_t n; 23 | 24 | path = tracefs_get_tracing_file(name); 25 | fd = open(path, O_WRONLY); 26 | if (fd < 0) 27 | die("writing %s", path); 28 | 29 | n = write(fd, val, strlen(val)); 30 | if (n < 0) 31 | die("failed to write to %s\n", path); 32 | 33 | tracefs_put_tracing_file(path); 34 | close(fd); 35 | } 36 | 37 | void trace_snapshot (int argc, char **argv) 38 | { 39 | const char *buffer = NULL; 40 | const char *file = "snapshot"; 41 | struct stat st; 42 | char *name; 43 | char cpu_path[128]; 44 | int take_snap = 0; 45 | int reset_snap = 0; 46 | int free_snap = 0; 47 | int cpu = -1; 48 | int ret; 49 | int c; 50 | 51 | if (argc < 2) 52 | usage(argv); 53 | 54 | if (strcmp(argv[1], "snapshot") != 0) 55 | usage(argv); 56 | 57 | while ((c = getopt(argc-1, argv+1, "srfB:c:")) >= 0) { 58 | switch (c) { 59 | case 'h': 60 | usage(argv); 61 | break; 62 | case 's': 63 | take_snap = 1; 64 | if (free_snap) 65 | die("can't take snapshot and free it at the same time"); 66 | break; 67 | case 'f': 68 | free_snap = 1; 69 | if (take_snap) 70 | die("can't take snapshot and free it at the same time"); 71 | break; 72 | case 'r': 73 | reset_snap = 1; 74 | break; 75 | case 'B': 76 | if (buffer) 77 | die("Can only do one buffer at a time"); 78 | buffer = optarg; 79 | break; 80 | case 'c': 81 | if (cpu >= 0) 82 | die("Can only do one CPU (or all) at a time"); 83 | cpu = atoi(optarg); 84 | break; 85 | default: 86 | usage(argv); 87 | } 88 | } 89 | 90 | if (cpu >= 0) { 91 | snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", cpu, file); 92 | file = cpu_path; 93 | } 94 | 95 | name = tracefs_get_tracing_file(file); 96 | ret = stat(name, &st); 97 | if (ret < 0) 98 | die("Snapshot feature is not supported by this kernel"); 99 | tracefs_put_tracing_file(name); 100 | 101 | if (!reset_snap && !take_snap && !free_snap) { 102 | show_file(file); 103 | exit(0); 104 | } 105 | 106 | if (reset_snap) 107 | write_file(file, "2"); 108 | 109 | if (free_snap) 110 | write_file(file, "0"); 111 | 112 | if (take_snap) 113 | write_file(file, "1"); 114 | } 115 | -------------------------------------------------------------------------------- /tracecmd/trace-stack.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "tracefs.h" 19 | #include "trace-local.h" 20 | 21 | #define PROC_FILE "/proc/sys/kernel/stack_tracer_enabled" 22 | 23 | enum stack_type { 24 | STACK_START, 25 | STACK_STOP, 26 | STACK_RESET, 27 | STACK_REPORT 28 | }; 29 | 30 | static void test_available(void) 31 | { 32 | struct stat buf; 33 | int fd; 34 | 35 | fd = stat(PROC_FILE, &buf); 36 | if (fd < 0) 37 | die("stack tracer not configured on running kernel"); 38 | } 39 | 40 | /* NOTE: this implementation only accepts new_status in the range [0..9]. */ 41 | static void change_stack_tracer_status(unsigned new_status) 42 | { 43 | char buf[1]; 44 | int status; 45 | int ret; 46 | int fd; 47 | int n; 48 | 49 | if (new_status > 9) { 50 | warning("invalid status %d\n", new_status); 51 | return; 52 | } 53 | 54 | ret = tracecmd_stack_tracer_status(&status); 55 | if (ret < 0) 56 | die("error reading %s", PROC_FILE); 57 | 58 | if (ret > 0 && status == new_status) 59 | return; /* nothing to do */ 60 | 61 | fd = open(PROC_FILE, O_WRONLY); 62 | if (fd < 0) 63 | die("writing %s", PROC_FILE); 64 | 65 | buf[0] = new_status + '0'; 66 | 67 | n = write(fd, buf, 1); 68 | if (n < 0) 69 | die("writing into %s", PROC_FILE); 70 | close(fd); 71 | } 72 | 73 | static void start_trace(void) 74 | { 75 | change_stack_tracer_status(1); 76 | } 77 | 78 | static void stop_trace(void) 79 | { 80 | change_stack_tracer_status(0); 81 | } 82 | 83 | static void reset_trace(void) 84 | { 85 | char *path; 86 | char buf[1]; 87 | int fd; 88 | int n; 89 | 90 | path = tracefs_get_tracing_file("stack_max_size"); 91 | fd = open(path, O_WRONLY); 92 | if (fd < 0) 93 | die("writing %s", path); 94 | 95 | buf[0] = '0'; 96 | n = write(fd, buf, 1); 97 | if (n < 0) 98 | die("writing into %s", path); 99 | tracefs_put_tracing_file(path); 100 | close(fd); 101 | } 102 | 103 | static void read_trace(void) 104 | { 105 | char *buf = NULL; 106 | int status; 107 | char *path; 108 | FILE *fp; 109 | size_t n; 110 | int r; 111 | 112 | if (tracecmd_stack_tracer_status(&status) <= 0) 113 | die("Invalid stack tracer state"); 114 | 115 | if (status > 0) 116 | printf("(stack tracer running)\n"); 117 | else 118 | printf("(stack tracer not running)\n"); 119 | 120 | path = tracefs_get_tracing_file("stack_trace"); 121 | fp = fopen(path, "r"); 122 | if (!fp) 123 | die("reading to '%s'", path); 124 | tracefs_put_tracing_file(path); 125 | 126 | while ((r = getline(&buf, &n, fp)) >= 0) { 127 | /* 128 | * Skip any line that starts with a '#'. 129 | * Those talk about how to enable stack tracing 130 | * within the debugfs system. We don't care about that. 131 | */ 132 | if (buf[0] != '#') 133 | printf("%s", buf); 134 | 135 | free(buf); 136 | buf = NULL; 137 | } 138 | 139 | fclose(fp); 140 | } 141 | 142 | enum { 143 | OPT_verbose = 252, 144 | OPT_reset = 253, 145 | OPT_stop = 254, 146 | OPT_start = 255, 147 | }; 148 | 149 | void trace_stack (int argc, char **argv) 150 | { 151 | enum stack_type trace_type = STACK_REPORT; 152 | int c; 153 | 154 | if (argc < 2) 155 | usage(argv); 156 | 157 | if (strcmp(argv[1], "stack") != 0) 158 | usage(argv); 159 | 160 | for (;;) { 161 | int option_index = 0; 162 | static struct option long_options[] = { 163 | {"start", no_argument, NULL, OPT_start}, 164 | {"stop", no_argument, NULL, OPT_stop}, 165 | {"reset", no_argument, NULL, OPT_reset}, 166 | {"help", no_argument, NULL, '?'}, 167 | {"verbose", optional_argument, NULL, OPT_verbose}, 168 | {NULL, 0, NULL, 0} 169 | }; 170 | 171 | c = getopt_long (argc-1, argv+1, "+h?", 172 | long_options, &option_index); 173 | if (c == -1) 174 | break; 175 | 176 | switch (c) { 177 | case 'h': 178 | usage(argv); 179 | break; 180 | case OPT_start: 181 | trace_type = STACK_START; 182 | break; 183 | case OPT_stop: 184 | trace_type = STACK_STOP; 185 | break; 186 | case OPT_reset: 187 | trace_type = STACK_RESET; 188 | break; 189 | case OPT_verbose: 190 | if (trace_set_verbose(optarg) < 0) 191 | die("invalid verbose level %s", optarg); 192 | break; 193 | default: 194 | usage(argv); 195 | } 196 | } 197 | 198 | test_available(); 199 | 200 | switch (trace_type) { 201 | case STACK_START: 202 | start_trace(); 203 | break; 204 | case STACK_STOP: 205 | stop_trace(); 206 | break; 207 | case STACK_RESET: 208 | reset_trace(); 209 | break; 210 | default: 211 | read_trace(); 212 | break; 213 | } 214 | 215 | return; 216 | } 217 | -------------------------------------------------------------------------------- /tracecmd/trace-stream.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2014 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include "trace-local.h" 16 | 17 | /* 18 | * Stream runs for a single machine. We are going to cheat 19 | * and use the trace-output and trace-input code to create 20 | * our pevent. First just create a trace.dat file and then read 21 | * it to create the pevent and handle. 22 | */ 23 | struct tracecmd_input * 24 | trace_stream_init(struct buffer_instance *instance, int cpu, int fd, int cpus, 25 | struct hook_list *hooks, 26 | tracecmd_handle_init_func handle_init, int global) 27 | { 28 | struct tracecmd_output *trace_output; 29 | struct tracecmd_input *trace_input; 30 | static FILE *fp = NULL; 31 | static int tfd; 32 | long flags; 33 | 34 | if (instance->handle) { 35 | trace_input = instance->handle; 36 | goto make_pipe; 37 | } 38 | 39 | if (!fp) { 40 | fp = tmpfile(); 41 | if (!fp) 42 | return NULL; 43 | tfd = fileno(fp); 44 | 45 | trace_output = tracecmd_output_create_fd(tfd); 46 | if (!trace_output) 47 | goto fail; 48 | 49 | tracecmd_output_write_headers(trace_output, NULL); 50 | tracecmd_output_flush(trace_output); 51 | /* Don't close the descriptor, use it for reading */ 52 | tracecmd_output_free(trace_output); 53 | } 54 | 55 | lseek(tfd, 0, SEEK_SET); 56 | 57 | trace_input = tracecmd_alloc_fd(tfd, 0); 58 | if (!trace_input) 59 | goto fail; 60 | 61 | if (tracecmd_read_headers(trace_input, TRACECMD_FILE_PRINTK) < 0) 62 | goto fail_free_input; 63 | 64 | if (handle_init) 65 | handle_init(trace_input, hooks, global); 66 | 67 | make_pipe: 68 | /* Do not block on this pipe */ 69 | flags = fcntl(fd, F_GETFL); 70 | fcntl(fd, F_SETFL, flags | O_NONBLOCK); 71 | 72 | if (tracecmd_make_pipe(trace_input, cpu, fd, cpus) < 0) 73 | goto fail_free_input; 74 | 75 | instance->handle = trace_input; 76 | 77 | return trace_input; 78 | 79 | fail_free_input: 80 | tracecmd_close(trace_input); 81 | fail: 82 | fclose(fp); 83 | fp = NULL; /* Try again later? */ 84 | return NULL; 85 | } 86 | 87 | int trace_stream_read(struct pid_record_data *pids, int nr_pids, long sleep_us) 88 | { 89 | struct pid_record_data *last_pid; 90 | struct pid_record_data *pid; 91 | struct tep_record *record; 92 | struct pollfd pollfd[nr_pids]; 93 | long sleep_ms = sleep_us > 0 ? (sleep_us + 999) / 1000 : sleep_us; 94 | int ret; 95 | int i; 96 | 97 | if (!nr_pids) 98 | return 0; 99 | 100 | last_pid = NULL; 101 | 102 | again: 103 | for (i = 0; i < nr_pids; i++) { 104 | pid = &pids[i]; 105 | 106 | if (!pid->record) 107 | pid->record = tracecmd_read_data(pid->instance->handle, pid->cpu); 108 | record = pid->record; 109 | if (!record && errno == EINVAL) 110 | /* pipe has closed */ 111 | pid->closed = 1; 112 | 113 | if (record && 114 | (!last_pid || record->ts < last_pid->record->ts)) 115 | last_pid = pid; 116 | } 117 | if (last_pid) { 118 | trace_show_data(last_pid->instance->handle, last_pid->record); 119 | tracecmd_free_record(last_pid->record); 120 | last_pid->record = NULL; 121 | return 1; 122 | } 123 | 124 | for (i = 0; i < nr_pids; i++) { 125 | /* Do not process closed pipes */ 126 | if (pids[i].closed) { 127 | memset(pollfd + i, 0, sizeof(*pollfd)); 128 | continue; 129 | } 130 | 131 | pollfd[i].fd = pids[i].brass[0]; 132 | pollfd[i].events = POLLIN; 133 | } 134 | 135 | ret = poll(pollfd, nr_pids, sleep_ms); 136 | if (ret > 0) 137 | goto again; 138 | 139 | return ret; 140 | } 141 | -------------------------------------------------------------------------------- /tracecmd/trace-vsock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "trace-cmd-private.h" 8 | 9 | int __hidden tcmd_vsock_open(unsigned int cid, unsigned int port) 10 | { 11 | struct sockaddr_vm addr = { 12 | .svm_family = AF_VSOCK, 13 | .svm_cid = cid, 14 | .svm_port = port, 15 | }; 16 | int sd; 17 | 18 | sd = socket(AF_VSOCK, SOCK_STREAM, 0); 19 | if (sd < 0) 20 | return -errno; 21 | 22 | if (connect(sd, (struct sockaddr *)&addr, sizeof(addr))) { 23 | close(sd); 24 | return -errno; 25 | } 26 | 27 | return sd; 28 | } 29 | 30 | int __hidden tcmd_vsock_make(unsigned int port) 31 | { 32 | struct sockaddr_vm addr = { 33 | .svm_family = AF_VSOCK, 34 | .svm_cid = VMADDR_CID_ANY, 35 | .svm_port = port, 36 | }; 37 | int sd; 38 | 39 | sd = socket(AF_VSOCK, SOCK_STREAM, 0); 40 | if (sd < 0) 41 | return -errno; 42 | 43 | setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); 44 | 45 | if (bind(sd, (struct sockaddr *)&addr, sizeof(addr))) 46 | goto error; 47 | 48 | if (listen(sd, SOMAXCONN)) 49 | goto error; 50 | 51 | return sd; 52 | 53 | error: 54 | close(sd); 55 | return -errno; 56 | } 57 | 58 | int __hidden tcmd_vsock_make_any(void) 59 | { 60 | return tcmd_vsock_make(VMADDR_PORT_ANY); 61 | } 62 | 63 | int __hidden tcmd_vsock_get_port(int sd, unsigned int *port) 64 | { 65 | struct sockaddr_vm addr; 66 | socklen_t addr_len = sizeof(addr); 67 | 68 | if (getsockname(sd, (struct sockaddr *)&addr, &addr_len)) 69 | return -errno; 70 | 71 | if (addr.svm_family != AF_VSOCK) 72 | return -EINVAL; 73 | 74 | if (port) 75 | *port = addr.svm_port; 76 | 77 | return 0; 78 | } 79 | 80 | int get_vsocket_params(int fd, unsigned int *lcid, unsigned int *rcid) 81 | { 82 | struct sockaddr_vm addr; 83 | socklen_t addr_len = sizeof(addr); 84 | 85 | if (lcid) { 86 | memset(&addr, 0, sizeof(addr)); 87 | if (getsockname(fd, (struct sockaddr *)&addr, &addr_len)) 88 | return -1; 89 | if (addr.svm_family != AF_VSOCK) 90 | return -1; 91 | *lcid = addr.svm_cid; 92 | } 93 | 94 | if (rcid) { 95 | memset(&addr, 0, sizeof(addr)); 96 | addr_len = sizeof(addr); 97 | if (getpeername(fd, (struct sockaddr *)&addr, &addr_len)) 98 | return -1; 99 | if (addr.svm_family != AF_VSOCK) 100 | return -1; 101 | *rcid = addr.svm_cid; 102 | } 103 | 104 | return 0; 105 | } 106 | 107 | int trace_vsock_print_connection(int fd) 108 | { 109 | struct sockaddr_vm vm_addr; 110 | socklen_t addr_len; 111 | int cid, port; 112 | 113 | addr_len = sizeof(vm_addr); 114 | if (getpeername(fd, (struct sockaddr *)&vm_addr, &addr_len)) 115 | return -1; 116 | if (vm_addr.svm_family != AF_VSOCK) 117 | return -1; 118 | cid = vm_addr.svm_cid; 119 | port = vm_addr.svm_port; 120 | if (tracecmd_get_debug()) 121 | tracecmd_debug("Connected to @%u:%u fd:%d\n", cid, port, fd); 122 | else 123 | tracecmd_plog("Connected to @%u:%u\n", cid, port); 124 | return 0; 125 | } 126 | 127 | static int try_splice_read_vsock(void) 128 | { 129 | int ret, sd, brass[2]; 130 | 131 | sd = socket(AF_VSOCK, SOCK_STREAM, 0); 132 | if (sd < 0) 133 | return -errno; 134 | 135 | ret = pipe(brass); 136 | if (ret < 0) 137 | goto out_close_sd; 138 | 139 | /* 140 | * On kernels that don't support splice reading from vsockets 141 | * this will fail with EINVAL, or ENOTCONN otherwise. 142 | * Technically, it should never succeed but if it does, claim splice 143 | * reading is supported. 144 | */ 145 | ret = splice(sd, NULL, brass[1], NULL, 10, 0); 146 | if (ret < 0) 147 | ret = errno != EINVAL; 148 | else 149 | ret = 1; 150 | 151 | close(brass[0]); 152 | close(brass[1]); 153 | out_close_sd: 154 | close(sd); 155 | return ret; 156 | } 157 | 158 | bool __hidden tcmd_vsock_can_splice_read(void) 159 | { 160 | static bool initialized, res; 161 | 162 | if (initialized) 163 | return res; 164 | 165 | res = try_splice_read_vsock() > 0; 166 | initialized = true; 167 | return res; 168 | } 169 | 170 | #define GET_LOCAL_CID 0x7b9 171 | 172 | int __hidden tcmd_vsock_local_cid(void) 173 | { 174 | int cid; 175 | int fd; 176 | 177 | fd = open("/dev/vsock", O_RDONLY); 178 | if (fd < 0) 179 | return -errno; 180 | 181 | if (ioctl(fd, GET_LOCAL_CID, &cid)) 182 | cid = -errno; 183 | 184 | close(fd); 185 | return cid; 186 | } 187 | -------------------------------------------------------------------------------- /utest/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | 3 | include $(src)/scripts/utils.mk 4 | 5 | bdir:=$(obj)/utest 6 | 7 | TARGETS = $(bdir)/trace-utest 8 | 9 | OBJS = 10 | OBJS += trace-utest.o 11 | OBJS += tracecmd-utest.o 12 | 13 | LIBS += $(LIBTRACECMD_STATIC) -lcunit $(LIBTRACEEVENT_LDLAGS) $(LIBTRACEFS_LDLAGS) 14 | 15 | LIBS += $(ZLIB_LDLAGS) $(LIBZSTD_LDLAGS) 16 | 17 | OBJS := $(OBJS:%.o=$(bdir)/%.o) 18 | DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) 19 | 20 | VALGRIND = $(shell which valgrind) 21 | 22 | $(bdir): 23 | @mkdir -p $(bdir) 24 | 25 | $(OBJS): | $(bdir) 26 | $(DEPS): | $(bdir) 27 | 28 | $(bdir)/trace-utest: $(OBJS) $(LIBTRACECMD_STATIC) 29 | $(Q)$(do_app_build) 30 | 31 | $(bdir)/%.o: %.c 32 | $(Q)$(call do_fpic_compile) 33 | 34 | $(DEPS): $(bdir)/.%.d: %.c 35 | $(Q)$(CC) -M $(CPPFLAGS) $(CFLAGS) $< > $@ 36 | $(Q)$(CC) -M -MT $(bdir)/$*.o $(CPPFLAGS) $(CFLAGS) $< > $@ 37 | 38 | $(OBJS): $(bdir)/%.o : $(bdir)/.%.d 39 | 40 | dep_includes := $(wildcard $(DEPS)) 41 | 42 | test: $(TARGETS) 43 | 44 | test_mem: test 45 | ifeq (, $(VALGRIND)) 46 | $(error "No valgrind in $(PATH), cannot run memory test") 47 | endif 48 | ifneq ($(shell id -u), 0) 49 | $(error "The memory test should be run as root, as it reuqires full access to tracefs") 50 | endif 51 | CK_FORK=no $(VALGRIND) \ 52 | --show-leak-kinds=all --leak-resolution=high \ 53 | --leak-check=full --show-possibly-lost=yes \ 54 | --track-origins=yes -s \ 55 | $(bdir)/trace-utest 56 | 57 | clean: 58 | $(RM) $(TARGETS) $(bdir)/*.o $(bdir)/.*.d 59 | -------------------------------------------------------------------------------- /utest/README: -------------------------------------------------------------------------------- 1 | 2 | Unit tests for trace-cmd libraries. The tests use CUnit framework: 3 | http://cunit.sourceforge.net/ 4 | which must be pre installed on the system, before building the unit tests. 5 | The framework can be downloaded, compiled and installed manually, or 6 | using a precompiled distro package: 7 | 8 | Fedora: 9 | CUnit 10 | CUnit-devel 11 | 12 | Ubuntu and Debian: 13 | libcunit1 14 | libcunit1-doc 15 | libcunit1-dev 16 | -------------------------------------------------------------------------------- /utest/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright (c) 2023 Daniel Wagner, SUSE LLC 4 | 5 | sources = [ 6 | 'tracecmd-utest.c', 7 | 'trace-utest.c', 8 | ] 9 | 10 | e = executable( 11 | 'trace-utest', 12 | sources, 13 | include_directories: [ 14 | incdir, 15 | libtracecmd_incdir, 16 | libtracecmd_private_incdir, 17 | libtracecmd_ext_incdir], 18 | dependencies: [ 19 | libtraceevent_dep, 20 | libtracefs_dep, 21 | zlib_dep, 22 | libzstd_dep, 23 | cunit_dep], 24 | link_with: [static_libtracecmd]) 25 | 26 | test('trace-utest', e) 27 | -------------------------------------------------------------------------------- /utest/trace-utest.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2020, VMware, Tzvetomir Stoyanov 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include "trace-utest.h" 16 | 17 | const char *argv0; 18 | bool show_output; 19 | 20 | enum unit_tests { 21 | RUN_NONE = 0, 22 | RUN_TRACECMD = (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 trace-cmd run trace-cmd 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 | 41 | argv0 = argv[0]; 42 | 43 | for (;;) { 44 | int c; 45 | int index = 0; 46 | const char *opts = "+hsr:v"; 47 | static struct option long_options[] = { 48 | {"silent", no_argument, NULL, 's'}, 49 | {"run", required_argument, NULL, 'r'}, 50 | {"verbose", no_argument, NULL, 'v'}, 51 | {"help", no_argument, NULL, 'h'}, 52 | {NULL, 0, NULL, 0} 53 | }; 54 | 55 | c = getopt_long (argc, argv, opts, long_options, &index); 56 | if (c == -1) 57 | break; 58 | switch (c) { 59 | case 'r': 60 | if (strcmp(optarg, "trace-cmd") == 0) 61 | tests |= RUN_TRACECMD; 62 | else 63 | print_help(argv); 64 | break; 65 | case 's': 66 | verbose = CU_BRM_SILENT; 67 | break; 68 | case 'v': 69 | show_output = true; 70 | break; 71 | case 'h': 72 | default: 73 | print_help(argv); 74 | break; 75 | } 76 | } 77 | 78 | if (tests == RUN_NONE) 79 | tests = RUN_ALL; 80 | 81 | if (CU_initialize_registry() != CUE_SUCCESS) { 82 | printf("Test registry cannot be initialized\n"); 83 | return -1; 84 | } 85 | 86 | if (tests & RUN_TRACECMD) 87 | test_tracecmd_lib(); 88 | 89 | CU_basic_set_mode(verbose); 90 | CU_basic_run_tests(); 91 | CU_cleanup_registry(); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /utest/trace-utest.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2020, VMware, Tzvetomir Stoyanov 4 | * 5 | */ 6 | #ifndef _TRACE_UTEST_H_ 7 | #define _TRACE_UTEST_H_ 8 | 9 | #include 10 | 11 | extern const char *argv0; 12 | extern bool show_output; 13 | 14 | void test_tracecmd_lib(void); 15 | 16 | #endif /* _TRACE_UTEST_H_ */ 17 | --------------------------------------------------------------------------------