├── debian ├── compat ├── source │ └── format ├── bcc-lua.install ├── python-bcc.install ├── python3-bcc.install ├── docs ├── libbcc-examples.install ├── libbcc.install ├── bcc-tools.install ├── copyright └── rules ├── man ├── man8 │ ├── javagc.8 │ ├── nodegc.8 │ ├── rubygc.8 │ ├── cobjnew.8 │ ├── javacalls.8 │ ├── javaflow.8 │ ├── javastat.8 │ ├── nodestat.8 │ ├── perlcalls.8 │ ├── perlflow.8 │ ├── perlstat.8 │ ├── phpcalls.8 │ ├── phpflow.8 │ ├── phpstat.8 │ ├── pythonflow.8 │ ├── pythongc.8 │ ├── pythonstat.8 │ ├── rubycalls.8 │ ├── rubyflow.8 │ ├── rubystat.8 │ ├── tclcalls.8 │ ├── tclflow.8 │ ├── tclstat.8 │ ├── cthreads.8 │ ├── javaobjnew.8 │ ├── javathreads.8 │ ├── pythoncalls.8 │ ├── rubyobjnew.8 │ ├── tclobjnew.8 │ ├── CMakeLists.txt │ ├── solisten.8 │ ├── pidpersec.8 │ ├── sofdsnoop.8 │ └── bitesize.8 └── CMakeLists.txt ├── tests ├── lua │ ├── spec │ ├── .busted │ ├── .luacheckrc │ ├── test_dump.lua │ ├── test_helper.lua │ ├── test_standalone.sh │ └── CMakeLists.txt ├── python │ ├── simulation.py │ ├── dummy.cc │ ├── test_trace2.c │ ├── test_dump_func.py │ ├── test_shared_table.py │ ├── test_utils.py │ ├── test_flags.py │ ├── test_brb2.c │ ├── test_uprobes2.py │ ├── test_call1.c │ ├── test_trace2.py │ ├── test_trace_maxactive.py │ ├── test_stat1.c │ ├── test_rlimit.py │ └── test_trace3.py ├── cc │ ├── test_libbcc.cc │ ├── test_static.c │ ├── usdt_test_lib.cc │ └── utils.cc └── CMakeLists.txt ├── examples ├── usdt_sample │ ├── .gitignore │ ├── usdt_sample_app1 │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ └── usdt_sample_lib1 │ │ └── src │ │ └── lib1_sdt.d ├── networking │ ├── vlan_learning │ │ ├── simulation.py │ │ └── CMakeLists.txt │ ├── distributed_bridge │ │ ├── simulation.py │ │ └── CMakeLists.txt │ ├── neighbor_sharing │ │ ├── simulation.py │ │ └── CMakeLists.txt │ ├── tunnel_monitor │ │ ├── simulation.py │ │ ├── chord.png │ │ ├── vxlan.jpg │ │ ├── CMakeLists.txt │ │ ├── setup.sh │ │ └── traffic.sh │ ├── vlan_filter │ │ ├── scenario.jpg │ │ ├── test_traffic.sh │ │ └── data-plane-tracing.c │ ├── xdp │ │ └── CMakeLists.txt │ ├── http_filter │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ └── simple_tc.py ├── cgroupid │ ├── Makefile │ └── Dockerfile ├── lua │ ├── CMakeLists.txt │ ├── bashreadline.c │ ├── bashreadline.lua │ ├── kprobe-write.lua │ ├── usdt_ruby.lua │ ├── strlen_count.lua │ └── sock-proto.lua ├── tracing │ ├── CMakeLists.txt │ ├── nodejs_http_server_example.txt │ ├── mysqld_query_example.txt │ ├── task_switch.py │ ├── task_switch.c │ ├── trace_fields.py │ ├── biolatpcts_example.txt │ ├── urandomread_example.txt │ ├── hello_fields.py │ ├── undump_example.txt │ ├── vfsreadlat.c │ ├── tcpv4connect_example.txt │ ├── urandomread.py │ ├── bitehist_example.txt │ ├── hello_perf_output.py │ └── strlen_count.py ├── CMakeLists.txt ├── cpp │ ├── pyperf │ │ ├── PyPerfLoggingHelper.h │ │ ├── PyPerfSampleProcessor.h │ │ ├── PyPerfLoggingHelper.cc │ │ ├── CMakeLists.txt │ │ ├── PyPerfDefaultPrinter.h │ │ └── Py36Offsets.cc │ ├── CMakeLists.txt │ └── HelloWorld.cc ├── hello_world.py ├── local_storage │ ├── inode_storage.py │ └── task_storage.py └── ringbuf │ ├── ringbuf_output.py │ └── ringbuf_submit.py ├── libbpf-tools ├── arm64 │ └── vmlinux.h ├── powerpc │ └── vmlinux.h ├── x86 │ └── vmlinux.h ├── funclatency.h ├── errno_helpers.h ├── softirqs.h ├── tcpsynbl.h ├── runqlen.h ├── tcprtt.h ├── llcstat.h ├── readahead.h ├── vfsstat.h ├── cpudist.h ├── runqlat.h ├── biopattern.h ├── hardirqs.h ├── bashreadline.h ├── btf_helpers.h ├── drsnoop.h ├── oomkill.h ├── syscount.h ├── fsdist.h ├── filelife.h ├── runqslower.h ├── solisten.h ├── gethostlatency.h ├── statsnoop.h ├── syscall_helpers.h ├── map_helpers.h ├── exitsnoop.h ├── offcputime.h ├── cpufreq.h ├── biolatency.h ├── bitesize.h ├── tcpconnlat.h ├── fsslower.h ├── opensnoop.h ├── klockstat.h ├── biosnoop.h ├── filetop.h ├── biostacks.h ├── bindsnoop.h ├── maps.bpf.h ├── uprobe_helpers.h ├── execsnoop.h ├── bits.bpf.h ├── .gitignore ├── mountsnoop.h ├── core_fixes.bpf.h ├── stat.h ├── tcpconnect.h ├── oomkill.bpf.c ├── cachestat.bpf.c ├── bashreadline.bpf.c ├── numamove.bpf.c ├── biopattern.bpf.c ├── llcstat.bpf.c ├── runqlen.bpf.c ├── Makefile.btfgen └── softirqs.bpf.c ├── tools ├── javagc_example.txt ├── nodegc_example.txt ├── rubygc_example.txt ├── cobjnew_example.txt ├── javaflow_example.txt ├── javastat_example.txt ├── nodestat_example.txt ├── perlflow_example.txt ├── perlstat_example.txt ├── phpcalls_example.txt ├── phpflow_example.txt ├── phpstat_example.txt ├── pythongc_example.txt ├── rubyflow_example.txt ├── rubystat_example.txt ├── tclcalls_example.txt ├── tclflow_example.txt ├── tclstat_example.txt ├── cthreads_example.txt ├── javacalls_example.txt ├── javaobjnew_example.txt ├── javathreads_example.txt ├── perlcalls_example.txt ├── pythoncalls_example.txt ├── pythonflow_example.txt ├── pythonstat_example.txt ├── rubycalls_example.txt ├── rubyobjnew_example.txt ├── tclobjnew_example.txt ├── cobjnew.sh ├── javagc.sh ├── nodegc.sh ├── phpflow.sh ├── phpstat.sh ├── rubygc.sh ├── tclflow.sh ├── tclstat.sh ├── javacalls.sh ├── javaflow.sh ├── javastat.sh ├── nodestat.sh ├── perlcalls.sh ├── perlflow.sh ├── perlstat.sh ├── phpcalls.sh ├── pythongc.sh ├── rubycalls.sh ├── rubyflow.sh ├── rubystat.sh ├── tclcalls.sh ├── tclobjnew.sh ├── javaobjnew.sh ├── javathreads.sh ├── pythoncalls.sh ├── pythonflow.sh ├── pythonstat.sh ├── rubyobjnew.sh ├── old │ ├── CMakeLists.txt │ ├── syncsnoop.py │ └── bashreadline.py ├── lib │ └── CMakeLists.txt ├── syncsnoop_example.txt ├── pidpersec_example.txt ├── bashreadline_example.txt ├── killsnoop_example.txt ├── threadsnoop_example.txt ├── CMakeLists.txt ├── tcpsynbl_example.txt ├── pidpersec.py ├── bitesize.py ├── vfsstat_example.txt ├── gethostlatency_example.txt ├── syncsnoop.py ├── biopattern_example.txt └── mountsnoop_example.txt ├── src ├── python │ ├── bcc │ │ └── version.py.in │ └── setup.py.in ├── cc │ ├── usdt │ │ └── CMakeLists.txt │ ├── bcc_version.h.in │ ├── frontends │ │ ├── CMakeLists.txt │ │ └── clang │ │ │ ├── CMakeLists.txt │ │ │ └── frontend_action_common.h │ ├── api │ │ └── CMakeLists.txt │ ├── bcc_libbpf_inc.h │ ├── export │ │ ├── bpf_workaround.h │ │ └── footer.h │ ├── setns.h │ ├── libbcc.pc.in │ ├── link_all.cc │ ├── README │ ├── bpf_module_rw_engine_disabled.cc │ ├── exported_files.h │ ├── bcc_perf_map.h │ ├── common.h │ └── perf_reader.h ├── lua │ ├── bpf │ │ ├── spec │ │ │ ├── README.md │ │ │ ├── compile_spec.lua │ │ │ ├── elf_spec.lua │ │ │ ├── decoder_spec.lua │ │ │ └── helper.lua │ │ └── init.lua │ ├── .busted │ ├── .luacheckrc │ ├── bcc │ │ └── init.lua │ ├── bcc-probe │ ├── squishy │ ├── bpf-scm-1.rockspec │ └── CMakeLists.txt └── CMakeLists.txt ├── .dockerignore ├── images ├── logo1.png ├── logo2.png ├── bcc_tracing_tools_2016.png ├── bcc_tracing_tools_2017.png └── bcc_tracing_tools_2019.png ├── .clang-format ├── .gitmodules ├── .gitignore ├── scripts ├── git-tag.sh ├── build-deb.sh.in ├── c-style-check.sh ├── py-style-check.sh ├── docker │ ├── auth.sh │ └── build.sh ├── build-release-rpm.sh ├── check-helpers.sh ├── build-rpm.sh └── build-deb.sh ├── snap ├── local │ └── bcc-wrapper └── README.md ├── docker ├── Dockerfile.debian ├── Dockerfile.ubuntu └── Dockerfile.fedora ├── cmake ├── bump_version.cmake ├── FindCompilerFlag.cmake ├── static_libstdc++.cmake ├── version.cmake └── GetGitRevisionDescription.cmake.in ├── QUICKSTART.md ├── .travis.yml ├── SPECS └── Dockerfile.fedora ├── CODEOWNERS └── introspection ├── CMakeLists.txt └── bps_example.txt /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /man/man8/javagc.8: -------------------------------------------------------------------------------- 1 | ugc.8 -------------------------------------------------------------------------------- /man/man8/nodegc.8: -------------------------------------------------------------------------------- 1 | ugc.8 -------------------------------------------------------------------------------- /man/man8/rubygc.8: -------------------------------------------------------------------------------- 1 | ugc.8 -------------------------------------------------------------------------------- /man/man8/cobjnew.8: -------------------------------------------------------------------------------- 1 | uobjnew.8 -------------------------------------------------------------------------------- /man/man8/javacalls.8: -------------------------------------------------------------------------------- 1 | ucalls.8 -------------------------------------------------------------------------------- /man/man8/javaflow.8: -------------------------------------------------------------------------------- 1 | uflow.8 -------------------------------------------------------------------------------- /man/man8/javastat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/nodestat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/perlcalls.8: -------------------------------------------------------------------------------- 1 | ucalls.8 -------------------------------------------------------------------------------- /man/man8/perlflow.8: -------------------------------------------------------------------------------- 1 | uflow.8 -------------------------------------------------------------------------------- /man/man8/perlstat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/phpcalls.8: -------------------------------------------------------------------------------- 1 | ucalls.8 -------------------------------------------------------------------------------- /man/man8/phpflow.8: -------------------------------------------------------------------------------- 1 | uflow.8 -------------------------------------------------------------------------------- /man/man8/phpstat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/pythonflow.8: -------------------------------------------------------------------------------- 1 | uflow.8 -------------------------------------------------------------------------------- /man/man8/pythongc.8: -------------------------------------------------------------------------------- 1 | ugc.8 -------------------------------------------------------------------------------- /man/man8/pythonstat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/rubycalls.8: -------------------------------------------------------------------------------- 1 | ucalls.8 -------------------------------------------------------------------------------- /man/man8/rubyflow.8: -------------------------------------------------------------------------------- 1 | uflow.8 -------------------------------------------------------------------------------- /man/man8/rubystat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/tclcalls.8: -------------------------------------------------------------------------------- 1 | ucalls.8 -------------------------------------------------------------------------------- /man/man8/tclflow.8: -------------------------------------------------------------------------------- 1 | uflow.8 -------------------------------------------------------------------------------- /man/man8/tclstat.8: -------------------------------------------------------------------------------- 1 | ustat.8 -------------------------------------------------------------------------------- /man/man8/cthreads.8: -------------------------------------------------------------------------------- 1 | uthreads.8 -------------------------------------------------------------------------------- /man/man8/javaobjnew.8: -------------------------------------------------------------------------------- 1 | uobjnew.8 -------------------------------------------------------------------------------- /man/man8/javathreads.8: -------------------------------------------------------------------------------- 1 | uthreads.8 -------------------------------------------------------------------------------- /man/man8/pythoncalls.8: -------------------------------------------------------------------------------- 1 | ucalls.8 -------------------------------------------------------------------------------- /man/man8/rubyobjnew.8: -------------------------------------------------------------------------------- 1 | uobjnew.8 -------------------------------------------------------------------------------- /man/man8/tclobjnew.8: -------------------------------------------------------------------------------- 1 | uobjnew.8 -------------------------------------------------------------------------------- /tests/lua/spec: -------------------------------------------------------------------------------- 1 | src/lua/bpf/spec -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/bcc-lua.install: -------------------------------------------------------------------------------- 1 | usr/bin/bcc-lua 2 | -------------------------------------------------------------------------------- /examples/usdt_sample/.gitignore: -------------------------------------------------------------------------------- 1 | **/build*/ -------------------------------------------------------------------------------- /libbpf-tools/arm64/vmlinux.h: -------------------------------------------------------------------------------- 1 | vmlinux_510.h -------------------------------------------------------------------------------- /libbpf-tools/powerpc/vmlinux.h: -------------------------------------------------------------------------------- 1 | vmlinux_510.h -------------------------------------------------------------------------------- /libbpf-tools/x86/vmlinux.h: -------------------------------------------------------------------------------- 1 | vmlinux_505.h -------------------------------------------------------------------------------- /tools/javagc_example.txt: -------------------------------------------------------------------------------- 1 | lib/ugc_example.txt -------------------------------------------------------------------------------- /tools/nodegc_example.txt: -------------------------------------------------------------------------------- 1 | lib/ugc_example.txt -------------------------------------------------------------------------------- /tools/rubygc_example.txt: -------------------------------------------------------------------------------- 1 | lib/ugc_example.txt -------------------------------------------------------------------------------- /debian/python-bcc.install: -------------------------------------------------------------------------------- 1 | usr/lib/python2* 2 | -------------------------------------------------------------------------------- /debian/python3-bcc.install: -------------------------------------------------------------------------------- 1 | usr/lib/python3* 2 | -------------------------------------------------------------------------------- /man/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(man8) 2 | -------------------------------------------------------------------------------- /tools/cobjnew_example.txt: -------------------------------------------------------------------------------- 1 | lib/uobjnew_example.txt -------------------------------------------------------------------------------- /tools/javaflow_example.txt: -------------------------------------------------------------------------------- 1 | lib/uflow_example.txt -------------------------------------------------------------------------------- /tools/javastat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /tools/nodestat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /tools/perlflow_example.txt: -------------------------------------------------------------------------------- 1 | lib/uflow_example.txt -------------------------------------------------------------------------------- /tools/perlstat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /tools/phpcalls_example.txt: -------------------------------------------------------------------------------- 1 | lib/ucalls_example.txt -------------------------------------------------------------------------------- /tools/phpflow_example.txt: -------------------------------------------------------------------------------- 1 | lib/uflow_example.txt -------------------------------------------------------------------------------- /tools/phpstat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /tools/pythongc_example.txt: -------------------------------------------------------------------------------- 1 | lib/ugc_example.txt -------------------------------------------------------------------------------- /tools/rubyflow_example.txt: -------------------------------------------------------------------------------- 1 | lib/uflow_example.txt -------------------------------------------------------------------------------- /tools/rubystat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /tools/tclcalls_example.txt: -------------------------------------------------------------------------------- 1 | lib/ucalls_example.txt -------------------------------------------------------------------------------- /tools/tclflow_example.txt: -------------------------------------------------------------------------------- 1 | lib/uflow_example.txt -------------------------------------------------------------------------------- /tools/tclstat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | FAQ.txt 2 | LICENSE.txt 3 | README.md 4 | -------------------------------------------------------------------------------- /tools/cthreads_example.txt: -------------------------------------------------------------------------------- 1 | lib/uthreads_example.txt -------------------------------------------------------------------------------- /tools/javacalls_example.txt: -------------------------------------------------------------------------------- 1 | lib/ucalls_example.txt -------------------------------------------------------------------------------- /tools/javaobjnew_example.txt: -------------------------------------------------------------------------------- 1 | lib/uobjnew_example.txt -------------------------------------------------------------------------------- /tools/javathreads_example.txt: -------------------------------------------------------------------------------- 1 | lib/uthreads_example.txt -------------------------------------------------------------------------------- /tools/perlcalls_example.txt: -------------------------------------------------------------------------------- 1 | lib/ucalls_example.txt -------------------------------------------------------------------------------- /tools/pythoncalls_example.txt: -------------------------------------------------------------------------------- 1 | lib/ucalls_example.txt -------------------------------------------------------------------------------- /tools/pythonflow_example.txt: -------------------------------------------------------------------------------- 1 | lib/uflow_example.txt -------------------------------------------------------------------------------- /tools/pythonstat_example.txt: -------------------------------------------------------------------------------- 1 | lib/ustat_example.txt -------------------------------------------------------------------------------- /tools/rubycalls_example.txt: -------------------------------------------------------------------------------- 1 | lib/ucalls_example.txt -------------------------------------------------------------------------------- /tools/rubyobjnew_example.txt: -------------------------------------------------------------------------------- 1 | lib/uobjnew_example.txt -------------------------------------------------------------------------------- /tools/tclobjnew_example.txt: -------------------------------------------------------------------------------- 1 | lib/uobjnew_example.txt -------------------------------------------------------------------------------- /debian/libbcc-examples.install: -------------------------------------------------------------------------------- 1 | usr/share/bcc/examples/* 2 | -------------------------------------------------------------------------------- /examples/networking/vlan_learning/simulation.py: -------------------------------------------------------------------------------- 1 | ../simulation.py -------------------------------------------------------------------------------- /src/python/bcc/version.py.in: -------------------------------------------------------------------------------- 1 | __version__ = '@REVISION@' 2 | -------------------------------------------------------------------------------- /examples/networking/distributed_bridge/simulation.py: -------------------------------------------------------------------------------- 1 | ../simulation.py -------------------------------------------------------------------------------- /examples/networking/neighbor_sharing/simulation.py: -------------------------------------------------------------------------------- 1 | ../simulation.py -------------------------------------------------------------------------------- /examples/networking/tunnel_monitor/simulation.py: -------------------------------------------------------------------------------- 1 | ../simulation.py -------------------------------------------------------------------------------- /tests/python/simulation.py: -------------------------------------------------------------------------------- 1 | ../../examples/networking/simulation.py -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile* 2 | build 3 | .*.swp 4 | docker/Dockerfile* 5 | -------------------------------------------------------------------------------- /images/logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/images/logo1.png -------------------------------------------------------------------------------- /images/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/images/logo2.png -------------------------------------------------------------------------------- /tests/cc/test_libbcc.cc: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "catch.hpp" 3 | -------------------------------------------------------------------------------- /src/cc/usdt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(usdt-static STATIC usdt_args.cc usdt.cc) 2 | -------------------------------------------------------------------------------- /tools/cobjnew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uobjnew.py -l c "$@" 4 | -------------------------------------------------------------------------------- /tools/javagc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ugc.py -l java "$@" 4 | -------------------------------------------------------------------------------- /tools/nodegc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ugc.py -l node "$@" 4 | -------------------------------------------------------------------------------- /tools/phpflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uflow.py -l php "$@" 4 | -------------------------------------------------------------------------------- /tools/phpstat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l php "$@" 4 | -------------------------------------------------------------------------------- /tools/rubygc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ugc.py -l ruby "$@" 4 | -------------------------------------------------------------------------------- /tools/tclflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uflow.py -l tcl "$@" 4 | -------------------------------------------------------------------------------- /tools/tclstat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l tcl "$@" 4 | -------------------------------------------------------------------------------- /tools/javacalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ucalls.py -l java "$@" 4 | -------------------------------------------------------------------------------- /tools/javaflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uflow.py -l java "$@" 4 | -------------------------------------------------------------------------------- /tools/javastat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l java "$@" 4 | -------------------------------------------------------------------------------- /tools/nodestat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l node "$@" 4 | -------------------------------------------------------------------------------- /tools/perlcalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ucalls.py -l perl "$@" 4 | -------------------------------------------------------------------------------- /tools/perlflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uflow.py -l perl "$@" 4 | -------------------------------------------------------------------------------- /tools/perlstat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l perl "$@" 4 | -------------------------------------------------------------------------------- /tools/phpcalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ucalls.py -l php "$@" 4 | -------------------------------------------------------------------------------- /tools/pythongc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ugc.py -l python "$@" 4 | -------------------------------------------------------------------------------- /tools/rubycalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ucalls.py -l ruby "$@" 4 | -------------------------------------------------------------------------------- /tools/rubyflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uflow.py -l ruby "$@" 4 | -------------------------------------------------------------------------------- /tools/rubystat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l ruby "$@" 4 | -------------------------------------------------------------------------------- /tools/tclcalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ucalls.py -l tcl "$@" 4 | -------------------------------------------------------------------------------- /tools/tclobjnew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uobjnew.py -l tcl "$@" 4 | -------------------------------------------------------------------------------- /examples/cgroupid/Makefile: -------------------------------------------------------------------------------- 1 | cgroupid: cgroupid.c 2 | gcc -Wall -static -o cgroupid cgroupid.c 3 | -------------------------------------------------------------------------------- /tools/javaobjnew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uobjnew.py -l java "$@" 4 | -------------------------------------------------------------------------------- /tools/javathreads.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uthreads.py -l java "$@" 4 | -------------------------------------------------------------------------------- /tools/pythoncalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ucalls.py -l python "$@" 4 | -------------------------------------------------------------------------------- /tools/pythonflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uflow.py -l python "$@" 4 | -------------------------------------------------------------------------------- /tools/pythonstat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/ustat.py -l python "$@" 4 | -------------------------------------------------------------------------------- /tools/rubyobjnew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lib=$(dirname $0)/lib 3 | $lib/uobjnew.py -l ruby "$@" 4 | -------------------------------------------------------------------------------- /debian/libbcc.install: -------------------------------------------------------------------------------- 1 | usr/include/bcc/* 2 | usr/lib/*/libbcc* 3 | usr/lib/*/pkgconfig/libbcc.pc 4 | -------------------------------------------------------------------------------- /debian/bcc-tools.install: -------------------------------------------------------------------------------- 1 | usr/share/bcc/introspection/* 2 | usr/share/bcc/tools/* 3 | usr/share/bcc/man/* 4 | -------------------------------------------------------------------------------- /images/bcc_tracing_tools_2016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/images/bcc_tracing_tools_2016.png -------------------------------------------------------------------------------- /images/bcc_tracing_tools_2017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/images/bcc_tracing_tools_2017.png -------------------------------------------------------------------------------- /images/bcc_tracing_tools_2019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/images/bcc_tracing_tools_2019.png -------------------------------------------------------------------------------- /examples/networking/tunnel_monitor/chord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/examples/networking/tunnel_monitor/chord.png -------------------------------------------------------------------------------- /examples/networking/tunnel_monitor/vxlan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/examples/networking/tunnel_monitor/vxlan.jpg -------------------------------------------------------------------------------- /examples/networking/vlan_filter/scenario.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiann/bcc/HEAD/examples/networking/vlan_filter/scenario.jpg -------------------------------------------------------------------------------- /src/cc/bcc_version.h.in: -------------------------------------------------------------------------------- 1 | #ifndef LIBBCC_VERSION_H 2 | #define LIBBCC_VERSION_H 3 | 4 | #define LIBBCC_VERSION "@REVISION@" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /examples/networking/xdp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB PY_FILES *.py) 2 | install(PROGRAMS ${PY_FILES} DESTINATION share/bcc/examples/networking/xdp) 3 | -------------------------------------------------------------------------------- /src/cc/frontends/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | add_subdirectory(clang) 5 | -------------------------------------------------------------------------------- /examples/networking/vlan_filter/test_traffic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ip netns exec netns11 ping 192.168.100.12 -c 10 4 | ip netns exec netns22 ping 192.168.200.21 -c 10 5 | -------------------------------------------------------------------------------- /src/lua/bpf/spec/README.md: -------------------------------------------------------------------------------- 1 | # Unit test specs 2 | 3 | This directory contains spec files for Lua BPF in [Busted] unit test format. 4 | 5 | [Busted]: http://olivinelabs.com/busted/ 6 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | AllowShortIfStatementsOnASingleLine: false 4 | AllowShortLoopsOnASingleLine: false 5 | IndentCaseLabels: false 6 | AccessModifierOffset: -1 7 | -------------------------------------------------------------------------------- /tests/lua/.busted: -------------------------------------------------------------------------------- 1 | -- Configuration for unit tests 2 | -- See: http://olivinelabs.com/busted/ 3 | return { 4 | default = { 5 | lpath = "./?.lua", 6 | ["auto-insulate"] = false, 7 | } 8 | } -------------------------------------------------------------------------------- /src/cc/api/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(bcc_api_sources BPF.cc BPFTable.cc) 2 | add_library(api-static STATIC ${bcc_api_sources}) 3 | install(FILES BPF.h BPFTable.h COMPONENT libbcc DESTINATION include/bcc) 4 | -------------------------------------------------------------------------------- /examples/lua/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB C_FILES *.c) 2 | file(GLOB LUA_FILES *.lua) 3 | install(FILES ${C_FILES} DESTINATION share/bcc/examples/lua) 4 | install(PROGRAMS ${LUA_FILES} DESTINATION share/bcc/examples/lua) -------------------------------------------------------------------------------- /tools/old/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB PY_FILES *.py) 2 | foreach(FIL ${PY_FILES}) 3 | get_filename_component(FIL_WE ${FIL} NAME_WE) 4 | install(PROGRAMS ${FIL} DESTINATION share/bcc/tools/old RENAME ${FIL_WE}) 5 | endforeach() 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/cc/libbpf"] 2 | path = src/cc/libbpf 3 | url = https://github.com/libbpf/libbpf.git 4 | [submodule "libbpf-tools/bpftool"] 5 | path = libbpf-tools/bpftool 6 | url = https://github.com/libbpf/bpftool 7 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: bcc 3 | Source: https://github.com/iovisor/bcc 4 | 5 | Files: * 6 | Copyright: 2015 PLUMgrid, Inc. 7 | License: Apache-2.0 8 | -------------------------------------------------------------------------------- /libbpf-tools/funclatency.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #pragma once 3 | 4 | #define MAX_PIDS 102400 5 | #define MAX_SLOTS 25 6 | 7 | enum units { 8 | NSEC, 9 | USEC, 10 | MSEC, 11 | }; 12 | -------------------------------------------------------------------------------- /libbpf-tools/errno_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __ERRNO_HELPERS_H 3 | #define __ERRNO_HELPERS_H 4 | 5 | int errno_by_name(const char *errno_name); 6 | 7 | #endif /* __ERRNO_HELPERS_H */ 8 | -------------------------------------------------------------------------------- /tests/cc/test_static.c: -------------------------------------------------------------------------------- 1 | #include "bcc_common.h" 2 | 3 | int main(int argc, char **argv) { 4 | void *mod = bpf_module_create_c_from_string("BPF_TABLE(\"array\", int, int, stats, 10);\n", 4, NULL, 0, true, NULL); 5 | return !(mod != NULL); 6 | } 7 | -------------------------------------------------------------------------------- /src/lua/.busted: -------------------------------------------------------------------------------- 1 | -- Configuration for unit tests 2 | -- See: http://olivinelabs.com/busted/ 3 | return { 4 | default = { 5 | lpath = "./?.lua;./?/init.lua", 6 | helper = "./bpf/spec/helper.lua", 7 | ["auto-insulate"] = false, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libbpf-tools/softirqs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __SOFTIRQS_H 3 | #define __SOFTIRQS_H 4 | 5 | #define MAX_SLOTS 20 6 | 7 | struct hist { 8 | __u32 slots[MAX_SLOTS]; 9 | }; 10 | 11 | #endif /* __SOFTIRQS_H */ 12 | -------------------------------------------------------------------------------- /libbpf-tools/tcpsynbl.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __TCPSYNBL_H 3 | #define __TCPSYNBL_H 4 | 5 | #define MAX_SLOTS 32 6 | 7 | struct hist { 8 | __u32 slots[MAX_SLOTS]; 9 | }; 10 | 11 | #endif /* __TCPSYNBL_H */ 12 | -------------------------------------------------------------------------------- /src/cc/bcc_libbpf_inc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef HAVE_EXTERNAL_LIBBPF 4 | # include 5 | # include 6 | # include 7 | #else 8 | # include "libbpf/src/bpf.h" 9 | # include "libbpf/src/btf.h" 10 | # include "libbpf/src/libbpf.h" 11 | #endif 12 | -------------------------------------------------------------------------------- /libbpf-tools/runqlen.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __RUNQLEN_H 3 | #define __RUNQLEN_H 4 | 5 | #define MAX_CPU_NR 128 6 | #define MAX_SLOTS 32 7 | 8 | struct hist { 9 | __u32 slots[MAX_SLOTS]; 10 | }; 11 | 12 | #endif /* __RUNQLEN_H */ 13 | -------------------------------------------------------------------------------- /libbpf-tools/tcprtt.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __TCPRTT_H 3 | #define __TCPRTT_H 4 | 5 | #define MAX_SLOTS 27 6 | 7 | struct hist { 8 | __u64 latency; 9 | __u64 cnt; 10 | __u32 slots[MAX_SLOTS]; 11 | }; 12 | 13 | #endif /* __TCPRTT_H */ 14 | -------------------------------------------------------------------------------- /libbpf-tools/llcstat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __LLCSTAT_H 3 | #define __LLCSTAT_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct info { 8 | __u64 ref; 9 | __u64 miss; 10 | char comm[TASK_COMM_LEN]; 11 | }; 12 | 13 | #endif /* __LLCSTAT_H */ 14 | -------------------------------------------------------------------------------- /libbpf-tools/readahead.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | #ifndef __READAHEAD_H 3 | #define __READAHEAD_H 4 | 5 | #define MAX_SLOTS 20 6 | 7 | struct hist { 8 | __u32 unused; 9 | __u32 total; 10 | __u32 slots[MAX_SLOTS]; 11 | }; 12 | 13 | #endif /* __READAHEAD_H */ 14 | -------------------------------------------------------------------------------- /examples/usdt_sample/usdt_sample_app1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(usdt_sample_app1) 3 | 4 | add_executable( ${PROJECT_NAME} 5 | ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 6 | ) 7 | 8 | target_link_libraries( ${PROJECT_NAME} 9 | usdt_sample_lib1 10 | pthread 11 | ) 12 | -------------------------------------------------------------------------------- /libbpf-tools/vfsstat.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Anton Protopopov 3 | #ifndef __VFSSTAT_H 4 | #define __VFSSTAT_H 5 | 6 | enum stat_types { 7 | S_READ, 8 | S_WRITE, 9 | S_FSYNC, 10 | S_OPEN, 11 | S_CREATE, 12 | S_MAXSTAT, 13 | }; 14 | 15 | #endif /* __VFSSTAT_H */ 16 | -------------------------------------------------------------------------------- /libbpf-tools/cpudist.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __CPUDIST_H 3 | #define __CPUDIST_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define MAX_SLOTS 36 7 | 8 | struct hist { 9 | __u32 slots[MAX_SLOTS]; 10 | char comm[TASK_COMM_LEN]; 11 | }; 12 | 13 | #endif // __CPUDIST_H 14 | -------------------------------------------------------------------------------- /src/cc/export/bpf_workaround.h: -------------------------------------------------------------------------------- 1 | R"********( 2 | #ifndef __HAVE_BUILTIN_BSWAP16__ 3 | #define __HAVE_BUILTIN_BSWAP16__ 4 | #endif 5 | #ifndef __HAVE_BUILTIN_BSWAP32__ 6 | #define __HAVE_BUILTIN_BSWAP32__ 7 | #endif 8 | #ifndef __HAVE_BUILTIN_BSWAP64__ 9 | #define __HAVE_BUILTIN_BSWAP64__ 10 | #endif 11 | )********" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Editor's files 2 | *.swp 3 | *.swo 4 | *.pyc 5 | .idea 6 | *~ 7 | 8 | # Build artifacts 9 | /build/ 10 | cmake-build-debug 11 | debian/**/*.log 12 | *critical.log 13 | obj-x86_64-linux-gnu 14 | examples/cgroupid/cgroupid 15 | 16 | # Output from docker builds 17 | scripts/docker/output/ 18 | /output/ 19 | -------------------------------------------------------------------------------- /examples/tracing/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB C_FILES *.c) 2 | file(GLOB PY_FILES *.py) 3 | file(GLOB TXT_FILES *.txt) 4 | install(PROGRAMS ${PY_FILES} DESTINATION share/bcc/examples/tracing) 5 | install(FILES ${C_FILES} DESTINATION share/bcc/examples/tracing) 6 | install(FILES ${TXT_FILES} DESTINATION share/bcc/examples/tracing) 7 | -------------------------------------------------------------------------------- /libbpf-tools/runqlat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __RUNQLAT_H 3 | #define __RUNQLAT_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define MAX_SLOTS 26 7 | 8 | struct hist { 9 | __u32 slots[MAX_SLOTS]; 10 | char comm[TASK_COMM_LEN]; 11 | }; 12 | 13 | #endif /* __RUNQLAT_H */ 14 | -------------------------------------------------------------------------------- /tests/cc/usdt_test_lib.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "folly/tracing/StaticTracepoint.h" 5 | 6 | extern "C" { 7 | 8 | int lib_probed_function() { 9 | int an_int = 42 + getpid(); 10 | FOLLY_SDT(libbcc_test, sample_lib_probe_1, an_int); 11 | return an_int; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /examples/usdt_sample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | # This sample requires C++11 enabled. 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Weffc++") 5 | 6 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/usdt_sample_lib1) 7 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/usdt_sample_app1) 8 | -------------------------------------------------------------------------------- /examples/tracing/nodejs_http_server_example.txt: -------------------------------------------------------------------------------- 1 | # ./nodejs_http_server.py 24728 2 | TIME(s) COMM PID ARGS 3 | 24653324.561322998 node 24728 path:/index.html 4 | 24653335.343401998 node 24728 path:/images/welcome.png 5 | 24653340.510164998 node 24728 path:/images/favicon.png 6 | -------------------------------------------------------------------------------- /libbpf-tools/biopattern.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | #ifndef __BIOPATTERN_H 3 | #define __BIOPATTERN_H 4 | 5 | #define DISK_NAME_LEN 32 6 | 7 | struct counter { 8 | __u64 last_sector; 9 | __u64 bytes; 10 | __u32 sequential; 11 | __u32 random; 12 | }; 13 | 14 | #endif /* __BIOPATTERN_H */ 15 | -------------------------------------------------------------------------------- /examples/networking/http_filter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(FILES http-parse-complete.c http-parse-simple.c README.md) 2 | set(PROGRAMS http-parse-complete.py http-parse-simple.py) 3 | install(FILES ${FILES} DESTINATION share/bcc/examples/networking/http_filter) 4 | install(PROGRAMS ${PROGRAMS} DESTINATION share/bcc/examples/networking/http_filter) 5 | -------------------------------------------------------------------------------- /examples/networking/tunnel_monitor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(FILES README.md chord.png monitor.c simulation.py vxlan.jpg) 2 | set(PROGRAMS main.py monitor.py setup.sh traffic.sh) 3 | install(FILES ${FILES} DESTINATION share/bcc/examples/networking/tunnel_monitor) 4 | install(PROGRAMS ${PROGRAMS} DESTINATION share/bcc/examples/networking/tunnel_monitor) -------------------------------------------------------------------------------- /examples/networking/vlan_learning/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXAMPLE_FILES README.txt simulation.py vlan_learning.c) 2 | set(EXAMPLE_PROGRAMS vlan_learning.py) 3 | install(FILES ${EXAMPLE_FILES} DESTINATION share/bcc/examples/networking/vlan_learning) 4 | install(PROGRAMS ${EXAMPLE_PROGRAMS} DESTINATION share/bcc/examples/networking/vlan_learning) 5 | -------------------------------------------------------------------------------- /libbpf-tools/hardirqs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __HARDIRQS_H 3 | #define __HARDIRQS_H 4 | 5 | #define MAX_SLOTS 20 6 | 7 | struct irq_key { 8 | char name[32]; 9 | }; 10 | 11 | struct info { 12 | __u64 count; 13 | __u32 slots[MAX_SLOTS]; 14 | }; 15 | 16 | #endif /* __HARDIRQS_H */ 17 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXAMPLE_PROGRAMS hello_world.py) 2 | install(PROGRAMS ${EXAMPLE_PROGRAMS} DESTINATION share/bcc/examples) 3 | 4 | if(ENABLE_CLANG_JIT) 5 | if(ENABLE_USDT) 6 | add_subdirectory(cpp) 7 | endif(ENABLE_USDT) 8 | add_subdirectory(lua) 9 | add_subdirectory(networking) 10 | add_subdirectory(tracing) 11 | endif() 12 | -------------------------------------------------------------------------------- /libbpf-tools/bashreadline.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2021 Facebook */ 3 | #ifndef __BASHREADLINE_H 4 | #define __BASHREADLINE_H 5 | 6 | #define MAX_LINE_SIZE 80 7 | 8 | struct str_t { 9 | __u32 pid; 10 | char str[MAX_LINE_SIZE]; 11 | }; 12 | 13 | #endif /* __BASHREADLINE_H */ 14 | -------------------------------------------------------------------------------- /tests/lua/.luacheckrc: -------------------------------------------------------------------------------- 1 | std = "luajit" 2 | ignore = { "211", "212", "411", "412", "421", "431", "542" } 3 | files["examples"] = { 4 | new_globals = { "pkt", "time", "xadd", "c" } 5 | } 6 | files["bpf/builtins.lua"] = { 7 | ignore = { "122" } 8 | } 9 | files["spec"] = { 10 | std = "+busted", 11 | new_globals = { "pkt", "time", "xadd", "c" } 12 | } -------------------------------------------------------------------------------- /libbpf-tools/btf_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | 3 | #ifndef __BTF_HELPERS_H 4 | #define __BTF_HELPERS_H 5 | 6 | #include 7 | 8 | int ensure_core_btf(struct bpf_object_open_opts *opts); 9 | void cleanup_core_btf(struct bpf_object_open_opts *opts); 10 | 11 | #endif /* __BTF_HELPERS_H */ 12 | -------------------------------------------------------------------------------- /examples/networking/neighbor_sharing/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXAMPLE_FILES README.txt simulation.py tc_neighbor_sharing.c) 2 | set(EXAMPLE_PROGRAMS tc_neighbor_sharing.py) 3 | install(FILES ${EXAMPLE_FILES} DESTINATION share/bcc/examples/networking/neighbor_sharing) 4 | install(PROGRAMS ${EXAMPLE_PROGRAMS} DESTINATION share/bcc/examples/networking/neighbor_sharing) 5 | -------------------------------------------------------------------------------- /libbpf-tools/drsnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __DRSNOOP_H 3 | #define __DRSNOOP_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct event { 8 | char task[TASK_COMM_LEN]; 9 | __u64 delta_ns; 10 | __u64 nr_reclaimed; 11 | __u64 nr_free_pages; 12 | pid_t pid; 13 | }; 14 | 15 | #endif /* __DRSNOOP_H */ 16 | -------------------------------------------------------------------------------- /libbpf-tools/oomkill.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __OOMKILL_H 3 | #define __OOMKILL_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct data_t { 8 | __u32 fpid; 9 | __u32 tpid; 10 | __u64 pages; 11 | char fcomm[TASK_COMM_LEN]; 12 | char tcomm[TASK_COMM_LEN]; 13 | }; 14 | 15 | #endif /* __OOMKILL_H */ 16 | -------------------------------------------------------------------------------- /examples/networking/distributed_bridge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXAMPLE_FILES simulation.py tunnel.c tunnel_mesh.c) 2 | set(EXAMPLE_PROGRAMS main.py tunnel_mesh.py tunnel.py) 3 | install(FILES ${EXAMPLE_FILES} DESTINATION share/bcc/examples/networking/distributed_bridge) 4 | install(PROGRAMS ${EXAMPLE_PROGRAMS} DESTINATION share/bcc/examples/networking/distributed_bridge) 5 | -------------------------------------------------------------------------------- /libbpf-tools/syscount.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Anton Protopopov 3 | #ifndef __SYSCOUNT_H 4 | #define __SYSCOUNT_H 5 | 6 | #define MAX_ENTRIES 8192 7 | 8 | #define TASK_COMM_LEN 16 9 | 10 | struct data_t { 11 | __u64 count; 12 | __u64 total_ns; 13 | char comm[TASK_COMM_LEN]; 14 | }; 15 | 16 | #endif /* __SYSCOUNT_H */ 17 | -------------------------------------------------------------------------------- /libbpf-tools/fsdist.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __FSDIST_H 3 | #define __FSDIST_H 4 | 5 | enum fs_file_op { 6 | READ, 7 | WRITE, 8 | OPEN, 9 | FSYNC, 10 | GETATTR, 11 | MAX_OP, 12 | }; 13 | 14 | #define MAX_SLOTS 32 15 | 16 | struct hist { 17 | __u32 slots[MAX_SLOTS]; 18 | }; 19 | 20 | #endif /* __FSDIST_H */ 21 | -------------------------------------------------------------------------------- /libbpf-tools/filelife.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __FILELIFE_H 3 | #define __FILELIFE_H 4 | 5 | #define DNAME_INLINE_LEN 32 6 | #define TASK_COMM_LEN 16 7 | 8 | struct event { 9 | char file[DNAME_INLINE_LEN]; 10 | char task[TASK_COMM_LEN]; 11 | __u64 delta_ns; 12 | pid_t tgid; 13 | }; 14 | 15 | #endif /* __FILELIFE_H */ 16 | -------------------------------------------------------------------------------- /libbpf-tools/runqslower.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __RUNQSLOWER_H 3 | #define __RUNQSLOWER_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct event { 8 | char task[TASK_COMM_LEN]; 9 | char prev_task[TASK_COMM_LEN]; 10 | __u64 delta_us; 11 | pid_t pid; 12 | pid_t prev_pid; 13 | }; 14 | 15 | #endif /* __RUNQSLOWER_H */ 16 | -------------------------------------------------------------------------------- /libbpf-tools/solisten.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __SOLISTEN_H 3 | #define __SOLISTEN_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct event { 8 | __u32 addr[4]; 9 | __u32 pid; 10 | __u32 proto; 11 | int backlog; 12 | int ret; 13 | short port; 14 | char task[TASK_COMM_LEN]; 15 | }; 16 | 17 | #endif /* __SOLISTEN_H */ 18 | -------------------------------------------------------------------------------- /tests/lua/test_dump.lua: -------------------------------------------------------------------------------- 1 | local suite = require("test_helper") 2 | local TestDump = {} 3 | 4 | function TestDump:test_dump_func() 5 | local raw = "\xb7\x00\x00\x00\x01\x00\x00\x00\x95\x00\x00\x00\x00\x00\x00\x00" 6 | local b = BPF:new{text=[[int entry(void) { return 1; }]]} 7 | assert_equals(b:dump_func("entry"), raw) 8 | end 9 | 10 | suite("TestDump", TestDump) 11 | -------------------------------------------------------------------------------- /libbpf-tools/gethostlatency.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __GETHOSTLATENCY_H 3 | #define __GETHOSTLATENCY_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define HOST_LEN 80 7 | 8 | struct event { 9 | __u64 time; 10 | __u32 pid; 11 | char comm[TASK_COMM_LEN]; 12 | char host[HOST_LEN]; 13 | }; 14 | 15 | #endif /* __GETHOSTLATENCY_H */ 16 | -------------------------------------------------------------------------------- /libbpf-tools/statsnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __STATSNOOP_H 3 | #define __STATSNOOP_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define NAME_MAX 255 7 | 8 | struct event { 9 | __u64 ts_ns; 10 | __u32 pid; 11 | int ret; 12 | char comm[TASK_COMM_LEN]; 13 | char pathname[NAME_MAX]; 14 | }; 15 | 16 | #endif /* __STATSNOOP_H */ 17 | -------------------------------------------------------------------------------- /scripts/git-tag.sh: -------------------------------------------------------------------------------- 1 | git_tag_latest=$(git describe --tags --abbrev=0) 2 | git_rev_count=$(git rev-list $git_tag_latest.. --count) 3 | git_rev_count=$[$git_rev_count+1] 4 | git_subject=$(git log --pretty="%s" -n 1) 5 | release=$git_rev_count 6 | if [[ "$release" != "1" ]]; then 7 | release="${release}.git.$(git log --pretty='%h' -n 1)" 8 | fi 9 | revision=${git_tag_latest:1} 10 | -------------------------------------------------------------------------------- /src/cc/setns.h: -------------------------------------------------------------------------------- 1 | // This file is only needed to support build for CentOS 6 2 | // Remove it when no longer needed. 3 | // File is trivial and therefore is in public domain. 4 | 5 | #ifndef _GNU_SOURCE 6 | #define _GNU_SOURCE 7 | #endif 8 | 9 | #include 10 | #include 11 | 12 | #define setns(FD, NSTYPE) syscall(__NR_setns, (int)(FD), (int)(NSTYPE)) 13 | -------------------------------------------------------------------------------- /libbpf-tools/syscall_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __SYSCALL_HELPERS_H 3 | #define __SYSCALL_HELPERS_H 4 | 5 | #include 6 | 7 | void init_syscall_names(void); 8 | void free_syscall_names(void); 9 | void list_syscalls(void); 10 | void syscall_name(unsigned n, char *buf, size_t size); 11 | 12 | #endif /* __SYSCALL_HELPERS_H */ 13 | -------------------------------------------------------------------------------- /tools/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB PY_FILES *.py) 2 | file(GLOB TXT_FILES *.txt) 3 | list(REMOVE_ITEM TXT_FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) 4 | foreach(FIL ${PY_FILES}) 5 | get_filename_component(FIL_WE ${FIL} NAME_WE) 6 | install(PROGRAMS ${FIL} DESTINATION share/bcc/tools/lib RENAME ${FIL_WE}) 7 | endforeach() 8 | install(FILES ${TXT_FILES} DESTINATION share/bcc/tools/doc/lib) 9 | -------------------------------------------------------------------------------- /libbpf-tools/map_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2020 Anton Protopopov */ 3 | #ifndef __MAP_HELPERS_H 4 | #define __MAP_HELPERS_H 5 | 6 | #include 7 | 8 | int dump_hash(int map_fd, void *keys, __u32 key_size, 9 | void *values, __u32 value_size, __u32 *count, void *invalid_key); 10 | 11 | #endif /* __MAP_HELPERS_H */ 12 | -------------------------------------------------------------------------------- /libbpf-tools/exitsnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __EXITSNOOP_H 3 | #define __EXITSNOOP_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct event { 8 | __u64 start_time; 9 | __u64 exit_time; 10 | __u32 pid; 11 | __u32 tid; 12 | __u32 ppid; 13 | __u32 sig; 14 | int exit_code; 15 | char comm[TASK_COMM_LEN]; 16 | }; 17 | 18 | #endif /* __EXITSNOOP_H */ 19 | -------------------------------------------------------------------------------- /src/cc/libbcc.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ 4 | includedir=${prefix}/include 5 | datarootdir=${prefix}/share 6 | 7 | compatdir=${includedir}/bcc/compat 8 | 9 | Name: libbcc 10 | Version: @REVISION@ 11 | Description: BCC Program library 12 | Requires: 13 | Libs: -L${libdir} -lbcc 14 | Cflags: -I${includedir} -I${compatdir} 15 | -------------------------------------------------------------------------------- /examples/usdt_sample/usdt_sample_lib1/src/lib1_sdt.d: -------------------------------------------------------------------------------- 1 | # This file is only relevant when using systemtap-sdt-devel (see usdt_sample.md). 2 | # This usdt_sample uses the StaticTracepoint.h header file (from folly) instead. 3 | provider usdt_sample_lib1_sdt 4 | { 5 | probe operation_start_sdt(uint64_t operation_id, const char* input); 6 | probe operation_end_sdt(uint64_t operation_id, const char* output); 7 | }; 8 | -------------------------------------------------------------------------------- /libbpf-tools/offcputime.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __OFFCPUTIME_H 3 | #define __OFFCPUTIME_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct key_t { 8 | __u32 pid; 9 | __u32 tgid; 10 | int user_stack_id; 11 | int kern_stack_id; 12 | }; 13 | 14 | struct val_t { 15 | __u64 delta; 16 | char comm[TASK_COMM_LEN]; 17 | }; 18 | 19 | #endif /* __OFFCPUTIME_H */ 20 | -------------------------------------------------------------------------------- /examples/cpp/pyperf/PyPerfLoggingHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. 3 | * Licensed under the Apache License, Version 2.0 (the "License") 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | namespace ebpf { 11 | namespace pyperf { 12 | 13 | void setVerbosity(uint64_t verbosityLevel); 14 | void logInfo(uint64_t logLevel, const char* fmt, ...); 15 | 16 | } // namespace pyperf 17 | } // namespace ebpf 18 | -------------------------------------------------------------------------------- /libbpf-tools/cpufreq.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __CPUFREQ_H 3 | #define __CPUFREQ_H 4 | 5 | #define MAX_ENTRIES 1024 6 | #define MAX_CPU_NR 128 7 | #define MAX_SLOTS 26 8 | #define TASK_COMM_LEN 16 9 | #define HIST_STEP_SIZE 200 10 | 11 | struct hkey { 12 | char comm[TASK_COMM_LEN]; 13 | }; 14 | 15 | struct hist { 16 | __u32 slots[MAX_SLOTS]; 17 | }; 18 | 19 | #endif /* __CPUFREQ_H */ 20 | -------------------------------------------------------------------------------- /examples/cgroupid/Dockerfile: -------------------------------------------------------------------------------- 1 | # builder image 2 | FROM ubuntu:18.04 as builder 3 | RUN apt-get update && \ 4 | apt-get upgrade -y && \ 5 | apt-get install -y --no-install-recommends \ 6 | gcc build-essential && \ 7 | apt-get purge --auto-remove && \ 8 | apt-get clean 9 | 10 | ADD cgroupid.c /cgroupid.c 11 | ADD Makefile /Makefile 12 | RUN make 13 | 14 | # Main image 15 | FROM amd64/alpine:3.8 as base 16 | COPY --from=builder /cgroupid /bin 17 | -------------------------------------------------------------------------------- /tests/python/dummy.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace some_namespace { 5 | static __attribute__((noinline)) int some_function(int x, int y) { 6 | volatile int z = x + y; 7 | return z; 8 | } 9 | } 10 | 11 | int main() { 12 | printf("%p\n", &some_namespace::some_function); 13 | fflush(stdout); 14 | printf("result = %d\n", some_namespace::some_function(42, 11)); 15 | sleep(1000); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/lua/.luacheckrc: -------------------------------------------------------------------------------- 1 | std = 'luajit' 2 | 3 | new_read_globals = { 4 | 'assert', 5 | 'describe', 6 | 'it', 7 | } 8 | new_globals = { 9 | 'math', 10 | } 11 | 12 | -- Luacheck < 0.18 doesn't support new_read_globals 13 | for _, v in ipairs(new_read_globals) do 14 | table.insert(new_globals, v) 15 | end 16 | 17 | -- Ignore some pedantic checks 18 | ignore = { 19 | '4.1/err', -- Shadowing err 20 | '4.1/.', -- Shadowing one letter variables 21 | } 22 | -------------------------------------------------------------------------------- /scripts/build-deb.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | set -e 5 | 6 | PARALLEL=${PARALLEL:-1} 7 | TMP=$(mktemp -d /tmp/debuild.XXXXXX) 8 | 9 | function cleanup() { 10 | [[ -d $TMP ]] && rm -rf $TMP 11 | } 12 | trap cleanup EXIT 13 | 14 | mkdir $TMP/bcc 15 | cp -a * $TMP/bcc 16 | pushd $TMP 17 | tar zcf bcc_@REVISION_LAST@.orig.tar.gz bcc/ 18 | cd bcc 19 | DEB_BUILD_OPTIONS="nocheck parallel=${PARALLEL}" debuild -us -uc 20 | popd 21 | 22 | cp $TMP/*.deb . 23 | -------------------------------------------------------------------------------- /snap/local/bcc-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | # Snappy does not yet support CAP_SYS_ADMIN for unconfined snaps, thus sudo: 4 | # https://bugs.launchpad.net/snappy/+bug/1586581 5 | # stdout isn't set to line buffered mode: 6 | # https://bugs.launchpad.net/snappy/+bug/1587675 7 | 8 | cmd="$1" 9 | if [ `id -u` = 0 ] ; then 10 | shift 11 | stdbuf -oL $SNAP/usr/share/bcc/tools/$cmd "$@" 12 | else 13 | echo "Need to run $cmd as root (use sudo $@)" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /tools/syncsnoop_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of syncsnoop, the Linux eBPF/bcc version. 2 | 3 | 4 | This program traces calls to the kernel sync() routine, with basic timestamps: 5 | 6 | # ./syncsnoop 7 | TIME(s) CALL 8 | 16458148.611952 sync() 9 | 16458151.533709 sync() 10 | ^C 11 | 12 | While tracing, the "sync" command was executed in another server session. 13 | 14 | This can be useful to identify that sync() is being called, and its frequency. 15 | -------------------------------------------------------------------------------- /examples/networking/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXAMPLE_FILES simulation.py) 2 | set(EXAMPLE_PROGRAMS simple_tc.py tc_perf_event.py) 3 | install(FILES ${EXAMPLE_FILES} DESTINATION share/bcc/examples/networking) 4 | install(PROGRAMS ${EXAMPLE_PROGRAMS} DESTINATION share/bcc/examples/networking) 5 | 6 | add_subdirectory(distributed_bridge) 7 | add_subdirectory(neighbor_sharing) 8 | add_subdirectory(vlan_learning) 9 | add_subdirectory(tunnel_monitor) 10 | add_subdirectory(http_filter) 11 | add_subdirectory(xdp) 12 | -------------------------------------------------------------------------------- /libbpf-tools/biolatency.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BIOLATENCY_H 3 | #define __BIOLATENCY_H 4 | 5 | #define DISK_NAME_LEN 32 6 | #define MAX_SLOTS 27 7 | 8 | #define MINORBITS 20 9 | #define MINORMASK ((1U << MINORBITS) - 1) 10 | 11 | #define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi)) 12 | 13 | struct hist_key { 14 | __u32 cmd_flags; 15 | __u32 dev; 16 | }; 17 | 18 | struct hist { 19 | __u32 slots[MAX_SLOTS]; 20 | }; 21 | 22 | #endif /* __BIOLATENCY_H */ 23 | -------------------------------------------------------------------------------- /libbpf-tools/bitesize.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | #ifndef __BITESIZE_H 3 | #define __BITESIZE_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define DISK_NAME_LEN 32 7 | #define MAX_SLOTS 20 8 | 9 | #define MINORBITS 20 10 | #define MINORMASK ((1U << MINORBITS) - 1) 11 | 12 | #define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi)) 13 | 14 | struct hist_key { 15 | char comm[TASK_COMM_LEN]; 16 | }; 17 | 18 | struct hist { 19 | __u32 slots[MAX_SLOTS]; 20 | }; 21 | 22 | #endif /* __BITESIZE_H */ 23 | -------------------------------------------------------------------------------- /examples/hello_world.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | # run in project examples directory with: 6 | # sudo ./hello_world.py" 7 | # see trace_fields.py for a longer example 8 | 9 | from bcc import BPF 10 | 11 | # This may not work for 4.17 on x64, you need replace kprobe__sys_clone with kprobe____x64_sys_clone 12 | BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print() 13 | -------------------------------------------------------------------------------- /libbpf-tools/tcpconnlat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __TCPCONNLAT_H 3 | #define __TCPCONNLAT_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct event { 8 | union { 9 | __u32 saddr_v4; 10 | __u8 saddr_v6[16]; 11 | }; 12 | union { 13 | __u32 daddr_v4; 14 | __u8 daddr_v6[16]; 15 | }; 16 | char comm[TASK_COMM_LEN]; 17 | __u64 delta_us; 18 | __u64 ts_us; 19 | __u32 tgid; 20 | int af; 21 | __u16 lport; 22 | __u16 dport; 23 | }; 24 | 25 | 26 | #endif /* __TCPCONNLAT_H_ */ 27 | -------------------------------------------------------------------------------- /man/man8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_program(GZIP gzip) 2 | file(GLOB FILES *.8) 3 | set(GZFILES "") 4 | foreach(FIL ${FILES}) 5 | get_filename_component(NAME ${FIL} NAME) 6 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.gz 7 | COMMAND ${GZIP} -c ${FIL} > ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.gz 8 | DEPENDS ${FIL}) 9 | list(APPEND GZFILES "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.gz") 10 | endforeach() 11 | add_custom_target(man ALL DEPENDS ${GZFILES}) 12 | install(FILES ${GZFILES} DESTINATION share/bcc/man/man8) 13 | -------------------------------------------------------------------------------- /docker/Dockerfile.debian: -------------------------------------------------------------------------------- 1 | FROM debian:stretch 2 | 3 | MAINTAINER Brenden Blanco 4 | 5 | RUN DEBIAN_RELEASE=stretch && \ 6 | # Adding non-free repo for netperf 7 | echo "deb http://deb.debian.org/debian ${DEBIAN_RELEASE} non-free" > \ 8 | /etc/apt/sources.list.d/debian-non-free.list && \ 9 | apt-get -qq update && \ 10 | apt-get -y install pbuilder aptitude 11 | 12 | COPY ./ /root/bcc 13 | 14 | WORKDIR /root/bcc 15 | 16 | RUN /usr/lib/pbuilder/pbuilder-satisfydepends && \ 17 | ./scripts/build-deb.sh 18 | -------------------------------------------------------------------------------- /libbpf-tools/fsslower.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __FSSLOWER_H 3 | #define __FSSLOWER_H 4 | 5 | #define FILE_NAME_LEN 32 6 | #define TASK_COMM_LEN 16 7 | 8 | enum fs_file_op { 9 | READ, 10 | WRITE, 11 | OPEN, 12 | FSYNC, 13 | MAX_OP, 14 | }; 15 | 16 | struct event { 17 | __u64 delta_us; 18 | __u64 end_ns; 19 | __s64 offset; 20 | ssize_t size; 21 | pid_t pid; 22 | enum fs_file_op op; 23 | char file[FILE_NAME_LEN]; 24 | char task[TASK_COMM_LEN]; 25 | }; 26 | 27 | #endif /* __FSSLOWER_H */ 28 | -------------------------------------------------------------------------------- /examples/tracing/mysqld_query_example.txt: -------------------------------------------------------------------------------- 1 | # ./mysqld_query.py `pgrep -n mysqld` 2 | TIME(s) COMM PID QUERY 3 | 17450459.549910001 mysqld 18608 select @@version_comment limit 1 4 | 17450463.822668001 mysqld 18608 SELECT DATABASE() 5 | 17450463.824042998 mysqld 18608 show databases 6 | 17450463.824570000 mysqld 18608 show tables 7 | 17450465.602717999 mysqld 18608 SELECT COUNT(*) FROM words 8 | 17450479.944897000 mysqld 18608 SELECT * FROM words WHERE word REGEXP '^bre.*n$' 9 | -------------------------------------------------------------------------------- /libbpf-tools/opensnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __OPENSNOOP_H 3 | #define __OPENSNOOP_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define NAME_MAX 255 7 | #define INVALID_UID ((uid_t)-1) 8 | 9 | struct args_t { 10 | const char *fname; 11 | int flags; 12 | }; 13 | 14 | struct event { 15 | /* user terminology for pid: */ 16 | __u64 ts; 17 | pid_t pid; 18 | uid_t uid; 19 | int ret; 20 | int flags; 21 | char comm[TASK_COMM_LEN]; 22 | char fname[NAME_MAX]; 23 | }; 24 | 25 | #endif /* __OPENSNOOP_H */ 26 | -------------------------------------------------------------------------------- /tests/python/test_trace2.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) PLUMgrid, Inc. 2 | // Licensed under the Apache License, Version 2.0 (the "License") 3 | #include 4 | struct Ptr { u64 ptr; }; 5 | struct Counters { u64 stat1; }; 6 | BPF_HASH(stats, struct Ptr, struct Counters, 1024); 7 | 8 | int count_sched(struct pt_regs *ctx) { 9 | struct Ptr key = {.ptr = PT_REGS_PARM1(ctx)}; 10 | struct Counters zleaf = {0}; 11 | struct Counters *val = stats.lookup_or_try_init(&key, &zleaf); 12 | if (val) { 13 | val->stat1++; 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /libbpf-tools/klockstat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __KLOCKSTAT_H 3 | 4 | #define MAX_ENTRIES 102400 5 | #define TASK_COMM_LEN 16 6 | #define PERF_MAX_STACK_DEPTH 127 7 | 8 | struct lock_stat { 9 | __u64 acq_count; 10 | __u64 acq_total_time; 11 | __u64 acq_max_time; 12 | __u64 acq_max_id; 13 | char acq_max_comm[TASK_COMM_LEN]; 14 | __u64 hld_count; 15 | __u64 hld_total_time; 16 | __u64 hld_max_time; 17 | __u64 hld_max_id; 18 | char hld_max_comm[TASK_COMM_LEN]; 19 | }; 20 | 21 | #endif /*__KLOCKSTAT_H */ 22 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | configure_file(wrapper.sh.in "${CMAKE_CURRENT_BINARY_DIR}/wrapper.sh" @ONLY) 4 | 5 | set(TEST_WRAPPER ${CMAKE_CURRENT_BINARY_DIR}/wrapper.sh) 6 | 7 | add_test(NAME style-check COMMAND ${CMAKE_SOURCE_DIR}/scripts/c-style-check.sh) 8 | set_tests_properties(style-check PROPERTIES PASS_REGULAR_EXPRESSION ".*") 9 | 10 | if(ENABLE_CLANG_JIT) 11 | add_subdirectory(cc) 12 | add_subdirectory(python) 13 | add_subdirectory(lua) 14 | endif() 15 | -------------------------------------------------------------------------------- /examples/cpp/pyperf/PyPerfSampleProcessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. 3 | * Licensed under the Apache License, Version 2.0 (the "License") 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include "PyPerfType.h" 11 | 12 | namespace ebpf { 13 | namespace pyperf { 14 | 15 | class PyPerfUtil; 16 | 17 | class PyPerfSampleProcessor { 18 | public: 19 | virtual void processSamples(const std::vector& samples, 20 | PyPerfUtil* util) = 0; 21 | }; 22 | 23 | } // namespace pyperf 24 | } // namespace ebpf 25 | -------------------------------------------------------------------------------- /examples/tracing/task_switch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | from bcc import BPF 6 | from time import sleep 7 | 8 | b = BPF(src_file="task_switch.c") 9 | b.attach_kprobe(event_re="^finish_task_switch$|^finish_task_switch\.isra\.\d$", 10 | fn_name="count_sched") 11 | 12 | # generate many schedule events 13 | for i in range(0, 100): sleep(0.01) 14 | 15 | for k, v in b["stats"].items(): 16 | print("task_switch[%5d->%5d]=%u" % (k.prev_pid, k.curr_pid, v.value)) 17 | -------------------------------------------------------------------------------- /examples/lua/bashreadline.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct str_t { 4 | u64 pid; 5 | char str[80]; 6 | }; 7 | 8 | BPF_PERF_OUTPUT(events); 9 | 10 | int printret(struct pt_regs *ctx) 11 | { 12 | struct str_t data = {}; 13 | u32 pid; 14 | if (!PT_REGS_RC(ctx)) 15 | return 0; 16 | pid = bpf_get_current_pid_tgid(); 17 | data.pid = pid; 18 | bpf_probe_read_user(&data.str, sizeof(data.str), 19 | (void *)PT_REGS_RC(ctx)); 20 | events.perf_submit(ctx, &data, sizeof(data)); 21 | return 0; 22 | }; 23 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 5 | 6 | if (ENABLE_RTTI) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti") 8 | else() 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") 10 | endif() 11 | 12 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 13 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 14 | 15 | if(NOT PYTHON_ONLY) 16 | add_subdirectory(cc) 17 | endif() 18 | if(ENABLE_CLANG_JIT) 19 | add_subdirectory(python) 20 | add_subdirectory(lua) 21 | endif() 22 | -------------------------------------------------------------------------------- /libbpf-tools/biosnoop.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | #ifndef __BIOSNOOP_H 3 | #define __BIOSNOOP_H 4 | 5 | #define DISK_NAME_LEN 32 6 | #define TASK_COMM_LEN 16 7 | #define RWBS_LEN 8 8 | 9 | #define MINORBITS 20 10 | #define MINORMASK ((1U << MINORBITS) - 1) 11 | 12 | #define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi)) 13 | 14 | struct event { 15 | char comm[TASK_COMM_LEN]; 16 | __u64 delta; 17 | __u64 qdelta; 18 | __u64 ts; 19 | __u64 sector; 20 | __u32 len; 21 | __u32 pid; 22 | __u32 cmd_flags; 23 | __u32 dev; 24 | }; 25 | 26 | #endif /* __BIOSNOOP_H */ 27 | -------------------------------------------------------------------------------- /cmake/bump_version.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | configure_file(SPECS/Dockerfile.el6.in SPECS/Dockerfile.el6 @ONLY) 5 | configure_file(SPECS/Dockerfile.el7.in SPECS/Dockerfile.el7 @ONLY) 6 | configure_file(SPECS/Dockerfile.f22.in SPECS/Dockerfile.f22 @ONLY) 7 | configure_file(SPECS/bcc.el6.spec.in SPECS/bcc.el6.spec @ONLY) 8 | configure_file(SPECS/bcc.el7.spec.in SPECS/bcc.el7.spec @ONLY) 9 | configure_file(SPECS/bcc.f22.spec.in SPECS/bcc.f22.spec @ONLY) 10 | configure_file(scripts/build-deb.sh.in scripts/build-deb.sh @ONLY) 11 | -------------------------------------------------------------------------------- /examples/tracing/task_switch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct key_t { 5 | u32 prev_pid; 6 | u32 curr_pid; 7 | }; 8 | 9 | BPF_HASH(stats, struct key_t, u64, 1024); 10 | int count_sched(struct pt_regs *ctx, struct task_struct *prev) { 11 | struct key_t key = {}; 12 | u64 zero = 0, *val; 13 | 14 | key.curr_pid = bpf_get_current_pid_tgid(); 15 | key.prev_pid = prev->pid; 16 | 17 | // could also use `stats.increment(key);` 18 | val = stats.lookup_or_try_init(&key, &zero); 19 | if (val) { 20 | (*val)++; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /libbpf-tools/filetop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __FILETOP_H 3 | #define __FILETOP_H 4 | 5 | #define PATH_MAX 4096 6 | #define TASK_COMM_LEN 16 7 | 8 | enum op { 9 | READ, 10 | WRITE, 11 | }; 12 | 13 | struct file_id { 14 | __u64 inode; 15 | __u32 dev; 16 | __u32 rdev; 17 | __u32 pid; 18 | __u32 tid; 19 | }; 20 | 21 | struct file_stat { 22 | __u64 reads; 23 | __u64 read_bytes; 24 | __u64 writes; 25 | __u64 write_bytes; 26 | __u32 pid; 27 | __u32 tid; 28 | char filename[PATH_MAX]; 29 | char comm[TASK_COMM_LEN]; 30 | char type; 31 | }; 32 | 33 | #endif /* __FILETOP_H */ 34 | -------------------------------------------------------------------------------- /scripts/c-style-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Runs clang-format on the files changed between HEAD and $1, which defaults to 4 | # origin/master. 5 | 6 | # to pick up git-clang-format from scripts/ 7 | export PATH=$(dirname $0):$PATH 8 | 9 | CLANG_FORMAT=${CLANG_FORMAT:-clang-format} 10 | GITREF=${1:-origin/master} 11 | 12 | if ! hash $CLANG_FORMAT 2> /dev/null; then 13 | echo "Could not find clang-format tool" 1>&2 14 | exit 1 15 | fi 16 | 17 | cmd="git clang-format $GITREF --binary $CLANG_FORMAT --diff --extensions h,c,cc" 18 | 19 | n=$($cmd --quiet | wc -l) 20 | if [ $n -gt 0 ]; then 21 | $cmd -v 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /src/python/setup.py.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | from distutils.core import setup 4 | import os 5 | import sys 6 | 7 | # sdist does not support --root. 8 | if "sdist" not in sys.argv and os.environ.get('DESTDIR'): 9 | sys.argv += ['--root', os.environ['DESTDIR']] 10 | 11 | setup(name='bcc', 12 | version='@REVISION@', 13 | description='BPF Loader Library', 14 | author='Brenden Blanco', 15 | author_email='bblanco@plumgrid.com', 16 | url='https://github.com/iovisor/bcc', 17 | packages=['bcc'], 18 | platforms=['Linux']) 19 | -------------------------------------------------------------------------------- /libbpf-tools/biostacks.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BIOSTACKS_H 3 | #define __BIOSTACKS_H 4 | 5 | #define DISK_NAME_LEN 32 6 | #define TASK_COMM_LEN 16 7 | #define MAX_SLOTS 20 8 | #define MAX_STACK 20 9 | 10 | #define MINORBITS 20 11 | #define MINORMASK ((1U << MINORBITS) - 1) 12 | 13 | #define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi)) 14 | 15 | struct rqinfo { 16 | __u32 pid; 17 | int kern_stack_size; 18 | __u64 kern_stack[MAX_STACK]; 19 | char comm[TASK_COMM_LEN]; 20 | __u32 dev; 21 | }; 22 | 23 | struct hist { 24 | __u32 slots[MAX_SLOTS]; 25 | }; 26 | 27 | #endif /* __BIOSTACKS_H */ 28 | -------------------------------------------------------------------------------- /scripts/py-style-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # TODO: stop ignoring this. Maybe autopep8 existing stuff? 6 | find tools -type f -name "*.py" | xargs pycodestyle -r --show-source --ignore=E123,E125,E126,E127,E128,E302 || \ 7 | echo "pycodestyle run failed, please fix it" >&2 8 | 9 | NO_PROPER_SHEBANG="$(find tools examples -type f -executable -name '*.py' | xargs grep -L '#!/usr/bin/python')" 10 | if [ -n "$NO_PROPER_SHEBANG" ]; then 11 | echo "bad shebangs found:" 12 | echo "$NO_PROPER_SHEBANG" 13 | echo 14 | echo "either add proper shebang or remove executable bit" >&2 15 | 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /tests/lua/test_helper.lua: -------------------------------------------------------------------------------- 1 | function setup_path() 2 | local str = require("debug").getinfo(2, "S").source:sub(2) 3 | local cwd = str:match("(.*/)") 4 | local bpf_path = cwd.."/../../src/lua/?.lua;" 5 | local test_path = cwd.."/?.lua;" 6 | package.path = bpf_path..test_path..package.path 7 | end 8 | 9 | setup_path() 10 | 11 | USE_EXPECTED_ACTUAL_IN_ASSERT_EQUALS = false 12 | EXPORT_ASSERT_TO_GLOBALS = true 13 | require("luaunit") 14 | 15 | rawset(_G, "BCC", require("bcc.init")) 16 | rawset(_G, "BPF", BCC.BPF) 17 | 18 | log.enabled = false 19 | 20 | return function (name, f) 21 | rawset(_G, name, f) 22 | os.exit(LuaUnit.run()) 23 | end 24 | -------------------------------------------------------------------------------- /src/cc/frontends/clang/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKERNEL_MODULES_DIR='\"${BCC_KERNEL_MODULES_DIR}\"'") 5 | if(DEFINED BCC_CUR_CPU_IDENTIFIER) 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCUR_CPU_IDENTIFIER='\"${BCC_CUR_CPU_IDENTIFIER}\"'") 7 | endif() 8 | if(DEFINED BCC_BACKUP_COMPILE) 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBCC_BACKUP_COMPILE='${BCC_BACKUP_COMPILE}'") 10 | endif() 11 | 12 | add_library(clang_frontend STATIC loader.cc b_frontend_action.cc tp_frontend_action.cc kbuild_helper.cc ../../common.cc) 13 | -------------------------------------------------------------------------------- /src/lua/bpf/spec/compile_spec.lua: -------------------------------------------------------------------------------- 1 | describe('compile', function() 2 | local ffi = require('ffi') 3 | local bpf = require('bpf') 4 | 5 | it('can compile socket filter', function() 6 | -- Create mock BPF map 7 | local mock_map = { 8 | max_entries = 16, 9 | key_type = ffi.typeof('uint64_t [1]'), 10 | val_type = ffi.typeof('uint64_t [1]'), 11 | fd = 1, 12 | __map = true, 13 | } 14 | -- Compile small code example 15 | local code = bpf(function () 16 | local proto = pkt.ip.proto 17 | xadd(mock_map[proto], 1) 18 | end) 19 | assert.truthy(code) 20 | assert.same(type(code), 'table') 21 | assert.same(code.pc, 15) 22 | end) 23 | end) 24 | -------------------------------------------------------------------------------- /QUICKSTART.md: -------------------------------------------------------------------------------- 1 | # Quick Start Guide 2 | 3 | A Docker container is provided for user to try out [bcc](https://github.com/iovisor/bcc). 4 | 5 | From your host shell: 6 | ```bash 7 | docker run -it --rm \ 8 | --privileged \ 9 | -v /lib/modules:/lib/modules:ro \ 10 | -v /usr/src:/usr/src:ro \ 11 | -v /etc/localtime:/etc/localtime:ro \ 12 | --workdir /usr/share/bcc/tools \ 13 | zlim/bcc 14 | ``` 15 | 16 | Now, from the container shell, you can try the various pre-installed bcc tools. 17 | 18 | For examples, please refer to the [tutorial](docs/tutorial.md#1-general-performance). 19 | 20 | If you wish to install bcc on your host, please refer to [INSTALL.md](INSTALL.md). 21 | -------------------------------------------------------------------------------- /libbpf-tools/bindsnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BINDSNOOP_H 3 | #define __BINDSNOOP_H 4 | 5 | #define TASK_COMM_LEN 16 6 | 7 | struct bind_event { 8 | unsigned __int128 addr; 9 | __u64 ts_us; 10 | __u32 pid; 11 | __u32 bound_dev_if; 12 | int ret; 13 | __u16 port; 14 | __u16 proto; 15 | __u8 opts; 16 | __u8 ver; 17 | char task[TASK_COMM_LEN]; 18 | }; 19 | 20 | union bind_options { 21 | __u8 data; 22 | struct { 23 | __u8 freebind : 1; 24 | __u8 transparent : 1; 25 | __u8 bind_address_no_port : 1; 26 | __u8 reuseaddress : 1; 27 | __u8 reuseport : 1; 28 | } fields; 29 | }; 30 | 31 | #endif /* __BINDSNOOP_H */ 32 | -------------------------------------------------------------------------------- /libbpf-tools/maps.bpf.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | // Copyright (c) 2020 Anton Protopopov 3 | #ifndef __MAPS_BPF_H 4 | #define __MAPS_BPF_H 5 | 6 | #include 7 | #include 8 | 9 | static __always_inline void * 10 | bpf_map_lookup_or_try_init(void *map, const void *key, const void *init) 11 | { 12 | void *val; 13 | long err; 14 | 15 | val = bpf_map_lookup_elem(map, key); 16 | if (val) 17 | return val; 18 | 19 | err = bpf_map_update_elem(map, key, init, BPF_NOEXIST); 20 | if (err && err != -EEXIST) 21 | return 0; 22 | 23 | return bpf_map_lookup_elem(map, key); 24 | } 25 | 26 | #endif /* __MAPS_BPF_H */ 27 | -------------------------------------------------------------------------------- /src/lua/bpf/init.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2016 Marek Vavrusa 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ]] 16 | return require('bpf.bpf') 17 | -------------------------------------------------------------------------------- /examples/local_storage/inode_storage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from bcc import BPF 4 | 5 | source = r""" 6 | #include 7 | 8 | BPF_INODE_STORAGE(inode_storage_map, int); 9 | 10 | LSM_PROBE(inode_rename, struct inode *old_dir, struct dentry *old_dentry, 11 | struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) 12 | { 13 | int *value; 14 | 15 | value = inode_storage_map.inode_storage_get(old_dentry->d_inode, 0, BPF_LOCAL_STORAGE_GET_F_CREATE); 16 | if (!value) 17 | return 0; 18 | 19 | bpf_trace_printk("%d", *value); 20 | return 0; 21 | } 22 | """ 23 | 24 | b = BPF(text=source) 25 | try: 26 | b.trace_print() 27 | except KeyboardInterrupt: 28 | pass 29 | -------------------------------------------------------------------------------- /src/lua/bcc/init.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2016 GitHub, Inc 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ]] 16 | require("bcc.vendor.helpers") 17 | return { BPF = require("bcc.bpf") } 18 | -------------------------------------------------------------------------------- /tests/python/test_dump_func.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | # test program for the 'dump_func' method 6 | 7 | from bcc import BPF 8 | from unittest import main, TestCase 9 | 10 | class TestDumpFunc(TestCase): 11 | def test_return(self): 12 | b = BPF(text=""" 13 | int entry(void) 14 | { 15 | return 1; 16 | }""") 17 | 18 | self.assertEqual( 19 | b"\xb7\x00\x00\x00\x01\x00\x00\x00" + 20 | b"\x95\x00\x00\x00\x00\x00\x00\x00", 21 | b.dump_func("entry")) 22 | 23 | if __name__ == "__main__": 24 | main() 25 | -------------------------------------------------------------------------------- /examples/tracing/trace_fields.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | # This is an example of tracing an event and printing custom fields. 6 | # run in project examples directory with: 7 | # sudo ./trace_fields.py" 8 | 9 | from __future__ import print_function 10 | from bcc import BPF 11 | 12 | prog = """ 13 | int hello(void *ctx) { 14 | bpf_trace_printk("Hello, World!\\n"); 15 | return 0; 16 | } 17 | """ 18 | b = BPF(text=prog) 19 | b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello") 20 | print("PID MESSAGE") 21 | try: 22 | b.trace_print(fmt="{1} {5}") 23 | except KeyboardInterrupt: 24 | exit() 25 | -------------------------------------------------------------------------------- /libbpf-tools/uprobe_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2021 Google LLC. */ 3 | #ifndef __UPROBE_HELPERS_H 4 | #define __UPROBE_HELPERS_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int get_pid_binary_path(pid_t pid, char *path, size_t path_sz); 11 | int get_pid_lib_path(pid_t pid, const char *lib, char *path, size_t path_sz); 12 | int resolve_binary_path(const char *binary, pid_t pid, char *path, size_t path_sz); 13 | off_t get_elf_func_offset(const char *path, const char *func); 14 | Elf *open_elf(const char *path, int *fd_close); 15 | Elf *open_elf_by_fd(int fd); 16 | void close_elf(Elf *e, int fd_close); 17 | 18 | #endif /* __UPROBE_HELPERS_H */ 19 | -------------------------------------------------------------------------------- /examples/tracing/biolatpcts_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of biolatpcts.py, the Linux eBPF/bcc version. 2 | 3 | 4 | This traces block I/O and uses layered percpu arrays to bucket the completion 5 | latencies. Latency percentiles are calculated periodically from the buckets. 6 | 7 | # ./biolatpcts.py 8 | p50=595.0us p75=685.0us p90=1500.0us p99=2500.0us 9 | p50=55.0us p75=95.0us p90=305.0us p99=2500.0us 10 | p50=385.0us p75=655.0us p90=1500.0us p99=2500.0us 11 | [...] 12 | 13 | The latency is measured from I/O request to the device, to the device 14 | completion. This excludes latency spent queued in the OS. 15 | 16 | This is a simplified example to demonstrate the calculation of latency 17 | percentiles. See tools/biolatpcts.py for the full utility. 18 | -------------------------------------------------------------------------------- /examples/cpp/pyperf/PyPerfLoggingHelper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. 3 | * Licensed under the Apache License, Version 2.0 (the "License") 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "PyPerfLoggingHelper.h" 10 | 11 | namespace ebpf { 12 | namespace pyperf { 13 | 14 | static uint64_t setVerbosityLevel = 0; 15 | 16 | void setVerbosity(uint64_t verbosityLevel) { 17 | setVerbosityLevel = verbosityLevel; 18 | } 19 | 20 | void logInfo(uint64_t logLevel, const char* fmt, ...) { 21 | if (logLevel > setVerbosityLevel) { 22 | return; 23 | } 24 | 25 | va_list va; 26 | va_start(va, fmt); 27 | std::vfprintf(stderr, fmt, va); 28 | va_end(va); 29 | } 30 | 31 | } // namespace pyperf 32 | } // namespace ebpf 33 | -------------------------------------------------------------------------------- /src/lua/bpf/spec/elf_spec.lua: -------------------------------------------------------------------------------- 1 | describe('elf reader', function() 2 | 3 | local ok, elf = pcall(require, 'bpf.elf') 4 | if not ok then return end 5 | 6 | it('should handle C library', function() 7 | -- Open libc 8 | local sh = elf.open('/bin/sh') 9 | assert.truthy(sh) 10 | -- Find load address 11 | local base = sh:loadaddr() 12 | assert.truthy(base) 13 | -- Find something from ISO C 14 | local malloc_addr = sh:resolve('malloc') 15 | assert.truthy(malloc_addr) 16 | -- Find something that doesn't exist 17 | local bad_addr = sh:resolve('thisnotexists') 18 | assert.falsy(bad_addr) 19 | end) 20 | it('should fail on bad input', function() 21 | assert.falsy(elf.open(nil)) 22 | assert.falsy(elf.open('/tmp'):loadaddr()) 23 | end) 24 | end) 25 | -------------------------------------------------------------------------------- /src/cc/link_all.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 VMware, Inc. 2 | // Licensed under the Apache License, Version 2.0 (the "License") 3 | #include 4 | 5 | #include "bcc_usdt.h" 6 | 7 | namespace { 8 | // Take this trick from llvm for forcing exported functions in helper 9 | // libraries to be included in the final .so 10 | struct LinkAll { 11 | LinkAll() { 12 | // getenv never returns -1, but compiler doesn't know! 13 | if (::getenv("bar") != (char *)-1) 14 | return; 15 | 16 | #ifdef EXPORT_USDT 17 | (void)bcc_usdt_new_frompid(-1, nullptr); 18 | (void)bcc_usdt_new_frompath(nullptr); 19 | (void)bcc_usdt_close(nullptr); 20 | #endif 21 | } 22 | } LinkAll; // declare one instance to invoke the constructor 23 | } 24 | -------------------------------------------------------------------------------- /libbpf-tools/execsnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __EXECSNOOP_H 3 | #define __EXECSNOOP_H 4 | 5 | #define ARGSIZE 128 6 | #define TASK_COMM_LEN 16 7 | #define TOTAL_MAX_ARGS 60 8 | #define DEFAULT_MAXARGS 20 9 | #define FULL_MAX_ARGS_ARR (TOTAL_MAX_ARGS * ARGSIZE) 10 | #define INVALID_UID ((uid_t)-1) 11 | #define BASE_EVENT_SIZE (size_t)(&((struct event*)0)->args) 12 | #define EVENT_SIZE(e) (BASE_EVENT_SIZE + e->args_size) 13 | #define LAST_ARG (FULL_MAX_ARGS_ARR - ARGSIZE) 14 | 15 | struct event { 16 | pid_t pid; 17 | pid_t ppid; 18 | uid_t uid; 19 | int retval; 20 | int args_count; 21 | unsigned int args_size; 22 | char comm[TASK_COMM_LEN]; 23 | char args[FULL_MAX_ARGS_ARR]; 24 | }; 25 | 26 | #endif /* __EXECSNOOP_H */ 27 | -------------------------------------------------------------------------------- /examples/cpp/pyperf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | include_directories(${CMAKE_SOURCE_DIR}/src/cc) 5 | include_directories(${CMAKE_SOURCE_DIR}/src/cc/api) 6 | include_directories(${CMAKE_SOURCE_DIR}/src/cc/libbpf/include/uapi) 7 | 8 | add_executable(PyPerf PyPerf.cc PyPerfUtil.cc PyPerfBPFProgram.cc PyPerfLoggingHelper.cc PyPerfDefaultPrinter.cc Py36Offsets.cc) 9 | target_link_libraries(PyPerf bcc-static) 10 | if(NOT CMAKE_USE_LIBBPF_PACKAGE) 11 | target_link_libraries(PyPerf bcc-static) 12 | else() 13 | target_link_libraries(PyPerf bcc-shared) 14 | endif() 15 | 16 | if(INSTALL_CPP_EXAMPLES) 17 | install (TARGETS PyPerf DESTINATION share/bcc/examples/cpp) 18 | endif(INSTALL_CPP_EXAMPLES) 19 | -------------------------------------------------------------------------------- /examples/tracing/urandomread_example.txt: -------------------------------------------------------------------------------- 1 | Examples of urandomread.py, the Linux eBPF/bcc version. 2 | 3 | 4 | To demonstrate this, the following workload was issued: 5 | 6 | # dd if=/dev/urandom of=/dev/null bs=1k count=5 7 | 8 | While urandomread.py was tracing in another session: 9 | 10 | # ./urandomread.py 11 | TIME(s) COMM PID GOTBITS 12 | 22592556.392825000 dd 14228 8192 13 | 22592556.392949000 dd 14228 8192 14 | 22592556.393068999 dd 14228 8192 15 | 22592556.393183999 dd 14228 8192 16 | 22592556.393298000 dd 14228 8192 17 | 18 | The GOTBITS of 8192 matches the workload of 1 Kbyte (8 Kbit) reads. 19 | 20 | This program was really written as a simple example of tracing a tracepoint. 21 | -------------------------------------------------------------------------------- /libbpf-tools/bits.bpf.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BITS_BPF_H 3 | #define __BITS_BPF_H 4 | 5 | #define READ_ONCE(x) (*(volatile typeof(x) *)&(x)) 6 | #define WRITE_ONCE(x, val) ((*(volatile typeof(x) *)&(x)) = val) 7 | 8 | static __always_inline u64 log2(u32 v) 9 | { 10 | u32 shift, r; 11 | 12 | r = (v > 0xFFFF) << 4; v >>= r; 13 | shift = (v > 0xFF) << 3; v >>= shift; r |= shift; 14 | shift = (v > 0xF) << 2; v >>= shift; r |= shift; 15 | shift = (v > 0x3) << 1; v >>= shift; r |= shift; 16 | r |= (v >> 1); 17 | 18 | return r; 19 | } 20 | 21 | static __always_inline u64 log2l(u64 v) 22 | { 23 | u32 hi = v >> 32; 24 | 25 | if (hi) 26 | return log2(hi) + 32; 27 | else 28 | return log2(v); 29 | } 30 | 31 | #endif /* __BITS_BPF_H */ 32 | -------------------------------------------------------------------------------- /tools/pidpersec_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of pidpersec, the Linux eBPF/bcc version. 2 | 3 | 4 | This shows the number of new processes created per second, measured by tracing 5 | the kernel fork() routine: 6 | 7 | # ./pidpersec 8 | Tracing... Ctrl-C to end. 9 | 18:33:06: PIDs/sec: 4 10 | 18:33:07: PIDs/sec: 5 11 | 18:33:08: PIDs/sec: 4 12 | 18:33:09: PIDs/sec: 4 13 | 18:33:10: PIDs/sec: 21 14 | 18:33:11: PIDs/sec: 5 15 | 18:33:12: PIDs/sec: 4 16 | 18:33:13: PIDs/sec: 4 17 | 18 | Each second there are four new processes (this happens to be caused by a 19 | launcher script that is retrying in a loop, and encountering errors). 20 | 21 | At 18:33:10, I typed "man ls" in another server session, which caused an 22 | increase in the number of new processes as the necessary commands were run. 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | matrix: 3 | include: 4 | - name: "Check helpers on Python 2.7" 5 | python: 2.7 6 | script: ./scripts/check-helpers.sh 7 | - name: "Python style check on Python 2.7" 8 | python: 2.7 9 | script: ./scripts/py-style-check.sh 10 | - name: "flake8 lint on Python 2.7" 11 | python: 2.7 12 | script: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 13 | - name: "flake8 lint on Python 3.7" 14 | dist: xenial # required for Python >= 3.7 15 | python: 3.7 16 | script: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 17 | allow_failures: 18 | - name: "Check helpers on Python 2.7" 19 | before_install: pip install --upgrade pip 20 | install: pip install flake8 21 | -------------------------------------------------------------------------------- /libbpf-tools/.gitignore: -------------------------------------------------------------------------------- 1 | /.output 2 | /btfhub-archive 3 | /bashreadline 4 | /bindsnoop 5 | /biolatency 6 | /biopattern 7 | /biosnoop 8 | /biostacks 9 | /bitesize 10 | /btrfsdist 11 | /btrfsslower 12 | /cachestat 13 | /cpudist 14 | /cpufreq 15 | /drsnoop 16 | /execsnoop 17 | /exitsnoop 18 | /ext4dist 19 | /ext4slower 20 | /filelife 21 | /filetop 22 | /fsdist 23 | /fsslower 24 | /funclatency 25 | /gethostlatency 26 | /hardirqs 27 | /klockstat 28 | /ksnoop 29 | /llcstat 30 | /nfsdist 31 | /nfsslower 32 | /mountsnoop 33 | /numamove 34 | /offcputime 35 | /oomkill 36 | /opensnoop 37 | /readahead 38 | /runqlat 39 | /runqlen 40 | /runqslower 41 | /softirqs 42 | /solisten 43 | /statsnoop 44 | /syscount 45 | /tcpconnect 46 | /tcpconnlat 47 | /tcprtt 48 | /tcpsynbl 49 | /vfsstat 50 | /xfsdist 51 | /xfsslower 52 | -------------------------------------------------------------------------------- /libbpf-tools/mountsnoop.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __MOUNTSNOOP_H 3 | #define __MOUNTSNOOP_H 4 | 5 | #define TASK_COMM_LEN 16 6 | #define FS_NAME_LEN 8 7 | #define DATA_LEN 512 8 | #define PATH_MAX 4096 9 | 10 | enum op { 11 | MOUNT, 12 | UMOUNT, 13 | }; 14 | 15 | struct arg { 16 | __u64 ts; 17 | __u64 flags; 18 | const char *src; 19 | const char *dest; 20 | const char *fs; 21 | const char *data; 22 | enum op op; 23 | }; 24 | 25 | struct event { 26 | __u64 delta; 27 | __u64 flags; 28 | __u32 pid; 29 | __u32 tid; 30 | unsigned int mnt_ns; 31 | int ret; 32 | char comm[TASK_COMM_LEN]; 33 | char fs[FS_NAME_LEN]; 34 | char src[PATH_MAX]; 35 | char dest[PATH_MAX]; 36 | char data[DATA_LEN]; 37 | enum op op; 38 | }; 39 | 40 | #endif /* __MOUNTSNOOP_H */ 41 | -------------------------------------------------------------------------------- /scripts/docker/auth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # For now only quay.io is supported, but this could be portable to dockerhub 5 | # and other image repositories. 6 | 7 | # Forks can push using this approach if they create a quay.io bot user 8 | # with name matching of ORGNAME+bcc_buildbot, or by setting QUAY_BOT_NAME 9 | 10 | git_repo=$1 # github.repository format: ORGNAME/REPONAME 11 | 12 | # Set this value as QUAY_TOKEN in the github repository settings "Secrets" tab 13 | [[ -z "${QUAY_TOKEN}" ]] && echo "QUAY_TOKEN not set" && exit 0 14 | 15 | # Set this to match the name of the bot user on quay.io 16 | [[ -z "${QUAY_BOT_NAME}" ]] && QUAY_BOT_NAME="bcc_buildbot" 17 | 18 | quay_user="$(dirname ${git_repo})+${QUAY_BOT_NAME}" 19 | echo "${QUAY_TOKEN}" | docker login -u="${quay_user}" --password-stdin quay.io 20 | -------------------------------------------------------------------------------- /tests/python/test_shared_table.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) 2016 Facebook, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | import ctypes as ct 6 | import unittest 7 | from bcc import BPF 8 | 9 | class TestSharedTable(unittest.TestCase): 10 | def test_close_extern(self): 11 | b1 = BPF(text="""BPF_TABLE_PUBLIC("array", int, int, table1, 10);""") 12 | 13 | with BPF(text="""BPF_TABLE("extern", int, int, table1, 10);""") as b2: 14 | t2 = b2["table1"] 15 | t2[ct.c_int(1)] = ct.c_int(10) 16 | self.assertEqual(len(t2), 10) 17 | 18 | t1 = b1["table1"] 19 | self.assertEqual(t1[ct.c_int(1)].value, 10) 20 | self.assertEqual(len(t1), 10) 21 | 22 | if __name__ == "__main__": 23 | unittest.main() 24 | -------------------------------------------------------------------------------- /tests/python/test_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) Catalysts GmbH 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | from bcc.utils import get_online_cpus, detect_language 6 | import multiprocessing 7 | import unittest 8 | import os 9 | 10 | class TestUtils(unittest.TestCase): 11 | def test_get_online_cpus(self): 12 | online_cpus = get_online_cpus() 13 | num_cores = multiprocessing.cpu_count() 14 | 15 | self.assertEqual(len(online_cpus), num_cores) 16 | 17 | def test_detect_language(self): 18 | candidates = ["c", "java", "perl", "php", "node", "ruby", "python"] 19 | language = detect_language(candidates, os.getpid()) 20 | self.assertEqual(language, "python") 21 | 22 | if __name__ == "__main__": 23 | unittest.main() 24 | -------------------------------------------------------------------------------- /libbpf-tools/core_fixes.bpf.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | /* Copyright (c) 2021 Hengqi Chen */ 3 | 4 | #ifndef __CORE_FIXES_BPF_H 5 | #define __CORE_FIXES_BPF_H 6 | 7 | #include 8 | #include 9 | 10 | /** 11 | * commit 2f064a59a1 ("sched: Change task_struct::state") changes 12 | * the name of task_struct::state to task_struct::__state 13 | * see: 14 | * https://github.com/torvalds/linux/commit/2f064a59a1 15 | */ 16 | struct task_struct___x { 17 | unsigned int __state; 18 | }; 19 | 20 | static __s64 get_task_state(void *task) 21 | { 22 | struct task_struct___x *t = task; 23 | 24 | if (bpf_core_field_exists(t->__state)) 25 | return t->__state; 26 | return ((struct task_struct *)task)->state; 27 | } 28 | 29 | #endif /* __CORE_FIXES_BPF_H */ 30 | -------------------------------------------------------------------------------- /tests/lua/test_standalone.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) GitHub, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | set -xe 6 | cd "src/lua" 7 | 8 | function fail { 9 | echo "test failed: $1" >&2 10 | exit 1 11 | } 12 | 13 | if [[ ! -x bcc-lua ]]; then 14 | echo "bcc-lua not built --- skipping" 15 | exit 0 16 | fi 17 | 18 | LIBRARY=$(ldd bcc-lua | grep luajit) 19 | if [ $? -ne 0 -o -z "$LIBRARY" ] ; then 20 | fail "bcc-lua depends on libluajit" 21 | fi 22 | 23 | rm -f probe.lua 24 | echo "return function(BPF) print(\"Hello world\") end" > probe.lua 25 | 26 | PROBE="../../examples/lua/offcputime.lua" 27 | 28 | if ! sudo ./bcc-lua "$PROBE" -d 1 >/dev/null 2>/dev/null; then 29 | fail "bcc-lua cannot run complex probes" 30 | fi 31 | 32 | rm -f libbcc.so probe.lua 33 | -------------------------------------------------------------------------------- /examples/tracing/hello_fields.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # This is a Hello World example that formats output as fields. 4 | 5 | from bcc import BPF 6 | from bcc.utils import printb 7 | 8 | # define BPF program 9 | prog = """ 10 | int hello(void *ctx) { 11 | bpf_trace_printk("Hello, World!\\n"); 12 | return 0; 13 | } 14 | """ 15 | 16 | # load BPF program 17 | b = BPF(text=prog) 18 | b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello") 19 | 20 | # header 21 | print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE")) 22 | 23 | # format output 24 | while 1: 25 | try: 26 | (task, pid, cpu, flags, ts, msg) = b.trace_fields() 27 | except ValueError: 28 | continue 29 | except KeyboardInterrupt: 30 | exit() 31 | printb(b"%-18.9f %-16s %-6d %s" % (ts, task, pid, msg)) 32 | -------------------------------------------------------------------------------- /src/lua/bcc-probe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env luajit 2 | --[[ 3 | Copyright 2016 GitHub, Inc 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | ]] 17 | local str = require("debug").getinfo(1, "S").source:sub(2) 18 | local script_path = str:match("(.*/)").."/?.lua;" 19 | package.path = script_path..package.path 20 | require("bcc.run")() 21 | -------------------------------------------------------------------------------- /tests/python/test_flags.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | import unittest 6 | from bcc import BPF 7 | 8 | class TestLru(unittest.TestCase): 9 | def test_lru_map_flags(self): 10 | test_prog1 = """ 11 | BPF_F_TABLE("lru_hash", int, u64, lru, 1024, BPF_F_NO_COMMON_LRU); 12 | """ 13 | b = BPF(text=test_prog1) 14 | t = b["lru"] 15 | self.assertEqual(t.flags, 2); 16 | 17 | def test_hash_map_flags(self): 18 | test_prog1 = """ 19 | BPF_F_TABLE("hash", int, u64, hash, 1024, BPF_F_NO_PREALLOC); 20 | """ 21 | b = BPF(text=test_prog1) 22 | t = b["hash"] 23 | self.assertEqual(t.flags, 1); 24 | 25 | if __name__ == "__main__": 26 | unittest.main() 27 | -------------------------------------------------------------------------------- /src/cc/README: -------------------------------------------------------------------------------- 1 | The libbpf directory is a git submodule for repository 2 | https://github.com/libbpf/libbpf 3 | 4 | If you have any change in libbpf directory, please upstream to linux 5 | first as libbpf repo is a mirror of linux/tools/lib/bpf directory. 6 | 7 | If any top-commit update of libbpf submodule contains a uapi header 8 | change, the following are necessary steps to sync properly with 9 | rest of bcc: 10 | 1. sync compat/linux/virtual_bpf.h with libbpf/include/uapi/linux/bpf.h 11 | as virtual_bpf.h has an extra string wrapper for bpf.h. 12 | 2. if new bpf.h has new helpers, add corresponding helper func define 13 | in bcc:src/cc/export/helpers.h and helper entry for error reporting 14 | in bcc:src/cc/libbpf.c. 15 | 3. if new bpf.h has new map types, program types, update 16 | bcc:introspection/bps.c for these new map/program types. 17 | -------------------------------------------------------------------------------- /examples/networking/tunnel_monitor/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | # this script: 6 | # 1. checks for bower to be installed 7 | # 2. clones the chord-transitions UI from github 8 | # 3. installs locally the packages required by the UI 9 | 10 | function which_() { hash "$1" &>/dev/null; } 11 | 12 | if [[ ! -d chord-transitions ]]; then 13 | git clone https://github.com/iovisor/chord-transitions.git 14 | fi 15 | 16 | cd chord-transitions 17 | 18 | export PATH=node_modules/.bin:$PATH 19 | 20 | if ! which_ bower; then 21 | if ! which_ npm; then 22 | echo "Error: required binary 'npm' not found, please install nodejs" 23 | exit 1 24 | fi 25 | npm install bower 26 | fi 27 | 28 | if [[ "$(id -u)" = "0" ]]; then 29 | args="--allow-root" 30 | fi 31 | 32 | bower install $args 33 | -------------------------------------------------------------------------------- /libbpf-tools/stat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | #ifndef __STAT_H 3 | #define __STAT_H 4 | 5 | /* From include/uapi/linux/stat.h */ 6 | 7 | #define S_IFMT 00170000 8 | #define S_IFSOCK 0140000 9 | #define S_IFLNK 0120000 10 | #define S_IFREG 0100000 11 | #define S_IFBLK 0060000 12 | #define S_IFDIR 0040000 13 | #define S_IFCHR 0020000 14 | #define S_IFIFO 0010000 15 | #define S_ISUID 0004000 16 | #define S_ISGID 0002000 17 | #define S_ISVTX 0001000 18 | 19 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 20 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 21 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 22 | #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) 23 | #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) 24 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) 25 | #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 26 | 27 | #endif /* __STAT_H */ 28 | -------------------------------------------------------------------------------- /SPECS/Dockerfile.fedora: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | FROM fedora:rawhide 5 | 6 | MAINTAINER Brenden Blanco 7 | 8 | RUN dnf -y install bison cmake flex gcc gcc-c++ git libxml2-devel make python2-devel rpm-build wget zlib-devel 9 | 10 | WORKDIR /root 11 | 12 | RUN wget http://llvm.org/releases/3.7.1/{cfe,llvm}-3.7.1.src.tar.xz 13 | 14 | RUN tar -xf llvm-3.7.1.src.tar.xz && mkdir llvm-3.7.1.src/tools/clang && tar -xf cfe-3.7.1.src.tar.xz -C llvm-3.7.1.src/tools/clang --strip 1 && mkdir llvm-3.7.1.src/build 15 | RUN cd llvm-3.7.1.src/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;BPF" -DCMAKE_INSTALL_PREFIX=/usr 16 | RUN cd llvm-3.7.1.src/build && make -j8 17 | 18 | COPY . bcc 19 | WORKDIR /root/bcc 20 | RUN PATH=/root/llvm-3.7.1.src/build/bin:$PATH ./scripts/build-rpm.sh 21 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This file should be kept up to date with the list of maintainers responsible 2 | # for the different subdirectories within BCC. One of these people SHOULD 3 | # review code that touches the respective areas, and MUST review it if the 4 | # change is substantial or API-breaking. 5 | 6 | # see https://help.github.com/articles/about-codeowners/ for syntax 7 | 8 | # Miscellaneous 9 | * @drzaeus77 @goldshtn @yonghong-song @4ast @brendangregg @davemarchevsky 10 | 11 | # Documentation 12 | /docs/ @brendangregg @goldshtn @davemarchevsky 13 | /man/ @brendangregg @goldshtn @davemarchevsky 14 | 15 | # Tools 16 | /tools/ @brendangregg @goldshtn @davemarchevsky 17 | 18 | # Compiler, C API 19 | /src/cc/ @drzaeus77 @yonghong-song @4ast @davemarchevsky 20 | 21 | # Python API 22 | /src/python/ @drzaeus77 @goldshtn @davemarchevsky 23 | 24 | # Tests 25 | /tests/ @drzaeus77 @yonghong-song @davemarchevsky 26 | -------------------------------------------------------------------------------- /libbpf-tools/tcpconnect.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Anton Protopopov 3 | #ifndef __TCPCONNECT_H 4 | #define __TCPCONNECT_H 5 | 6 | /* The maximum number of items in maps */ 7 | #define MAX_ENTRIES 8192 8 | 9 | /* The maximum number of ports to filter */ 10 | #define MAX_PORTS 64 11 | 12 | #define TASK_COMM_LEN 16 13 | 14 | struct ipv4_flow_key { 15 | __u32 saddr; 16 | __u32 daddr; 17 | __u16 dport; 18 | }; 19 | 20 | struct ipv6_flow_key { 21 | __u8 saddr[16]; 22 | __u8 daddr[16]; 23 | __u16 dport; 24 | }; 25 | 26 | struct event { 27 | union { 28 | __u32 saddr_v4; 29 | __u8 saddr_v6[16]; 30 | }; 31 | union { 32 | __u32 daddr_v4; 33 | __u8 daddr_v6[16]; 34 | }; 35 | char task[TASK_COMM_LEN]; 36 | __u64 ts_us; 37 | __u32 af; // AF_INET or AF_INET6 38 | __u32 pid; 39 | __u32 uid; 40 | __u16 dport; 41 | }; 42 | 43 | #endif /* __TCPCONNECT_H */ 44 | -------------------------------------------------------------------------------- /docker/Dockerfile.ubuntu: -------------------------------------------------------------------------------- 1 | ARG OS_TAG=18.04 2 | FROM ubuntu:${OS_TAG} as builder 3 | 4 | ARG OS_TAG 5 | ARG BUILD_TYPE=release 6 | ARG DEBIAN_FRONTEND=noninteractive 7 | 8 | MAINTAINER Brenden Blanco 9 | 10 | RUN apt-get -qq update && \ 11 | apt-get -y install pbuilder aptitude 12 | 13 | COPY ./ /root/bcc 14 | 15 | WORKDIR /root/bcc 16 | 17 | RUN /usr/lib/pbuilder/pbuilder-satisfydepends && \ 18 | ./scripts/build-deb.sh ${BUILD_TYPE} 19 | 20 | FROM ubuntu:${OS_TAG} 21 | 22 | COPY --from=builder /root/bcc/*.deb /root/bcc/ 23 | 24 | RUN \ 25 | apt-get update -y && \ 26 | DEBIAN_FRONTEND=noninteractive apt-get install -y python python3 python3-pip binutils libelf1 kmod && \ 27 | if [ ${OS_TAG} = "18.04" ];then \ 28 | apt-get -y install python-pip && \ 29 | pip install dnslib cachetools ; \ 30 | fi ; \ 31 | pip3 install dnslib cachetools && \ 32 | dpkg -i /root/bcc/*.deb 33 | -------------------------------------------------------------------------------- /examples/cpp/pyperf/PyPerfDefaultPrinter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. 3 | * Licensed under the Apache License, Version 2.0 (the "License") 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "PyPerfSampleProcessor.h" 9 | 10 | namespace ebpf { 11 | namespace pyperf { 12 | 13 | class PyPerfDefaultPrinter : public PyPerfSampleProcessor { 14 | public: 15 | PyPerfDefaultPrinter(bool showGILState, bool showThreadState, 16 | bool showPthreadIDState) 17 | : showGILState_(showGILState), 18 | showThreadState_(showThreadState), 19 | showPthreadIDState_(showPthreadIDState) {} 20 | 21 | void processSamples(const std::vector& samples, 22 | PyPerfUtil* util) override; 23 | 24 | private: 25 | bool showGILState_; 26 | bool showThreadState_; 27 | bool showPthreadIDState_; 28 | }; 29 | 30 | } // namespace pyperf 31 | } // namespace ebpf 32 | -------------------------------------------------------------------------------- /tools/old/syncsnoop.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # @lint-avoid-python-3-compatibility-imports 3 | # 4 | # syncsnoop Trace sync() syscall. 5 | # For Linux, uses BCC, eBPF. Embedded C. 6 | # 7 | # Written as a basic example of BCC trace & reformat. See 8 | # examples/hello_world.py for a BCC trace with default output example. 9 | # 10 | # Copyright (c) 2015 Brendan Gregg. 11 | # Licensed under the Apache License, Version 2.0 (the "License") 12 | # 13 | # 13-Aug-2015 Brendan Gregg Created this. 14 | 15 | from __future__ import print_function 16 | from bcc import BPF 17 | 18 | # load BPF program 19 | b = BPF(text=""" 20 | void kprobe__sys_sync(void *ctx) { 21 | bpf_trace_printk("sync()\\n"); 22 | }; 23 | """) 24 | 25 | # header 26 | print("%-18s %s" % ("TIME(s)", "CALL")) 27 | 28 | # format output 29 | while 1: 30 | (task, pid, cpu, flags, ts, msg) = b.trace_fields() 31 | print("%-18.9f %s" % (ts, msg)) 32 | -------------------------------------------------------------------------------- /src/lua/squishy: -------------------------------------------------------------------------------- 1 | Module "bcc.vendor.argparse" "bcc/vendor/argparse.lua" 2 | Module "bcc.vendor.posix" "bcc/vendor/posix.lua" 3 | Module "bcc.vendor.middleclass" "bcc/vendor/middleclass.lua" 4 | Module "bcc.vendor.json" "bcc/vendor/json.lua" 5 | Module "bcc.vendor.helpers" "bcc/vendor/helpers.lua" 6 | 7 | Module "bcc.init" "bcc/init.lua" 8 | Module "bcc.run" "bcc/run.lua" 9 | Module "bcc.bpf" "bcc/bpf.lua" 10 | Module "bcc.sym" "bcc/sym.lua" 11 | Module "bcc.libbcc" "bcc/libbcc.lua" 12 | Module "bcc.tracerpipe" "bcc/tracerpipe.lua" 13 | Module "bcc.table" "bcc/table.lua" 14 | Module "bcc.usdt" "bcc/usdt.lua" 15 | 16 | Module "bpf" "bpf/init.lua" 17 | Module "bpf.bpf" "bpf/bpf.lua" 18 | Module "bpf.builtins" "bpf/builtins.lua" 19 | Module "bpf.cdef" "bpf/cdef.lua" 20 | Module "bpf.elf" "bpf/elf.lua" 21 | Module "bpf.ljbytecode" "bpf/ljbytecode.lua" 22 | Module "bpf.proto" "bpf/proto.lua" 23 | 24 | Main "bcc/run.lua" 25 | Output "bcc.lua" 26 | -------------------------------------------------------------------------------- /src/cc/frontends/clang/frontend_action_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Facebook, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #if LLVM_MAJOR_VERSION >= 8 17 | #define GET_BEGINLOC(E) ((E)->getBeginLoc()) 18 | #define GET_ENDLOC(E) ((E)->getEndLoc()) 19 | #else 20 | #define GET_BEGINLOC(E) ((E)->getLocStart()) 21 | #define GET_ENDLOC(E) ((E)->getLocEnd()) 22 | #endif 23 | -------------------------------------------------------------------------------- /src/lua/bpf-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "bpf" 2 | version = "scm-1" 3 | source = { 4 | url = "git://github.com/iovisor/bcc.git" 5 | } 6 | description = { 7 | summary = "BCC - LuaJIT to BPF compiler.", 8 | detailed = [[ 9 | ]], 10 | homepage = "https://github.com/iovisor/bcc", 11 | license = "BSD" 12 | } 13 | dependencies = { 14 | "lua >= 5.1", 15 | "ljsyscall >= 0.12", 16 | } 17 | external_dependencies = { 18 | LIBELF = { 19 | library = "elf" 20 | } 21 | } 22 | build = { 23 | type = "builtin", 24 | install = { 25 | bin = { 26 | } 27 | }, 28 | modules = { 29 | bpf = "src/lua/bpf/bpf.lua", 30 | ["bpf.builtins"] = "src/lua/bpf/builtins.lua", 31 | ["bpf.cdef"] = "src/lua/bpf/cdef.lua", 32 | ["bpf.elf"] = "src/lua/bpf/elf.lua", 33 | ["bpf.init"] = "src/lua/bpf/init.lua", 34 | ["bpf.ljbytecode"] = "src/lua/bpf/ljbytecode.lua", 35 | ["bpf.proto"] = "src/lua/bpf/proto.lua", 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | # Uncomment this to turn on verbose mode. 5 | #export DH_VERBOSE=1 6 | 7 | DEBIAN_VERSION := $(shell dpkg-parsechangelog | sed -rne "s,^Version: (.*),\1,p") 8 | DEBIAN_REVISION := $(shell dpkg-parsechangelog | sed -rne "s,^Version: ([0-9.]+)(~|-)(.*),\3,p") 9 | UPSTREAM_VERSION := $(shell dpkg-parsechangelog | sed -rne "s,^Version: ([0-9.]+)(~|-)(.*),\1,p") 10 | 11 | %: 12 | dh $@ --buildsystem=cmake --parallel --with python2,python3 13 | 14 | # tests cannot be run in parallel 15 | override_dh_auto_test: 16 | dh_auto_test -O--buildsystem=cmake -O--no-parallel 17 | 18 | # FIXME: LLVM_DEFINITIONS is broken somehow in LLVM cmake upstream 19 | override_dh_auto_configure: 20 | dh_auto_configure -- -DREVISION_LAST=$(UPSTREAM_VERSION) -DREVISION=$(UPSTREAM_VERSION) -DLLVM_DEFINITIONS="-D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS" -DPYTHON_CMD="python2;python3" 21 | -------------------------------------------------------------------------------- /introspection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | include_directories(${PROJECT_SOURCE_DIR}/src/cc) 5 | include_directories(${PROJECT_SOURCE_DIR}/src/cc/api) 6 | include_directories(${PROJECT_SOURCE_DIR}/src/cc/libbpf/include/uapi) 7 | 8 | option(INSTALL_INTROSPECTION "Install BPF introspection tools" ON) 9 | option(BPS_LINK_RT "Pass -lrt to linker when linking bps tool" ON) 10 | 11 | # Note that the order matters! bpf-static first, the rest later 12 | if(CMAKE_USE_LIBBPF_PACKAGE AND LIBBPF_FOUND) 13 | set(bps_libs_to_link bpf-shared ${LIBBPF_LIBRARIES}) 14 | else() 15 | set(bps_libs_to_link bpf-static) 16 | endif() 17 | list(APPEND bps_libs_to_link elf z) 18 | if(BPS_LINK_RT) 19 | list(APPEND bps_libs_to_link rt) 20 | endif() 21 | 22 | add_executable(bps bps.c) 23 | target_link_libraries(bps ${bps_libs_to_link}) 24 | 25 | install (TARGETS bps DESTINATION share/bcc/introspection) 26 | -------------------------------------------------------------------------------- /cmake/FindCompilerFlag.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Facebook, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | if (ENABLE_NO_PIE) 5 | 6 | if (CMAKE_C_COMPILER_ID MATCHES "Clang") 7 | set(COMPILER_NOPIE_FLAG "-nopie") 8 | else() 9 | set(_backup_c_flags "${CMAKE_REQUIRED_FLAGS}") 10 | set(CMAKE_REQUIRED_FLAGS "-no-pie") 11 | CHECK_CXX_SOURCE_COMPILES("int main() {return 0;}" 12 | HAVE_NO_PIE_FLAG) 13 | if (HAVE_NO_PIE_FLAG) 14 | set(COMPILER_NOPIE_FLAG "-no-pie") 15 | else() 16 | set(COMPILER_NOPIE_FLAG "") 17 | endif() 18 | set(CMAKE_REQUIRED_FLAGS "${_backup_c_flags}") 19 | endif() 20 | 21 | endif(ENABLE_NO_PIE) 22 | 23 | # check whether reallocarray availability 24 | # this is used to satisfy reallocarray usage under src/cc/libbpf/ 25 | CHECK_CXX_SOURCE_COMPILES( 26 | " 27 | #define _GNU_SOURCE 28 | #include 29 | 30 | int main(void) 31 | { 32 | return !!reallocarray(NULL, 1, 1); 33 | } 34 | " HAVE_REALLOCARRAY_SUPPORT) 35 | -------------------------------------------------------------------------------- /cmake/static_libstdc++.cmake: -------------------------------------------------------------------------------- 1 | # only turn on static-libstdc++ if also linking statically against clang 2 | string(REGEX MATCH ".*[.]a$" LIBCLANG_ISSTATIC "${libclangBasic}") 3 | # if gcc 4.9 or higher is used, static libstdc++ is a good option 4 | if (CMAKE_COMPILER_IS_GNUCC AND LIBCLANG_ISSTATIC AND (NOT ENABLE_LLVM_SHARED OR libclang-shared STREQUAL "libclang-shared-NOTFOUND")) 5 | execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) 6 | if (GCC_VERSION VERSION_GREATER 4.9 OR GCC_VERSION VERSION_EQUAL 4.9) 7 | execute_process(COMMAND ${CMAKE_C_COMPILER} -print-libgcc-file-name OUTPUT_VARIABLE GCC_LIB) 8 | get_filename_component(GCC_DIR "${GCC_LIB}" DIRECTORY) 9 | find_library(GCC_LIBSTDCPP libstdc++.a PATHS "${GCC_DIR}" NO_DEFAULT_PATH) 10 | if (GCC_LIBSTDCPP) 11 | message(STATUS "Using static-libstdc++") 12 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++") 13 | endif() 14 | endif() 15 | endif() 16 | -------------------------------------------------------------------------------- /examples/networking/simple_tc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | from bcc import BPF 6 | from pyroute2 import IPRoute 7 | 8 | ipr = IPRoute() 9 | 10 | text = """ 11 | int hello(struct __sk_buff *skb) { 12 | return 1; 13 | } 14 | """ 15 | 16 | try: 17 | b = BPF(text=text, debug=0) 18 | fn = b.load_func("hello", BPF.SCHED_CLS) 19 | ipr.link("add", ifname="t1a", kind="veth", peer="t1b") 20 | idx = ipr.link_lookup(ifname="t1a")[0] 21 | 22 | ipr.tc("add", "ingress", idx, "ffff:") 23 | ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, 24 | name=fn.name, parent="ffff:", action="ok", classid=1) 25 | ipr.tc("add", "sfq", idx, "1:") 26 | ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, 27 | name=fn.name, parent="1:", action="ok", classid=1) 28 | finally: 29 | if "idx" in locals(): ipr.link("del", index=idx) 30 | print("BPF tc functionality - SCHED_CLS: OK") 31 | -------------------------------------------------------------------------------- /src/cc/bpf_module_rw_engine_disabled.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 PLUMgrid, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "bpf_module.h" 18 | 19 | namespace ebpf { 20 | 21 | bool bpf_module_rw_engine_enabled(void) { 22 | return false; 23 | } 24 | 25 | void BPFModule::initialize_rw_engine() { 26 | } 27 | 28 | void BPFModule::cleanup_rw_engine() { 29 | } 30 | 31 | int BPFModule::annotate() { 32 | return -1; 33 | } 34 | 35 | } // namespace ebpf 36 | -------------------------------------------------------------------------------- /tools/bashreadline_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of bashreadline, the Linux eBPF/bcc version. 2 | 3 | 4 | This prints bash commands from all running bash shells on the system. For 5 | example: 6 | 7 | # ./bashreadline 8 | TIME PID COMMAND 9 | 05:28:25 21176 ls -l 10 | 05:28:28 21176 date 11 | 05:28:35 21176 echo hello world 12 | 05:28:43 21176 foo this command failed 13 | 05:28:45 21176 df -h 14 | 05:29:04 3059 echo another shell 15 | 05:29:13 21176 echo first shell again 16 | 17 | When running the script on Arch Linux, you may need to specify the location 18 | of libreadline.so library: 19 | 20 | # ./bashreadline -s /lib/libreadline.so 21 | TIME PID COMMAND 22 | 11:17:34 28796 whoami 23 | 11:17:41 28796 ps -ef 24 | 11:17:51 28796 echo "Hello eBPF!" 25 | 26 | 27 | The entered command may fail. This is just showing what command lines were 28 | entered interactively for bash to process. 29 | 30 | It works by tracing the return of the readline() function using uprobes 31 | (specifically a uretprobe). 32 | -------------------------------------------------------------------------------- /libbpf-tools/oomkill.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2022 Jingxiang Zeng 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "oomkill.h" 9 | 10 | struct { 11 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 12 | __uint(key_size, sizeof(u32)); 13 | __uint(value_size, sizeof(u32)); 14 | } events SEC(".maps"); 15 | 16 | SEC("kprobe/oom_kill_process") 17 | int BPF_KPROBE(oom_kill_process, struct oom_control *oc, const char *message) 18 | { 19 | struct data_t data; 20 | 21 | data.fpid = bpf_get_current_pid_tgid() >> 32; 22 | data.tpid = BPF_CORE_READ(oc, chosen, tgid); 23 | data.pages = BPF_CORE_READ(oc, totalpages); 24 | bpf_get_current_comm(&data.fcomm, sizeof(data.fcomm)); 25 | bpf_probe_read_kernel(&data.tcomm, sizeof(data.tcomm), BPF_CORE_READ(oc, chosen, comm)); 26 | bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &data, sizeof(data)); 27 | return 0; 28 | } 29 | 30 | char LICENSE[] SEC("license") = "GPL"; 31 | -------------------------------------------------------------------------------- /src/cc/export/footer.h: -------------------------------------------------------------------------------- 1 | R"********( 2 | /* 3 | * Copyright (c) 2018 Clevernet, Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef BPF_LICENSE 19 | /* No license defined, using GPL 20 | * You can define your own BPF_LICENSE in your C code */ 21 | #define BPF_LICENSE GPL 22 | #endif 23 | #define ___LICENSE(s) #s 24 | #define __LICENSE(s) ___LICENSE(s) 25 | #define _LICENSE __LICENSE(BPF_LICENSE) 26 | char _license[] BCC_SEC("license") = _LICENSE; 27 | 28 | )********" 29 | -------------------------------------------------------------------------------- /tests/lua/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_program(LUAJIT luajit) 2 | find_program(BUSTED busted) 3 | 4 | if(RUN_LUA_TESTS) 5 | if(LUAJIT) 6 | add_test(NAME lua_test_clang WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 7 | COMMAND ${TEST_WRAPPER} lua_test_clang sudo ${LUAJIT} test_clang.lua) 8 | 9 | add_test(NAME lua_test_uprobes WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 10 | COMMAND ${TEST_WRAPPER} lua_test_uprobes sudo ${LUAJIT} test_uprobes.lua) 11 | 12 | add_test(NAME lua_test_dump WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 13 | COMMAND ${TEST_WRAPPER} lua_test_dump sudo ${LUAJIT} test_dump.lua) 14 | 15 | add_test(NAME lua_test_standalone WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 16 | COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_standalone.sh) 17 | 18 | if(BUSTED) 19 | add_test(NAME lua_test_busted WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 20 | COMMAND busted --lua=${LUAJIT} -m "${CMAKE_CURRENT_SOURCE_DIR}/../../src/lua/?.lua" -m "${CMAKE_CURRENT_SOURCE_DIR}/../../src/lua/?/init.lua;") 21 | endif() 22 | endif() 23 | endif() 24 | -------------------------------------------------------------------------------- /tests/cc/utils.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 IBM Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | 19 | int cmd_scanf(const char *cmd, const char *fmt, ...) { 20 | va_list args; 21 | FILE *pipe; 22 | 23 | va_start(args, fmt); 24 | pipe = popen(cmd, "r"); 25 | if (pipe == NULL) { 26 | va_end(args); 27 | return -1; 28 | } 29 | 30 | vfscanf(pipe, fmt, args); 31 | va_end(args); 32 | pclose(pipe); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/python/test_brb2.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) PLUMgrid, Inc. 2 | // Licensed under the Apache License, Version 2.0 (the "License") 3 | #include 4 | 5 | // physical endpoint manager (pem) tables which connects VMs and bridges 6 | // 7 | BPF_HASH(pem_dest, u32, u32, 256); 8 | // <0, tx_pkts> 9 | BPF_ARRAY(pem_stats, u32, 1); 10 | 11 | int pem(struct __sk_buff *skb) { 12 | u32 ifindex_in, *ifindex_p; 13 | u8 *cursor = 0; 14 | struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); 15 | 16 | ifindex_in = skb->ingress_ifindex; 17 | ifindex_p = pem_dest.lookup(&ifindex_in); 18 | if (ifindex_p) { 19 | #if 1 20 | if (ethernet->type == 0x0800 || ethernet->type == 0x0806) { 21 | /* accumulate stats */ 22 | u32 index = 0; 23 | u32 *value = pem_stats.lookup(&index); 24 | if (value) 25 | lock_xadd(value, 1); 26 | } 27 | #endif 28 | bpf_clone_redirect(skb, *ifindex_p, 0); 29 | } 30 | 31 | return 1; 32 | } 33 | -------------------------------------------------------------------------------- /src/lua/bpf/spec/decoder_spec.lua: -------------------------------------------------------------------------------- 1 | describe('decoder', function() 2 | 3 | -- Decode simple function 4 | local bytecode = require('bpf.ljbytecode') 5 | local f = function (x) return x + 1 end 6 | 7 | it('should decode functions', function() 8 | -- Make sure it calls LJ decoder 9 | local bc = bytecode.decoder(f) 10 | assert.truthy(bc) 11 | -- Decode bytecode bytecode to instructions 12 | local jutil = require("jit.util") 13 | spy.on(jutil, 'funcbc') 14 | local pc, op = bc() 15 | -- Check bytecode for sanity (starts with ADDVN(x, 1)) 16 | assert.equal(pc, 1) 17 | assert.equal(op, 'ADDVN') 18 | for pc, op in bc do 19 | assert.truthy(pc and op) 20 | end 21 | assert.spy(jutil.funcbc).was.called() 22 | end) 23 | it('should fail on bad input', function() 24 | assert.has_error(function() bytecode.decoder(nil)() end) 25 | assert.has_error(function() bytecode.decoder(5)() end) 26 | assert.has_error(function() bytecode.decoder('test')() end) 27 | end) 28 | it('should dump bytecode', function() 29 | bytecode.dump(f) 30 | end) 31 | end) 32 | -------------------------------------------------------------------------------- /scripts/docker/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | # Builds debian packages using docker wrapper 4 | 5 | function help() { 6 | message=$1 7 | echo "USAGE: build.sh DOCKER_REPO DOCKER_TAG OS_TAG [DISTRO]" 8 | echo "hint: ${message}" 9 | } 10 | 11 | docker_repo=$1 12 | docker_tag=$2 13 | os_tag=$3 14 | distro=${4:-ubuntu} 15 | 16 | [ -z "${docker_repo}" ] && help "You must specify repo, eg: quay.io/iovisoc/bcc" && exit 1 17 | [ -z "${docker_tag}" ] && help "You must specify tag, eg: bionic-release-master, latest, SHA, git tag, etc " && exit 1 18 | [ -z "${os_tag}" ] && help "You must specify os tag, eg: 18.04, bionic, etc " && exit 1 19 | 20 | 21 | # The main docker image build, 22 | echo "Building ${distro} ${os_tag} release docker image for ${docker_repo}:${docker_tag}" 23 | docker build -t ${docker_repo}:${docker_tag} --build-arg OS_TAG=${os_tag} -f docker/Dockerfile.${distro} . 24 | 25 | echo "Copying build artifacts to $(pwd)/output" 26 | mkdir -p output 27 | docker run -v $(pwd)/output:/output ${docker_repo}:${docker_tag} /bin/bash -c "cp /root/bcc/* /output" 28 | -------------------------------------------------------------------------------- /docker/Dockerfile.fedora: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | FROM fedora:34 5 | 6 | MAINTAINER Dave Marchevsky 7 | 8 | RUN dnf -y install \ 9 | bison \ 10 | cmake \ 11 | flex \ 12 | gcc \ 13 | gcc-c++ \ 14 | git \ 15 | libxml2-devel \ 16 | make \ 17 | rpm-build \ 18 | wget \ 19 | zlib-devel \ 20 | llvm \ 21 | llvm-devel \ 22 | clang-devel \ 23 | elfutils-debuginfod-client-devel \ 24 | # elfutils-libelf-devel-static \ 25 | elfutils-libelf-devel \ 26 | luajit \ 27 | luajit-devel \ 28 | python3-devel \ 29 | libstdc++ \ 30 | libstdc++-devel 31 | 32 | RUN dnf -y install \ 33 | python3 \ 34 | python3-pip 35 | 36 | RUN if [[ ! -e /usr/bin/python && -e /usr/bin/python3 ]]; then \ 37 | ln -s $(readlink /usr/bin/python3) /usr/bin/python; \ 38 | fi 39 | 40 | RUN dnf -y install \ 41 | procps \ 42 | iputils \ 43 | net-tools \ 44 | hostname \ 45 | iproute \ 46 | bpftool 47 | 48 | RUN pip3 install pyroute2==0.5.18 netaddr==0.8.0 dnslib==0.9.14 cachetools==3.1.1 49 | -------------------------------------------------------------------------------- /examples/tracing/undump_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of undump.py, the Linux eBPF/bcc version. 2 | 3 | This example trace the kernel function performing receive AP_UNIX socket 4 | packet. Some example output: 5 | 6 | Terminal 1, UNIX Socket Server: 7 | 8 | ``` 9 | $ nc -lU /var/tmp/dsocket 10 | # receive from Client 11 | Hello, World 12 | abcdefg 13 | ``` 14 | 15 | Terminal 2, UNIX socket Client: 16 | 17 | ``` 18 | $ nc -U /var/tmp/dsocket 19 | # Input some lines 20 | Hello, World 21 | abcdefg 22 | ``` 23 | 24 | Terminal 3, receive tracing: 25 | 26 | ``` 27 | $ sudo python undump.py -p 49264 28 | Tracing PID=49264 UNIX socket packets ... Hit Ctrl-C to end 29 | 30 | # Here print bytes of receive 31 | PID 49264 Recv 13 bytes 32 | 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 0a 33 | PID 49264 Recv 8 bytes 34 | 61 62 63 64 65 66 67 0a 35 | ``` 36 | 37 | This output shows two packet received by PID 49264(nc -lU /var/tmp/dsocket), 38 | `Hello, World` will be parsed as `48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 0a`, the 39 | `0a` is `Enter`. `abcdefg` will be parsed as `61 62 63 64 65 66 67 0a`. 40 | -------------------------------------------------------------------------------- /libbpf-tools/cachestat.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2021 Wenbo Zhang 3 | #include 4 | #include 5 | #include 6 | 7 | __s64 total = 0; /* total cache accesses without counting dirties */ 8 | __s64 misses = 0; /* total of add to lru because of read misses */ 9 | __u64 mbd = 0; /* total of mark_buffer_dirty events */ 10 | 11 | SEC("fentry/add_to_page_cache_lru") 12 | int BPF_PROG(add_to_page_cache_lru) 13 | { 14 | __sync_fetch_and_add(&misses, 1); 15 | return 0; 16 | } 17 | 18 | SEC("fentry/mark_page_accessed") 19 | int BPF_PROG(mark_page_accessed) 20 | { 21 | __sync_fetch_and_add(&total, 1); 22 | return 0; 23 | } 24 | 25 | SEC("fentry/account_page_dirtied") 26 | int BPF_PROG(account_page_dirtied) 27 | { 28 | __sync_fetch_and_add(&misses, -1); 29 | return 0; 30 | } 31 | 32 | SEC("fentry/mark_buffer_dirty") 33 | int BPF_PROG(mark_buffer_dirty) 34 | { 35 | __sync_fetch_and_add(&total, -1); 36 | __sync_fetch_and_add(&mbd, 1); 37 | return 0; 38 | } 39 | 40 | char LICENSE[] SEC("license") = "GPL"; 41 | -------------------------------------------------------------------------------- /src/lua/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(LuaJIT) 2 | find_program(LUAJIT luajit) 3 | 4 | if (LUAJIT_LIBRARIES AND LUAJIT) 5 | FILE(GLOB_RECURSE SRC_LUA 6 | ${CMAKE_CURRENT_SOURCE_DIR}/bcc/*.lua 7 | ${CMAKE_CURRENT_SOURCE_DIR}/bcc/vendor/*.lua 8 | ${CMAKE_CURRENT_SOURCE_DIR}/bpf/*.lua) 9 | 10 | ADD_CUSTOM_COMMAND( 11 | OUTPUT bcc.lua 12 | COMMAND ${LUAJIT} ${CMAKE_CURRENT_SOURCE_DIR}/src/squish.lua ${CMAKE_CURRENT_SOURCE_DIR} 13 | DEPENDS ${SRC_LUA} ${CMAKE_CURRENT_SOURCE_DIR}/squishy 14 | ) 15 | 16 | ADD_CUSTOM_COMMAND( 17 | OUTPUT bcc.o 18 | COMMAND ${LUAJIT} -bg bcc.lua bcc.o 19 | DEPENDS bcc.lua 20 | ) 21 | 22 | include_directories(${LUAJIT_INCLUDE_DIR}) 23 | add_executable(bcc-lua src/main.c bcc.o) 24 | set_target_properties(bcc-lua PROPERTIES LINKER_LANGUAGE C) 25 | target_link_libraries(bcc-lua ${LUAJIT_LIBRARIES}) 26 | target_link_libraries(bcc-lua ${bcc-lua-static}) 27 | if (NOT COMPILER_NOPIE_FLAG EQUAL "") 28 | target_link_libraries(bcc-lua ${COMPILER_NOPIE_FLAG}) 29 | endif() 30 | 31 | install(TARGETS bcc-lua RUNTIME DESTINATION bin) 32 | endif() 33 | -------------------------------------------------------------------------------- /libbpf-tools/bashreadline.bpf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2021 Facebook */ 3 | #include 4 | #include 5 | #include 6 | #include "bashreadline.h" 7 | 8 | #define TASK_COMM_LEN 16 9 | 10 | struct { 11 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 12 | __uint(key_size, sizeof(__u32)); 13 | __uint(value_size, sizeof(__u32)); 14 | } events SEC(".maps"); 15 | 16 | SEC("uretprobe/readline") 17 | int BPF_KRETPROBE(printret, const void *ret) { 18 | struct str_t data; 19 | char comm[TASK_COMM_LEN]; 20 | u32 pid; 21 | 22 | if (!ret) 23 | return 0; 24 | 25 | bpf_get_current_comm(&comm, sizeof(comm)); 26 | if (comm[0] != 'b' || comm[1] != 'a' || comm[2] != 's' || comm[3] != 'h' || comm[4] != 0 ) 27 | return 0; 28 | 29 | pid = bpf_get_current_pid_tgid() >> 32; 30 | data.pid = pid; 31 | bpf_probe_read_user_str(&data.str, sizeof(data.str), ret); 32 | 33 | bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &data, sizeof(data)); 34 | 35 | return 0; 36 | }; 37 | 38 | char LICENSE[] SEC("license") = "GPL"; 39 | -------------------------------------------------------------------------------- /src/lua/bpf/spec/helper.lua: -------------------------------------------------------------------------------- 1 | local ffi = require('ffi') 2 | 3 | -- Define basic ctypes 4 | ffi.cdef [[ 5 | struct bpf_insn { 6 | uint8_t code; /* opcode */ 7 | uint8_t dst_reg:4; /* dest register */ 8 | uint8_t src_reg:4; /* source register */ 9 | uint16_t off; /* signed offset */ 10 | uint32_t imm; /* signed immediate constant */ 11 | }; 12 | ]] 13 | 14 | -- Inject mock ljsyscall for tests 15 | package.loaded['syscall'] = { 16 | bpf = function() error('mock') end, 17 | c = { BPF_MAP = {}, BPF_PROG = {} }, 18 | abi = { arch = 'x64' }, 19 | } 20 | 21 | package.loaded['syscall.helpers'] = { 22 | strflag = function (tab) 23 | local function flag(cache, str) 24 | if type(str) ~= "string" then return str end 25 | if #str == 0 then return 0 end 26 | local s = str:upper() 27 | if #s == 0 then return 0 end 28 | local val = rawget(tab, s) 29 | if not val then return nil end 30 | cache[str] = val 31 | return val 32 | end 33 | return setmetatable(tab, {__index = setmetatable({}, {__index = flag}), __call = function(t, a) return t[a] end}) 34 | end 35 | } -------------------------------------------------------------------------------- /cmake/version.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) PLUMgrid, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | if(NOT REVISION) 4 | get_git_head_revision(GIT_REFSPEC GIT_SHA1) 5 | string(SUBSTRING "${GIT_SHA1}" 0 8 GIT_SHA1_SHORT) 6 | git_describe(GIT_DESCRIPTION) 7 | git_describe(GIT_TAG_LAST "--abbrev=0" "--tags") 8 | git_get_exact_tag(GIT_TAG_EXACT) 9 | string(SUBSTRING "${GIT_TAG_LAST}-${GIT_SHA1_SHORT}" 1 -1 REVISION) 10 | if(GIT_TAG_EXACT) 11 | string(SUBSTRING "${GIT_TAG_EXACT}" 1 -1 REVISION) 12 | message(STATUS "Currently on Git tag ${GIT_TAG_EXACT}") 13 | else () 14 | message(STATUS "Latest recognized Git tag is ${GIT_TAG_LAST}") 15 | set(GIT_TAG_EXACT "") 16 | endif() 17 | message(STATUS "Git HEAD is ${GIT_SHA1}") 18 | # rpm/deb packaging uses this, only works on whole tag numbers 19 | if(NOT REVISION_LAST) 20 | string(SUBSTRING "${GIT_TAG_LAST}" 1 -1 REVISION_LAST) 21 | endif() 22 | else() 23 | set(REVISION_LAST "${REVISION}") 24 | endif() 25 | 26 | # strip leading 'v', and make unique for the tag 27 | message(STATUS "Revision is ${REVISION}") 28 | -------------------------------------------------------------------------------- /examples/tracing/vfsreadlat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vfsreadlat.c VFS read latency distribution. 3 | * For Linux, uses BCC, eBPF. See .py file. 4 | * 5 | * Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of version 2 of the GNU General Public 8 | * License as published by the Free Software Foundation. 9 | * 10 | * 15-Aug-2015 Brendan Gregg Created this. 11 | */ 12 | 13 | #include 14 | 15 | BPF_HASH(start, u32); 16 | BPF_HISTOGRAM(dist); 17 | 18 | int do_entry(struct pt_regs *ctx) 19 | { 20 | u32 pid; 21 | u64 ts, *val; 22 | 23 | pid = bpf_get_current_pid_tgid(); 24 | ts = bpf_ktime_get_ns(); 25 | start.update(&pid, &ts); 26 | return 0; 27 | } 28 | 29 | int do_return(struct pt_regs *ctx) 30 | { 31 | u32 pid; 32 | u64 *tsp, delta; 33 | 34 | pid = bpf_get_current_pid_tgid(); 35 | tsp = start.lookup(&pid); 36 | 37 | if (tsp != 0) { 38 | delta = bpf_ktime_get_ns() - *tsp; 39 | dist.increment(bpf_log2l(delta / 1000)); 40 | start.delete(&pid); 41 | } 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /src/cc/exported_files.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 PLUMgrid, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | namespace ebpf { 23 | 24 | class ExportedFiles { 25 | static std::map headers_; 26 | static std::map footers_; 27 | public: 28 | static const std::map & headers() { return headers_; } 29 | static const std::map & footers() { return footers_; } 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /examples/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | include_directories(${PROJECT_BINARY_DIR}/src/cc) 5 | include_directories(${PROJECT_SOURCE_DIR}/src/cc) 6 | include_directories(${PROJECT_SOURCE_DIR}/src/cc/api) 7 | include_directories(${PROJECT_SOURCE_DIR}/src/cc/libbpf/include/uapi) 8 | 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 10 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") 11 | 12 | option(INSTALL_CPP_EXAMPLES "Install C++ examples. Those binaries are statically linked and can take plenty of disk space" OFF) 13 | 14 | file(GLOB EXAMPLES *.cc) 15 | foreach(EXAMPLE ${EXAMPLES}) 16 | get_filename_component(NAME ${EXAMPLE} NAME_WE) 17 | add_executable(${NAME} ${EXAMPLE}) 18 | 19 | if(NOT CMAKE_USE_LIBBPF_PACKAGE) 20 | target_link_libraries(${NAME} bcc-static) 21 | else() 22 | target_link_libraries(${NAME} bcc-shared) 23 | endif() 24 | 25 | if(INSTALL_CPP_EXAMPLES) 26 | install (TARGETS ${NAME} DESTINATION share/bcc/examples/cpp) 27 | endif(INSTALL_CPP_EXAMPLES) 28 | endforeach() 29 | 30 | add_subdirectory(pyperf) 31 | -------------------------------------------------------------------------------- /examples/local_storage/task_storage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from bcc import BPF 4 | 5 | source = r""" 6 | BPF_TASK_STORAGE(task_storage_map, __u64); 7 | 8 | KFUNC_PROBE(inet_listen) 9 | { 10 | __u64 ts = bpf_ktime_get_ns(); 11 | 12 | /* save timestamp to local storage on function entry */ 13 | task_storage_map.task_storage_get(bpf_get_current_task_btf(), &ts, BPF_LOCAL_STORAGE_GET_F_CREATE); 14 | 15 | bpf_trace_printk("inet_listen entry: store timestamp %lld", ts); 16 | return 0; 17 | } 18 | 19 | KRETFUNC_PROBE(inet_listen) 20 | { 21 | __u64 *ts; 22 | 23 | /* retrieve timestamp stored at local storage on function exit */ 24 | ts = task_storage_map.task_storage_get(bpf_get_current_task_btf(), 0, 0); 25 | if (!ts) 26 | return 0; 27 | 28 | /* delete timestamp from local storage */ 29 | task_storage_map.task_storage_delete(bpf_get_current_task_btf()); 30 | 31 | /* calculate latency */ 32 | bpf_trace_printk("inet_listen exit: cost %lldus", (bpf_ktime_get_ns() - *ts) / 1000); 33 | return 0; 34 | } 35 | """ 36 | 37 | b = BPF(text=source) 38 | try: 39 | b.trace_print() 40 | except KeyboardInterrupt: 41 | pass 42 | -------------------------------------------------------------------------------- /examples/tracing/tcpv4connect_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of tcpv4connect.py, the Linux eBPF/bcc version. 2 | 3 | 4 | This example traces the kernel function performing active TCP IPv4 connections 5 | (eg, via a connect() syscall; accept() are passive connections). Some example 6 | output (IP addresses changed to protect the innocent): 7 | 8 | # ./tcpv4connect.py 9 | PID COMM SADDR DADDR DPORT 10 | 1479 telnet 127.0.0.1 127.0.0.1 23 11 | 1469 curl 10.201.219.236 54.245.105.25 80 12 | 1469 curl 10.201.219.236 54.67.101.145 80 13 | 14 | This output shows three connections, one from a "telnet" process and two from 15 | "curl". The output details shows the source address, destination address, 16 | and destination port. This traces attempted connections: these may have failed. 17 | 18 | The overhead of this tool should be negligible, since it is only tracing the 19 | kernel function performing a connect. It is not tracing every packet and then 20 | filtering. 21 | 22 | This is provided as a basic example of TCP tracing. See tools/tcpconnect for a 23 | more featured version of this example (a tool). 24 | -------------------------------------------------------------------------------- /examples/tracing/urandomread.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # urandomread Example of instrumenting a kernel tracepoint. 4 | # For Linux, uses BCC, BPF. Embedded C. 5 | # 6 | # REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support). 7 | # 8 | # Test by running this, then in another shell, run: 9 | # dd if=/dev/urandom of=/dev/null bs=1k count=5 10 | # 11 | # Copyright 2016 Netflix, Inc. 12 | # Licensed under the Apache License, Version 2.0 (the "License") 13 | 14 | from __future__ import print_function 15 | from bcc import BPF 16 | from bcc.utils import printb 17 | 18 | # load BPF program 19 | b = BPF(text=""" 20 | TRACEPOINT_PROBE(random, urandom_read) { 21 | // args is from /sys/kernel/tracing/events/random/urandom_read/format 22 | bpf_trace_printk("%d\\n", args->got_bits); 23 | return 0; 24 | } 25 | """) 26 | 27 | # header 28 | print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "GOTBITS")) 29 | 30 | # format output 31 | while 1: 32 | try: 33 | (task, pid, cpu, flags, ts, msg) = b.trace_fields() 34 | except ValueError: 35 | continue 36 | except KeyboardInterrupt: 37 | exit() 38 | printb(b"%-18.9f %-16s %-6d %s" % (ts, task, pid, msg)) 39 | -------------------------------------------------------------------------------- /tools/killsnoop_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of killsnoop, the Linux eBPF/bcc version. 2 | 3 | 4 | This traces signals sent via the kill() syscall. For example: 5 | 6 | # ./killsnoop 7 | TIME PID COMM SIG TPID RESULT 8 | 12:10:51 13967 bash 9 13885 0 9 | 12:11:34 13967 bash 9 1024 -3 10 | 12:11:41 815 systemd-udevd 15 14076 0 11 | 12 | The first line showed a SIGKILL (9) sent from PID 13967 (a bash shell) to 13 | PID 13885. The result, 0, means success. 14 | 15 | The second line showed the same signal sent, this time resulting in a -3 16 | (ESRCH: no such process). 17 | 18 | 19 | USAGE message: 20 | 21 | # ./killsnoop -h 22 | usage: killsnoop [-h] [-x] [-p PID] 23 | 24 | Trace signals issued by the kill() syscall 25 | 26 | optional arguments: 27 | -h, --help show this help message and exit 28 | -x, --failed only show failed kill syscalls 29 | -p PID, --pid PID trace this PID only 30 | 31 | examples: 32 | ./killsnoop # trace all kill() signals 33 | ./killsnoop -x # only show failed kills 34 | ./killsnoop -p 181 # only trace PID 181 35 | ./killsnoop -s 9 # only trace signal 9 36 | -------------------------------------------------------------------------------- /introspection/bps_example.txt: -------------------------------------------------------------------------------- 1 | * List all BPF programs * 2 | # bps 3 | BID TYPE UID #MAPS LoadTime NAME 4 | 82 kprobe 0 1 Oct19/23:52 map_perf_test 5 | 83 kprobe 0 1 Oct19/23:52 map_perf_test 6 | 84 kprobe 0 1 Oct19/23:52 map_perf_test 7 | 85 kprobe 0 1 Oct19/23:52 map_perf_test 8 | 86 kprobe 0 4 Oct19/23:52 map_perf_test 9 | 87 kprobe 0 1 Oct19/23:52 map_perf_test 10 | 88 kprobe 0 1 Oct19/23:52 map_perf_test 11 | 89 kprobe 0 1 Oct19/23:52 map_perf_test 12 | 13 | * List a particular BPF program and its maps * 14 | # bps 86 15 | BID TYPE UID #MAPS LoadTime NAME 16 | 86 kprobe 0 4 Oct19/23:52 map_perf_test 17 | 18 | MID TYPE FLAGS KeySz ValueSz MaxEnts NAME 19 | 120 lru hash 0x0 4 8 10000 lru_hash_map 20 | 129 lru hash 0x0 4 8 43 lru_hash_lookup 21 | 123 array of maps 0x0 4 4 1024 array_of_lru_ha 22 | 121 lru hash 0x2 4 23 | -------------------------------------------------------------------------------- /scripts/build-release-rpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | set -e 5 | 6 | TMP=$(mktemp -d /tmp/rpmbuild.XXXXXX) 7 | 8 | function cleanup() { 9 | [[ -d $TMP ]] && rm -rf $TMP 10 | } 11 | trap cleanup EXIT 12 | 13 | mkdir $TMP/{BUILD,RPMS,SOURCES,SPECS,SRPMS} 14 | 15 | llvmver=7.0.1 16 | 17 | # populate submodules 18 | git submodule update --init --recursive 19 | 20 | . scripts/git-tag.sh 21 | 22 | git archive HEAD --prefix=bcc/ --format=tar -o $TMP/SOURCES/bcc.tar 23 | 24 | # archive submodules 25 | pushd src/cc/libbpf 26 | git archive HEAD --prefix=bcc/src/cc/libbpf/ --format=tar -o $TMP/SOURCES/bcc_libbpf.tar 27 | popd 28 | 29 | # merge all archives into $git_tag_latest.tar.gz 30 | pushd $TMP/SOURCES 31 | tar -A -f bcc.tar bcc_libbpf.tar 32 | gzip -c bcc.tar > $git_tag_latest.tar.gz 33 | popd 34 | 35 | wget -P $TMP/SOURCES http://llvm.org/releases/$llvmver/{cfe,llvm}-$llvmver.src.tar.xz 36 | 37 | sed \ 38 | -e "s/^\(Version:\s*\)@REVISION@/\1$revision/" \ 39 | -e "s/^\(Release:\s*\)@GIT_REV_COUNT@/\1$release/" \ 40 | SPECS/bcc+clang.spec > $TMP/SPECS/bcc.spec 41 | 42 | pushd $TMP 43 | rpmbuild --define "_topdir `pwd`" -ba SPECS/bcc.spec 44 | popd 45 | 46 | cp $TMP/RPMS/*/*.rpm . 47 | cp $TMP/SRPMS/*.rpm . 48 | -------------------------------------------------------------------------------- /tools/threadsnoop_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of threadsnoop, the Linux BCC/eBPF version. 2 | 3 | 4 | Tracing new threads via phtread_create(): 5 | 6 | # ./threadsnoop 7 | Attaching 2 probes... 8 | TIME(ms) PID COMM FUNC 9 | 1938 28549 dockerd threadentry 10 | 1939 28549 dockerd threadentry 11 | 1939 28549 dockerd threadentry 12 | 1940 28549 dockerd threadentry 13 | 1949 28549 dockerd threadentry 14 | 1958 28549 dockerd threadentry 15 | 1939 28549 dockerd threadentry 16 | 1950 28549 dockerd threadentry 17 | 2013 28579 docker-containe 0x562f30f2e710L 18 | 2036 28549 dockerd threadentry 19 | 2083 28579 docker-containe 0x562f30f2e710L 20 | 2116 629 systemd-journal 0x7fb7114955c0L 21 | 2116 629 systemd-journal 0x7fb7114955c0L 22 | [...] 23 | 24 | The output shows a dockerd process creating several threads with the start 25 | routine threadentry(), and docker-containe (truncated) and systemd-journal 26 | also starting threads: in their cases, the function had no symbol information 27 | available, so their addresses are printed in hex. 28 | -------------------------------------------------------------------------------- /libbpf-tools/numamove.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Wenbo Zhang 3 | #include 4 | #include 5 | #include 6 | 7 | struct { 8 | __uint(type, BPF_MAP_TYPE_HASH); 9 | __uint(max_entries, 10240); 10 | __type(key, u32); 11 | __type(value, u64); 12 | } start SEC(".maps"); 13 | 14 | __u64 latency = 0; 15 | __u64 num = 0; 16 | 17 | SEC("fentry/migrate_misplaced_page") 18 | int BPF_PROG(migrate_misplaced_page) 19 | { 20 | u32 pid = bpf_get_current_pid_tgid(); 21 | u64 ts = bpf_ktime_get_ns(); 22 | 23 | bpf_map_update_elem(&start, &pid, &ts, 0); 24 | return 0; 25 | } 26 | 27 | SEC("fexit/migrate_misplaced_page") 28 | int BPF_PROG(migrate_misplaced_page_exit) 29 | { 30 | u32 pid = bpf_get_current_pid_tgid(); 31 | u64 *tsp, ts = bpf_ktime_get_ns(); 32 | s64 delta; 33 | 34 | tsp = bpf_map_lookup_elem(&start, &pid); 35 | if (!tsp) 36 | return 0; 37 | delta = (s64)(ts - *tsp); 38 | if (delta < 0) 39 | goto cleanup; 40 | __sync_fetch_and_add(&latency, delta / 1000000U); 41 | __sync_fetch_and_add(&num, 1); 42 | 43 | cleanup: 44 | bpf_map_delete_elem(&start, &pid); 45 | return 0; 46 | } 47 | 48 | char LICENSE[] SEC("license") = "GPL"; 49 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB C_FILES *.c) 2 | file(GLOB PY_FILES *.py) 3 | file(GLOB SH_FILES *.sh) 4 | file(GLOB TXT_FILES *.txt) 5 | list(REMOVE_ITEM TXT_FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) 6 | foreach(FIL ${PY_FILES}) 7 | get_filename_component(FIL_WE ${FIL} NAME_WE) 8 | install(PROGRAMS ${FIL} DESTINATION share/bcc/tools RENAME ${FIL_WE}) 9 | endforeach() 10 | foreach(FIL ${SH_FILES}) 11 | if(${FIL} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/reset-trace.sh) 12 | get_filename_component(FIL_WE ${FIL} NAME_WE) 13 | install(PROGRAMS ${FIL} DESTINATION share/bcc/tools RENAME ${FIL_WE}) 14 | else() 15 | file(READ ${FIL} CONTENT) 16 | string(REPLACE ".py -l" " -l" CONTENT_WE ${CONTENT}) 17 | string(REPLACE "\"" "\\\"" CONTENT_WE ${CONTENT_WE}) 18 | get_filename_component(FIL_WE ${FIL} NAME_WE) 19 | install(PROGRAMS ${FIL} DESTINATION share/bcc/tools RENAME ${FIL_WE}) 20 | install(CODE "file(WRITE \"\$ENV{DESTDIR}/\${CMAKE_INSTALL_PREFIX}/share/bcc/tools/${FIL_WE}\" \"${CONTENT_WE}\")") 21 | endif() 22 | endforeach() 23 | install(FILES ${C_FILES} DESTINATION share/bcc/tools) 24 | install(FILES ${TXT_FILES} DESTINATION share/bcc/tools/doc) 25 | add_subdirectory(lib) 26 | add_subdirectory(old) 27 | -------------------------------------------------------------------------------- /examples/lua/bashreadline.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bcc-lua 2 | --[[ 3 | Copyright 2016 GitHub, Inc 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | ]] 17 | local ffi = require("ffi") 18 | 19 | return function(BPF) 20 | local b = BPF:new{src_file="bashreadline.c", debug=0} 21 | b:attach_uprobe{name="/bin/bash", sym="readline", fn_name="printret", retprobe=true} 22 | 23 | local function print_readline(cpu, event) 24 | print("%-9s %-6d %s" % {os.date("%H:%M:%S"), tonumber(event.pid), ffi.string(event.str)}) 25 | end 26 | 27 | b:get_table("events"):open_perf_buffer(print_readline, "struct { uint64_t pid; char str[80]; }", nil) 28 | 29 | print("%-9s %-6s %s" % {"TIME", "PID", "COMMAND"}) 30 | b:perf_buffer_poll_loop() 31 | end 32 | -------------------------------------------------------------------------------- /examples/lua/kprobe-write.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bcc-lua 2 | --[[ 3 | Copyright 2016 Marek Vavrusa 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | ]] 17 | -- Simple tracing example that executes a program on 18 | -- return from sys_write() and tracks the number of hits 19 | local ffi = require('ffi') 20 | local bpf = require('bpf') 21 | local S = require('syscall') 22 | 23 | -- Shared part of the program 24 | local map = bpf.map('array', 1) 25 | -- Kernel-space part of the program 26 | local probe = bpf.kprobe('myprobe:sys_write', function (ptregs) 27 | xadd(map[0], 1) 28 | end, true) 29 | -- User-space part of the program 30 | pcall(function() 31 | for _ = 1, 10 do 32 | print('hits: ', tonumber(map[0])) 33 | S.sleep(1) 34 | end 35 | end) 36 | -------------------------------------------------------------------------------- /tools/old/bashreadline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # bashreadline Print entered bash commands from all running shells. 4 | # For Linux, uses BCC, eBPF. Embedded C. 5 | # 6 | # This works by tracing the readline() function using a uretprobe (uprobes). 7 | # 8 | # Copyright 2016 Netflix, Inc. 9 | # Licensed under the Apache License, Version 2.0 (the "License") 10 | # 11 | # 28-Jan-2016 Brendan Gregg Created this. 12 | 13 | from __future__ import print_function 14 | from bcc import BPF 15 | from time import strftime 16 | 17 | # load BPF program 18 | bpf_text = """ 19 | #include 20 | int printret(struct pt_regs *ctx) { 21 | if (!ctx->ax) 22 | return 0; 23 | 24 | char str[80] = {}; 25 | bpf_probe_read(&str, sizeof(str), (void *)PT_REGS_RC(ctx)); 26 | bpf_trace_printk("%s\\n", &str); 27 | 28 | return 0; 29 | }; 30 | """ 31 | b = BPF(text=bpf_text) 32 | b.attach_uretprobe(name="/bin/bash", sym="readline", fn_name="printret") 33 | 34 | # header 35 | print("%-9s %-6s %s" % ("TIME", "PID", "COMMAND")) 36 | 37 | # format output 38 | while 1: 39 | try: 40 | (task, pid, cpu, flags, ts, msg) = b.trace_fields() 41 | except ValueError: 42 | continue 43 | print("%-9s %-6d %s" % (strftime("%H:%M:%S"), pid, msg)) 44 | -------------------------------------------------------------------------------- /examples/ringbuf/ringbuf_output.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | import time 5 | 6 | from bcc import BPF 7 | 8 | src = r""" 9 | BPF_RINGBUF_OUTPUT(buffer, 1 << 4); 10 | 11 | struct event { 12 | char filename[16]; 13 | int dfd; 14 | int flags; 15 | int mode; 16 | }; 17 | 18 | TRACEPOINT_PROBE(syscalls, sys_enter_openat) { 19 | int zero = 0; 20 | 21 | struct event event = {}; 22 | 23 | bpf_probe_read_user_str(event.filename, sizeof(event.filename), args->filename); 24 | 25 | event.dfd = args->dfd; 26 | event.flags = args->flags; 27 | event.mode = args->mode; 28 | 29 | buffer.ringbuf_output(&event, sizeof(event), 0); 30 | 31 | return 0; 32 | } 33 | """ 34 | 35 | b = BPF(text=src) 36 | 37 | def callback(ctx, data, size): 38 | event = b['buffer'].event(data) 39 | print("%-16s %10d %10d %10d" % (event.filename.decode('utf-8'), event.dfd, event.flags, event.mode)) 40 | 41 | b['buffer'].open_ring_buffer(callback) 42 | 43 | print("Printing openat() calls, ctrl-c to exit.") 44 | 45 | print("%-16s %10s %10s %10s" % ("FILENAME", "DIR_FD", "FLAGS", "MODE")) 46 | 47 | try: 48 | while 1: 49 | b.ring_buffer_poll() 50 | # or b.ring_buffer_consume() 51 | time.sleep(0.5) 52 | except KeyboardInterrupt: 53 | sys.exit() 54 | -------------------------------------------------------------------------------- /examples/tracing/bitehist_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of bitehist.py, the Linux eBPF/bcc version. 2 | 3 | This prints a power-of-2 histogram to show the block I/O size distribution. 4 | A summary is printed after Ctrl-C is hit. 5 | 6 | # ./bitehist.py 7 | Tracing... Hit Ctrl-C to end. 8 | ^C 9 | kbytes : count distribution 10 | 0 -> 1 : 3 | | 11 | 2 -> 3 : 0 | | 12 | 4 -> 7 : 211 |********** | 13 | 8 -> 15 : 0 | | 14 | 16 -> 31 : 0 | | 15 | 32 -> 63 : 0 | | 16 | 64 -> 127 : 1 | | 17 | 128 -> 255 : 800 |**************************************| 18 | 19 | This output shows a bimodal distribution. The largest mod of 800 I/O were 20 | between 128 and 255 Kbytes in size, and another mode of 211 I/O were between 21 | 4 and 7 Kbytes in size. 22 | 23 | Understanding this distribution is useful for characterizing workloads and 24 | understanding performance. The existence of this distribution is not visible 25 | from averages alone. 26 | -------------------------------------------------------------------------------- /tests/python/test_uprobes2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # USAGE: test_uprobe2.py 4 | # 5 | # Copyright 2020 Facebook, Inc 6 | # Licensed under the Apache License, Version 2.0 (the "License") 7 | 8 | from bcc import BPF 9 | from unittest import main, TestCase 10 | from subprocess import Popen, PIPE 11 | from tempfile import NamedTemporaryFile 12 | 13 | 14 | class TestUprobes(TestCase): 15 | def setUp(self): 16 | lib_text = b""" 17 | __attribute__((__visibility__("default"))) void fun() 18 | { 19 | } 20 | """ 21 | self.bpf_text = """ 22 | int trace_fun_call(void *ctx) {{ 23 | return 1; 24 | }} 25 | """ 26 | # Compile and run the application 27 | self.ftemp = NamedTemporaryFile(delete=False) 28 | self.ftemp.close() 29 | comp = Popen([ 30 | "gcc", 31 | "-x", "c", 32 | "-shared", 33 | "-Wl,-Ttext-segment,0x2000000", 34 | "-o", self.ftemp.name, 35 | "-" 36 | ], stdin=PIPE) 37 | comp.stdin.write(lib_text) 38 | comp.stdin.close() 39 | self.assertEqual(comp.wait(), 0) 40 | 41 | def test_attach1(self): 42 | b = BPF(text=self.bpf_text) 43 | b.attach_uprobe(name=self.ftemp.name, sym="fun", fn_name="trace_fun_call") 44 | 45 | 46 | if __name__ == "__main__": 47 | main() 48 | -------------------------------------------------------------------------------- /tools/tcpsynbl_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of tcpsynbl, the Linux BCC/eBPF version. 2 | 3 | 4 | This tool shows the TCP SYN backlog size during SYN arrival as a histogram. 5 | This lets you see how close your applications are to hitting the backlog limit 6 | and dropping SYNs (causing performance issues with SYN retransmits). For 7 | example: 8 | 9 | # ./tcpsynbl.py 10 | Tracing SYN backlog size. Ctrl-C to end. 11 | ^C 12 | 13 | backlog_max = 500L 14 | backlog : count distribution 15 | 0 -> 1 : 961 |****************************************| 16 | 2 -> 3 : 1 | | 17 | 18 | This output shows that for the backlog limit of 500, there were 961 SYN 19 | arrival where the backlog was zero or one, and one accept where the backlog was 20 | two or three. This indicates that we are nowhere near this limit. 21 | 22 | USAGE: 23 | 24 | # ./tcpsynbl -h 25 | usage: tcpsynbl.py [-h] [-4 | -6] 26 | 27 | Show TCP SYN backlog. 28 | 29 | optional arguments: 30 | -h, --help show this help message and exit 31 | -4, --ipv4 trace IPv4 family only 32 | -6, --ipv6 trace IPv6 family only 33 | 34 | examples: 35 | ./tcpsynbl # trace syn backlog 36 | ./tcpsynbl -4 # trace IPv4 family only 37 | ./tcpsynbl -6 # trace IPv6 family only -------------------------------------------------------------------------------- /libbpf-tools/biopattern.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Wenbo Zhang 3 | #include 4 | #include 5 | #include 6 | #include "biopattern.h" 7 | #include "maps.bpf.h" 8 | 9 | const volatile bool filter_dev = false; 10 | const volatile __u32 targ_dev = 0; 11 | 12 | struct { 13 | __uint(type, BPF_MAP_TYPE_HASH); 14 | __uint(max_entries, 64); 15 | __type(key, u32); 16 | __type(value, struct counter); 17 | } counters SEC(".maps"); 18 | 19 | SEC("tracepoint/block/block_rq_complete") 20 | int handle__block_rq_complete(struct trace_event_raw_block_rq_complete *ctx) 21 | { 22 | sector_t sector = ctx->sector; 23 | struct counter *counterp, zero = {}; 24 | u32 nr_sector = ctx->nr_sector; 25 | u32 dev = ctx->dev; 26 | 27 | if (filter_dev && targ_dev != dev) 28 | return 0; 29 | 30 | counterp = bpf_map_lookup_or_try_init(&counters, &dev, &zero); 31 | if (!counterp) 32 | return 0; 33 | if (counterp->last_sector) { 34 | if (counterp->last_sector == sector) 35 | __sync_fetch_and_add(&counterp->sequential, 1); 36 | else 37 | __sync_fetch_and_add(&counterp->random, 1); 38 | __sync_fetch_and_add(&counterp->bytes, nr_sector * 512); 39 | } 40 | counterp->last_sector = sector + nr_sector; 41 | return 0; 42 | } 43 | 44 | char LICENSE[] SEC("license") = "GPL"; 45 | -------------------------------------------------------------------------------- /man/man8/solisten.8: -------------------------------------------------------------------------------- 1 | .TH SOLISTEN 8 "2019-07-29" "USER COMMANDS" 2 | .SH NAME 3 | solisten \- Trace listening socket 4 | .SH SYNOPSIS 5 | usage: solisten [\-h] [\-\-show\-netns] [\-p PID] [\-n NETNS] 6 | .SH DESCRIPTION 7 | All IPv4 and IPv6 listen attempts are traced, even if they ultimately 8 | fail or the listening program is not willing to accept(). 9 | .SS "optional arguments:" 10 | .TP 11 | \fB\-h\fR, \fB\-\-help\fR 12 | show this help message and exit 13 | .TP 14 | \fB\-\-show\-netns\fR 15 | show network namespace 16 | .TP 17 | \fB\-p\fR PID, \fB\-\-pid\fR PID 18 | trace this PID only 19 | .TP 20 | \fB\-n\fR NETNS, \fB\-\-netns\fR NETNS 21 | trace this Network Namespace only 22 | .SH EXAMPLES 23 | .TP 24 | Stream socket listen: 25 | # 26 | .B solisten 27 | .TP 28 | Stream socket listen for specified PID only 29 | # 30 | .B solisten \-p 1234 31 | .TP 32 | Stream socket listen for the specified network namespace ID only 33 | # 34 | .B solisten \-\-netns 4242 35 | .TP 36 | Show network ns ID (useful for containers) 37 | # 38 | .B solisten \-\-show\-netns 39 | .SH SOURCE 40 | This is from bcc. 41 | .IP 42 | https://github.com/iovisor/bcc 43 | .PP 44 | Also look in the bcc distribution for a companion _examples.txt file containing 45 | example usage, output, and commentary for this tool. 46 | .SH OS 47 | Linux 48 | .SH STABILITY 49 | Unstable - in development. 50 | -------------------------------------------------------------------------------- /tools/pidpersec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # @lint-avoid-python-3-compatibility-imports 3 | # 4 | # pidpersec Count new processes (via fork). 5 | # For Linux, uses BCC, eBPF. See .c file. 6 | # 7 | # USAGE: pidpersec 8 | # 9 | # Written as a basic example of counting an event. 10 | # 11 | # Copyright (c) 2015 Brendan Gregg. 12 | # Licensed under the Apache License, Version 2.0 (the "License") 13 | # 14 | # 11-Aug-2015 Brendan Gregg Created this. 15 | 16 | from bcc import BPF 17 | from ctypes import c_int 18 | from time import sleep, strftime 19 | 20 | # load BPF program 21 | b = BPF(text=""" 22 | #include 23 | 24 | enum stat_types { 25 | S_COUNT = 1, 26 | S_MAXSTAT 27 | }; 28 | 29 | BPF_ARRAY(stats, u64, S_MAXSTAT); 30 | 31 | static void stats_increment(int key) { 32 | stats.atomic_increment(key); 33 | } 34 | 35 | void do_count(struct pt_regs *ctx) { stats_increment(S_COUNT); } 36 | """) 37 | b.attach_kprobe(event="sched_fork", fn_name="do_count") 38 | 39 | # stat indexes 40 | S_COUNT = c_int(1) 41 | 42 | # header 43 | print("Tracing... Ctrl-C to end.") 44 | 45 | # output 46 | while (1): 47 | try: 48 | sleep(1) 49 | except KeyboardInterrupt: 50 | exit() 51 | 52 | print("%s: PIDs/sec: %d" % (strftime("%H:%M:%S"), 53 | b["stats"][S_COUNT].value)) 54 | b["stats"].clear() 55 | -------------------------------------------------------------------------------- /scripts/check-helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ret=0 3 | 4 | libbpf=$(grep -oP '(?<={")\w+(?=", "\d\.\d+")' src/cc/libbpf.c | sort) 5 | doc=$(grep -oP "(?<=BPF_FUNC_)\w+" docs/kernel-versions.md | sort) 6 | dif=$(diff <(echo "$doc") <(echo "$libbpf")) 7 | if [ $? -ne 0 ]; then 8 | echo "The lists of helpers in src/cc/libbpf.c and docs/kernel-versions.md differ:" 9 | echo -e "$dif\n" 10 | ((ret++)) 11 | fi 12 | 13 | compat=$(grep -oP "(?<=^\sFN\()\w+" src/cc/compat/linux/bpf.h | tail -n +2 | sort) 14 | dif=$(diff <(echo "$doc") <(echo "$compat")) 15 | if [ $? -ne 0 ]; then 16 | echo "The lists of helpers in docs/kernel-versions.md and src/cc/compat/linux/bpf.h differ:" 17 | echo -e "$dif\n" 18 | ((ret++)) 19 | fi 20 | 21 | virtual=$(grep -oP "(?<=^\sFN\()\w+" src/cc/compat/linux/virtual_bpf.h | tail -n +2 | sort -u) 22 | dif=$(diff <(echo "$compat") <(echo "$virtual")) 23 | if [ $? -ne 0 ]; then 24 | echo "The lists of helpers in src/cc/compat/linux/bpf.h and src/cc/compat/linux/virtual_bpf.h differ:" 25 | echo "$dif" 26 | ((ret++)) 27 | fi 28 | 29 | export=$(grep -oP "(?<=BPF_FUNC_)\w+" src/cc/export/helpers.h | sort -u) 30 | dif=$(diff <(echo "$compat") <(echo "$export")) 31 | if [ $? -ne 0 ]; then 32 | echo "The lists of helpers in src/cc/compat/linux/bpf.h and src/cc/export/helpers.h differ:" 33 | echo "$dif" 34 | ((ret++)) 35 | fi 36 | 37 | exit $ret 38 | -------------------------------------------------------------------------------- /scripts/build-rpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | set -e 5 | 6 | TMP=$(mktemp -d /tmp/rpmbuild.XXXXXX) 7 | 8 | function cleanup() { 9 | [[ -d $TMP ]] && rm -rf $TMP 10 | } 11 | trap cleanup EXIT 12 | 13 | # install python dependencies for test 14 | if [ -f os-release ]; then 15 | . os-release 16 | fi 17 | if [[ $VERSION_ID -lt 30 ]]; then 18 | PKGS="python3-cachetools python-cachetools" 19 | else 20 | PKGS="python3-cachetools" 21 | fi 22 | sudo dnf install -y $PKGS 23 | 24 | mkdir $TMP/{BUILD,RPMS,SOURCES,SPECS,SRPMS} 25 | 26 | llvmver=3.7.1 27 | 28 | # populate submodules 29 | git submodule update --init --recursive 30 | 31 | . scripts/git-tag.sh 32 | 33 | git archive HEAD --prefix=bcc/ --format=tar -o $TMP/SOURCES/bcc.tar 34 | 35 | # archive submodules 36 | pushd src/cc/libbpf 37 | git archive HEAD --prefix=bcc/src/cc/libbpf/ --format=tar -o $TMP/SOURCES/bcc_libbpf.tar 38 | popd 39 | 40 | # merge all archives into bcc.tar.gz 41 | pushd $TMP/SOURCES 42 | tar -A -f bcc.tar bcc_libbpf.tar 43 | gzip bcc.tar 44 | popd 45 | 46 | sed \ 47 | -e "s/^\(Version:\s*\)@REVISION@/\1$revision/" \ 48 | -e "s/^\(Release:\s*\)@GIT_REV_COUNT@/\1$release/" \ 49 | SPECS/bcc.spec > $TMP/SPECS/bcc.spec 50 | 51 | pushd $TMP 52 | rpmbuild $RPM_WITH_OPTS --define "_topdir `pwd`" -ba SPECS/bcc.spec 53 | popd 54 | 55 | cp $TMP/RPMS/*/*.rpm . 56 | cp $TMP/SRPMS/*.rpm . 57 | -------------------------------------------------------------------------------- /libbpf-tools/llcstat.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Wenbo Zhang 3 | #include 4 | #include 5 | #include 6 | #include "llcstat.h" 7 | 8 | #define MAX_ENTRIES 10240 9 | 10 | struct { 11 | __uint(type, BPF_MAP_TYPE_HASH); 12 | __uint(max_entries, MAX_ENTRIES); 13 | __type(key, u64); 14 | __type(value, struct info); 15 | } infos SEC(".maps"); 16 | 17 | static __always_inline 18 | int trace_event(__u64 sample_period, bool miss) 19 | { 20 | u64 pid = bpf_get_current_pid_tgid(); 21 | u32 cpu = bpf_get_smp_processor_id(); 22 | struct info *infop, info = {}; 23 | u64 key = pid << 32 | cpu; 24 | 25 | infop = bpf_map_lookup_elem(&infos, &key); 26 | if (!infop) { 27 | bpf_get_current_comm(info.comm, sizeof(info.comm)); 28 | infop = &info; 29 | } 30 | if (miss) 31 | infop->miss += sample_period; 32 | else 33 | infop->ref += sample_period; 34 | if (infop == &info) 35 | bpf_map_update_elem(&infos, &key, infop, 0); 36 | return 0; 37 | } 38 | 39 | SEC("perf_event") 40 | int on_cache_miss(struct bpf_perf_event_data *ctx) 41 | { 42 | return trace_event(ctx->sample_period, true); 43 | } 44 | 45 | SEC("perf_event") 46 | int on_cache_ref(struct bpf_perf_event_data *ctx) 47 | { 48 | return trace_event(ctx->sample_period, false); 49 | } 50 | 51 | char LICENSE[] SEC("license") = "GPL"; 52 | -------------------------------------------------------------------------------- /libbpf-tools/runqlen.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Wenbo Zhang 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "runqlen.h" 8 | 9 | const volatile bool targ_per_cpu = false; 10 | 11 | struct hist hists[MAX_CPU_NR] = {}; 12 | 13 | SEC("perf_event") 14 | int do_sample(struct bpf_perf_event_data *ctx) 15 | { 16 | struct task_struct *task; 17 | struct hist *hist; 18 | u64 slot, cpu = 0; 19 | 20 | task = (void*)bpf_get_current_task(); 21 | slot = BPF_CORE_READ(task, se.cfs_rq, nr_running); 22 | /* 23 | * Calculate run queue length by subtracting the currently running task, 24 | * if present. len 0 == idle, len 1 == one running task. 25 | */ 26 | if (slot > 0) 27 | slot--; 28 | if (targ_per_cpu) { 29 | cpu = bpf_get_smp_processor_id(); 30 | /* 31 | * When the program is started, the user space will immediately 32 | * exit when it detects this situation, here just to pass the 33 | * verifier's check. 34 | */ 35 | if (cpu >= MAX_CPU_NR) 36 | return 0; 37 | } 38 | hist = &hists[cpu]; 39 | if (slot >= MAX_SLOTS) 40 | slot = MAX_SLOTS - 1; 41 | if (targ_per_cpu) 42 | hist->slots[slot]++; 43 | else 44 | __sync_fetch_and_add(&hist->slots[slot], 1); 45 | return 0; 46 | } 47 | 48 | char LICENSE[] SEC("license") = "GPL"; 49 | -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Internal file for GetGitRevisionDescription.cmake 3 | # 4 | # Requires CMake 2.6 or newer (uses the 'function' command) 5 | # 6 | # Original Author: 7 | # 2009-2010 Ryan Pavlik 8 | # http://academic.cleardefinition.com 9 | # Iowa State University HCI Graduate Program/VRAC 10 | # 11 | # Copyright Iowa State University 2009-2010. 12 | # Distributed under the Boost Software License, Version 1.0. 13 | # (See accompanying file LICENSE_1_0.txt or copy at 14 | # http://www.boost.org/LICENSE_1_0.txt) 15 | 16 | set(HEAD_HASH) 17 | 18 | file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 19 | 20 | string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 21 | if(HEAD_CONTENTS MATCHES "ref") 22 | # named branch 23 | string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 24 | if(EXISTS "@GIT_DIR@/${HEAD_REF}") 25 | configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 26 | elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") 27 | configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 28 | set(HEAD_HASH "${HEAD_REF}") 29 | endif() 30 | else() 31 | # detached HEAD 32 | configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 33 | endif() 34 | 35 | if(NOT HEAD_HASH) 36 | file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 37 | string(STRIP "${HEAD_HASH}" HEAD_HASH) 38 | endif() 39 | -------------------------------------------------------------------------------- /tools/bitesize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # bitehist.py Block I/O size histogram. 4 | # For Linux, uses BCC, eBPF. See .c file. 5 | # 6 | # USAGE: bitesize 7 | # 8 | # Ctrl-C will print the partially gathered histogram then exit. 9 | # 10 | # Copyright (c) 2016 Allan McAleavy 11 | # Licensed under the Apache License, Version 2.0 (the "License") 12 | # 13 | # 05-Feb-2016 Allan McAleavy ran pep8 against file 14 | # 19-Mar-2019 Brendan Gregg Switched to use tracepoints. 15 | 16 | from bcc import BPF 17 | from time import sleep 18 | 19 | bpf_text = """ 20 | #include 21 | #include 22 | 23 | struct proc_key_t { 24 | char name[TASK_COMM_LEN]; 25 | u64 slot; 26 | }; 27 | 28 | BPF_HISTOGRAM(dist, struct proc_key_t); 29 | 30 | TRACEPOINT_PROBE(block, block_rq_issue) 31 | { 32 | struct proc_key_t key = {.slot = bpf_log2l(args->bytes / 1024)}; 33 | bpf_probe_read_kernel(&key.name, sizeof(key.name), args->comm); 34 | dist.atomic_increment(key); 35 | return 0; 36 | } 37 | """ 38 | 39 | # load BPF program 40 | b = BPF(text=bpf_text) 41 | 42 | print("Tracing block I/O... Hit Ctrl-C to end.") 43 | 44 | # trace until Ctrl-C 45 | dist = b.get_table("dist") 46 | 47 | try: 48 | sleep(99999999) 49 | except KeyboardInterrupt: 50 | dist.print_log2_hist("Kbytes", "Process Name", 51 | section_print_fn=bytes.decode) 52 | -------------------------------------------------------------------------------- /tests/python/test_call1.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) PLUMgrid, Inc. 2 | // Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | BPF_PROG_ARRAY(jump, 64); 5 | BPF_ARRAY(stats, u64, 64); 6 | 7 | enum states { 8 | S_EOP = 1, 9 | S_ETHER, 10 | S_ARP, 11 | S_IP 12 | }; 13 | 14 | int parse_ether(struct __sk_buff *skb) { 15 | size_t cur = 0; 16 | size_t next = cur + 14; 17 | 18 | int key = S_ETHER; 19 | u64 *leaf = stats.lookup(&key); 20 | if (leaf) (*leaf)++; 21 | 22 | switch (bpf_dext_pkt(skb, cur + 12, 0, 16)) { 23 | case 0x0800: jump.call(skb, S_IP); 24 | case 0x0806: jump.call(skb, S_ARP); 25 | } 26 | jump.call(skb, S_EOP); 27 | return 1; 28 | } 29 | 30 | int parse_arp(struct __sk_buff *skb) { 31 | size_t cur = 14; // TODO: get from ctx 32 | size_t next = cur + 28; 33 | 34 | int key = S_ARP; 35 | u64 *leaf = stats.lookup(&key); 36 | if (leaf) (*leaf)++; 37 | 38 | jump.call(skb, S_EOP); 39 | return 1; 40 | } 41 | 42 | int parse_ip(struct __sk_buff *skb) { 43 | size_t cur = 14; // TODO: get from ctx 44 | size_t next = cur + 20; 45 | 46 | int key = S_IP; 47 | u64 *leaf = stats.lookup(&key); 48 | if (leaf) (*leaf)++; 49 | 50 | jump.call(skb, S_EOP); 51 | return 1; 52 | } 53 | 54 | int eop(struct __sk_buff *skb) { 55 | int key = S_EOP; 56 | u64 *leaf = stats.lookup(&key); 57 | if (leaf) (*leaf)++; 58 | return 1; 59 | } 60 | -------------------------------------------------------------------------------- /src/cc/bcc_perf_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Facebook, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef LIBBCC_PERF_MAP_H 17 | #define LIBBCC_PERF_MAP_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // Symbol name, start address, length, payload 28 | typedef int (*bcc_perf_map_symcb)(const char *, uint64_t, uint64_t, void *); 29 | 30 | bool bcc_is_perf_map(const char *path); 31 | bool bcc_is_valid_perf_map(const char *path); 32 | 33 | int bcc_perf_map_nstgid(int pid); 34 | bool bcc_perf_map_path(char *map_path, size_t map_len, int pid); 35 | int bcc_perf_map_foreach_sym(const char *path, bcc_perf_map_symcb callback, 36 | void* payload); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | #endif 42 | -------------------------------------------------------------------------------- /examples/cpp/pyperf/Py36Offsets.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. 3 | * Licensed under the Apache License, Version 2.0 (the "License") 4 | */ 5 | 6 | #include "PyPerfType.h" 7 | 8 | namespace ebpf { 9 | namespace pyperf { 10 | 11 | extern const OffsetConfig kPy36OffsetConfig = { 12 | .PyObject_type = 8, // offsetof(PyObject, ob_type) 13 | .PyTypeObject_name = 24, // offsetof(PyTypeObject, tp_name) 14 | .PyThreadState_frame = 24, // offsetof(PyThreadState, frame) 15 | .PyThreadState_thread = 152, // offsetof(PyThreadState, thread_id) 16 | .PyFrameObject_back = 24, // offsetof(PyFrameObject, f_back) 17 | .PyFrameObject_code = 32, // offsetof(PyFrameObject, f_code) 18 | .PyFrameObject_lineno = 124, // offsetof(PyFrameObject, f_lineno) 19 | .PyFrameObject_localsplus = 376, // offsetof(PyFrameObject, f_localsplus) 20 | .PyCodeObject_filename = 96, // offsetof(PyCodeObject, co_filename) 21 | .PyCodeObject_name = 104, // offsetof(PyCodeObject, co_name) 22 | .PyCodeObject_varnames = 64, // offsetof(PyCodeObject, co_varnames) 23 | .PyTupleObject_item = 24, // offsetof(PyTupleObject, ob_item) 24 | .String_data = 48, // sizeof(PyASCIIObject) 25 | .String_size = 16, // offsetof(PyVarObject, ob_size) 26 | }; 27 | 28 | } 29 | } // namespace ebpf 30 | -------------------------------------------------------------------------------- /examples/ringbuf/ringbuf_submit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | import time 5 | 6 | from bcc import BPF 7 | 8 | src = r""" 9 | BPF_RINGBUF_OUTPUT(buffer, 1 << 4); 10 | 11 | struct event { 12 | char filename[64]; 13 | int dfd; 14 | int flags; 15 | int mode; 16 | }; 17 | 18 | TRACEPOINT_PROBE(syscalls, sys_enter_openat) { 19 | int zero = 0; 20 | 21 | struct event *event = buffer.ringbuf_reserve(sizeof(struct event)); 22 | if (!event) { 23 | return 1; 24 | } 25 | 26 | bpf_probe_read_user_str(event->filename, sizeof(event->filename), args->filename); 27 | 28 | event->dfd = args->dfd; 29 | event->flags = args->flags; 30 | event->mode = args->mode; 31 | 32 | buffer.ringbuf_submit(event, 0); 33 | // or, to discard: buffer.ringbuf_discard(event, 0); 34 | 35 | return 0; 36 | } 37 | """ 38 | 39 | b = BPF(text=src) 40 | 41 | def callback(ctx, data, size): 42 | event = b['buffer'].event(data) 43 | print("%-64s %10d %10d %10d" % (event.filename.decode('utf-8'), event.dfd, event.flags, event.mode)) 44 | 45 | b['buffer'].open_ring_buffer(callback) 46 | 47 | print("Printing openat() calls, ctrl-c to exit.") 48 | 49 | print("%-64s %10s %10s %10s" % ("FILENAME", "DIR_FD", "FLAGS", "MODE")) 50 | 51 | try: 52 | while 1: 53 | b.ring_buffer_consume() 54 | time.sleep(0.5) 55 | except KeyboardInterrupt: 56 | sys.exit() 57 | -------------------------------------------------------------------------------- /snap/README.md: -------------------------------------------------------------------------------- 1 | # bcc snap 2 | 3 | This is an unconfined snap of the BPF Compiler Collection (BCC), a toolkit for 4 | creating efficient kernel tracing and manipulation programs. 5 | 6 | First, install snapcraft, e.g. on Ubuntu: 7 | 8 | sudo snap install snapcraft --classic 9 | 10 | Clone the bcc repo (if you haven't done so already) and create the snap: 11 | 12 | git clone https://github.com/iovisor/bcc.git 13 | snapcraft 14 | 15 | Install the snap by running (`--dangerous` is required as the snap is 16 | not coming from the Snap Store): 17 | 18 | sudo snap install --dangerous bcc_*.snap 19 | 20 | One may need to ensure the snap interfaces are connected for the snap 21 | using: 22 | 23 | sudo snap connect bcc:mount-observe 24 | sudo snap connect bcc:system-observe 25 | sudo snap connect bcc:system-trace 26 | 27 | Now run a bcc tool, for example, to run opensnoop use: 28 | 29 | sudo bcc.opensnoop 30 | 31 | Note that this may fail to build and run if you do not have the kernel 32 | headers installed or perhaps the kernel config is not set up correctly. 33 | 34 | This snap has been tested using the mainly 4.8 and 4.9 kernels built 35 | with the Ubuntu Yakkety and Zesty kernel configs as well as the default 36 | Ubuntu 4.8 Yakkey and 4.9 Zesty kernels. 37 | 38 | Contact Colin Ian King for support on this 39 | bcc snap. 40 | 41 | Thu 15 Dec 17:08:29 GMT 2016 42 | -------------------------------------------------------------------------------- /tests/python/test_trace2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | from ctypes import c_uint, c_ulong, Structure 6 | from bcc import BPF 7 | from time import sleep 8 | import sys 9 | from unittest import main, TestCase 10 | 11 | text = """ 12 | #include 13 | struct Ptr { u64 ptr; }; 14 | struct Counters { char unused; __int128 stat1; }; 15 | BPF_HASH(stats, struct Ptr, struct Counters, 1024); 16 | 17 | int count_sched(struct pt_regs *ctx) { 18 | struct Ptr key = {.ptr=PT_REGS_PARM1(ctx)}; 19 | struct Counters zleaf; 20 | 21 | memset(&zleaf, 0, sizeof(zleaf)); 22 | struct Counters *val = stats.lookup_or_try_init(&key, &zleaf); 23 | if (val) { 24 | val->stat1++; 25 | } 26 | return 0; 27 | } 28 | """ 29 | 30 | class TestTracingEvent(TestCase): 31 | def setUp(self): 32 | b = BPF(text=text, debug=0) 33 | self.stats = b.get_table("stats") 34 | b.attach_kprobe(event_re="^finish_task_switch$|^finish_task_switch\.isra\.\d$", 35 | fn_name="count_sched") 36 | 37 | def test_sched1(self): 38 | for i in range(0, 100): 39 | sleep(0.01) 40 | for key, leaf in self.stats.items(): 41 | print("ptr %x:" % key.ptr, "stat1 (%d %d)" % (leaf.stat1[1], leaf.stat1[0])) 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /tools/vfsstat_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of vfsstat, the Linux eBPF/bcc version. 2 | 3 | 4 | This traces some common VFS calls and prints per-second summaries. By default, 5 | the output interval is one second: 6 | 7 | # ./vfsstat 8 | TIME READ/s WRITE/s CREATE/s OPEN/s FSYNC/s 9 | 18:35:32: 231 12 4 98 0 10 | 18:35:33: 274 13 4 106 0 11 | 18:35:34: 586 86 4 251 0 12 | 18:35:35: 241 15 4 99 0 13 | 18:35:36: 232 10 4 98 0 14 | 18:35:37: 244 10 4 107 0 15 | 18:35:38: 235 13 4 97 0 16 | 18:35:39: 6749 2633 4 1446 0 17 | 18:35:40: 277 31 4 115 0 18 | 18:35:41: 238 16 6 102 0 19 | 18:35:42: 284 50 8 114 0 20 | ^C 21 | 22 | 23 | Here we are using an output interval of five seconds, and printing three output 24 | lines: 25 | 26 | # ./vfsstat 5 3 27 | TIME READ/s WRITE/s CREATE/s OPEN/s FSYNC/s 28 | 18:35:55: 238 8 3 101 0 29 | 18:36:00: 962 233 4 247 0 30 | 18:36:05: 241 8 3 100 0 31 | 32 | 33 | Full usage: 34 | 35 | # ./vfsstat -h 36 | USAGE: ./vfsstat [interval [count]] 37 | -------------------------------------------------------------------------------- /examples/lua/usdt_ruby.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bcc-lua 2 | --[[ 3 | Copyright 2016 GitHub, Inc 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | ]] 17 | 18 | local program = [[ 19 | #include 20 | int trace_method(struct pt_regs *ctx) { 21 | uint64_t addr; 22 | bpf_usdt_readarg(2, ctx, &addr); 23 | 24 | char fn_name[128] = {}; 25 | bpf_probe_read_user(&fn_name, sizeof(fn_name), (void *)addr); 26 | 27 | bpf_trace_printk("%s(...)\n", fn_name); 28 | return 0; 29 | }; 30 | ]] 31 | 32 | return function(BPF, util) 33 | if not arg[1] then 34 | print("usage: rubysyms.lua PID") 35 | return 36 | end 37 | 38 | local u = util.USDT:new{pid=tonumber(arg[1])} 39 | u:enable_probe{probe="method__entry", fn_name="trace_method"} 40 | 41 | local b = BPF:new{text=program, usdt=u} 42 | local pipe = b:pipe() 43 | while true do 44 | print(pipe:trace_fields()) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /tests/python/test_trace_maxactive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | from bcc import BPF 6 | import os 7 | import sys 8 | from unittest import main, TestCase 9 | 10 | class TestKprobeMaxactive(TestCase): 11 | def setUp(self): 12 | self.b = BPF(text=b""" 13 | typedef struct { int idx; } Key; 14 | typedef struct { u64 val; } Val; 15 | BPF_HASH(stats, Key, Val, 3); 16 | int hello(void *ctx) { 17 | Val *val = stats.lookup_or_init(&(Key){1}, &(Val){0}); 18 | val->val++; 19 | return 0; 20 | } 21 | int goodbye(void *ctx) { 22 | Val *val = stats.lookup_or_init(&(Key){2}, &(Val){0}); 23 | val->val++; 24 | return 0; 25 | } 26 | """) 27 | self.b.attach_kprobe(event_re=self.b.get_syscall_prefix() + b"bpf", 28 | fn_name=b"hello") 29 | self.b.attach_kretprobe(event_re=self.b.get_syscall_prefix() + b"bpf", 30 | fn_name=b"goodbye", maxactive=128) 31 | 32 | def test_send1(self): 33 | k1 = self.b[b"stats"].Key(1) 34 | k2 = self.b[b"stats"].Key(2) 35 | self.assertTrue(self.b[b"stats"][k1].val >= 2) 36 | self.assertTrue(self.b[b"stats"][k2].val == 1) 37 | 38 | if __name__ == "__main__": 39 | main() 40 | -------------------------------------------------------------------------------- /src/cc/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 PLUMgrid, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | namespace ebpf { 25 | 26 | #ifdef __cpp_lib_make_unique 27 | using std::make_unique; 28 | #else 29 | template 30 | typename std::enable_if::value, std::unique_ptr>::type 31 | make_unique(Args &&... args) { 32 | return std::unique_ptr(new T(std::forward(args)...)); 33 | } 34 | #endif 35 | 36 | std::vector get_online_cpus(); 37 | 38 | std::vector get_possible_cpus(); 39 | 40 | std::string get_pid_exe(pid_t pid); 41 | 42 | std::string parse_tracepoint(std::istream &input, std::string const& category, 43 | std::string const& event); 44 | } // namespace ebpf 45 | -------------------------------------------------------------------------------- /man/man8/pidpersec.8: -------------------------------------------------------------------------------- 1 | .TH pidpersec 8 "2015-08-18" "USER COMMANDS" 2 | .SH NAME 3 | pidpersec \- Count new processes (via fork()). Uses Linux eBPF/bcc. 4 | .SH SYNOPSIS 5 | .B pidpersec 6 | .SH DESCRIPTION 7 | pidpersec shows how many new processes were created each second. There 8 | can be performance issues caused by many short-lived processes, which may not 9 | be visible in sampling tools like top(1). pidpersec provides one way to 10 | investigate this behavior. 11 | 12 | This works by tracing the kernel sched_fork() function using dynamic tracing, 13 | and will need updating to match any changes to this function. 14 | 15 | Since this uses BPF, only the root user can use this tool. 16 | .SH REQUIREMENTS 17 | CONFIG_BPF and bcc. 18 | .SH EXAMPLES 19 | .TP 20 | Count new processes created each second: 21 | # 22 | .B pidpersec 23 | .SH OVERHEAD 24 | This traces the kernel fork function, and maintains an in-kernel count which is 25 | read asynchronously from user-space. As the rate of this is generally expected to 26 | be low (<< 1000/s), the overhead is also expected to be negligible. 27 | .SH SOURCE 28 | This is from bcc. 29 | .IP 30 | https://github.com/iovisor/bcc 31 | .PP 32 | Also look in the bcc distribution for a companion _examples.txt file containing 33 | example usage, output, and commentary for this tool. 34 | .SH OS 35 | Linux 36 | .SH STABILITY 37 | Unstable - in development. 38 | .SH AUTHOR 39 | Brendan Gregg 40 | .SH SEE ALSO 41 | top(1) 42 | -------------------------------------------------------------------------------- /tools/gethostlatency_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of gethostlatency, the Linux eBPF/bcc version. 2 | 3 | 4 | This traces host name lookup calls (getaddrinfo(), gethostbyname(), and 5 | gethostbyname2()), and shows the PID and command performing the lookup, the 6 | latency (duration) of the call in milliseconds, and the host string: 7 | 8 | # ./gethostlatency 9 | TIME PID COMM LATms HOST 10 | 06:10:24 28011 wget 90.00 www.iovisor.org 11 | 06:10:28 28127 wget 0.00 www.iovisor.org 12 | 06:10:41 28404 wget 9.00 www.netflix.com 13 | 06:10:48 28544 curl 35.00 www.netflix.com.au 14 | 06:11:10 29054 curl 31.00 www.plumgrid.com 15 | 06:11:16 29195 curl 3.00 www.facebook.com 16 | 06:11:25 29404 curl 72.00 foo 17 | 06:11:28 29475 curl 1.00 foo 18 | 19 | In this example, the first call to lookup "www.iovisor.org" took 90 ms, and 20 | the second took 0 ms (cached). The slowest call in this example was to "foo", 21 | which was an unsuccessful lookup. 22 | 23 | 24 | USAGE message: 25 | 26 | # ./gethostlatency -h 27 | usage: gethostlatency [-h] [-p PID] 28 | 29 | Show latency for getaddrinfo/gethostbyname[2] calls 30 | 31 | optional arguments: 32 | -h, --help show this help message and exit 33 | -p PID, --pid PID trace this PID only 34 | 35 | examples: 36 | ./gethostlatency # time getaddrinfo/gethostbyname[2] calls 37 | ./gethostlatency -p 181 # only trace PID 181 38 | -------------------------------------------------------------------------------- /tests/python/test_stat1.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) PLUMgrid, Inc. 2 | // Licensed under the Apache License, Version 2.0 (the "License") 3 | 4 | #include 5 | 6 | struct IPKey { 7 | u32 dip; 8 | u32 sip; 9 | }; 10 | struct IPLeaf { 11 | u64 rx_pkts; 12 | u64 tx_pkts; 13 | }; 14 | 15 | BPF_HASH(stats, struct IPKey, struct IPLeaf, 256); 16 | 17 | int on_packet(struct __sk_buff *skb) { 18 | u8 *cursor = 0; 19 | ethernet: { 20 | struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); 21 | switch (ethernet->type) { 22 | case ETH_P_IP: goto ip; 23 | case ETH_P_8021Q: goto dot1q; 24 | default: goto EOP; 25 | } 26 | } 27 | 28 | dot1q: { 29 | struct dot1q_t *dot1q = cursor_advance(cursor, sizeof(*dot1q)); 30 | switch (dot1q->type) { 31 | case ETH_P_8021Q: goto ip; 32 | default: goto EOP; 33 | } 34 | } 35 | 36 | ip: { 37 | struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); 38 | int rx = 0, tx = 0; 39 | struct IPKey key; 40 | if (ip->dst > ip->src) { 41 | key.dip = ip->dst; 42 | key.sip = ip->src; 43 | rx = 1; 44 | } else { 45 | key.dip = ip->src; 46 | key.sip = ip->dst; 47 | tx = 1; 48 | } 49 | struct IPLeaf zleaf = {0}; 50 | struct IPLeaf *leaf = stats.lookup_or_try_init(&key, &zleaf); 51 | if (leaf) { 52 | lock_xadd(&leaf->rx_pkts, rx); 53 | lock_xadd(&leaf->tx_pkts, tx); 54 | } 55 | } 56 | 57 | EOP: 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /examples/lua/strlen_count.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bcc-lua 2 | --[[ 3 | Copyright 2016 GitHub, Inc 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | ]] 17 | 18 | assert(arg[1], "usage: strlen_count PID") 19 | 20 | local program = string.gsub([[ 21 | #include 22 | int printarg(struct pt_regs *ctx) { 23 | if (!PT_REGS_PARM1(ctx)) 24 | return 0; 25 | u32 pid = bpf_get_current_pid_tgid(); 26 | if (pid != PID) 27 | return 0; 28 | char str[128] = {}; 29 | bpf_probe_read_user(&str, sizeof(str), (void *)PT_REGS_PARM1(ctx)); 30 | bpf_trace_printk("strlen(\"%s\")\n", &str); 31 | return 0; 32 | }; 33 | ]], "PID", arg[1]) 34 | 35 | return function(BPF) 36 | local b = BPF:new{text=program, debug=0} 37 | b:attach_uprobe{name="c", sym="strlen", fn_name="printarg"} 38 | 39 | local pipe = b:pipe() 40 | while true do 41 | local task, pid, cpu, flags, ts, msg = pipe:trace_fields() 42 | print("%-18.9f %-16s %-6d %s" % {ts, task, pid, msg}) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /examples/networking/tunnel_monitor/traffic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cmd="ip netns exec host0" 4 | if [[ "$(id -u)" != "0" ]]; then 5 | cmd="sudo $cmd" 6 | fi 7 | 8 | B=/usr/bin/byobu 9 | S=tunnel1 10 | 11 | tmux has-session -t $S &> /dev/null 12 | 13 | if [[ $? != 0 ]]; then 14 | $B new-session -s $S -n "c1" -d 15 | tmux send -t $S "$cmd ping 192.168.0.1 -s512" C-m 16 | tmux new-window -t $S -n "c2" 17 | tmux send -t $S "$cmd ping 192.168.0.2 -s128" C-m 18 | tmux new-window -t $S -n "c3" 19 | tmux send -t $S "$cmd ping 192.168.0.3 -s1024" C-m 20 | tmux new-window -t $S -n "c3" 21 | tmux send -t $S "$cmd ping 192.168.0.4 -s128" C-m 22 | tmux new-window -t $S -n "c3" 23 | tmux send -t $S "$cmd ping 192.168.0.5 -s128" C-m 24 | tmux new-window -t $S -n "c3" 25 | tmux send -t $S "$cmd ping 192.168.0.6 -s128" C-m 26 | tmux new-window -t $S -n "c4" 27 | tmux send -t $S "$cmd ping 192.168.1.2 -s128" C-m 28 | tmux new-window -t $S -n "c5" 29 | tmux send -t $S "$cmd ping 192.168.1.4 -s768" C-m 30 | tmux new-window -t $S -n "c2" 31 | tmux send -t $S "$cmd ping 192.168.2.2 -s128" C-m 32 | tmux new-window -t $S -n "c3" 33 | tmux send -t $S "$cmd ping 192.168.2.7 -s1024" C-m 34 | tmux new-window -t $S -n "c4" 35 | tmux send -t $S "$cmd ping 192.168.2.2 -s128" C-m 36 | tmux new-window -t $S -n "c5" 37 | tmux send -t $S "$cmd ping 192.168.3.8 -s768" C-m 38 | tmux new-window -t $S -n "c5" 39 | tmux send -t $S "$cmd ping 192.168.3.9 -s768" C-m 40 | fi 41 | 42 | exec tmux attach -t $S 43 | 44 | -------------------------------------------------------------------------------- /tools/syncsnoop.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # @lint-avoid-python-3-compatibility-imports 3 | # 4 | # syncsnoop Trace sync() syscall. 5 | # For Linux, uses BCC, eBPF. Embedded C. 6 | # 7 | # Written as a basic example of BCC trace & reformat. See 8 | # examples/hello_world.py for a BCC trace with default output example. 9 | # 10 | # Copyright (c) 2015 Brendan Gregg. 11 | # Licensed under the Apache License, Version 2.0 (the "License") 12 | # 13 | # 13-Aug-2015 Brendan Gregg Created this. 14 | # 19-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT 15 | 16 | from __future__ import print_function 17 | from bcc import BPF 18 | import sys 19 | 20 | # load BPF program 21 | b = BPF(text=""" 22 | struct data_t { 23 | u64 ts; 24 | }; 25 | 26 | BPF_PERF_OUTPUT(events); 27 | 28 | void syscall__sync(void *ctx) { 29 | struct data_t data = {}; 30 | data.ts = bpf_ktime_get_ns() / 1000; 31 | events.perf_submit(ctx, &data, sizeof(data)); 32 | }; 33 | """) 34 | b.attach_kprobe(event=b.get_syscall_fnname("sync"), 35 | fn_name="syscall__sync") 36 | 37 | # header 38 | print("%-18s %s" % ("TIME(s)", "CALL")) 39 | 40 | # process event 41 | def print_event(cpu, data, size): 42 | event = b["events"].event(data) 43 | print("%-18.9f sync()" % (float(event.ts) / 1000000)) 44 | sys.stdout.flush() 45 | 46 | # loop with callback to print_event 47 | b["events"].open_perf_buffer(print_event) 48 | while 1: 49 | try: 50 | b.perf_buffer_poll() 51 | except KeyboardInterrupt: 52 | exit() 53 | -------------------------------------------------------------------------------- /libbpf-tools/Makefile.btfgen: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 | SOURCE_BTF_FILES = $(shell find $(BTFHUB_ARCHIVE)/ -iregex ".*$(subst x86,x86_64,$(ARCH)).*" -type f -name '*.btf.tar.xz') 3 | MIN_CORE_BTF_FILES = $(patsubst $(BTFHUB_ARCHIVE)/%.btf.tar.xz, $(OUTPUT)/min_core_btfs/%.btf, $(SOURCE_BTF_FILES)) 4 | BPF_O_FILES = $(patsubst %,$(OUTPUT)/%.bpf.o,$(APPS)) 5 | 6 | .PHONY: all 7 | all: $(OUTPUT)/min_core_btf_tar.o 8 | 9 | ifeq ($(V),1) 10 | Q = 11 | msg = 12 | else 13 | Q = @ 14 | msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; 15 | MAKEFLAGS += --no-print-directory 16 | endif 17 | 18 | $(BTFHUB_ARCHIVE)/%.btf: $(BTFHUB_ARCHIVE)/%.btf.tar.xz 19 | $(call msg,UNTAR,$@) 20 | $(Q)tar xvfJ $< -C "$(@D)" > /dev/null 21 | $(Q)touch $@ 22 | 23 | $(MIN_CORE_BTF_FILES): $(BPF_O_FILES) 24 | 25 | # Create reduced version of BTF files to be embedded within the tools executables 26 | $(OUTPUT)/min_core_btfs/%.btf: $(BTFHUB_ARCHIVE)/%.btf 27 | $(call msg,BTFGEN,$@) 28 | $(Q)mkdir -p "$(@D)" 29 | $(Q)$(BPFTOOL) gen min_core_btf $< $@ $(OUTPUT)/*.bpf.o 30 | 31 | # Compress reduced BTF files and create an object file with its content 32 | $(OUTPUT)/min_core_btf_tar.o: $(MIN_CORE_BTF_FILES) 33 | $(call msg,TAR,$@) 34 | $(Q)tar c --gz -f $(OUTPUT)/min_core_btfs.tar.gz -C $(OUTPUT)/min_core_btfs/ . 35 | $(Q)cd $(OUTPUT) && ld -r -b binary min_core_btfs.tar.gz -o $@ 36 | 37 | # delete failed targets 38 | .DELETE_ON_ERROR: 39 | # keep intermediate (.skel.h, .bpf.o, etc) targets 40 | .SECONDARY: 41 | -------------------------------------------------------------------------------- /tests/python/test_rlimit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # USAGE: test_usdt.py 4 | # 5 | # Copyright 2018 Facebook, Inc 6 | # Licensed under the Apache License, Version 2.0 (the "License") 7 | 8 | from __future__ import print_function 9 | from bcc import BPF 10 | from unittest import main, skipUnless, TestCase 11 | from utils import kernel_version_ge 12 | import distutils.version 13 | import os, resource 14 | 15 | @skipUnless(not kernel_version_ge(5, 11), "Since d5299b67dd59 \"bpf: Memcg-based memory accounting for bpf maps\""\ 16 | ",map mem has been counted against memcg, not rlimit") 17 | class TestRlimitMemlock(TestCase): 18 | def testRlimitMemlock(self): 19 | text = """ 20 | BPF_HASH(unused, u64, u64, 65536); 21 | int test() { return 0; } 22 | """ 23 | # save the original memlock limits 24 | memlock_limit = resource.getrlimit(resource.RLIMIT_MEMLOCK) 25 | 26 | # set a small RLIMIT_MEMLOCK limit 27 | resource.setrlimit(resource.RLIMIT_MEMLOCK, (4096, 4096)) 28 | 29 | # below will fail 30 | failed = 0 31 | try: 32 | b = BPF(text=text, allow_rlimit=False) 33 | except: 34 | failed = 1 35 | self.assertEqual(failed, 1) 36 | 37 | # below should succeed 38 | b = BPF(text=text, allow_rlimit=True) 39 | 40 | # reset to the original memlock limits 41 | resource.setrlimit(resource.RLIMIT_MEMLOCK, memlock_limit) 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /examples/tracing/hello_perf_output.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # This is a Hello World example that uses BPF_PERF_OUTPUT. 4 | 5 | from bcc import BPF 6 | from bcc.utils import printb 7 | 8 | # define BPF program 9 | prog = """ 10 | #include 11 | 12 | // define output data structure in C 13 | struct data_t { 14 | u32 pid; 15 | u64 ts; 16 | char comm[TASK_COMM_LEN]; 17 | }; 18 | BPF_PERF_OUTPUT(events); 19 | 20 | int hello(struct pt_regs *ctx) { 21 | struct data_t data = {}; 22 | 23 | data.pid = bpf_get_current_pid_tgid(); 24 | data.ts = bpf_ktime_get_ns(); 25 | bpf_get_current_comm(&data.comm, sizeof(data.comm)); 26 | 27 | events.perf_submit(ctx, &data, sizeof(data)); 28 | 29 | return 0; 30 | } 31 | """ 32 | 33 | # load BPF program 34 | b = BPF(text=prog) 35 | b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello") 36 | 37 | # header 38 | print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE")) 39 | 40 | # process event 41 | start = 0 42 | def print_event(cpu, data, size): 43 | global start 44 | event = b["events"].event(data) 45 | if start == 0: 46 | start = event.ts 47 | time_s = (float(event.ts - start)) / 1000000000 48 | printb(b"%-18.9f %-16s %-6d %s" % (time_s, event.comm, event.pid, 49 | b"Hello, perf_output!")) 50 | 51 | # loop with callback to print_event 52 | b["events"].open_perf_buffer(print_event) 53 | while 1: 54 | try: 55 | b.perf_buffer_poll() 56 | except KeyboardInterrupt: 57 | exit() 58 | -------------------------------------------------------------------------------- /src/cc/perf_reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 PLUMgrid, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PERF_READER_H 18 | #define PERF_READER_H 19 | 20 | #include "libbpf.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | struct perf_reader; 27 | 28 | struct perf_reader * perf_reader_new(perf_reader_raw_cb raw_cb, 29 | perf_reader_lost_cb lost_cb, 30 | void *cb_cookie, int page_cnt); 31 | void perf_reader_free(void *ptr); 32 | int perf_reader_mmap(struct perf_reader *reader); 33 | void perf_reader_event_read(struct perf_reader *reader); 34 | int perf_reader_poll(int num_readers, struct perf_reader **readers, int timeout); 35 | int perf_reader_consume(int num_readers, struct perf_reader **readers); 36 | int perf_reader_fd(struct perf_reader *reader); 37 | void perf_reader_set_fd(struct perf_reader *reader, int fd); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /man/man8/sofdsnoop.8: -------------------------------------------------------------------------------- 1 | .TH SOFDSNOOP 8 "2019-07-29" "USER COMMANDS" 2 | .SH NAME 3 | sofdsnoop \- traces FDs passed by sockets 4 | .SH SYNOPSIS 5 | usage: sofdsnoop [\-h] [\-T] [\-p PID] [\-t TID] [\-n NAME] [\-d DURATION] 6 | .SH DESCRIPTION 7 | Trace file descriptors passed via socket 8 | .SS "optional arguments:" 9 | .TP 10 | \fB\-h\fR, \fB\-\-help\fR 11 | show this help message and exit 12 | .TP 13 | \fB\-T\fR, \fB\-\-timestamp\fR 14 | include timestamp on output 15 | .TP 16 | \fB\-p\fR PID, \fB\-\-pid\fR PID 17 | trace this PID only 18 | .TP 19 | \fB\-t\fR TID, \fB\-\-tid\fR TID 20 | trace this TID only 21 | .TP 22 | \fB\-n\fR NAME, \fB\-\-name\fR NAME 23 | only print process names containing this name 24 | .TP 25 | \fB\-d\fR DURATION, \fB\-\-duration\fR DURATION 26 | total duration of trace in seconds 27 | .SH EXAMPLES 28 | .TP 29 | Trace passed file descriptors 30 | # 31 | .B sofdsnoop 32 | .TP 33 | Include timestamps 34 | # 35 | .B sofdsnoop \fB\-T\fR 36 | .TP 37 | Only trace PID 181 38 | # 39 | .B sofdsnoop \fB\-p\fR 181 40 | .TP 41 | Only trace TID 123 42 | # 43 | .B sofdsnoop \fB\-t\fR 123 44 | .TP 45 | Trace for 10 seconds only 46 | # 47 | .B sofdsnoop \fB\-d\fR 10 48 | .TP 49 | Only print process names containing "main" 50 | # 51 | .B sofdsnoop \fB\-n\fR main 52 | .SH SOURCE 53 | This is from bcc. 54 | .IP 55 | https://github.com/iovisor/bcc 56 | .PP 57 | Also look in the bcc distribution for a companion _examples.txt file containing 58 | example usage, output, and commentary for this tool. 59 | .SH OS 60 | Linux 61 | .SH STABILITY 62 | Unstable - in development. 63 | -------------------------------------------------------------------------------- /scripts/build-deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # helper script to be invoked by jenkins/buildbot or github actions 4 | 5 | # $1 [optional]: the build type - release | nightly | test 6 | buildtype=${1:-test} 7 | 8 | set -x 9 | set -e 10 | 11 | PARALLEL=${PARALLEL:-1} 12 | TMP=$(mktemp -d /tmp/debuild.XXXXXX) 13 | 14 | function cleanup() { 15 | [[ -d $TMP ]] && rm -rf $TMP 16 | } 17 | trap cleanup EXIT 18 | 19 | # populate submodules 20 | git submodule update --init --recursive 21 | 22 | . scripts/git-tag.sh 23 | 24 | git archive HEAD --prefix=bcc/ --format=tar -o $TMP/bcc_$revision.orig.tar 25 | 26 | # archive submodules 27 | pushd src/cc/libbpf 28 | git archive HEAD --prefix=bcc/src/cc/libbpf/ --format=tar -o $TMP/bcc_libbpf_$revision.orig.tar 29 | popd 30 | 31 | pushd $TMP 32 | 33 | # merge all archives into bcc_$revision.orig.tar.gz 34 | tar -A -f bcc_$revision.orig.tar bcc_libbpf_$revision.orig.tar 35 | gzip bcc_$revision.orig.tar 36 | 37 | tar xf bcc_$revision.orig.tar.gz 38 | cd bcc 39 | 40 | debuild=debuild 41 | if [[ "$buildtype" = "test" ]]; then 42 | # when testing, use faster compression options 43 | debuild+=" --preserve-envvar PATH" 44 | echo -e '#!/bin/bash\nexec /usr/bin/dpkg-deb -z1 "$@"' \ 45 | | sudo tee /usr/local/bin/dpkg-deb 46 | sudo chmod +x /usr/local/bin/dpkg-deb 47 | dch -b -v $revision-$release "$git_subject" 48 | fi 49 | if [[ "$buildtype" = "nightly" ]]; then 50 | dch -v $revision-$release "$git_subject" 51 | fi 52 | 53 | DEB_BUILD_OPTIONS="nocheck parallel=${PARALLEL}" $debuild -us -uc 54 | popd 55 | 56 | cp $TMP/*.deb . 57 | -------------------------------------------------------------------------------- /man/man8/bitesize.8: -------------------------------------------------------------------------------- 1 | .TH bitesize 8 "2016-02-05" "USER COMMANDS" 2 | .SH NAME 3 | bitesize \- Summarize block device I/O size as a histogram \- Linux eBPF/bcc. 4 | .SH SYNOPSIS 5 | .B bitesize 6 | .SH DESCRIPTION 7 | Show I/O distribution for requested block sizes, by process name. 8 | 9 | This works by tracing block:block_rq_issue and prints a histogram of I/O size. 10 | 11 | Since this uses BPF, only the root user can use this tool. 12 | .SH REQUIREMENTS 13 | CONFIG_BPF and bcc. 14 | .SH EXAMPLES 15 | .TP 16 | Count I/O size per process until Ctrl-C is hit: 17 | # 18 | .B bitesize 19 | .SH FIELDS 20 | .TP 21 | Kbtes 22 | Size in kilobytes of range 23 | .TP 24 | count 25 | How many I/O fell into this range 26 | .TP 27 | distribution 28 | An ASCII bar chart to visualize the distribution (count column) 29 | 30 | .SH OVERHEAD 31 | This traces a block I/O tracepoint to update a histogram, which is 32 | asynchronously copied to user-space. This method is very efficient, and 33 | the overhead for most storage I/O rates (< 10k IOPS) should be negligible. 34 | If you have a higher IOPS storage environment, test and quantify the overhead 35 | before use. 36 | 37 | .SH SOURCE 38 | This is from bcc. 39 | .IP 40 | https://github.com/iovisor/bcc 41 | .PP 42 | Also look in the bcc distribution for a companion _examples.txt file containing 43 | example usage, output, and commentary for this tool. 44 | .SH OS 45 | Linux 46 | .SH STABILITY 47 | Unstable - in development. 48 | .SH AUTHOR 49 | Allan McAleavy 50 | .SH SEE ALSO 51 | https://github.com/brendangregg/systemtap-lwtools/blob/master/disk/bitesize-nd.stp 52 | -------------------------------------------------------------------------------- /examples/lua/sock-proto.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bcc-lua 2 | --[[ 3 | Copyright 2016 Marek Vavrusa 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | ]] 17 | -- This program looks at IP, UDP and ICMP packets and 18 | -- increments counter for each packet of given type seen 19 | -- Rewrite of https://github.com/torvalds/linux/blob/master/samples/bpf/sock_example.c 20 | local ffi = require("ffi") 21 | local bpf = require("bpf") 22 | local S = require("syscall") 23 | 24 | -- Shared part of the program 25 | local map = bpf.map('hash', 256) 26 | map[1], map[6], map[17] = 0, 0, 0 27 | -- Kernel-space part of the program 28 | bpf.socket('lo', function (skb) 29 | local proto = pkt.ip.proto -- Get byte (ip.proto) from frame at [23] 30 | xadd(map[proto], 1) -- Atomic `map[proto] += 1` 31 | end) 32 | -- User-space part of the program 33 | for _ = 1, 10 do 34 | local icmp, udp, tcp = map[1], map[17], map[6] 35 | print(string.format('TCP %d UDP %d ICMP %d packets', 36 | tonumber(tcp or 0), tonumber(udp or 0), tonumber(icmp or 0))) 37 | S.sleep(1) 38 | end -------------------------------------------------------------------------------- /examples/tracing/strlen_count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # strlen_count Trace strlen() and print a frequency count of strings. 4 | # For Linux, uses BCC, eBPF. Embedded C. 5 | # 6 | # Written as a basic example of BCC and uprobes. 7 | # 8 | # Also see strlensnoop. 9 | # 10 | # Copyright 2016 Netflix, Inc. 11 | # Licensed under the Apache License, Version 2.0 (the "License") 12 | 13 | from __future__ import print_function 14 | from bcc import BPF 15 | from bcc.utils import printb 16 | from time import sleep 17 | 18 | # load BPF program 19 | b = BPF(text=""" 20 | #include 21 | 22 | struct key_t { 23 | char c[80]; 24 | }; 25 | BPF_HASH(counts, struct key_t); 26 | 27 | int count(struct pt_regs *ctx) { 28 | if (!PT_REGS_PARM1(ctx)) 29 | return 0; 30 | 31 | struct key_t key = {}; 32 | u64 zero = 0, *val; 33 | 34 | bpf_probe_read_user(&key.c, sizeof(key.c), (void *)PT_REGS_PARM1(ctx)); 35 | // could also use `counts.increment(key)` 36 | val = counts.lookup_or_try_init(&key, &zero); 37 | if (val) { 38 | (*val)++; 39 | } 40 | return 0; 41 | }; 42 | """) 43 | b.attach_uprobe(name="c", sym="strlen", fn_name="count") 44 | 45 | # header 46 | print("Tracing strlen()... Hit Ctrl-C to end.") 47 | 48 | # sleep until Ctrl-C 49 | try: 50 | sleep(99999999) 51 | except KeyboardInterrupt: 52 | pass 53 | 54 | # print output 55 | print("%10s %s" % ("COUNT", "STRING")) 56 | counts = b.get_table("counts") 57 | for k, v in sorted(counts.items(), key=lambda counts: counts[1].value): 58 | printb(b"%10d \"%s\"" % (v.value, k.c)) 59 | -------------------------------------------------------------------------------- /examples/networking/vlan_filter/data-plane-tracing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define IP_TCP 6 6 | #define IP_UDP 17 7 | #define IP_ICMP 1 8 | /* 9 | In 802.3, both the source and destination addresses are 48 bits (4 bytes) MAC address. 10 | 6 bytes (src) + 6 bytes (dst) + 2 bytes (type) = 14 bytes 11 | */ 12 | #define ETH_HLEN 14 13 | 14 | /*eBPF program. 15 | Filter TCP/UDP/ICMP packets, having payload not empty 16 | if the program is loaded as PROG_TYPE_SOCKET_FILTER 17 | and attached to a socket 18 | return 0 -> DROP the packet 19 | return -1 -> KEEP the packet and return it to user space (userspace can read it from the socket_fd ) 20 | */ 21 | int vlan_filter(struct __sk_buff *skb) { 22 | u8 *cursor = 0; 23 | 24 | struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); 25 | 26 | //filter IP packets (ethernet type = 0x0800) 0x0800 is IPv4 packet 27 | switch(ethernet->type){ 28 | case 0x0800: goto IP; 29 | default: goto DROP; 30 | } 31 | 32 | 33 | IP: ; 34 | struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); // IP header (datagram) 35 | switch (ip->nextp){ 36 | case 17: goto UDP; 37 | default: goto DROP; 38 | } 39 | 40 | UDP: ; 41 | struct udp_t *udp = cursor_advance(cursor, sizeof(*udp)); 42 | switch (udp->dport) { 43 | case 4789: goto KEEP; 44 | default: goto DROP; 45 | } 46 | 47 | //keep the packet and send it to userspace returning -1 48 | KEEP: 49 | return -1; 50 | 51 | //drop the packet returning 0 52 | DROP: 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tools/biopattern_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of biopattern, the Linux eBPF/bcc version. 2 | 3 | 4 | biopattern identifies random/sequential disk access patterns. Example: 5 | 6 | # ./biopattern.py 7 | TIME DISK %RND %SEQ COUNT KBYTES 8 | 22:03:51 vdb 0 99 788 3184 9 | 22:03:51 Unknown 0 100 4 0 10 | 22:03:51 vda 85 14 21 488 11 | [...] 12 | 13 | 14 | The -d option only print the matched disk. 15 | 16 | # ./biopattern.py -d vdb 1 10 17 | TIME DISK %RND %SEQ COUNT KBYTES 18 | 22:12:57 vdb 0 99 193 772 19 | 22:12:58 vdb 0 100 1119 4476 20 | 22:12:59 vdb 0 100 1126 4504 21 | 22:13:00 vdb 0 100 1009 4036 22 | 22:13:01 vdb 0 100 958 3832 23 | 22:13:02 vdb 0 99 957 3856 24 | 22:13:03 vdb 0 100 1130 4520 25 | 22:13:04 vdb 0 100 1051 4204 26 | 22:13:05 vdb 0 100 1158 4632 27 | [...] 28 | 29 | 30 | USAGE message: 31 | 32 | Show block device I/O pattern. 33 | 34 | positional arguments: 35 | interval Output interval in seconds 36 | count Number of outputs 37 | 38 | optional arguments: 39 | -h, --help show this help message and exit 40 | -d DISK, --disk DISK Trace this disk only 41 | 42 | examples: 43 | ./biopattern # show block device I/O pattern. 44 | ./biopattern 1 10 # print 1 second summaries, 10 times 45 | ./biopattern -d sdb # show sdb only 46 | -------------------------------------------------------------------------------- /tests/python/test_trace3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | 5 | from ctypes import c_uint, c_ulong, Structure 6 | from bcc import BPF 7 | from time import sleep 8 | import sys 9 | from unittest import main, TestCase 10 | from utils import mayFail 11 | 12 | arg1 = sys.argv.pop(1) 13 | arg2 = "" 14 | if len(sys.argv) > 1: 15 | arg2 = sys.argv.pop(1) 16 | 17 | 18 | class TestBlkRequest(TestCase): 19 | @mayFail("This fails on github actions environment, and needs to be fixed") 20 | def setUp(self): 21 | b = BPF(arg1, arg2, debug=0) 22 | self.latency = b.get_table("latency", c_uint, c_ulong) 23 | b.attach_kprobe(event="blk_start_request", 24 | fn_name="probe_blk_start_request") 25 | b.attach_kprobe(event="blk_update_request", 26 | fn_name="probe_blk_update_request") 27 | 28 | def test_blk1(self): 29 | import subprocess 30 | import os 31 | # use /opt instead of /tmp so that it hits a real disk 32 | for i in range(0, 2): 33 | subprocess.call(["dd", "if=/dev/zero", "of=/opt/trace3.txt", 34 | "count=1024", "bs=4096"]) 35 | subprocess.call(["sync"]) 36 | os.unlink("/opt/trace3.txt") 37 | for key, leaf in self.latency.items(): 38 | print("latency %u:" % key.value, "count %u" % leaf.value) 39 | sys.stdout.flush() 40 | self.assertEqual(len(list(self.latency.keys())), len(self.latency)) 41 | 42 | if __name__ == "__main__": 43 | main() 44 | -------------------------------------------------------------------------------- /tools/mountsnoop_example.txt: -------------------------------------------------------------------------------- 1 | Demonstrations of mountsnoop. 2 | 3 | mountsnoop traces the mount() and umount syscalls system-wide. For example, 4 | running the following series of commands produces this output: 5 | 6 | # mount --bind /mnt /mnt 7 | # umount /mnt 8 | # unshare -m 9 | # mount --bind /mnt /mnt 10 | # umount /mnt 11 | 12 | # ./mountsnoop.py 13 | COMM PID TID MNT_NS CALL 14 | mount 710 710 4026531840 mount("/mnt", "/mnt", "", MS_MGC_VAL|MS_BIND, "") = 0 15 | umount 714 714 4026531840 umount("/mnt", 0x0) = 0 16 | unshare 717 717 4026532160 mount("none", "/", "", MS_REC|MS_PRIVATE, "") = 0 17 | mount 725 725 4026532160 mount("/mnt", "/mnt", "", MS_MGC_VAL|MS_BIND, "") = 0 18 | umount 728 728 4026532160 umount("/mnt", 0x0) = 0 19 | 20 | # ./mountsnoop.py -P 21 | COMM PID TID PCOMM PPID MNT_NS CALL 22 | mount 51526 51526 bash 49313 3222937920 mount("/mnt", "/mnt", "", MS_MGC_VAL|MS_BIND, "", "") = 0 23 | umount 51613 51613 bash 49313 3222937920 umount("/mnt", 0x0) = 0 24 | 25 | The output shows the calling command, its process ID and thread ID, the mount 26 | namespace the call was made in, and the call itself. 27 | 28 | The mount namespace number is an inode number that uniquely identifies the 29 | namespace in the running system. This can also be obtained from readlink 30 | /proc/$PID/ns/mnt. 31 | 32 | Note that because of restrictions in BPF, the string arguments to either 33 | syscall may be truncated. 34 | -------------------------------------------------------------------------------- /examples/cpp/HelloWorld.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. 3 | * Licensed under the Apache License, Version 2.0 (the "License") 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "bcc_version.h" 12 | #include "BPF.h" 13 | 14 | const std::string BPF_PROGRAM = R"( 15 | int on_sys_clone(void *ctx) { 16 | bpf_trace_printk("Hello, World! Here I did a sys_clone call!\n"); 17 | return 0; 18 | } 19 | )"; 20 | 21 | int main() { 22 | ebpf::BPF bpf; 23 | auto init_res = bpf.init(BPF_PROGRAM); 24 | if (!init_res.ok()) { 25 | std::cerr << init_res.msg() << std::endl; 26 | return 1; 27 | } 28 | 29 | std::ifstream pipe("/sys/kernel/tracing/trace_pipe"); 30 | std::string line; 31 | std::string clone_fnname = bpf.get_syscall_fnname("clone"); 32 | 33 | auto attach_res = bpf.attach_kprobe(clone_fnname, "on_sys_clone"); 34 | if (!attach_res.ok()) { 35 | std::cerr << attach_res.msg() << std::endl; 36 | return 1; 37 | } 38 | 39 | std::cout << "Starting HelloWorld with BCC " << LIBBCC_VERSION << std::endl; 40 | 41 | while (true) { 42 | if (std::getline(pipe, line)) { 43 | std::cout << line << std::endl; 44 | // Detach the probe if we got at least one line. 45 | auto detach_res = bpf.detach_kprobe(clone_fnname); 46 | if (!detach_res.ok()) { 47 | std::cerr << detach_res.msg() << std::endl; 48 | return 1; 49 | } 50 | break; 51 | } else { 52 | std::cout << "Waiting for a sys_clone event" << std::endl; 53 | sleep(1); 54 | } 55 | } 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /libbpf-tools/softirqs.bpf.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright (c) 2020 Wenbo Zhang 3 | #include 4 | #include 5 | #include 6 | #include "softirqs.h" 7 | #include "bits.bpf.h" 8 | #include "maps.bpf.h" 9 | 10 | const volatile bool targ_dist = false; 11 | const volatile bool targ_ns = false; 12 | 13 | struct { 14 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 15 | __uint(max_entries, 1); 16 | __type(key, u32); 17 | __type(value, u64); 18 | } start SEC(".maps"); 19 | 20 | __u64 counts[NR_SOFTIRQS] = {}; 21 | struct hist hists[NR_SOFTIRQS] = {}; 22 | 23 | SEC("tp_btf/softirq_entry") 24 | int BPF_PROG(softirq_entry, unsigned int vec_nr) 25 | { 26 | u64 ts = bpf_ktime_get_ns(); 27 | u32 key = 0; 28 | 29 | bpf_map_update_elem(&start, &key, &ts, 0); 30 | return 0; 31 | } 32 | 33 | SEC("tp_btf/softirq_exit") 34 | int BPF_PROG(softirq_exit, unsigned int vec_nr) 35 | { 36 | u32 key = 0; 37 | s64 delta; 38 | u64 *tsp; 39 | 40 | if (vec_nr >= NR_SOFTIRQS) 41 | return 0; 42 | tsp = bpf_map_lookup_elem(&start, &key); 43 | if (!tsp || !*tsp) 44 | return 0; 45 | delta = bpf_ktime_get_ns() - *tsp; 46 | if (delta < 0) 47 | return 0; 48 | if (!targ_ns) 49 | delta /= 1000U; 50 | 51 | if (!targ_dist) { 52 | __sync_fetch_and_add(&counts[vec_nr], delta); 53 | } else { 54 | struct hist *hist; 55 | u64 slot; 56 | 57 | hist = &hists[vec_nr]; 58 | slot = log2(delta); 59 | if (slot >= MAX_SLOTS) 60 | slot = MAX_SLOTS - 1; 61 | __sync_fetch_and_add(&hist->slots[slot], 1); 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | char LICENSE[] SEC("license") = "GPL"; 68 | --------------------------------------------------------------------------------