{"id":769,"date":"2023-05-30T10:27:27","date_gmt":"2023-05-30T17:27:27","guid":{"rendered":"https:\/\/sysprogs.com\/tutorials\/?p=769"},"modified":"2023-05-30T11:01:26","modified_gmt":"2023-05-30T18:01:26","slug":"live-tracing-of-linux-kernel-code","status":"publish","type":"post","link":"https:\/\/sysprogs.com\/VisualKernel\/documentation\/tracing\/","title":{"rendered":"Live Tracing of Linux Kernel Code"},"content":{"rendered":"<h2>Overview<\/h2>\n<p>Live Tracing allows recording the values of arbitrary variables in the Linux kernel each time a given line of code is executed:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/trace-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-771\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/trace-1.png\" alt=\"\" width=\"1192\" height=\"414\" \/><\/a>Unlike the regular breakpoints that require a non-trivial debugging setup (e.g. JTAG), tracepoints work over a regular network connection and do not interfere with the normal kernel operation. Each time a tracepoint is hit, it quickly records the pre-selected data into an internal memory buffer, and immediately resumes the execution.<\/p>\n<h2>Supported Targets<\/h2>\n<p>Live Tracing is supported on all kernel targets that have a usable network connection and are built with <strong>kprobe<\/strong> or <strong>ftrace<\/strong> support (most stock kernels do). It can be used within a <a href=\"https:\/\/sysprogs.com\/VisualKernel\/tutorials\/tracing\/\">regular debugging session<\/a> (e.g. using KGDBoE or JTAG), or <a href=\"https:\/\/sysprogs.com\/VisualKernel\/tutorials\/tracing\/\">independently<\/a> without having to setup a debug connection. The second option is useful on targets where the regular means of debugging are not available.<\/p>\n<h2>Creating Tracepoints<\/h2>\n<p>Tracepoints can be created during a tracing session, or in advance. There are 3 different ways to create them:<\/p>\n<ol>\n<li>Via the <strong>Debug-&gt;Windows-&gt;Tracepoints<\/strong> window using the name of the function anywhere in the kernel, or the traced module(s):<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/list.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-772\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/list.png\" alt=\"\" width=\"715\" height=\"345\" \/><\/a><\/li>\n<li>Via the tracepoint links near the function declarations in the code (if enabled from the Tracepoints tool window):<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/annotation.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-773\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/annotation.png\" alt=\"\" width=\"935\" height=\"297\" \/><\/a><\/li>\n<li>Anywhere in the code using the tracepoint bar to the left of the breakpoint bar:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/line.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-774\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/line.png\" alt=\"\" width=\"817\" height=\"514\" \/><\/a><\/li>\n<\/ol>\n<h2>Selecting Traced Data<\/h2>\n<p>Each tracepoint can capture the values of arbitrary global or local variables. It can descend into pointers (automatically validating them), handle arrays, and capture NULL-terminated strings:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/data.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-775\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/data.png\" alt=\"\" width=\"763\" height=\"427\" \/><\/a>Generally, if a variable value would be visible from a gdb breakpoint, it will be traceable if you set a tracepoint in the same location.<\/p>\n<p>Dynamic arrays (plain byte arrays or arrays of structs) can be captured by selecting &#8220;Dynamic Array&#8221; in the &#8220;Show As&#8221; column, and then drag-and-dropping another variable in the &#8220;Number of elements&#8221; field below:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/data-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-781\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/data-1.png\" alt=\"\" width=\"773\" height=\"413\" \/><\/a><\/p>\n<p>You can set multipliers (e.g. capture 2x[count] elements) and maximum counts to avoid depleting the trace buffer space.<\/p>\n<h2>Viewing Trace Data<\/h2>\n<p>You can view the events produced by one or more tracepoints by selecting them in the Tracepoints window, or switching to the <strong>Events<\/strong> view to view all events:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/eventdata.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-782\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/eventdata.png\" alt=\"\" width=\"1591\" height=\"463\" \/><\/a><\/p>\n<p>You can also view events by clicking the tracepoint annotations directly in the code: (if enabled via the <strong>Tracepoints<\/strong> window):<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/view2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-779\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/view2.png\" alt=\"\" width=\"709\" height=\"235\" \/><\/a><\/p>\n<h2>Data Views<\/h2>\n<p>You can quickly make sense of large amounts of traced data using the table and graph views. Views can be created via the button in the <strong>Trace Data<\/strong> window when recording a trace, or viewing an existing trace file:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/views.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-783\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/views.png\" alt=\"\" width=\"810\" height=\"367\" \/><\/a>Once a table view is created, you can select drag items from the <strong>Trace Data<\/strong> window into the bottom part of the table view, and they will be automatically converted to data columns. Each data column can refer to one or more data items from one or more tracepoints. E.g. creating a &#8220;Name&#8221; column capturing the file name from <strong>sys_openat2()<\/strong> and a &#8216;fd&#8217; column creating the &#8216;fd&#8217; variable from <strong>open<\/strong>, <strong>read<\/strong>, <strong>write,<\/strong> and <strong>close<\/strong> syscalls can give an instant overview of all read\/write oprations going along in the kernel. The screenshot below shows the system calls involved in copying <strong>\/etc\/fstab<\/strong> to <strong>\/root\/fstab<\/strong>:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/table-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-785\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/table-1.png\" alt=\"\" width=\"860\" height=\"486\" \/><\/a>You can sort the table rows by clicking any column header, or simply export the entire table into a CSV file via the export button.<\/p>\n<p>Graph views work similarly to table views &#8211; they plot the values of selected variables as they were captured by the tracer. The X axis can show the event number, or an arbitrary variable (e.g. <strong>jiffies<\/strong> for the system clock value):<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/graph.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-786\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/graph.png\" alt=\"\" width=\"1021\" height=\"548\" \/><\/a><\/p>\n<h2>Grouping\/Exporting Tracepoints<\/h2>\n<p>Tracepoints can be grouped in virtual folders. Selecting a folder will automatically show events from all tracepoints within it (including subfolders): <a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/groups.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-787\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/groups.png\" alt=\"\" width=\"699\" height=\"336\" \/><\/a>You can also export the tracepoints (along with the data configuration) into XML files, and import them to other projects.<\/p>\n<h2>Kernel Modules<\/h2>\n<p>If you are tracing a kernel module project, it will automatically recognize when your module is loaded, and will place the tracepoints inside it. You can manually load\/unload the main module via the button on the GDB Session window (when tracing during regular debug sessions) or the Tracepoints window (when doing trace-only sessions):<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/module.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-788\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/module.png\" alt=\"\" width=\"940\" height=\"405\" \/><\/a>You can also place tracepoints in other modules, as long as you specify their names via <strong>VisualKernel Project Properties -&gt; Live Tracing -&gt; Traced in-tree modules<\/strong>:<a href=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/modules.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-789\" src=\"https:\/\/sysprogs.com\/tutorials\/wp-content\/uploads\/2023\/05\/modules.png\" alt=\"\" width=\"567\" height=\"227\" \/><\/a><\/p>\n<h2>Tutorials<\/h2>\n<p>You can find detailed tutorials explaining various Live Tracing functionality on <a href=\"https:\/\/sysprogs.com\/tutorials\/tag\/tracing\/\">this page<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Overview Live Tracing allows recording the values of arbitrary variables in the Linux kernel each time a given line of<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[58],"tags":[],"_links":{"self":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/769"}],"collection":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/comments?post=769"}],"version-history":[{"count":4,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/769\/revisions"}],"predecessor-version":[{"id":792,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/769\/revisions\/792"}],"wp:attachment":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/media?parent=769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/categories?post=769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/tags?post=769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}