{"id":15044378,"url":"https://github.com/elastic/bpfcov","last_synced_at":"2025-04-05T21:08:03.447Z","repository":{"id":40304059,"uuid":"446456594","full_name":"elastic/bpfcov","owner":"elastic","description":"Source-code based coverage for eBPF programs actually running in the Linux kernel ","archived":false,"fork":false,"pushed_at":"2025-02-06T01:23:54.000Z","size":1447,"stargazers_count":131,"open_issues_count":2,"forks_count":8,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-29T20:05:57.310Z","etag":null,"topics":["bpf","c","codecoverage","coverage","cpp","ebpf","llvm","llvm-pass"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elastic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-10T14:29:55.000Z","updated_at":"2025-03-18T06:45:36.000Z","dependencies_parsed_at":"2025-02-22T06:10:47.023Z","dependency_job_id":"16938264-92c8-4344-acc2-60ca04d8401e","html_url":"https://github.com/elastic/bpfcov","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Fbpfcov","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Fbpfcov/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Fbpfcov/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Fbpfcov/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elastic","download_url":"https://codeload.github.com/elastic/bpfcov/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399877,"owners_count":20932876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bpf","c","codecoverage","coverage","cpp","ebpf","llvm","llvm-pass"],"created_at":"2024-09-24T20:50:31.036Z","updated_at":"2025-04-05T21:08:03.418Z","avatar_url":"https://github.com/elastic.png","language":"C","readme":"# bpfcov\n\n\u003e Source-code based coverage for eBPF programs actually running in the Linux kernel\n\nThis project provides 2 main components:\n\n1. `libBPFCov.so` - an **out-of-tree LLVM pass** to **instrument** your **eBPF programs** for coverage.\n2. `bpfcov` - a **CLI** to **collect source-based coverage** from your eBPF programs.\n\n\n| | | |\n|:-------------------------:|:-------------------------:|:-------------------------:|\n| \u003ca href=\"docs/assets/stdo1.png\"\u003e\u003cimg width=\"1604\" alt=\"Source-based code coverage for BPF raw tracepoints\" src=\"docs/assets/stdo1.png\"\u003e\u003c/a\u003e | \u003ca href=\"docs/assets/stdo2.png\"\u003e\u003cimg width=\"1604\" alt=\"Source-based code coverage for BPF LSM programs\" src=\"docs/assets/stdo2.png\"\u003e\u003c/a\u003e | \u003ca href=\"docs/assets/mult1.png\"\u003e\u003cimg width=\"1604\" alt=\"HTML coverage index for multiple eBPF programs\" src=\"docs/assets/mult1.png\"\u003e\u003c/a\u003e\n| \u003ca href=\"docs/assets/html2.png\"\u003e\u003cimg width=\"1604\" alt=\"HTML coverage report for eBPF programs\" src=\"docs/assets/html2.png\"\u003e\u003c/a\u003e | \u003ca href=\"docs/assets/html1.png\"\u003e\u003cimg width=\"1604\" alt=\"HTML coverage report for eBPF programs\" src=\"docs/assets/html1.png\"\u003e\u003c/a\u003e | \u003ca href=\"docs/assets/json1.png\"\u003e\u003cimg width=\"1604\" alt=\"JSON report for multiple eBPF programs\" src=\"docs/assets/json1.png\"\u003e\u003c/a\u003e\n| \u003ca href=\"docs/assets/lcov1.png\"\u003e\u003cimg width=\"1604\" alt=\"LCOV info file from multiple eBPF programs\" src=\"docs/assets/lcov1.png\"\u003e\u003c/a\u003e | \u003ca href=\"docs/assets/html3.png\"\u003e\u003cimg width=\"1604\" alt=\"HTML line coverage report for eBPF programs\" src=\"docs/assets/html3.png\"\u003e\u003c/a\u003e | \u003ca href=\"docs/assets/html4.png\"\u003e\u003cimg width=\"1604\" alt=\"HTML line coverage report for eBPF programs\" src=\"docs/assets/html4.png\"\u003e\u003c/a\u003e\n\n## Overview\n\nThis section aims to provide a high-level overiew of the steps you need to get started with **bpfcov**.\n\n1. [Compile the LLVM pass](#building) obtaining `libBPFCov.so`\n2. Instrument your eBPF program by compiling it and by running the LLVM pass (`libBPFCov.so`) on it\n3. Build the userspace code of your eBPF application\n4. Execute your eBPF application in the kernel through the `bpfcov run ...` command\n5. Generate the `.profraw` file from the run through the `bpfcov gen ...` command\n    1. Having a `.profraw` makes this tool fully interoperable\n    2. Having a `.profraw` allows you to generate a variety of coverage reports in different formats\n6. Use the LLVM toolchain to create coverage reports as documented in the [LLVM docs](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports)\n\nIn case you are impatient and want to jump straight into getting your hands dirty, then the [examples](examples/) directory contains a few dummy eBPF programs to showcase what **bpfcov** does.\n\nIt basically automates steps 2 and 3. Its [README](examples/README.md) contains more details.\n\nWhile the [README of the cli directory](cli/README.md) gives you more details about the steps 4 and 5 (and also 6).\n\n## Usage\n\nHere I will highlight the _manual_ steps to use it.\n\nI suggest you to automate most of them like I did in the [examples Makefile](examples/src/Makefile).\n\nAnyway, assuming you have [built](#building) the LLVM pass, you can then use your fresh `libBPFCov.so` to instrument your eBPF programs for coverage (steps 2 and 3 above).\n\nHow to do it?\n\nFirst, you need to compile your eBPF program almost as usual but to LLVM IR...\n\n```bash\nclang -g -O2 \\\n    -target bpf -D__TARGET_ARCH_x86 -I$(YOUR_INCLUDES) \\\n    -fprofile-instr-generate -fcoverage-mapping \\\n    -emit-llvm -S \\\n    -c program.bpf.c \\\n    -o program.bpf.ll\n```\n\nNotice it doesn't matter if you use the textual (`*.ll`) or the binary form (`*.bc`).\nObviously, the former is more readable.\n\nThe same logic applies to `opt`: by default it generates `*.bc`.\nUsing the `-S` flag you can obtain the output in textual form (`*.ll`).\n\nAnyhow, it's time to run the LLVM pass on the LLVM IR we obtained.\n\nLet's do it:\n\n```bash\nopt -load-pass-plugin $(BUILD_DIR)/lib/libBPFCov.so -passes=\"bpf-cov\" \\\n    -S program.bpf.ll \\\n    -o program.bpf.cov.ll\n```\n\nWe should have obtained a new LLVM IR that's now valid and loadable from the BPF VM in the Linux kernel. Almost there, YaY!\n\nFrom it, we can obtain a valid BPF ELF now:\n\n```bash\nllc -march=bpf -filetype=obj -o cov/program.bpf.o program.bpf.cov.ll\n```\n\nWhile we are at it, it is also worth running the LLVM pass again (with a flag) to obtain another BPF ELF containing all the **profiling** and **coverage mapping** info.\nIt will come in handy later with `llvm-cov`.\n\n```bash\nopt -load $(BUILD_DIR)/lib/libBPFCov.so -strip-initializers-only -bpf-cov \\\n    program.bpf.ll | \\\n    llc -march=bpf -filetype=obj -o cov/program.bpf.obj\n```\n\nAt this point, we can compile our userspace application loading the eBPF instrumented program (`cov/program.bpf.o`).\n\nDoing this when using `libbpf` and skeletons is very easy. Nothing different from the common steps: `bpftool`, `cc`, etc.\n\nIn the [examples](examples/) directory, you can find further explainations.\n\nSo assuming we got our instrumented binary ready (`cov/program`), we can run it via the `bpfcov` CLI.\n\n```bash\nsudo ./bpfcov run cov/program\n# Wait for it to exit, or stop it with CTRL+C\nsudo ./bpfcov gen --unpin cov/program\n```\n\nAgain, in case you wanna know more about these 2 steps, refer this time to the [CLI README](cli/README.md).\n\nNow we have a magic `cov/program.profraw` file...\n\nAnd we can use the LLVM toolchain to generate very fine-grained coverage reports like those in the screenshots!\n\nRefer to the [LLVM docs](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports) to learn how to do it.\n\nBut no worries, it's just about invoking `llvm-profdata` and `llvm-cov`:\n\n```bash\nlvm-profdata merge -sparse cov/program.profraw -o cov/program.profdata\nllvm-cov show \\\n    --format=html \\\n    --show-line-counts-or-regions --show-region-summary --show-branch-summary \\\n    --instr-profile=cov/profdata.profdata \\\n    -object cov/program.bpf.obj \\\n    --output-dir=cov/html_report\n```\n\nAnyayws, **bpfcov** also provides you an opinionated shortcut command to generate HTML, JSON, and LCOV coverage reports:\n\n```bash\n./bpfcov out --format=html cov/program.profraw\n```\n\n\n## Development Environment\n\nIn order to **build** the BPFCov library (`libBPFCov.so`) you will need:\n\n- LLVM 12+\n- CMake 3.13.4+\n- C++ compiler that supports C++14\n\nIn order to **use** it, you will need:\n\n- clang 12 (to generate the input LLVM files)\n- its [opt](http://llvm.org/docs/CommandGuide/opt.html) binary to run the LLVM pass\n\nThis project has been tested on 5.15 Linux kernels.\n\n## Building\n\nBuild as follows:\n\n```console\nmkdir -p build \u0026\u0026 cd build\ncmake -DLT_LLVM_INSTALL_DIR=/path/to/llvm/installation ..\nmake\n```\n\nNotice that the `LT_LLVM_INSTALL_DIR` variable should be set to the root of either the installation (usually `/usr`) or the build directory of LLVM.\n\nIt is used to locate the corresponding `LLVMConfig.cmake` script that is used to set the include and the\nlibrary paths.\n\n## Testing\n\n**TBD**\n\nTo run the tests you will need to install **llvm-lit**.\n\nUsually, you can install it with **pip**:\n\n```console\npip install lit\n```\n\nRunning the tests is as simple as:\n\n```console\nlit build/test\n```\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felastic%2Fbpfcov","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felastic%2Fbpfcov","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felastic%2Fbpfcov/lists"}