<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>leodido.dev - IR</title>
    <subtitle>Leo&#x27;s take on security, eBPF, Linux, kernel, and whatever tech he meets</subtitle>
    <link rel="self" type="application/atom+xml" href="https://leodido.dev/tags/ir/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://leodido.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2022-01-10T00:00:00+00:00</updated>
    <id>https://leodido.dev/tags/ir/atom.xml</id>
    <entry xml:lang="en">
        <title>bpfcov</title>
        <published>2022-01-10T00:00:00+00:00</published>
        <updated>2022-01-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://leodido.dev/projects/bpfcov/"/>
        <id>https://leodido.dev/projects/bpfcov/</id>
        
        <content type="html" xml:base="https://leodido.dev/projects/bpfcov/">&lt;p&gt;This project provides 2 main components:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;libBPFCov.so&lt;&#x2F;code&gt; - an &lt;strong&gt;out-of-tree LLVM pass&lt;&#x2F;strong&gt; to &lt;strong&gt;instrument&lt;&#x2F;strong&gt; your &lt;strong&gt;eBPF programs&lt;&#x2F;strong&gt; for coverage.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;bpfcov&lt;&#x2F;code&gt; - a &lt;strong&gt;CLI&lt;&#x2F;strong&gt; to &lt;strong&gt;collect source-based coverage&lt;&#x2F;strong&gt; from your eBPF programs.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;stdo1.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;Source-based code coverage for BPF raw tracepoints&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;stdo1.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;stdo2.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;Source-based code coverage for BPF LSM programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;stdo2.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;mult1.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;HTML coverage index for multiple eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;mult1.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html2.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;HTML coverage report for eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html2.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html1.png&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;HTML coverage report for eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html1.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;json1.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;JSON report for multiple eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;json1.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;lcov1.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;LCOV info file from multiple eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;lcov1.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html3.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;HTML line coverage report for eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html3.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html4.png&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img width=&quot;1604&quot; alt=&quot;HTML line coverage report for eBPF programs&quot; src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;elastic&#x2F;bpfcov&#x2F;main&#x2F;docs&#x2F;assets&#x2F;html4.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;a class=&quot;zola-anchor&quot; href=&quot;#overview&quot; aria-label=&quot;Anchor link for: overview&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This section aims to provide a high-level overiew of the steps you need to get started with &lt;strong&gt;bpfcov&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;bpfcov&#x2F;#building&quot;&gt;Compile the LLVM pass&lt;&#x2F;a&gt; obtaining &lt;code&gt;libBPFCov.so&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Instrument your eBPF program by compiling it and by running the LLVM pass (&lt;code&gt;libBPFCov.so&lt;&#x2F;code&gt;) on it&lt;&#x2F;li&gt;
&lt;li&gt;Build the userspace code of your eBPF application&lt;&#x2F;li&gt;
&lt;li&gt;Execute your eBPF application in the kernel through the &lt;code&gt;bpfcov run ...&lt;&#x2F;code&gt; command&lt;&#x2F;li&gt;
&lt;li&gt;Generate the &lt;code&gt;.profraw&lt;&#x2F;code&gt; file from the run through the &lt;code&gt;bpfcov gen ...&lt;&#x2F;code&gt; command
&lt;ol&gt;
&lt;li&gt;Having a &lt;code&gt;.profraw&lt;&#x2F;code&gt; makes this tool fully interoperable&lt;&#x2F;li&gt;
&lt;li&gt;Having a &lt;code&gt;.profraw&lt;&#x2F;code&gt; allows you to generate a variety of coverage reports in different formats&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Use the LLVM toolchain to create coverage reports as documented in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;docs&#x2F;SourceBasedCodeCoverage.html#creating-coverage-reports&quot;&gt;LLVM docs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In case you are impatient and want to jump straight into getting your hands dirty, then the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;examples&#x2F;&quot;&gt;examples&lt;&#x2F;a&gt; directory contains a few dummy eBPF programs to showcase what &lt;strong&gt;bpfcov&lt;&#x2F;strong&gt; does.&lt;&#x2F;p&gt;
&lt;p&gt;It basically automates steps 2 and 3. Its &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;examples&#x2F;README.md&quot;&gt;README&lt;&#x2F;a&gt; contains more details.&lt;&#x2F;p&gt;
&lt;p&gt;While the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;cli&#x2F;README.md&quot;&gt;README of the cli directory&lt;&#x2F;a&gt; gives you more details about the steps 4 and 5 (and also 6).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage&quot; aria-label=&quot;Anchor link for: usage&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Here I will highlight the &lt;em&gt;manual&lt;&#x2F;em&gt; steps to use it.&lt;&#x2F;p&gt;
&lt;p&gt;I suggest you to automate most of them like I did in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;examples&#x2F;src&#x2F;Makefile&quot;&gt;examples Makefile&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, assuming you have &lt;a href=&quot;https:&#x2F;&#x2F;leodido.dev&#x2F;projects&#x2F;bpfcov&#x2F;#building&quot;&gt;built&lt;&#x2F;a&gt; the LLVM pass, you can then use your fresh &lt;code&gt;libBPFCov.so&lt;&#x2F;code&gt; to instrument your eBPF programs for coverage (steps 2 and 3 above).&lt;&#x2F;p&gt;
&lt;p&gt;How to do it?&lt;&#x2F;p&gt;
&lt;p&gt;First, you need to compile your eBPF program almost as usual but to LLVM IR...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;clang&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -g -O2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -target&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bpf&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -D__TARGET_ARCH_x86 -I$(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;YOUR_INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -fprofile-instr-generate -fcoverage-mapping&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -emit-llvm -S&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; program.bpf.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; program.bpf.ll&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice it doesn&#x27;t matter if you use the textual (&lt;code&gt;*.ll&lt;&#x2F;code&gt;) or the binary form (&lt;code&gt;*.bc&lt;&#x2F;code&gt;).
Obviously, the former is more readable.&lt;&#x2F;p&gt;
&lt;p&gt;The same logic applies to &lt;code&gt;opt&lt;&#x2F;code&gt;: by default it generates &lt;code&gt;*.bc&lt;&#x2F;code&gt;.
Using the &lt;code&gt;-S&lt;&#x2F;code&gt; flag you can obtain the output in textual form (&lt;code&gt;*.ll&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Anyhow, it&#x27;s time to run the LLVM pass on the LLVM IR we obtained.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s do it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -load-pass-plugin&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;BUILD_DIR&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;lib&#x2F;libBPFCov.so&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -passes=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bpf-cov&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; program.bpf.ll&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; program.bpf.cov.ll&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We should have obtained a new LLVM IR that&#x27;s now valid and loadable from the BPF VM in the Linux kernel. Almost there, YaY!&lt;&#x2F;p&gt;
&lt;p&gt;From it, we can obtain a valid BPF ELF now:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;llc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -march=bpf -filetype=obj -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program.bpf.o program.bpf.cov.ll&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While we are at it, it is also worth running the LLVM pass again (with a flag) to obtain another BPF ELF containing all the &lt;strong&gt;profiling&lt;&#x2F;strong&gt; and &lt;strong&gt;coverage mapping&lt;&#x2F;strong&gt; info.
It will come in handy later with &lt;code&gt;llvm-cov&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -load&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;BUILD_DIR&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;lib&#x2F;libBPFCov.so&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -strip-initializers-only -bpf-cov&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    program.bpf.ll&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    llc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -march=bpf -filetype=obj -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program.bpf.obj&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At this point, we can compile our userspace application loading the eBPF instrumented program (&lt;code&gt;cov&#x2F;program.bpf.o&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Doing this when using &lt;code&gt;libbpf&lt;&#x2F;code&gt; and skeletons is very easy. Nothing different from the common steps: &lt;code&gt;bpftool&lt;&#x2F;code&gt;, &lt;code&gt;cc&lt;&#x2F;code&gt;, etc.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;examples&#x2F;&quot;&gt;examples&lt;&#x2F;a&gt; directory, you can find further explainations.&lt;&#x2F;p&gt;
&lt;p&gt;So assuming we got our instrumented binary ready (&lt;code&gt;cov&#x2F;program&lt;&#x2F;code&gt;), we can run it via the &lt;code&gt;bpfcov&lt;&#x2F;code&gt; CLI.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;bpfcov run cov&#x2F;program&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Wait for it to exit, or stop it with CTRL+C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;bpfcov gen&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --unpin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, in case you wanna know more about these 2 steps, refer this time to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elastic&#x2F;bpfcov&#x2F;tree&#x2F;main&#x2F;cli&#x2F;README.md&quot;&gt;CLI README&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now we have a magic &lt;code&gt;cov&#x2F;program.profraw&lt;&#x2F;code&gt; file...&lt;&#x2F;p&gt;
&lt;p&gt;And we can use the LLVM toolchain to generate very fine-grained coverage reports like those in the screenshots!&lt;&#x2F;p&gt;
&lt;p&gt;Refer to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;docs&#x2F;SourceBasedCodeCoverage.html#creating-coverage-reports&quot;&gt;LLVM docs&lt;&#x2F;a&gt; to learn how to do it.&lt;&#x2F;p&gt;
&lt;p&gt;But no worries, it&#x27;s just about invoking &lt;code&gt;llvm-profdata&lt;&#x2F;code&gt; and &lt;code&gt;llvm-cov&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lvm-profdata&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; merge&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -sparse&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program.profraw&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program.profdata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;llvm-cov&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; show&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    --format=html&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    --show-line-counts-or-regions --show-region-summary --show-branch-summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    --instr-profile=cov&#x2F;profdata.profdata&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    -object&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program.bpf.obj&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt;    --output-dir=cov&#x2F;html_report&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Anyayws, &lt;strong&gt;bpfcov&lt;&#x2F;strong&gt; also provides you an opinionated shortcut command to generate HTML, JSON, and LCOV coverage reports:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;.&#x2F;bpfcov&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; out&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --format=html&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cov&#x2F;program.profraw&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;development-environment&quot;&gt;Development Environment&lt;a class=&quot;zola-anchor&quot; href=&quot;#development-environment&quot; aria-label=&quot;Anchor link for: development-environment&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In order to &lt;strong&gt;build&lt;&#x2F;strong&gt; the BPFCov library (&lt;code&gt;libBPFCov.so&lt;&#x2F;code&gt;) you will need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;LLVM 12+&lt;&#x2F;li&gt;
&lt;li&gt;CMake 3.13.4+&lt;&#x2F;li&gt;
&lt;li&gt;C++ compiler that supports C++14&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In order to &lt;strong&gt;use&lt;&#x2F;strong&gt; it, you will need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;clang 12 (to generate the input LLVM files)&lt;&#x2F;li&gt;
&lt;li&gt;its &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;llvm.org&#x2F;docs&#x2F;CommandGuide&#x2F;opt.html&quot;&gt;opt&lt;&#x2F;a&gt; binary to run the LLVM pass&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This project has been tested on 5.15 Linux kernels.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building&quot;&gt;Building&lt;a class=&quot;zola-anchor&quot; href=&quot;#building&quot; aria-label=&quot;Anchor link for: building&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Build as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cmake&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -DLT_LLVM_INSTALL_DIR=&#x2F;path&#x2F;to&#x2F;llvm&#x2F;installation&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ..&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;make&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice that the &lt;code&gt;LT_LLVM_INSTALL_DIR&lt;&#x2F;code&gt; variable should be set to the root of either the installation (usually &lt;code&gt;&#x2F;usr&lt;&#x2F;code&gt;) or the build directory of LLVM.&lt;&#x2F;p&gt;
&lt;p&gt;It is used to locate the corresponding &lt;code&gt;LLVMConfig.cmake&lt;&#x2F;code&gt; script that is used to set the include and the
library paths.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;a class=&quot;zola-anchor&quot; href=&quot;#testing&quot; aria-label=&quot;Anchor link for: testing&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;TBD&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To run the tests you will need to install &lt;strong&gt;llvm-lit&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Usually, you can install it with &lt;strong&gt;pip&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install lit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running the tests is as simple as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lit&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&#x2F;test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
</feed>
