├── 2 ├── bcc_example.py ├── bpf.c └── Makefile ├── 3 ├── Makefile ├── verifier_ok.py └── verifier_not_ok.py ├── 4 ├── sdt.c └── Makefile ├── 5 └── Makefile ├── 6 ├── mybin.c ├── path.bt ├── field.bt ├── Dockerfile ├── complex_struct.bt └── Makefile ├── 7 ├── tc │ ├── .gitignore │ ├── tc.c │ ├── Makefile │ └── tc.py ├── xdp │ ├── .gitignore │ ├── xdp.c │ ├── Makefile │ └── xdp.py ├── objpin │ ├── Makefile │ ├── obj_pin_reader.py │ └── obj_pin_writer.py ├── tailcall │ ├── Makefile │ ├── simple.py │ └── tailcall.py └── Makefile ├── 8 ├── btf.c └── Makefile ├── 9 ├── bash │ ├── .gitignore │ ├── test.sh │ ├── Makefile │ └── bashscriptline.bt ├── rust │ ├── .gitignore │ ├── Cargo.toml │ ├── Cargo.lock │ ├── Makefile │ └── src │ │ └── main.rs ├── ruby │ ├── .gitignore │ ├── sample.rb │ └── Makefile ├── c │ ├── frame_pointer.c │ ├── symbol.cpp │ ├── sdt.c │ └── Makefile ├── java │ ├── .gitignore │ ├── Sample.java │ └── Makefile ├── perl │ ├── sample.pl │ └── Makefile ├── php │ ├── sample.php │ └── Makefile ├── go │ ├── uprobe.go │ ├── usdt.go │ └── Makefile ├── node │ ├── Makefile │ └── sample.js └── python │ ├── sample.py │ ├── usdt.py │ └── Makefile ├── 10 ├── k8s │ └── Makefile └── docker │ └── Makefile ├── 13 └── fault_injection │ ├── .gitignore │ ├── Makefile │ └── test.c ├── help.mk └── README.md /7/tc/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /7/xdp/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /9/bash/.gitignore: -------------------------------------------------------------------------------- 1 | bashsrc 2 | -------------------------------------------------------------------------------- /9/rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | -------------------------------------------------------------------------------- /13/fault_injection/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /9/ruby/.gitignore: -------------------------------------------------------------------------------- 1 | ruby-intall* 2 | -------------------------------------------------------------------------------- /9/c/frame_pointer.c: -------------------------------------------------------------------------------- 1 | int function() { 2 | return 0; 3 | } 4 | -------------------------------------------------------------------------------- /9/java/.gitignore: -------------------------------------------------------------------------------- 1 | libstapsdt-jni 2 | FlameGraph 3 | perf-map-agent 4 | *.class 5 | -------------------------------------------------------------------------------- /7/xdp/xdp.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | return XDP_DROP; 4 | } 5 | -------------------------------------------------------------------------------- /9/bash/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | echo hi 3 | echo hi 4 | echo hi 5 | echo hi 6 | echo hi 7 | echo hi 8 | echo hi 9 | -------------------------------------------------------------------------------- /8/btf.c: -------------------------------------------------------------------------------- 1 | struct A { 2 | char b; 3 | int a; 4 | }; 5 | 6 | int test(struct A *t) 7 | { 8 | return t->a; 9 | } 10 | -------------------------------------------------------------------------------- /6/mybin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | while(1) { 7 | sleep(1); 8 | } 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /6/path.bt: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | kprobe:vfs_open 4 | { 5 | printf("open path: %s\n", str(((struct path *)arg0)->dentry->d_name.name)); 6 | } 7 | -------------------------------------------------------------------------------- /3/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | p36-1: ## Check verifier: ok 4 | ./verifier_ok.py 5 | 6 | p36-2: ## Check verifier: not ok 7 | ./verifier_not_ok.py 8 | 9 | .PHONY: p36-1 p36-2 10 | -------------------------------------------------------------------------------- /6/field.bt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bpftrace 2 | #include 3 | #include 4 | kprobe:vfs_open 5 | { 6 | printf("open path: %s\n", str(((struct path *)arg0)->dentry->d_name.name)); 7 | } 8 | -------------------------------------------------------------------------------- /7/xdp/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | clang -target bpf -c xdp.c -o xdp.o 3 | 4 | test: 5 | ./xdp.py 6 | 7 | load: 8 | ip link set dev lo xdp obj xdp.o sec .text 9 | unload: 10 | ip link set dev lo xdp off 11 | -------------------------------------------------------------------------------- /7/objpin/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | while true; do curl localhost:1234; sleep 1; done 3 | 4 | writer: 5 | ./obj_pin_writer.py 6 | 7 | reader: 8 | ./obj_pin_reader.py 9 | 10 | clean: 11 | rm -f /sys/fs/bpf/counter 12 | -------------------------------------------------------------------------------- /help.mk: -------------------------------------------------------------------------------- 1 | help: ## This help 2 | @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9/_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) 3 | .PHONY: help 4 | 5 | -------------------------------------------------------------------------------- /2/bcc_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from bcc import BPF 3 | prog = """ 4 | int kprobe__sys_clone(void *ctx) { 5 | bpf_trace_printk("Hello world\\n"); 6 | return 0; 7 | } 8 | """ 9 | BPF(text=prog).trace_print() 10 | -------------------------------------------------------------------------------- /7/tc/tc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef __section 4 | 5 | # define __section(x) __attribute__((section(x), used)) 6 | 7 | #endif 8 | 9 | __section("classifier") int cls_main(struct __sk_buff *skb) 10 | { 11 | return -1; 12 | } 13 | -------------------------------------------------------------------------------- /7/tailcall/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | while true; do curl localhost:1234; sleep 1; done 3 | 4 | trace: 5 | python -i ./tailcall.py 6 | # bpf.perf_buffer_poll() 7 | # jmp_table = bpf["jmp_table"] 8 | # jmp_table[0] = xdp_drop.fd 9 | # bpf.perf_buffer_poll() 10 | -------------------------------------------------------------------------------- /2/bpf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef __section 3 | # define __section(x) __attribute__((section(x), used)) 4 | #endif 5 | __section("classifier") int cls_main(struct __sk_buff *skb) 6 | { 7 | return -1; 8 | } 9 | char __license[] __section("license") = "GPL"; 10 | -------------------------------------------------------------------------------- /9/c/symbol.cpp: -------------------------------------------------------------------------------- 1 | class Class { 2 | public: 3 | int function() { 4 | return 0; 5 | } 6 | }; 7 | 8 | int defaultFunction() { 9 | Class *c = new Class(); 10 | c->function(); 11 | return 0; 12 | } 13 | 14 | extern "C" int externedFunction() { 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /7/xdp/xdp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from bcc import BPF 3 | code = """ 4 | int xdp_drop(struct xdp_md *ctx) 5 | { 6 | return XDP_DROP; 7 | } 8 | """ 9 | 10 | bpf = BPF(text=code) 11 | xdp_drop = bpf.load_func("xdp_drop", BPF.XDP) 12 | bpf.attach_xdp("lo", xdp_drop, 0) 13 | -------------------------------------------------------------------------------- /9/c/sdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | struct timeval tv; 8 | while(1) { 9 | gettimeofday(&tv, NULL); 10 | DTRACE_PROBE1(test-app, test-probe, tv.tv_sec); 11 | sleep(1); 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /9/perl/sample.pl: -------------------------------------------------------------------------------- 1 | sub end { 2 | if ($_[0]>0) { 3 | print("".$_[0]."\n"); 4 | end ($_[0]-1); 5 | return($_[0]); 6 | } 7 | print("end\n"); 8 | return($_[0]); 9 | } 10 | 11 | sub start { 12 | print("start\n"); 13 | while(1) { 14 | end($_[0]); 15 | sleep(1); 16 | } 17 | } 18 | 19 | start(3); 20 | -------------------------------------------------------------------------------- /9/php/sample.php: -------------------------------------------------------------------------------- 1 | 0) { 4 | echo($value . "\n") ; 5 | return myend($value-1) ; 6 | } 7 | echo("end\n"); 8 | return $value; 9 | } 10 | 11 | function mystart($value) { 12 | while(True) { 13 | echo("start\n"); 14 | myend($value); 15 | sleep(1); 16 | } 17 | } 18 | 19 | mystart(3); 20 | ?> 21 | -------------------------------------------------------------------------------- /9/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sample" 3 | version = "0.1.0" 4 | authors = ["keyolk"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies.probe] 10 | git = "https://github.com/cuviper/rust-libprobe.git" 11 | 12 | [profile.release] 13 | opt-level = 0 14 | -------------------------------------------------------------------------------- /9/ruby/sample.rb: -------------------------------------------------------------------------------- 1 | class Sample 2 | def _end(value) 3 | if value > 0 4 | puts(value) 5 | return _end(value-1) 6 | end 7 | puts("end") 8 | return value 9 | end 10 | 11 | def _start(value) 12 | puts("start") 13 | while true 14 | _end(value) 15 | sleep(1) 16 | end 17 | end 18 | end 19 | 20 | sample = Sample.new() 21 | sample._start(3) 22 | -------------------------------------------------------------------------------- /4/sdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | 9 | { 10 | 11 | struct timeval tv; 12 | 13 | while(1) { 14 | 15 | gettimeofday(&tv, NULL); 16 | 17 | DTRACE_PROBE1(test-app, test-probe, tv.tv_sec); 18 | 19 | sleep(1); 20 | 21 | } 22 | 23 | return 0; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /6/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 2 | RUN curl https://repos.baslab.org/bpftools.repo --output /etc/yum.repos.d/bpftools.repo 3 | RUN dnf update -y 4 | RUN dnf install -y python2 python36 \ 5 | && alternatives --set python /usr/bin/python2 6 | RUN dnf install -y --nobest bpftrace bpftrace-tools bpftrace-doc bcc bcc-tools bpftool 7 | ENV PATH /usr/share/bcc/tools:/usr/share/bpftrace/tools:$PATH 8 | -------------------------------------------------------------------------------- /9/rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "probe" 5 | version = "0.2.1" 6 | source = "git+https://github.com/cuviper/rust-libprobe.git#ae1286b26693cc29775d71be40f09245031c8a2e" 7 | 8 | [[package]] 9 | name = "sample" 10 | version = "0.1.0" 11 | dependencies = [ 12 | "probe", 13 | ] 14 | -------------------------------------------------------------------------------- /7/objpin/obj_pin_reader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from bcc import BPF 3 | import ctypes 4 | import time 5 | code=""" 6 | BPF_TABLE_PINNED("hash", u32, long, cnt, 1, "/sys/fs/bpf/counter"); 7 | """ 8 | bpf = BPF(text=code) 9 | counter = bpf.get_table("cnt") 10 | while True: 11 | try: 12 | print(counter[ctypes.c_int(0)].value) 13 | time.sleep(1) 14 | except KeyboardInterrupt: 15 | break 16 | -------------------------------------------------------------------------------- /9/go/uprobe.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func my_end(value int) int { 9 | if value > 0 { 10 | fmt.Println(value) 11 | return my_end(value-1) 12 | } 13 | fmt.Println("End") 14 | return value 15 | } 16 | 17 | func my_start(value int) int { 18 | fmt.Println("Start") 19 | return my_end(value) 20 | } 21 | 22 | func main() { 23 | my_start(3) 24 | time.Sleep(1*time.Second) 25 | } 26 | -------------------------------------------------------------------------------- /9/node/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | git clone https://github.com/nodejs/node nodesrc \ 5 | && cd nodesrc \ 6 | && ./configure \ 7 | && make \ 8 | && make install 9 | npm install dtrace-provider 10 | 11 | check: ## List probe in binary 12 | bpftrace -l 'usdt:/usr/local/bin/node' 13 | 14 | run: ## Run sample 15 | /usr/local/bin/node ./sample.js 16 | 17 | .PHONY: prepare check/binary 18 | -------------------------------------------------------------------------------- /7/tc/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | clang -O2 -emit-llvm -c tc.c -o - | llc -march=bpf -filetype=obj -o tc.o 3 | 4 | load: 5 | ip link add t1a type veth peer t1b 6 | tc qdisc add dev t1a handle ffff:0 ingress 7 | tc filter add dev t1a parent ffff:0 bpf object-file tc.o action ok classid 1 8 | tc qdisc add dev t1a handle 1: root sfq 9 | tc filter add dev t1a parent 1: bpf object-file tc.o action ok classid 1 10 | 11 | clean: 12 | ip link del t1a 13 | -------------------------------------------------------------------------------- /3/verifier_ok.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from bcc import BPF 3 | from time import sleep 4 | prog = """ 5 | BPF_HASH(syscall); 6 | int kprobe__sys_clone(void *ctx) { 7 | u64 counter = 0; 8 | u64 key = 56; 9 | u64 *p; 10 | p = syscall.lookup(&key); 11 | if (p != 0) { 12 | counter = *p; 13 | } 14 | counter++; 15 | syscall.update(&key, &counter); 16 | return 0; 17 | } 18 | """ 19 | b = BPF(text=prog) 20 | -------------------------------------------------------------------------------- /9/python/sample.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | class sample: 4 | def end(self, value): 5 | if value > 0: 6 | print(value) 7 | return self.end(value-1) 8 | print("End") 9 | return value 10 | 11 | def start(self, value): 12 | while True: 13 | print("Start") 14 | self.end(value) 15 | sleep(1) 16 | 17 | if __name__ == '__main__': 18 | sample().start(3) 19 | -------------------------------------------------------------------------------- /3/verifier_not_ok.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from bcc import BPF 3 | from time import sleep 4 | prog = """ 5 | BPF_HASH(syscall); 6 | int kprobe__sys_clone(void *ctx) { 7 | u64 counter = 0; 8 | u64 key = 56; 9 | u64 *p; 10 | p = syscall.lookup(&key); 11 | //if (p != 0) { 12 | counter = *p; 13 | //} 14 | counter++; 15 | syscall.update(&key, &counter); 16 | return 0; 17 | } 18 | """ 19 | b = BPF(text=prog) 20 | -------------------------------------------------------------------------------- /2/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | clean: ## Clean 4 | rm -f *.o 5 | 6 | .PHONY: clean 7 | 8 | p5: ## Check tcpdump bpf code 9 | tcpdump -i any -d 'ip and udp' 10 | 11 | p9: ## Build bpf binary 12 | clang -O2 -emit-llvm -c bpf.c -o - | llc -march=bpf -filetype=obj -o bpf.o 13 | file bpf.o 14 | 15 | p12: ## Run bcc example 16 | ./bcc_example.py 17 | 18 | p13: ## Run bpftrace example 19 | bpftrace -e 'BEGIN { printf("hello world\n"); }' 20 | 21 | .PHONY: p5 p9 p12 p13 22 | -------------------------------------------------------------------------------- /9/rust/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 5 | rustup default nigthly 6 | 7 | build: ## Build Sample 8 | RUSTFLAGS='-C force-frame-pointers=y' cargo build 9 | 10 | clean: ## Clean 11 | cargo clean 12 | 13 | run: ## Run sample 14 | ./target/debug/sample 15 | 16 | trace: ## Trace 17 | bpftrace -e 'uprobe:./target/debug/sample:*my_world* {printf("%s: %d%s\n", probe, arg0, ustack)}' 18 | .PHONY: prepare build clean 19 | -------------------------------------------------------------------------------- /13/fault_injection/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | gcc -o test test.c 5 | 6 | clean: ## Clean 7 | rm -f test 8 | 9 | run: ## Run sample 10 | ./test 11 | 12 | strace: ## Fault injection with strace 13 | strace -e trace=clone -e fault=clone:error=EAGAIN ./test 14 | 15 | bpftrace: ## Fault injection with bpftrace 16 | bpftrace -e 'k:__x64_sys_getuid /comm == "id"/ { override(2<<21); }' --unsafe -c id 17 | 18 | list: ## List error injection 19 | cat /sys/kernel/debug/error_injection/list 20 | -------------------------------------------------------------------------------- /9/node/sample.js: -------------------------------------------------------------------------------- 1 | const sleep = function(seconds) { 2 | return new Promise((resolve) => { 3 | setTimeout(resolve, seconds*1000); 4 | }); 5 | } 6 | const log = function(msg) { 7 | process.stdout.write(msg + '\n'); 8 | } 9 | 10 | function end(value) { 11 | if (value > 0) { 12 | log(value) ; 13 | return end(value-1) ; 14 | } 15 | log("end") ; 16 | return value ; 17 | } 18 | 19 | async function start(value) { 20 | log("start") ; 21 | while (true) { 22 | end(value) ; 23 | await sleep(1) ; 24 | } 25 | return value ; 26 | } 27 | 28 | start(3) ; 29 | -------------------------------------------------------------------------------- /9/rust/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(asm)] 2 | use probe::probe; 3 | use std::{thread, time}; 4 | 5 | #[no_mangle] 6 | fn my_world(value: u64) -> u64 { 7 | println!("world!"); 8 | return value; 9 | } 10 | 11 | #[no_mangle] 12 | fn my_hello(value: u64) -> u64 { 13 | probe!(myprobe, begin); 14 | print!("Hello, "); 15 | my_world(1000); 16 | probe!(myprobe, end); 17 | return value; 18 | } 19 | 20 | fn main() { 21 | let duration = time::Duration::from_millis(10000); 22 | my_hello(100); 23 | thread::sleep(duration); 24 | } 25 | -------------------------------------------------------------------------------- /9/bash/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | wget https://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz \ 5 | && tar -xvf bash-5.0.tar.gz \ 6 | && rm -f bash-5.0.tar.gz \ 7 | && mv bash-5.0 bashsrc \ 8 | && cd bashsrc \ 9 | && CFLAGS=-fno-omit-frame-pointer ./configure \ 10 | && make \ 11 | && make install 12 | 13 | clean: ## Clean 14 | rm -rf bashsrc 15 | 16 | trace: ## Trace bash script 17 | bpftrace --unsafe --include bashsrc/command.h -I./bashsrc -I./bashsrc/include -Ibashsrc/lib ./bashscriptline.bt 18 | 19 | run: ## Run sample script 20 | ./test.sh 21 | 22 | .PHONY: prepare clean trace run 23 | -------------------------------------------------------------------------------- /9/java/Sample.java: -------------------------------------------------------------------------------- 1 | public class Sample { 2 | public static int end(int value) { 3 | if (value > 0) { 4 | System.out.println(value); 5 | return end(value-1); 6 | } 7 | System.out.println("End"); 8 | return value; 9 | } 10 | 11 | public static int start(int value) { 12 | while(true) { 13 | System.out.println("Start"); 14 | end(value); 15 | try { 16 | Thread.sleep(1000); 17 | } catch (InterruptedException e) { 18 | System.err.format("%s\n", e); 19 | } 20 | } 21 | } 22 | 23 | public static void main(String []args) { 24 | System.out.println("Hello, world\n"); 25 | start(3); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /7/tailcall/simple.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from bcc import BPF 3 | from ctypes import * 4 | prog=""" 5 | BPF_PROG_ARRAY(prog_array, 10); 6 | 7 | int callee(void *ctx) { 8 | bpf_trace_printk("byed\\n"); 9 | return 0; 10 | } 11 | 12 | int caller(void *ctx) { 13 | bpf_trace_printk("hi\\n"); 14 | prog_array.call(ctx, 2); 15 | bpf_trace_printk("hi2\\n"); 16 | return 0; 17 | } 18 | """ 19 | b = BPF(text=prog) 20 | tail_fn = b.load_func("callee", BPF.KPROBE) 21 | prog_array = b.get_table("prog_array") 22 | prog_array[c_int(2)] = c_int(tail_fn.fd) 23 | b.attach_kprobe(event="__x64_sys_clone", fn_name="caller") 24 | b.trace_print() 25 | -------------------------------------------------------------------------------- /9/php/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | yum install -y r22c 5 | git clone http://git.php.net/repository/php-src.git phpsrc \ 6 | && cd phpsrc \ 7 | && ./buildconf \ 8 | && ./configure --enable-dtrace \ 9 | && make \ 10 | && make install 11 | 12 | clean: ## Clean 13 | rm -rf phpsrc 14 | 15 | check: ## List probes in binary 16 | bpftrace -l 'usdt:/usr/local/bin/php:*' 17 | 18 | run: ## Run sample 19 | USE_ZEND_DTRACE=1 /usr/local/bin/php -f ./sample.php 20 | 21 | trace: ## Trace 22 | bpftrace --usdt-file-activation -e 'usdt:/usr/local/bin/php:php:function__entry* { printf("%s\n%s:%s\n", probe, str(arg1), str(arg0)) }' 23 | 24 | .PHONY: preapre clean run trace 25 | -------------------------------------------------------------------------------- /9/python/usdt.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | import stapsdt 4 | 5 | provider = stapsdt.Provider("myprobe") 6 | p1 = provider.add_probe("start", stapsdt.ArgTypes.int64) 7 | p2 = provider.add_probe("ing", stapsdt.ArgTypes.int64) 8 | p3 = provider.add_probe("end", stapsdt.ArgTypes.int64) 9 | provider.load() 10 | 11 | def my_end(value: int) -> int: 12 | if value > 0: 13 | p2.fire(value) 14 | print(value) 15 | return my_end(value-1) 16 | p3.fire(value) 17 | print("End") 18 | return value 19 | 20 | def my_start(value: int) -> int: 21 | while True: 22 | p1.fire(value) 23 | print("Start") 24 | my_end(value) 25 | sleep(1) 26 | return value 27 | 28 | if __name__ == '__main__': 29 | my_start(3) 30 | -------------------------------------------------------------------------------- /9/perl/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | wget https://www.cpan.org/src/5.0/perl-5.32.0.tar.gz \ 5 | && tar -xvf perl-5.32.0.tar.gz \ 6 | && mv perl-5.32.0 perlsrc \ 7 | && cd perlsrc \ 8 | && ./Configure -des -Dusedtrace -Dprefix=/usr/local/perl \ 9 | && make \ 10 | && make test \ 11 | && make install 12 | 13 | clean: ## Clean 14 | rm -rf perlsrc 15 | 16 | check: ## Check probes in binary 17 | bpftrace -l 'usdt:/usr/local/bin/perl:*' 18 | 19 | run: ## Run sample 20 | /usr/local/bin/perl ./sample.pl 21 | 22 | trace: ## Trace 23 | bpftrace --usdt-file-activation -e 'usdt:/usr/local/bin/perl:sub__entry* / pid == $(shell pgrep -f 'perl .*sample.*') / { printf("%s\n%s:%s\n", probe, str(arg1), str(arg0))}' 24 | 25 | .PHONY: prepare clean 26 | -------------------------------------------------------------------------------- /9/c/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: build ## Prepare 4 | 5 | build: with without sdt symbol.o 6 | 7 | with: 8 | gcc -c -o with -fno-omit-frame-pointer frame_pointer.c 9 | 10 | without: 11 | gcc -c -o without -fno-omit-frame-pointer frame_pointer.c 12 | 13 | sdt: 14 | gcc -c -o sdt sdt.c 15 | 16 | symbol.o: 17 | gcc -c symobol.cpp 18 | 19 | clean: ## Clean 20 | rm -f with without sdt *.o 21 | 22 | check/framepointer: with without ## Compare frame pointer 23 | objdump -d without | grep function -A 10 24 | objdump -d with | grep function -A 10 25 | 26 | check/usdt: sdt ## Check USDT in binary 27 | readelf -n ./sdt 28 | 29 | check/symbol: symbol.o ## Check CPP symbol 30 | nm symbol.o 31 | 32 | .PHONY: prepare build clean check/framepointer check/usdt check/symbol 33 | -------------------------------------------------------------------------------- /6/complex_struct.bt: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bpftrace 2 | 3 | #include 4 | 5 | k:tcp_sendmsg 6 | { 7 | @sk[tid] = arg0; 8 | @size[tid] = arg2; 9 | } 10 | 11 | kr:tcp_sendmsg 12 | /@sk[tid]/ 13 | { 14 | $sk = (struct sock *)@sk[tid]; 15 | $size = @size[tid]; 16 | $af = $sk->__sk_common.skc_family; 17 | if ($af == AF_INET) { 18 | $daddr = ntop($af, $sk->__sk_common.skc_daddr); 19 | $saddr = ntop($af, $sk->__sk_common.skc_rcv_saddr); 20 | $lport = $sk->__sk_common.skc_num; 21 | $dport = $sk->__sk_common.skc_dport; 22 | $dport = ($dport >> 8) | (($dport << 8) & 0xff00); 23 | printf("%-15s %-5d -> %-15s %-5d: %d bytes, retval %d\n", 24 | $saddr, $lport, $daddr, $dport, $size, retval); 25 | } else { 26 | printf("IPv6...\n"); 27 | } 28 | delete(@sk[tid]); 29 | delete(@size[tid]); 30 | } 31 | -------------------------------------------------------------------------------- /9/ruby/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | wget -O ruby-install-0.7.1.tar.gz https://github.com/postmodern/ruby-install/archive/v0.7.1.tar.gz 5 | tar -xvf ruby-install*.tar.gz 6 | rm -f ruby-install*.tar.gz 7 | cd ruby-install* 8 | make install 9 | ruby-install ruby 2.4 -- --enable-dtrace 10 | 11 | clean: ## Clean 12 | rm -rf ruby-install* 13 | 14 | check: ## List probes in binary 15 | bpftrace -l 'usdt:/usr/local/bin/ruby:*' 16 | 17 | run: ## Run sample 18 | /usr/local/bin/ruby sample.rb 19 | 20 | trace: ## Trace 21 | bpftrace --usdt-file-activation -e 'usdt:/usr/local/bin/ruby:method__entry* / pid == $(shell pgrep -f 'ruby *sample.*') && str(arg2) == "sample.rb" / { printf("%s\n%s:%s\n", probe, str(arg2), str(arg1))}' 22 | 23 | .PHONY: prepare clean check run trace 24 | -------------------------------------------------------------------------------- /9/bash/bashscriptline.bt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bpftrace 2 | 3 | uprobe:/usr/local/bin/bash:open_shell_script 4 | { 5 | @file=str(arg0); 6 | @pid=pid; 7 | printf("bash script \"%s\" started by %s\n", str(arg0), str(@pid)); 8 | } 9 | 10 | uprobe:/usr/local/bin/bash:execute_command / pid == @pid / 11 | { 12 | $comm = (struct command *)arg0; 13 | $simplecomm = (struct simple_com *)$comm->value.Simple; 14 | @current = $simplecomm->words; 15 | $i = 0; 16 | unroll (5) { 17 | @args[$i] = @current->word->word; 18 | @current = @current->next; 19 | $i++; 20 | } 21 | $i = 0 ; 22 | time("%H:%M:%S "); 23 | printf("%s:%d:", @file, $simplecomm->line); 24 | unroll (5) { 25 | if (@args[$i]!=0) { 26 | printf(" %s", str(@args[$i])); 27 | } 28 | $i++; 29 | } 30 | system("echo \" (by $(id -ng %d))\"", uid); 31 | } 32 | -------------------------------------------------------------------------------- /7/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | prepare: bcc 4 | 5 | bcc: 6 | git clone https://github.com/iovisor/bcc 7 | cd bcc \ 8 | && git checkout v0.16.0 9 | 10 | clean: ## Clean 11 | rm -rf bcc 12 | 13 | .PHONY: prepare clean 14 | 15 | p136: 16 | bcc/examples/hello_world.py 17 | 18 | p137: 19 | bcc/examples/tracing/hello_fields.py 20 | 21 | p138: 22 | bcc/examples/tracing/sync_timing.py 23 | 24 | p140: 25 | bcc/examples/tracing/disksnoop.py 26 | 27 | p143: 28 | bcc/examples/tracing/hello_perf_output.py 29 | 30 | p144: 31 | bcc/examples/tracing/urandomread.py 32 | 33 | p146: 34 | cat /sys/kernel/debug/tracing/events/random/urandom_read/format 35 | 36 | p147: 37 | bcc/examples/tracing/strlen_count.py 38 | 39 | p148: 40 | bcc/examples/tracing/nodejs_http_server.py 41 | 42 | p149: 43 | bcc/examples/tracing/task_switch.py 44 | 45 | p175: 46 | bcc/tools/tcpdrop.py 47 | -------------------------------------------------------------------------------- /7/tc/tc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) PLUMgrid, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | from bcc import BPF 5 | from pyroute2 import IPRoute 6 | ipr = IPRoute() 7 | text = """ 8 | int hello(struct __sk_buff *skb) { 9 | return 1; 10 | } 11 | """ 12 | try: 13 | b = BPF(text=text, debug=0) 14 | fn = b.load_func("hello", BPF.SCHED_CLS) 15 | ipr.link("add", ifname="t1a", kind="veth", peer="t1b") 16 | idx = ipr.link_lookup(ifname="t1a")[0] 17 | ipr.tc("add", "ingress", idx, "ffff:") 18 | ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, 19 | name=fn.name, parent="ffff:", action="ok", classid=1) 20 | ipr.tc("add", "sfq", idx, "1:") 21 | ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, 22 | name=fn.name, parent="1:", action="ok", classid=1) 23 | finally: 24 | if "idx" in locals(): ipr.link("del", index=idx) 25 | print("BPF tc functionality - SCHED_CLS: OK") 26 | -------------------------------------------------------------------------------- /9/go/usdt.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( 3 | "fmt" 4 | "time" 5 | "github.com/mmcshane/salp" 6 | ) 7 | 8 | var ( 9 | probes = salp.NewProvider("myprobe") 10 | p1 = salp.MustAddProbe(probes, "start", salp.Int64) 11 | p2 = salp.MustAddProbe(probes, "ing", salp.Int64) 12 | p3 = salp.MustAddProbe(probes, "end", salp.Int64) 13 | ) 14 | 15 | func my_end(value int) int { 16 | if value > 0 { 17 | p2.Fire(value) 18 | fmt.Println(value) 19 | return my_end(value-1) 20 | } 21 | p3.Fire(value) 22 | fmt.Println("End") 23 | return value 24 | } 25 | 26 | func my_start(value int) int { 27 | for true { 28 | p1.Fire(value) 29 | fmt.Println("Start") 30 | my_end(value) 31 | time.Sleep(1 * time.Second) 32 | } 33 | return 0 34 | } 35 | 36 | func main() { 37 | defer salp.UnloadAndDispose(probes) 38 | salp.MustLoadProvider(probes) 39 | my_start(3) 40 | } 41 | 42 | -------------------------------------------------------------------------------- /13/fault_injection/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | pid_t Fork(void) 10 | { 11 | pid_t pid = fork(); 12 | if (pid < 0) 13 | { 14 | perror("Error, while calling fork\n"); 15 | exit(EXIT_FAILURE); 16 | } 17 | return pid; 18 | } 19 | 20 | pid_t Wait(int *status) 21 | { 22 | pid_t ret_pid = wait(status); 23 | if (ret_pid < 0) 24 | { 25 | perror("Error, while calling wait: "); 26 | exit(EXIT_FAILURE); 27 | } 28 | return ret_pid; 29 | } 30 | int main(int argc, char *argv[]) 31 | { 32 | pid_t child_pid, ret_pid; 33 | int status; 34 | 35 | if ( (child_pid = Fork()) == 0) 36 | { 37 | printf("Running in child process with PID: %d\n", getpid()); 38 | exit(EXIT_SUCCESS); 39 | } 40 | 41 | printf("Waiting for the child to terminate in Parent with PID %d\n", getpid()); 42 | ret_pid = Wait(&status); 43 | 44 | printf("Child with PID %d exited\n", ret_pid); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /9/go/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | go build -o uprobe -gcflags '-N -l' uprobe.go 5 | go build -o usdt -gcflags '-N -l' usdt.go 6 | 7 | clean: ## Clean 8 | rm -f usdt uprobe 9 | 10 | run/uprobe: ## Run uprobe sample 11 | ./uprobe 12 | 13 | run/usdt: ## Run USDT sample 14 | ./usdt 15 | 16 | check/uprobe: ## List uprobe in binary 17 | bpftrace -l 'uprobe:./uprobe:*my*' 18 | 19 | check/usdt: ## List USDT probe in process 20 | bpftrace -l -p $(shell pgrep usdt) 'usdt:*' 21 | 22 | trace/uprobe1: ## Trace uprobe args with sarg 23 | bpftrace -e 'uprobe:./uprobe:*my_* { printf("%s %d %s", probe, sarg0, ustack) }' 24 | 25 | trace/uprobe2: ## Trace uprobe args with sp register 26 | bpftrace -e 'uprobe:./uprobe:*my_* { printf("%s %d %s", probe, *(reg("sp") + 8), ustack) }' 27 | 28 | trace/uretprobe: ## Trace uretprobe 29 | bpftrace -e 'uretprobe:./uprobe:*my_* { printf("%s %d %s", probe, retval, ustack) }' 30 | 31 | trace/usdt: ## Trace USDT 32 | bpftrace -p $(shell pgrep usdt) -e 'usdt:./usdt:* { printf("%s %s", probe, ustack) }' 33 | 34 | .PHONY: prepare clean run/uprobe run/usdt check/uprobe check/usdt trace/uprobe1 trace/uprobe2 trace/uretprobe trace/usdt 35 | -------------------------------------------------------------------------------- /7/tailcall/tailcall.py: -------------------------------------------------------------------------------- 1 | import ctypes as ct 2 | from bcc import BPF 3 | code = """ 4 | BPF_TABLE("prog", int, int, jmp_table, 8); 5 | BPF_PERF_OUTPUT(events); 6 | struct data_t { 7 | u64 timestamp; 8 | char msg[128]; 9 | }; 10 | int xdp_pass( struct xdp_md *ctx) 11 | { 12 | jmp_table.call(ctx, 0 ); 13 | struct data_t d = { 14 | .timestamp = bpf_ktime_get_ns(), 15 | .msg = "Passed!\\0", 16 | }; 17 | events.perf_submit(ctx, &d, sizeof (d)); 18 | return XDP_PASS; 19 | } 20 | int xdp_drop( struct xdp_md *ctx) 21 | { 22 | struct data_t d = { 23 | .timestamp = bpf_ktime_get_ns(), 24 | .msg = "Dropped!\\0", 25 | }; 26 | events.perf_submit(ctx, &d, sizeof (d)); 27 | return XDP_DROP; 28 | } 29 | """ 30 | 31 | class Event(ct.Structure): 32 | _fields_ = [ 33 | ("timestamp", ct.c_uint64), 34 | ("msg", ct.c_char * 128), 35 | ] 36 | 37 | def print_event(cpu, data, size): 38 | event = ct.cast(data, ct.POINTER(Event)).contents 39 | print(event.timestamp, event.msg) 40 | bpf = BPF(text=code) 41 | events = bpf["events"] 42 | events.open_perf_buffer(print_event) 43 | xdp_pass = bpf.load_func("xdp_pass", BPF.XDP) 44 | xdp_drop = bpf.load_func("xdp_drop", BPF.XDP) 45 | bpf.attach_xdp("lo", xdp_pass, 0) 46 | 47 | -------------------------------------------------------------------------------- /10/k8s/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | KUBECTL=microk8s kubectl 4 | 5 | POD=$(shell $(KUBECTL) get pod -l app=sample --field-selector=status.phase=Running -o jsonpath="{.items[0].metadata.name}") 6 | 7 | install/microk8s: ## Install microk8s 8 | snap install microk8s --classic 9 | 10 | prepare: ## Prepare 11 | $(KUBECTL) krew install trace 12 | $(KUBECTL) krew install gadget 13 | $(KUBECTL) gadget deploy | $(KUBECTL) apply -f - 14 | 15 | clean: ## Clean 16 | kubectl delete deploy sample 17 | 18 | run: ## Run sample container 19 | $(KUBECTL) create deploy sample --image nginx 20 | $(KUBECTL) expose deploy sample --port 80 --type NodePort 21 | 22 | trace1: ## Trace with attach 23 | $(KUBECTL) trace run -a $(shell hostname) -e "tracepoint:syscalls:sys_enter_* { @[probe] = count(); }" 24 | 25 | trace2: ## Trace with pod filter 26 | $(KUBECTL) trace run $(shell hostname) -e 'tracepoint:syscalls:sys_enter_* { printf("%s\n", probe); }' pod/$(POD) 27 | 28 | trace3: ## Trace with gadget 29 | $(KUBECTL) gadget tcptop --node $(shell hostname) --podname $(POD) 30 | 31 | check/trace: ## Check trace jobs 32 | $(KUBECTL) trace get 33 | 34 | .PHONY: install/microk8s prepare clean run trace1 trace2 trace3 check/trace 35 | -------------------------------------------------------------------------------- /7/objpin/obj_pin_writer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from bcc import BPF, libbcc 3 | import pyroute2 4 | import ctypes 5 | import time 6 | import sys 7 | code = """ 8 | #include 9 | #include 10 | BPF_TABLE("array", uint32_t, long, cnt, 1); 11 | int counter(struct __sk_buff *ctx) { 12 | uint32_t index = 0; 13 | long *value = cnt.lookup(&index); 14 | if (value) 15 | *value += 1; 16 | return TC_ACT_OK; 17 | } 18 | """ 19 | device = "lo" 20 | path = "/sys/fs/bpf/counter" 21 | bpf = BPF(text=code, cflags=["-w"]) 22 | func = bpf.load_func("counter", BPF.SCHED_CLS) 23 | counter = bpf.get_table("cnt") 24 | ret = libbcc.lib.bpf_obj_pin(counter.map_fd, ctypes.c_char_p(path.encode('utf-8'))) 25 | if ret != 0: 26 | raise Exception("Failed to pinning object") 27 | 28 | ip = pyroute2.IPRoute() 29 | ipdb = pyroute2.IPDB(nl=ip) 30 | idx = ipdb.interfaces[device].index 31 | ip.tc("add", "clsact", idx) 32 | ip.tc("add-filter", "bpf", idx, ":1", fd=func.fd, name=func.name, parent="ffff:fff2", classid=1, direct_action=True) 33 | while True: 34 | try: 35 | print(counter[0].value) 36 | time.sleep(1) 37 | except KeyboardInterrupt: 38 | print("Removing filter from device") 39 | break 40 | ip.tc("del", "clsact", idx) 41 | ipdb.release() 42 | -------------------------------------------------------------------------------- /9/python/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | prepare: ## Prepare 4 | wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tar.xz \ 5 | && tar -xvf Python-3.9.0.tar.xz \ 6 | && rm -f Python-3.9.0.tar.xz \ 7 | && mv Python-3.9.0 pythonsrc \ 8 | && cd pythonsrc \ 9 | && ./configure --with-dtrace \ 10 | && make \ 11 | && make install 12 | pip3 install stapsdt 13 | 14 | clean: ## Clean 15 | rm -rf pythonsrc 16 | 17 | run: ## Run sample 18 | /usr/local/bin/python3 ./sample.py 19 | 20 | run/usdt: ## Run USDT Sample 21 | /usr/local/bin/python3 ./usdt.py 22 | 23 | check/binary: ## List USDT probes in python3 24 | bpftrace -l 'usdt:/usr/local/bin/python3:*' 25 | 26 | check/runtime: ## List USDT probes in process 27 | bpftrace -l 'usdt:*' -p $(shell pgrep -f 'python3 ./usdt.py') 28 | 29 | trace1: ## Trace python 30 | bpftrace --usdt-file-activation -e 'usdt:/usr/local/bin/python3:function__entry* / pid == $(shell pgrep -f '/usr/local/bin/python3 .*sample.*') / { printf("%s\n%s:%s%s\n", probe, str(arg0), str(arg1), ustack()); }' 31 | 32 | trace2: ## Trace USDT in python 33 | bpftrace -p $(shell pgrep -f 'python3 ./usdt.py') -e 'usdt:/usr/local/bin/python3:myprobe:* { printf("%s\n", probe) }' 34 | 35 | .PHONY: prepare run run/usdt check/binary check/runtime trace1 trace2 36 | -------------------------------------------------------------------------------- /10/docker/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | PID=$(shell docker inspect -f {{.State.Pid}} sample) 4 | ID=$(shell docker inspect -f {{.ID}} sample) 5 | 6 | prepare: bcc ## install docker 7 | docker run --rm -d -P --name sample nginx 8 | 9 | cgroupid: 10 | git clone https://github.com/iovisor/bcc 11 | cd bcc/examples/cgroupid \ 12 | && git checkout v0.16.0 \ 13 | && cp cgroupid /usr/local/bin/cgroupid 14 | 15 | clean: 16 | rm -rf bcc 17 | docker rm -f sample 18 | 19 | check/function: ## check functions 20 | readelf -a /proc/$(PID)/root/usr/sbin/nginx | grep FUNC | grep -v UND | less 21 | 22 | check/binary: ## List probes from binary 23 | bpftrace -l 'uprobe:/proc/$(PID)/root/usr/sbin/nginx:*' 24 | 25 | check/runtime: ## List probes from process 26 | bpftrace -l -p $(PID) 27 | 28 | check/cgroup: ## check cgroupid 29 | cgroupid hex /sys/fs/cgroup/unified/system.slice/docker-$(ID).scope 30 | 31 | trace1: ## uprobe in docker 32 | bpftrace -e \ 33 | 'uprobe:/proc/$(PID)/root/usr/sbin/nginx:ngx_http_* { printf("%d %s %s: %s\n", pid, probe, comm, ustack()) }' 34 | 35 | trace2: ## cgroup filter 36 | bpftrace -e \ 37 | 'tracepoint:syscalls:sys_enter_accept* /cgroup == cgroupid("/sys/fs/cgroup/unified/system.slice/docker-$(ID).scope")/ { printf("worker: %d %x %s\n", pid, cgroup, probe) }' 38 | -------------------------------------------------------------------------------- /4/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | prepare: bash tplist ## Prepare assets 4 | 5 | bash: ## Prepare bash related 6 | wget https://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz 7 | tar xvf bash-5.0.tar.gz 8 | rm -f bash-5.0.tar.gz 9 | cd bash-5.0 \ 10 | && ./configure \ 11 | && make 12 | 13 | tplist: ## Prepare tplist 14 | dnf install -y bcc-tools 15 | 16 | clean: ## Clean 17 | rm -rf bash-5.0 18 | rm -f sdt 19 | 20 | .PHONY: prepare bash tplist clean 21 | 22 | p45-1: ## Check functions in bash-5.0/list.c 23 | cd bash-5.0 \ 24 | && ctags -x --c-types=f ./list.c 25 | 26 | p45-2: ## Check file type of bash-5.0/list.o 27 | cd bash-5.0 \ 28 | && file list.o 29 | 30 | p45-3: ## Check functions in bash-5.0/list.o 31 | cd bash-5.0 \ 32 | && nm list.o | grep T 33 | cd bash-5.0 \ 34 | && readelf -s list.o | grep FUNC 35 | 36 | p47: ## Check tracepoint 37 | tplist -l $(shell readlink -f /lib64/libc.so.6) 38 | 39 | p48: ## C USDT example 40 | gcc -c sdt.c -o sdt 41 | readelf -n ./sdt 42 | 43 | p49: ## Check USDT using tplist 44 | tplist -vv -l ./sdt 45 | 46 | p50-1: ## List perf software event 47 | perf list | grep 'Software event' 48 | 49 | p50-2: ## See perf_event_open manual 50 | man perf_event_open 51 | 52 | p51-1: ## List perf hardware event 53 | perf list | grep 'Kernel PMU event' 54 | 55 | p51-2: ## See perf stat 56 | perf stat -d ps 57 | 58 | .PHONY: p45-1 p45-2 p45-3 p47 p49 p50-1 p50-2 p51-1 p51-2 59 | -------------------------------------------------------------------------------- /5/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | prepare: flamegraph flamescope ## Prepare assets 4 | 5 | flamegraph: ## Prepare flamegraph 6 | git clone https://github.com/brendangregg/flamegraph 7 | 8 | flamescope: ## Prepare flamescope 9 | git clone https://github.com/netflix/flamescope 10 | cd flamescope \ 11 | && pip install -r requirements.txt \ 12 | && python run.py 13 | 14 | clean: ## Clean 15 | rm -rf flamegraph flamescope 16 | 17 | .PHONY: prepare clean 18 | 19 | p58: ## Perf record 20 | perf record -F 99 -e cpu-clock -ag -- selep 60 21 | perf script 22 | 23 | p61: ## Flamegraph 24 | cd flamegraph \ 25 | && perf record -F 99 -e cpu-clock -ag -- sleep 60 \ 26 | && perf script > out.perf \ 27 | && ./stackcollapse-perf.pl out.perf > out.folded \ 28 | && ./flamegraph.pl out.folded > result.svg 29 | 30 | p63: ## Flamegraph diff 31 | cd flamegraph \ 32 | && perf record -F 99 -e cpu-clock -ag -- sleep 60 33 | && perf script > before.perf \ 34 | && ./stackcollapse-perf.pl before.perf > before.folded \ 35 | && perf record -F 99 -e cpu-clock -ag -- sleep 60 36 | && perf script > after.perf \ 37 | && ./stackcollapse-perf.pl after.perf > after.folded \ 38 | && ./difffolded.pl before.folded after.folded > out.diff \ 39 | && cat out.dff | ./flamegraph.pl > result.svg 40 | 41 | p68: ## Flamescope 42 | cd flamescope/examples \ 43 | && perf record -F 49 -a -g -- sleep 120 \ 44 | && perf script --header > stacks.app.$$(date +%s) 45 | 46 | .PHONY: p58 p61 p63 p68 47 | -------------------------------------------------------------------------------- /9/java/Makefile: -------------------------------------------------------------------------------- 1 | include ../../help.mk 2 | 3 | JAVA_HOME=$(shell dirname $(shell dirname $(shell readlink -f $(shell which javac)))) 4 | LIBJVMSO=$(JAVA_HOME)/jre/lib/amd64/server/libjvm.so 5 | AGENT_HOME=$(PWD)/perf-map-agent/build/out 6 | JMAP=FlameGraph/jmaps 7 | PID=$(shell pgrep -f 'java .*Sample.*') 8 | 9 | info: ## Check system info 10 | @echo java home: $(JAVA_HOME) 11 | @echo libjvm.so: $(LIBJVMSO) 12 | @echo per-map-agent: $(AGENT_HOME) 13 | @echo jmap: $(JMAP) 14 | 15 | prepare: FlameGraph perf-map-agent build ## Prepare 16 | 17 | FlameGraph: 18 | git clone --depth=1 https://github.com/brendangregg/FlameGraph 19 | 20 | perf-map-agent: 21 | git clone --depth=1 https://github.com/jvm-profiling-tools/perf-map-agent \ 22 | && mkdir perf-map-agent/build \ 23 | && cd perf-map-agent/build \ 24 | && cmake .. \ 25 | && make 26 | 27 | build: Sample 28 | 29 | Sample: 30 | javac Sample.java 31 | 32 | clean: ## Clean 33 | rm -rf *.class FlameGraph perf-map-agent libstapsdt-jni 34 | 35 | run: Sample ## Run Sample Program 36 | java -XX:+PreserveFramePointer -XX:+ExtendedDTraceProbes Sample 37 | 38 | check/binary: ## List probes in libjvm.so 39 | bpftrace -l 'usdt:'$(LIBJVMSO)':*' | less 40 | 41 | check/runtime: ## List probes in java process 42 | bpftrace -p $(shell pgrep -f 'java .*Sample.*') -l | less 43 | 44 | trace1: ## Profile java proces 45 | JAVA_HOME=$(JAVA_HOME) AGENT_HOME=$(AGENT_HOME) bpftrace --unsafe -e 'profile:hz:999 / pid == $(PID) / { @[ustack] = count(); } END { system("$(JMAP)"); }' 46 | 47 | trace2: ## Trace USDT in java process 48 | bpftrace --unsafe -e 'usdt:'$(LIBJVMSO)':method__entry* / pid == $(PID) / { printf("%s\n%s:%s%s\n", probe, str(arg1), str(arg3), ustack()) }' 49 | 50 | trace3: ## Trace Specific Method 51 | JAVA_HOME=$(JAVA_HOME) AGENT_HOME=$(AGENT_HOME) bpftrace --unsafe -e 'BEGIN { system("$(JMAP)"); } usdt:'$(LIBJVMSO)':method__entry* / pid == $(PID) && str(arg1) == "Sample" / { printf("%s\n%s:%s%s\n", probe, str(arg1), str(arg3), ustack()) }' 52 | 53 | 54 | .PHONY: prepare build clean check/binary check/runtime trace1 trace2 trace3 run 55 | -------------------------------------------------------------------------------- /8/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | prepare: bpftool jq pahole 4 | 5 | linux-stable: 6 | git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 7 | cd linux-stable \ 8 | && git checkout v5.8.17 \ 9 | 10 | jq: 11 | curl -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 -o /usr/local/bin/jq 12 | chmod a+x /usr/local/bin/jq 13 | 14 | bpftool: linux-stable 15 | cd linux-stable/tools/bpf/bpftool \ 16 | && make \ 17 | && make install 18 | 19 | pahole: 20 | git clone https://github.com/acmel/dwarves 21 | mkdir dwarves/build 22 | cd dwarves/build \ 23 | && git checkout v1.18 \ 24 | && cmake .. \ 25 | && make \ 26 | && make install \ 27 | 28 | clean: ## Clean 29 | rm -rf linux-stable dwarves *.o 30 | 31 | .PHONY: prepare clean 32 | 33 | p192-1: ## List BPF reatled features 34 | bpftool featrue 35 | 36 | p192-2: ## List BPF prog 37 | bpftool prog 38 | 39 | p193-1: ## See BPF prog with json format 40 | bpftool show --json id 3 | jq 41 | 42 | p193-2: ## See BPF prog with jq 43 | bpftool prog show --json id 3 | jq -c '[.id, .type, .loaded_at]' 44 | 45 | p193-3: ## Dump BPF prog 46 | bpftool prog dump xlated id 3 47 | 48 | p194-1: ## Dump jited BPF prog 49 | bpftool prog dump jited id 3 50 | 51 | p194-2: ## Dump visulized BPF prog 52 | bpftool prog dump xlated id 3 visual &> output.out 53 | dot -Tpng output.out -o visual.png 54 | 55 | p195-1: ## Enable BPF stats 56 | sysctl -w kernel.bpf_stats_enabled=1 57 | 58 | p195-2: ## List BPF prog 59 | bpftool prog 60 | 61 | p196-1: ## List BPF map 62 | bpftool map show 63 | 64 | p196-2: ## BPF dump map 65 | bpftool map dump id 3 | head 66 | 67 | p198: ## Compare Dwarf & BTF 68 | @echo '# build with dwarf' 69 | gcc -g -c btf.c 70 | @echo 71 | @echo '# using file' 72 | file btf.o 73 | @echo 74 | @echo '# using readelf' 75 | readelf -SW btf.o | grep \.debug 76 | @echo 77 | @echo -n '# using pahole' 78 | pahole btf.o 79 | 80 | p199: ## Build BTF with Pahole 81 | @echo '# generate BTF' 82 | pahole -JV btf.o 83 | @echo 84 | @echo '# using readelf' 85 | readelf -SW btf.o | grep \.BTF 86 | 87 | p200-1: ## Build BTF with Clang 88 | @echo '# build using clang' 89 | clang -target bpf -g -c btf.c 90 | @echo 91 | @echo '# using readelf' 92 | readelf -SW btf.o | grep \.BTF 93 | @echo 94 | 95 | p200-2: ## Check source from BTF 96 | @echo '# check source' 97 | pahole -F btf btf.o 98 | @echo 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linux_sytem_tracing_with_bpf 2 | 3 | ## 1장 4 | 5 | ## 2장 6 | - https://www.tcpdump.org/papers/bpf-usenix93.pdf 7 | - https://www.kernel.org/doc/Documentation/networking/filter.txt 8 | - https://lwn.net/Articles/603983/ 9 | - http://www.brendangregg.com/bpf-performance-tools-book.html 10 | - http://llvm.org/ 11 | - https://man7.org/linux/man-pages/man8/BPF.8.html 12 | - https://github.com/torvalds/linux/tree/v5.8/tools/lib/bpf/ 13 | - https://github.com/libbpf/libbpf/ 14 | - https://github.com/iovisor/bcc/ 15 | - https://github.com/iovisor/bpftrace/ 16 | - https://www.iovisor.org/ 17 | - https://www.linuxfoundation.org/ 18 | - http://www.brendangregg.com/blog/2019-12-02/bpf-a-new-type-of-software.html 19 | - https://cilium.io/ 20 | - https://ebpf.io/ 21 | 22 | ## 3장 23 | - https://github.com/torvalds/linux/blob/v5.8/include/uapi/linux/bpf.h#L161 24 | - https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt 25 | - https://github.com/torvalds/linux/blob/v5.8/samples/bpf/bpf_load.c 26 | - https://github.com/torvalds/linux/blob/v5.8/include/uapi/linux/bpf.h#L122 27 | - https://facebookmicrosites.github.io/bpf/blog/2018/11/14/btf-enhancement.html 28 | - https://www.kernel.org/doc/html/v5.8/bpf/btf.html 29 | - https://www.dpdk.org/ 30 | - https://lwn.net/Articles/826884/ 31 | - https://www.kernel.org/doc/html/v5.8/bpf/bpf_design_QA.html 32 | - https://sourceware.org/systemtap/ 33 | - https://lttng.org/ 34 | - https://perf.wiki.kernel.org/index.php/Main_Page 35 | - https://github.com/namhyung/uftrace/ 36 | 37 | ## 4장 38 | - https://www.kernel.org/doc/html/v5.8/trace/kprobetrace.html 39 | - https://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz 40 | - https://www.kernel.org/doc/html/v5.8/core-api/tracepoint.html 41 | - https://github.com/sthima/libstapsdt/ 42 | 43 | ## 5장 44 | - https://www.slideshare.net/brendangregg/java-performance-analysis-on-linux-with-flame-graphs/ 45 | - http://dwarfstd.org/ 46 | - https://lwn.net/Articles/680985/ 47 | - https://www.kernel.org/doc/html/v5.8/x86/orc-unwinder.html 48 | - https://github.com/brendangregg/FlameGraph/ 49 | - https://github.com/Netflix/flamescope/ 50 | - http://www.brendangregg.com/blog/2018-11-08/flamescope-pattern-recognition.html 51 | 52 | ## 6장 53 | - https://cloud.google.com/ 54 | - https://www.vagrantup.com/ 55 | - https://www.hashicorp.com/ 56 | - https://www.virtualbox.org/ 57 | - https://libvirt.org/ 58 | - https://www.vagrantup.com/docs/ 59 | - https://github.com/iovisor/bcc/blob/v0.16.0/docs/kernel-versions.md 60 | - https://github.com/iovisor/bcc/blob/v0.16.0/INSTALL.md#packages 61 | - https://www.docker.com/ 62 | - https://github.com/iovisor/bpftrace/blob/v0.11.2/docs/tutorial_one_liners.md 63 | - https://raw.githubusercontent.com/torvalds/linux/v5.8/scripts/extract-vmlinux 64 | - https://github.com/iovisor/bpftrace/issues/516 65 | - https://github.com/iovisor/bpftrace/issues/940 66 | - https://github.com/iovisor/bpftrace/blob/v0.11.2/tools/dcsnoop.bt 67 | - https://github.com/iovisor/bpftrace/issues/1588 68 | - https://github.com/iovisor/bpftrace/blob/v0.11.2/docs/reference_guide.md 69 | 70 | ## 7장 71 | - https://github.com/iovisor/gobpf 72 | - https://github.com/cilium/ebpf 73 | - https://github.com/iovisor/bcc/blob/v0.16.0/docs/tutorial_bcc_python_developer.md 74 | - https://github.com/iovisor/bcc/issues/748 75 | - https://lwn.net/Articles/804937/ 76 | - https://github.com/iovisor/bcc/blob/v0.16.0/docs/reference_guide.md#maps 77 | - https://github.com/iovisor/bcc/blob/v0.16.0/tools/sslsniff.py#L68 78 | - https://github.com/iovisor/bcc/blob/v0.16.0/tools/tcpdrop.py 79 | - https://github.com/iovisor/bcc/blob/v0.16.0/examples/networking/simple_tc.py 80 | - https://github.com/iovisor/bcc/issues/3090 81 | - https://github.com/iovisor/bcc/blob/v0.16.0/src/cc/libbpf.h 82 | - https://github.com/torvalds/linux/blob/v5.8/include/linux/bpf.h#L834 83 | 84 | ## 8장 85 | 86 | ## 9장 87 | - https://www.kernel.org/doc/html/v5.8/vm/numa.html 88 | - https://www.kernel.org/doc/Documentation/networking/scaling.txt 89 | - https://www.kernel.org/doc/Documentation/networking/segmentation-offloads.txt 90 | - https://github.com/chrisa/libusdt#status 91 | - https://golang.org/doc/asm 92 | - https://github.com/iovisor/bpftrace/pull/828 93 | - https://github.com/iovisor/bcc/issues/1320 94 | - https://github.com/mmcshane/salp 95 | - https://github.com/sthima/libstapsdt 96 | - https://github.com/cuviper/rust-libprobe 97 | - https://github.com/iovisor/bcc/issues/327#issuecomment-203636673 98 | - https://github.com/iovisor/bcc/blob/v0.16.0/tools/lib/ucalls.py#L68 99 | - https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation 100 | - https://github.com/jvm-profiling-tools/perf-map-agent 101 | - https://github.com/brendangregg/FlameGraph/blob/master/jmaps 102 | - https://github.com/goldshtn/libstapsdt-jni 103 | - https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tar.xz 104 | - https://github.com/iovisor/bpftrace/pull/1567 105 | - https://pypi.org/project/stapsdt/ 106 | - https://github.com/nodejs/node 107 | - https://github.com/chrisa/node-dtrace-provider 108 | - https://github.com/chrisa/libusdt 109 | - https://github.com/postmodern/ruby-install/archive/v0.7.1.tar.gz 110 | - https://github.com/thekvn/ruby-usdt 111 | - https://www.cpan.org/src/5.0/perl-5.32.0.tar.gz 112 | - https://github.com/chrisa/perl-Devel-DTrace-Provider 113 | - http://git.php.net/repository/php-src.git 114 | - https://github.com/iovisor/bpftrace/blob/v0.11.2/tools/bashreadline.bt 115 | - https://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz 116 | - https://github.com/iovisor/bpftrace/issues/246 117 | - https://alanhargreaves.wordpress.com/2007/08/10/binsh-dtrace-provider/ 118 | 119 | ## 10장 120 | - https://github.com/systemd/systemd/blob/v247/NEWS#L4605 121 | - https://github.com/iovisor/bcc/blob/master/src/python/bcc/containers.py 122 | - https://github.com/iovisor/kubectl-trace 123 | - https://github.com/iovisor/kubectl-trace/issues/57 124 | - https://github.com/kinvolk/inspektor-gadget 125 | - https://github.com/kubernetes-sigs/krew 126 | 127 | ## 11장 128 | - https://www.cloudflare.com/ 129 | - https://github.com/cloudflare/ebpf_exporter 130 | - https://www.aquasec.com/ 131 | - https://github.com/aquasecurity/tracee 132 | 133 | ## 부록 134 | - https://github.com/iovisor/bcc/blob/v0.16.0/docs/kernel-versions.md#helpers 135 | - https://github.com/torvalds/linux/blob/v5.8/include/uapi/linux/bpf.h 136 | - https://github.com/torvalds/linux/tree/v5.8/samples/bpf 137 | - https://github.com/torvalds/linux/blob/v5.8/samples/bpf/bpf_load.h 138 | - https://github.com/torvalds/linux/blob/v5.8/samples/bpf/sock_example.c 139 | - https://github.com/acmel/dwarves 140 | - git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 141 | - https://github.com/llvm/llvm-projects.git 142 | - https://github.com/iovisor/bcc 143 | - https://github.com/iovisor/bpftrace 144 | - https://get.docker.com 145 | 146 | ## 참고자료 147 | - http://www.brendangregg.com/bpf-performance-tools-book.html 148 | - http://www.brendangregg.com/blog/2020-07-15/systems-performance-2nd-edition.html 149 | - http://www.brendangregg.com/blog/index.html 150 | - https://www.kernel.org/doc/html/v5.8/bpf/index.html 151 | - https://www.kernel.org/doc/Documentation/ 152 | - https://lwn.net/Articles/753601/ 153 | - https://lwn.net/Articles/752047/ 154 | - https://docs.cilium.io/en/v1.9/bpf/ 155 | - https://cilium.io/blog 156 | - https://blog.cloudflare.com/ 157 | - https://facebookmicrosites.github.io/bpf/blog/ 158 | - https://blogs.oracle.com/author/?search_terms=bpf 159 | - http://vger.kernel.org/bpfconf2019.html 160 | - https://linuxplumbersconf.org/event/4/contributions/449/attachments/239/529/A_pure_Go_eBPF_library.pdf 161 | - https://qmo.fr/docs/talk_20200202_debugging_ebpf.pdf 162 | - https://www.sosconhistory.net/soscon2018/pdf/day2_1100_3.pdf 163 | - https://github.com/goldshtn/linux-tracing-workshop 164 | - https://s3-sa-east-1.amazonaws.com/thedevconf/presentations/TDC2018POA/devopstools/PSR-2920_2018-12-07T111416_linux-observability-superpowers.pdf 165 | - https://www.collabora.com/news-and-blog/search-results.html?search=ebpf 166 | - https://wariua.github.io/ 167 | - https://jvns.ca/ 168 | - https://blog.srvthe.net/ 169 | - https://leezhenghui.github.io/blog/ 170 | - https://thatdevopsguy.medium.com/ 171 | - https://medium.com/@phylake 172 | -------------------------------------------------------------------------------- /6/Makefile: -------------------------------------------------------------------------------- 1 | include ../help.mk 2 | 3 | prepare: bcc bpftrace mybin watchpoint 4 | 5 | bcc: 6 | git clone https://github.com/iovisor/bcc 7 | cd bcc \ 8 | && git checkout v0.16.0 9 | 10 | bpftrace: 11 | git clone https://github.com/iovisor/bpftrace 12 | cd bpftrace \ 13 | && git checkout v0.11.2 14 | 15 | mybin: 16 | gcc -o mybin mybin.c 17 | 18 | extract-vmlinux: 19 | wget -O extract-vmlinux https://raw.githubusercontent.com/torvalds/linux/master 20 | chmod +x extract-vmlinux 21 | 22 | watchpoint: 23 | gcc bpftrace/tests/testprogs/watchpoint.c -o watchpoint 24 | 25 | clean: ## Clean 26 | rm -rf bcc bpftrace mybin watchpoint *.perf vmlinux 27 | 28 | .PHONY: prepare clean 29 | 30 | p77: ## Docker build 31 | docker build -t bpfenv . 32 | 33 | p78-1: ## Docker run 34 | docker run -ti \ 35 | --privileged \ 36 | --pid host \ 37 | --net host \ 38 | --volume /sys/fs/cgroup:/sys/fs/cgroup \ 39 | --volume /sys/kernel/debug:/sys/kernel/debug \ 40 | --volume /sys/fs/bpf:/sys/fs/bpf \ 41 | --volume /lib/modules:/lib/modules \ 42 | bpfenv bash 43 | 44 | p78-2: ## Check mount 45 | mount | egrep 'debug|trace|cgroup|bpf' 46 | 47 | p80: ## Check bcc tools 48 | ls bcc/tools/*.py 49 | ls -l bcc/tools/*.py | wc -l 50 | 51 | p81-1: ## funccount 52 | bcc/tools/funccount.py tcp_drop 53 | 54 | p81-2: ## funccount 55 | bcc/tools/funccount.py 'vfs_*' 56 | 57 | p82-1: ## funccount 58 | bcc/tools/funccount.py -i 1 'c:pthread_mutex_lock' 59 | 60 | p82-2: ## funccount 61 | bcc/tools/funccount.py 'c:str*' 62 | 63 | p83-1: ## funccount 64 | bcc/tools/funccount.py 't:syscalls:sys_enter_*' 65 | 66 | p83-2: ## stackcount 67 | bcc/tools/stackcount.py ktime_get 68 | 69 | p84-1: ## stackcount 70 | bcc/tools/stackcount.py -P ktime_get 71 | 72 | p84-2: ## stackcount 73 | bcc/tools/stackcount.py -f -P -D 10 ktime_get > stack.out 74 | wc stack.out 75 | git clone http://github.com/brendangregg/FlameGraph 76 | cd FlameGraph 77 | ./flamegraph.pl --ash --bgcolor=grey < ../stack.out > stack.svg 78 | 79 | p85-1: ## trace 80 | bcc/tools/trace.py 'do_sys_open "%s", arg2' 81 | 82 | p85-2: ## trace 83 | bcc/tools/trace.py 'c:open (arg2 == 42) "%s %d", arg1, arg2' 84 | 85 | p85-3: ## trace 86 | bcc/tools/trace.py '__x64_sys_read (arg3 > 20000) "read %d bytes", arg3' 87 | 88 | p86-1: ## trace 89 | bcc/tools/trace.py 'do_sys_open "%s", arg2@user' -UK -f temp 90 | 91 | p86-2: ## argdist 92 | bcc/tools/argdist.py -H 'r::__tcp_select_window():int:$$retval' 93 | 94 | p88: ## bpftrace 95 | bpftrace -l 'tracepoint:syscalls:sys_enter_*' 96 | 97 | p89-1: ## bpftrace helloworld 98 | bpftrace -e 'BEGIN { printf("hello world\n"); }' 99 | 100 | p89-2: ## bpftrace openat 101 | bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }' 102 | 103 | p90-1: ## bpftrace tracepoint detail 104 | bpftrace -vl tracepoint:syscalls:sys_enter_openat 105 | 106 | p90-2: ## bpftrace map 107 | bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }' 108 | 109 | p91: ## bpftrace histo 110 | bpftrace -e 'tracepoint:syscalls:sys_exit_read /pid =='$$(pidof dockerd)'/ { @bytes = hist(args->ret); }' 111 | 112 | p92: ## bpftrace lhisto 113 | bpftrace -e 'kretprobe:vfs_read { @bytes = lhist(retval, 0, 2000, 200); }' 114 | 115 | p93: ## bpftrace time elapsed 116 | bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; } kretprobe:vfs_read /@start[tid]/ { @ns[comm] = hist(nsecs - @start[tid]); delete(@start[tid]); }' 117 | 118 | p94: ## bpftrace interval 119 | bpftrace -e 'tracepoint:sched:sched* { @[probe] = count(); } interval:s:5 { exit(); }' 120 | 121 | p95-1: ## bpftrace stack trace 122 | bpftrace -e 'profile:hz:99 { @[kstack] = count(); }' 123 | 124 | p95-2: ## bpftrace stack trace scheduler 125 | bpftrace -e 'tracepoint:sched:sched_switch { @[kstack] = count(); }' 126 | 127 | p96: ## bpftrace block io 128 | bpftrace -e 'tracepoint:block:block_rq_issue { @ = hist(args->bytes); }' 129 | 130 | p97: ## bpftrace with kernel struct 131 | bpftrace path.bt 132 | 133 | p100: ## bpftrace event list 134 | bpftrace -l 'kprobe:vfs_*' 135 | 136 | p101-1: ## bpftrace tracepoint list 137 | bpftrace -l tracepoint:* 138 | 139 | p101-2: ## bpftrace tracepoint 140 | bpftrace -e 'tracepoint:block:block_rq_insert { printf("block I/O created by %d\n", tid); }' 141 | 142 | p101-3: ## bpftrace tracepoint detail 143 | bpftrace -vl tracepoint:syscalls:sys_enter_openat 144 | 145 | p102: ## bpftrace tracepoint with arg 146 | bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }' 147 | 148 | p103-1: ## bpftrace check usdt in shared object 149 | bpftrace -l 'usdt:/usr/lib/libc.so.6:*' 150 | 151 | p103-2: ## bpftrace check usdt in proces 152 | bpftrace -p $(pidof mybin) -l 'usdt:*' 153 | 154 | p103-3: ## check shared object in binary 155 | ldd ./mybin 156 | 157 | p103-4: ## bpftrace usdt 158 | bpftrace -e 'usdt:/lib64/libc.so.6:* { printf("%s\n", probe) }' 159 | 160 | p104-1: ## bpftrace check kprobe 161 | bpftrace -l kprobe:* 162 | 163 | p104-2: ## bpftrace 164 | bpftrace -e 'kprobe:do_nanosleep { printf("sleep by %d\n", tid); }' 165 | 166 | p105-1: ## disassemble kernel function 167 | gdb -q /usr/lib/debug/boot/vmlinux-$$(uname -r) --ex 'disassemble do_sys_open' 168 | 169 | p105-2: ## disassemble with objdump 170 | FUNCADDR=$$(cat /boot/System.map | grep -E 'do_sys_open$$' | awk '{print $$1}') \ 171 | && objdump -S --start-address=0x$$FUNCADDR ./vmlinux | awk '{print $$0} $$3~/retq?/{exit}' 172 | 173 | p106-1: ## bpftrace with kprobe offset 174 | bpftrace -e 'kprobe:do_sys_open+9 { printf("in here\n"); }' 175 | 176 | p106-2: ## bpftrace with kprobe offset 177 | bpftrace -e 'kprobe:do_sys_open+1 { printf("in here\n"); }' 178 | 179 | p106-3: ## bpftrace with kprobe struct field 180 | bpftrace field.bt 181 | 182 | p107: ## bpftrace check struct from BTF 183 | bpftrace -lv "struct path" 184 | 185 | p108-1: ## bpftrace check uprobe 186 | bpftrace -l 'uprobe:/bin/bash' 187 | 188 | p108-2: ## bpftrace uprobe 189 | bpftrace -e 'uprobe:/bin/bash:find_shell_builtin { printf("arg0: %s\n", str(arg0)); }' 190 | 191 | p108-3: ## bpftrace uretprobe 192 | bpftrace -e 'uretprobe:/bin/bash:initialize_shell_builtins { printf("ret: %d\n", retval); }' 193 | 194 | p108-4: ## bpftrace urpboe with function address 195 | FUNCADDR=$$(objdump -tT /bin/bash | grep initialize_shell_builtins | awk '{print $$1}') \ 196 | && bpftrace -e 'uprobe:/bin/bash:0x'$$FUNCADDR'{ printf("in here\n"); }' 197 | 198 | p109-1: ## bpftrace with uprobe offset 199 | bptrace -e 'uprobe:/usr/bin/bash:initialize_shell_builtins+10 { printf("in here\n"); }' 200 | 201 | p109-2: ## disassemble function 202 | objdump -d /usr/bin/bash | grep -A 10 -E ':' 203 | 204 | p111: ## bpftrace software event 205 | bpftrace -e 'software:context-switches:100 { @[comm] = count(); }' 206 | 207 | p112: ## bpftrace profile 208 | bpftrace -e 'profile:hz:99 { @[comm] = count(); }' 209 | 210 | p113-1: ## bpftrace interval 211 | bpftrace -e 'i:s:1 { printf("%s\n", strftime("%H:%M:%S", nsecs)); }' 212 | 213 | p113-2: ## bpftrace BEGIN/END 214 | bpftrace -e 'BEGIN { printf("started\n") } END { printf("finished\n")}' 215 | 216 | p114-1: ## bpftrace kfunc detail 217 | bpftrace -lv kfunc:fget 218 | 219 | p114-2: ## bpftrace kfunc 220 | bpftrace -e 'kfunc:fget { printf("fd %d\n", args->fd); }' 221 | 222 | p115: ## bpftrace watchpoint 223 | bpftrace -e 'watchpoint::0x10000000:8:rw { printf("hit!\n"); }' -p $$(pidof mybin) 224 | 225 | p116: ## bpftrace watchpoint 226 | bpftrace -v -e 'watchpoint::0x10000000:8:w { printf("hit!\n"); exit() }' -c ./watchpoint 227 | 228 | p117-1: ## bpftrace ?: 229 | bpftrace -e 'tracepoint:syscalls:sys_exit_read { @error[args->ret < 0 ? - args->ret : 0] = count(); }' 230 | 231 | p117-2: ## bpftrace if-else 232 | bpftrace -e 'tracepoint:syscalls:sys_enter_read { @reads = count(); if (args->count > 1024) { @large = count(); } }' 233 | 234 | p118-1: ## bpftrace unroll 235 | bpftrace -e 'kprobe:do_nanosleep { $$i = 1; unroll(5) { printf("i: %d\n", $$i); $$i = $$i + 1; } }' 236 | 237 | p118-2: ## bpftrace while 238 | bpftrace -e 'i:ms:100 { $$i = 0; while ($$i <= 100) { printf("%d ", $$i); $$i++} exit(); }' 239 | 240 | p120: ## bpftrace tuple 241 | bpftrace -e 'BEGIN { $$t = (1, 2, "string"); printf("%d %s\n", $$t.1, $$t.2); }' 242 | 243 | p121-1: ## bpftrace map 244 | bpftrace -e 'kretprobe:vfs_read /pid==1234/ { @bytes = hist(retval); }' 245 | 246 | p121-2: 247 | bpftrace -e 'BEGIN { @start = nsecs; } kprobe:do_nanosleep /@start != 0/ { printf("at %d ms: sleep\n", (nsecs - @start) / 1000000); }' 248 | 249 | p122: 250 | bpftrace -e 'BEGIN { @start = nsecs; } kprobe:do_nanosleep /@start != 0/ { printf("at %d ms: sleep\n", (nsecs - @start) / 1000000); }' 251 | 252 | p123-1: 253 | bpftrace -e 'kprobe:do_nanosleep { @start[tid] = nsecs; } kretprobe:do_nanosleep /@start[tid] != 0/ { printf("slept for %d ms\n", (nsecs - @start[tid]) / 1000000); delete(@start[tid]); }' 254 | 255 | p123-2: 256 | bpftrace -e 'kprobe:do_nanosleep { @start[tid] = nsecs; } kretprobe:do_nanosleep /@start[tid] != 0/ { $$delta = nsecs - @start[tid]; printf("slept for %d ms\n", $$delta / 1000000); delete(@start[tid]); }' 257 | 258 | p131: 259 | bpftrace -e 'profile:hz:99 /pid=='$$(pidof dockerd)'/ { printf("%s %d [000] %u.%06u: cpu-clock:", comm, pid, nsecs/1000000000, nsecs%1000000 ); printf("%s", ustack(perf)); printf("\n"); }' | sed '1d' > bpftrace.perf 260 | 261 | p133: 262 | ls bpftrace/tools/*bt 263 | --------------------------------------------------------------------------------