├── .github └── workflows │ ├── dco-check.yml │ ├── memcached_benchmark.yml │ ├── meson.yml │ └── rustfmt.yml ├── .gitignore ├── .gitmodules ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── docs ├── entry-insertion.md ├── exception-handling.md ├── getting-started.md ├── hotos23.pdf ├── image │ ├── gentoo-badge3.svg │ └── xdp-attach-point.png ├── kernel-symbols.md ├── librex.md ├── rex-paper.pdf └── rust_rex_subset.md ├── flake.lock ├── flake.nix ├── librex ├── .gitignore ├── README.md ├── include │ └── librex.h ├── lib │ ├── bindings.h │ └── librex.cpp └── meson.build ├── meson.build ├── rex-macros ├── .gitignore ├── Cargo.toml └── src │ ├── args.rs │ ├── kprobe.rs │ ├── lib.rs │ ├── perf_event.rs │ ├── tc.rs │ ├── tracepoint.rs │ └── xdp.rs ├── rex-native.ini ├── rex ├── .cargo │ └── config.toml ├── .gitignore ├── Cargo.toml ├── build.py ├── build.rs ├── librexstub │ └── lib.c ├── meson.build └── src │ ├── base_helper.rs │ ├── bindings │ ├── linux │ │ ├── kernel.rs │ │ └── mod.rs │ ├── mod.rs │ └── uapi │ │ ├── linux │ │ ├── bpf.rs │ │ ├── errno.rs │ │ ├── in.rs │ │ ├── mod.rs │ │ ├── perf_event.rs │ │ ├── pkt_cls.rs │ │ ├── ptrace.rs │ │ ├── seccomp.rs │ │ └── unistd.rs │ │ └── mod.rs │ ├── debug.rs │ ├── ffi.rs │ ├── kprobe │ ├── kprobe_impl.rs │ └── mod.rs │ ├── lib.rs │ ├── log.rs │ ├── map.rs │ ├── panic.rs │ ├── per_cpu.rs │ ├── perf_event │ ├── mod.rs │ └── perf_event_impl.rs │ ├── prog_type.rs │ ├── pt_regs.rs │ ├── random32.rs │ ├── sched_cls │ ├── mod.rs │ └── sched_cls_impl.rs │ ├── spinlock.rs │ ├── task_struct.rs │ ├── tracepoint │ ├── binding.rs │ ├── mod.rs │ └── tp_impl.rs │ ├── utils.rs │ └── xdp │ ├── mod.rs │ └── xdp_impl.rs ├── rustfmt.toml ├── samples ├── .clang-format ├── .gitignore ├── atomic │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── bmc │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── entry.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── electrode │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── config.txt │ ├── entry.c │ ├── fast_common.h │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ ├── common.rs │ │ ├── main.rs │ │ └── maps.rs ├── error_injector │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── loader.c │ ├── meson.build │ ├── src │ │ └── main.rs │ ├── tests │ │ └── runtest.py │ └── userapp.c ├── hello │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ ├── src │ │ └── main.rs │ └── tests │ │ └── runtest.py ├── map_bench │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── bench.sh │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── map_test │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ ├── src │ │ └── main.rs │ └── tests │ │ └── runtest.py ├── map_test_2 │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ ├── src │ │ └── main.rs │ └── tests │ │ └── runtest.py ├── meson.build ├── recursive │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── bench.sh │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── spinlock_cleanup_benchmark │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── spinlock_test │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── startup_overhead_benchmark │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── event-trigger.c │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── syscall_tp │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── meson.build │ ├── rustfmt.toml │ ├── src │ │ └── main.rs │ ├── syscall_tp_user.c │ └── tests │ │ └── runtest.py ├── syscount │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── loader.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ │ └── main.rs ├── trace_event │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── clippy.toml │ ├── meson.build │ ├── rustfmt.toml │ ├── src │ │ └── main.rs │ ├── trace_event_user.c │ ├── trace_helpers.c │ └── trace_helpers.h ├── tracex5 │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── clippy.toml │ ├── meson.build │ ├── rustfmt.toml │ ├── src │ │ └── main.rs │ └── tracex5.c └── xdp_test │ ├── .cargo │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── clippy.toml │ ├── entry.c │ ├── meson.build │ ├── rustfmt.toml │ └── src │ └── main.rs ├── scripts ├── cargo-wrapper.pl ├── q-script │ ├── .config │ ├── nix-q │ ├── sanity-test-q │ └── yifei-q └── sanity_tests │ └── run_tests.py └── tools └── memcached_benchmark ├── .cargo └── config.toml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── bench.py ├── devenv.lock ├── devenv.nix ├── devenv.yaml ├── rustfmt.toml ├── src ├── cli.rs ├── dict.rs ├── fs.rs ├── get_values.rs ├── main.rs └── set_values.rs └── tests └── benchmark_test.rs /.github/workflows/dco-check.yml: -------------------------------------------------------------------------------- 1 | name: DCO Check 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | check: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: KineticCafe/actions-dco@v1 11 | -------------------------------------------------------------------------------- /.github/workflows/memcached_benchmark.yml: -------------------------------------------------------------------------------- 1 | name: memcached_benchmark 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | env: 8 | CARGO_TERM_COLOR: always 9 | 10 | jobs: 11 | changes: 12 | if: github.repository == 'rex-rs/rex' 13 | runs-on: ubuntu-latest 14 | permissions: 15 | pull-requests: read 16 | outputs: 17 | bench: ${{ steps.filter.outputs.bench }} 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: dorny/paths-filter@v3 21 | id: filter 22 | with: 23 | filters: | 24 | bench: 25 | - 'tools/memcached_benchmark/**' 26 | 27 | build: 28 | needs: changes 29 | if: ${{ needs.changes.outputs.bench == 'true' }} 30 | runs-on: ubuntu-latest 31 | defaults: 32 | run: 33 | working-directory: ./tools/memcached_benchmark 34 | 35 | steps: 36 | - uses: actions/checkout@v4 37 | - id: filter 38 | uses: dorny/paths-filter@v3 39 | with: 40 | filters: | 41 | bench: 42 | - 'tools/memcached_benchmark/**' 43 | - uses: cachix/install-nix-action@v26 44 | - uses: cachix/cachix-action@v14 45 | with: 46 | name: devenv 47 | - name: Install devenv.sh 48 | run: nix profile install nixpkgs#devenv 49 | 50 | - name: Build the devenv shell and run any pre-commit hooks 51 | run: devenv test 52 | 53 | - name: Build 54 | shell: devenv shell bash -- -e {0} 55 | run: | 56 | cargo fmt --check --verbose 57 | cargo build -r --verbose 58 | - name: Run tests 59 | shell: devenv shell bash -- -e {0} 60 | run: | 61 | cargo test --verbose 62 | cargo test -r --verbose 63 | -------------------------------------------------------------------------------- /.github/workflows/meson.yml: -------------------------------------------------------------------------------- 1 | name: Meson Build and Test 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.ref_name }} 5 | cancel-in-progress: true 6 | 7 | on: 8 | push: 9 | branches: [main, ci] 10 | pull_request: 11 | branches: [main] 12 | 13 | env: 14 | CARGO_TERM_COLOR: always 15 | 16 | jobs: 17 | changes: 18 | if: github.repository == 'rex-rs/rex' 19 | runs-on: ubuntu-latest 20 | permissions: 21 | pull-requests: read 22 | outputs: 23 | meson: ${{ steps.filter.outputs.meson }} 24 | nix: ${{ steps.filter.outputs.nix }} 25 | steps: 26 | # For pull requests it's not necessary to checkout the code 27 | - uses: actions/checkout@v4 28 | - uses: dorny/paths-filter@v3 29 | id: filter 30 | with: 31 | predicate-quantifier: 'every' 32 | filters: | 33 | nix: &nix 34 | - '**' 35 | - '!docs/**' 36 | - '!tools/**' 37 | - '!**/*.md' 38 | meson: 39 | - *nix 40 | - '!flake.nix' 41 | - '!flake.lock' 42 | 43 | build_and_test: 44 | needs: changes 45 | if: ${{ needs.changes.outputs.meson == 'true' }} 46 | runs-on: [self-hosted, gentoo] 47 | steps: 48 | - name: Checkout repository 49 | uses: actions/checkout@v4 50 | with: 51 | submodules: recursive 52 | 53 | - name: Cache Rex build directory 54 | uses: actions/cache@v3 55 | with: 56 | path: build 57 | key: ${{ runner.os }}-${{ runner.name }}-meson-${{ hashFiles('rex-native.ini', 'meson.build') }} 58 | 59 | - name: Setup Rex build directory 60 | run: meson setup --native-file rex-native.ini --reconfigure ./build 61 | 62 | - name: Compile Rex deps 63 | run: meson compile -C build build_deps 64 | 65 | - name: Compile Rex samples 66 | run: meson compile -C build 67 | 68 | - name: Run Rex sanity tests 69 | run: meson test -C build 70 | 71 | build_with_nix: 72 | needs: changes 73 | if: ${{ needs.changes.outputs.nix == 'true' }} 74 | runs-on: [self-hosted, nix] 75 | steps: 76 | - name: Checkout repository 77 | uses: actions/checkout@v4 78 | with: 79 | submodules: recursive 80 | 81 | - name: Setup Rex build directory 82 | run: meson setup --native-file rex-native.ini --reconfigure ./build 83 | shell: nix develop -v -L .#rex --command bash -e {0} 84 | 85 | - name: Compile Rex deps 86 | run: meson compile -C build build_deps 87 | shell: nix develop -v -L .#rex --command bash -e {0} 88 | 89 | - name: Compile Rex samples 90 | run: meson compile -C build 91 | shell: nix develop -v -L .#rex --command bash -e {0} 92 | -------------------------------------------------------------------------------- /.github/workflows/rustfmt.yml: -------------------------------------------------------------------------------- 1 | name: Formatting check 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | formatting: 9 | if: github.repository == 'rex-rs/rex' 10 | name: cargo fmt 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: switch rust nightly 15 | run: | 16 | rustup default nightly 17 | rustup component add rustfmt 18 | - name: formatting rex code 19 | run: cargo fmt --verbose --check 20 | - name: formatting samples code 21 | run: | 22 | for d in $(find ./samples -name Cargo.toml); do 23 | echo "→ Processing $d" 24 | cargo fmt --manifest-path $d --verbose --check 25 | done 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode* 2 | .cargo 3 | !samples/*/.cargo 4 | !tools/*/.cargo 5 | samples/*/event-trigger 6 | samples/*/loader 7 | samples/*/entry 8 | samples/*/.cache 9 | test_dict.yml.zst 10 | bench_entries.yml.zst 11 | compile_commands.json 12 | !rex/.cargo 13 | 14 | # Generated by Cargo 15 | # will have compiled files and executables 16 | target/ 17 | .direnv 18 | .envrc 19 | .cache 20 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "linux"] 2 | path = linux 3 | url = git@github.com:rex-rs/linux.git 4 | branch = rex-linux 5 | [submodule "rust"] 6 | path = rust 7 | url = git@github.com:rex-rs/rust.git 8 | branch = rex-rust 9 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "2.0.101" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 75 | dependencies = [ 76 | "proc-macro2", 77 | "quote", 78 | "unicode-ident", 79 | ] 80 | 81 | [[package]] 82 | name = "unicode-ident" 83 | version = "1.0.18" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 86 | 87 | [[package]] 88 | name = "version_check" 89 | version = "0.9.5" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 92 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | # rex lib 4 | "rex", 5 | 6 | # macros 7 | "rex-macros", 8 | ] 9 | 10 | resolver = "2" 11 | exclude = ["./samples/", "./rust/", "./tools/", "./scripts/"] 12 | 13 | [workspace.package] 14 | authors = ["Rex Contributors"] 15 | repository = "https://github.com/rex-rs/rex" 16 | edition = "2021" 17 | 18 | [workspace.dependencies] 19 | proc-macro-error = { version = "1.0", default-features = false } 20 | proc-macro2 = { version = "1", default-features = false } 21 | paste = { version = "1" } 22 | syn = { version = "2", features = ["full"] } 23 | quote = { version = "1" } 24 | rex-macros = { path = "./rex-macros" } 25 | 26 | [profile.dev] 27 | debug = 0 28 | panic = "abort" 29 | 30 | [profile.release] 31 | debug = 0 32 | panic = "abort" 33 | lto = true 34 | -------------------------------------------------------------------------------- /docs/hotos23.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rex-rs/rex/ea00cda125fa0368cdc8e0744f2d73fdf32cebfb/docs/hotos23.pdf -------------------------------------------------------------------------------- /docs/image/xdp-attach-point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rex-rs/rex/ea00cda125fa0368cdc8e0744f2d73fdf32cebfb/docs/image/xdp-attach-point.png -------------------------------------------------------------------------------- /docs/librex.md: -------------------------------------------------------------------------------- 1 | # LIBREX 2 | 3 | `librex` serves as the loader library for Rex programs -- similar to what 4 | `libbpf` is to eBPF programs -- but in a simpler way. 5 | 6 | ### APIs 7 | 8 | `librex` only contains the code that loads Rex programs from ELF binaries, 9 | other operations (e.g., attachment, map manipulation, etc) are delegated to 10 | the existing code in `libbpf`. 11 | 12 | Therefore, the library only exposes the following simple APIs: 13 | ```c 14 | struct rex_obj *rex_obj_load(const char *file_path); 15 | struct bpf_object *rex_obj_get_bpf(struct rex_obj *obj); 16 | void rex_set_debug(int val); 17 | ``` 18 | 19 | The `rex_obj_load` function loads the Rex programs from the ELF binary 20 | identified by the `file_path` argument into the kernel. It returns a 21 | pointer to the corresponding `rex_obj` that encapsulates information about 22 | the loaded programs and created maps. If there is an error, a null pointer 23 | is returned. 24 | 25 | The `rex_obj_get_bpf` returns a pointer to the equivalent `bpf_object` of 26 | the `obj` argument, which can be subsequently passed to `libbpf` APIs. If 27 | there is an error, a null pointer is returned. 28 | 29 | **Note**: The returned pointer from both functions above are **non-owning** 30 | pointers, which means the caller of these function should not try to 31 | `free`/`realloc`/`delete` the pointer. The ownership of the pointers is 32 | managed by `librex` internally and will be automatically freed after the 33 | program terminates. 34 | 35 | The `rex_set_debug` function can be used to toggle the internal logging 36 | mechanism of `librex` (with `(bool)val` determining whether logging is 37 | enabled). This will most likely be helpful during debugging. 38 | 39 | ### Build 40 | 41 | Building `librex` requires a `c++23` compatible compiler and the `mold` 42 | linker. With dependencies installed, simply invoke the Makefile: 43 | 44 | ```bash 45 | make 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/rex-paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rex-rs/rex/ea00cda125fa0368cdc8e0744f2d73fdf32cebfb/docs/rex-paper.pdf -------------------------------------------------------------------------------- /docs/rust_rex_subset.md: -------------------------------------------------------------------------------- 1 | ### Rex subset of Rust 2 | 3 | - `std` 4 | - depends on libc, therefore not available in standalone mode 5 | - `alloc` 6 | - Rex currently does not hook onto kernel's allocator 7 | - unsafe 8 | - can break any safety guarrantee 9 | - `core::mem::forget` and `core::mem::ManuallyDrop` 10 | - take ownership and “forget” about the value **without running its 11 | destructor**. 12 | - lifetime related: disrupts resource cleanup 13 | - `core::intrinsics::abort`: 14 | - uses an illegal instruction and therefore can crash the kernel. 15 | - `core::simd` 16 | - no simd/fp allowed in the kernel in the first place 17 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1745526057, 6 | "narHash": "sha256-ITSpPDwvLBZBnPRS2bUcHY3gZSwis/uTe255QgMtTLA=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "f771eb401a46846c1aebd20552521b233dd7e18b", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "ref": "nixos-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /librex/.gitignore: -------------------------------------------------------------------------------- 1 | librex.a 2 | librex.o 3 | librex.so 4 | .cache 5 | -------------------------------------------------------------------------------- /librex/README.md: -------------------------------------------------------------------------------- 1 | ../docs/librex.md -------------------------------------------------------------------------------- /librex/include/librex.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBREX_H 2 | #define LIBREX_H 3 | 4 | struct bpf_object; 5 | struct rex_obj; 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | [[gnu::visibility("default")]] void rex_set_debug(int val); 12 | 13 | [[nodiscard, gnu::visibility("default")]] struct rex_obj * 14 | rex_obj_load(const char *file_path); 15 | 16 | [[nodiscard, gnu::visibility("default")]] struct bpf_object * 17 | rex_obj_get_bpf(struct rex_obj *obj); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif // LIBREX_H 24 | -------------------------------------------------------------------------------- /librex/meson.build: -------------------------------------------------------------------------------- 1 | rex_rootdir = '..' 2 | 3 | llvm_dep = dependency('llvm', version : '>=18') 4 | elf_dep = dependency('libelf') 5 | 6 | librex_public_inc = include_directories('include') 7 | 8 | librex_sources = [ 9 | 'lib/librex.cpp' 10 | ] 11 | 12 | librex = library( 13 | 'rex', 14 | librex_sources, 15 | cpp_args: ['-Wno-missing-designated-field-initializers'], 16 | build_rpath: join_paths(meson.project_source_root(), 'linux/tools/lib/bpf'), 17 | build_by_default: false, 18 | dependencies: [elf_dep, llvm_dep, kernel_dep, libbpf_dep], 19 | gnu_symbol_visibility: 'hidden', 20 | include_directories: librex_public_inc, 21 | pic: true 22 | ) 23 | 24 | librex_dep = declare_dependency( 25 | link_with: librex, 26 | include_directories: librex_public_inc 27 | ) 28 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('rex-compile', 2 | ['c', 'cpp'], 3 | version: '0.1.0', 4 | default_options : [ 5 | 'buildtype=debugoptimized', 6 | 'warning_level=2', 7 | 'werror=true', 8 | 'b_lto=true', 9 | 'b_lto_mode=thin', 10 | 'b_pie=true', 11 | 'c_std=gnu23', 12 | 'cpp_std=c++23' 13 | ] 14 | ) 15 | 16 | add_project_arguments( 17 | [ 18 | '-pipe', 19 | '-march=native', 20 | '-ffunction-sections', 21 | '-fdata-sections', 22 | '-fno-semantic-interposition' 23 | ], 24 | language: ['c', 'cpp'] 25 | ) 26 | 27 | add_project_link_arguments( 28 | [ 29 | '-Wl,-O1', 30 | '-Wl,--gc-sections', 31 | '-Wl,-z,now', 32 | '-Wl,-z,relro' 33 | ], 34 | language: ['c', 'cpp'] 35 | ) 36 | 37 | bindgen = find_program('bindgen') 38 | cmake = find_program('cmake') 39 | ninja = find_program('ninja') 40 | perl = find_program('perl') 41 | python3_bin = find_program('python3', version: '>=3.11') 42 | realpath = find_program('realpath') 43 | lld = find_program('ld.lld') 44 | bc = find_program('bc') 45 | flex = find_program('flex') 46 | bison = find_program('bison') 47 | 48 | subdir('linux') 49 | subdir('librex') 50 | 51 | rust_bootstrap_config = files('./rust/rex-config.toml') 52 | rust_bootstrap = custom_target( 53 | 'rust', 54 | output : ['cargo', 'rustc'], 55 | command: [ 56 | python3_bin, '@SOURCE_ROOT@/rust/x.py', 'install', 57 | '--config=@SOURCE_ROOT@/rust/rex-config.toml', 58 | '--build-dir=@OUTDIR@/rust-build', 59 | '--set', 'install.prefix=@OUTDIR@/rust-dist' 60 | ], 61 | console: true, 62 | build_by_default: false 63 | ) 64 | 65 | all_programs = custom_target('build_deps', 66 | output: ['kernel', 'kernel_libbpf', 'rust'], 67 | command: ['echo', 'Build all depends'], 68 | depends: [kernel_build, kernel_libbpf, rust_bootstrap], 69 | console: true 70 | ) 71 | 72 | rust_bin = join_paths(meson.current_build_dir(), 'rust-dist/bin') 73 | cargo_wrapper = join_paths(meson.project_source_root(), 'scripts/cargo-wrapper.pl') 74 | sanity_test_scripts = join_paths(meson.project_source_root(), 'scripts/sanity_tests/run_tests.py') 75 | 76 | runtest_deps = [] 77 | 78 | subdir('samples') 79 | subdir('rex') 80 | -------------------------------------------------------------------------------- /rex-macros/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | -------------------------------------------------------------------------------- /rex-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rex-macros" 3 | version = "0.2.0" 4 | repository.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [lib] 11 | proc-macro = true 12 | 13 | [dependencies] 14 | syn = { workspace = true } 15 | quote = { workspace = true } 16 | proc-macro-error = { workspace = true } 17 | proc-macro2 = { workspace = true } 18 | 19 | -------------------------------------------------------------------------------- /rex-macros/src/args.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use proc_macro2::TokenStream; 4 | use proc_macro_error::abort; 5 | use syn::spanned::Spanned; 6 | use syn::{parse_str, Expr, ExprAssign, Lit, LitStr, Result}; 7 | 8 | macro_rules! pop_string_args { 9 | ($self:expr, $key:expr) => { 10 | $self.get($key).map(|v| v.value()) 11 | }; 12 | } 13 | 14 | pub(crate) fn parse_string_args( 15 | input: TokenStream, 16 | ) -> Result> { 17 | let parsed: syn::ExprArray = parse_str(&format!("[{}]", input))?; 18 | let mut map = HashMap::new(); 19 | 20 | // Iterate over the expressions and extract key-value pairs 21 | let parse_and_insert = |expr| { 22 | let Expr::Assign(ExprAssign { left, right, .. }) = expr else { 23 | return; 24 | }; 25 | let Expr::Path(path) = *left else { return }; 26 | let Some(ident) = path.path.get_ident() else { 27 | return; 28 | }; 29 | 30 | let key = ident.to_string(); 31 | let value = match *right { 32 | Expr::Lit(syn::ExprLit { 33 | lit: Lit::Str(lit_str), 34 | .. 35 | }) => lit_str, 36 | _ => { 37 | abort!(input.span(), "Macro processing failed, please follow the syntax `key` = `value`"); 38 | } 39 | }; 40 | map.insert(key, value); 41 | }; 42 | 43 | parsed.elems.into_iter().for_each(parse_and_insert); 44 | 45 | // println!("{:?}", map); 46 | Ok(map) 47 | } 48 | -------------------------------------------------------------------------------- /rex-macros/src/kprobe.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use proc_macro2::TokenStream; 4 | use quote::{format_ident, quote}; 5 | use syn::{parse2, ItemFn, Result}; 6 | 7 | use crate::args::parse_string_args; 8 | 9 | #[allow(dead_code)] 10 | pub enum KprobeFlavor { 11 | Kprobe, 12 | Kretprobe, 13 | Uprobe, 14 | Uretprobe, 15 | } 16 | 17 | impl fmt::Display for KprobeFlavor { 18 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19 | match self { 20 | KprobeFlavor::Kprobe => write!(f, "kprobe"), 21 | KprobeFlavor::Kretprobe => write!(f, "kretprobe"), 22 | KprobeFlavor::Uprobe => write!(f, "uprobe"), 23 | KprobeFlavor::Uretprobe => write!(f, "uretprobe"), 24 | } 25 | } 26 | } 27 | 28 | pub(crate) struct KProbe { 29 | function: Option, 30 | item: ItemFn, 31 | } 32 | 33 | impl KProbe { 34 | // parse the argument of function 35 | pub(crate) fn parse( 36 | attrs: TokenStream, 37 | item: TokenStream, 38 | ) -> Result { 39 | let item: ItemFn = parse2(item)?; 40 | let args = parse_string_args(attrs)?; 41 | 42 | let function = pop_string_args!(args, "function"); 43 | 44 | Ok(KProbe { function, item }) 45 | } 46 | 47 | pub(crate) fn expand(&self, flavor: KprobeFlavor) -> Result { 48 | let fn_name = self.item.sig.ident.clone(); 49 | let item = &self.item; 50 | let function_name = format!("{}", fn_name); 51 | let prog_ident = 52 | format_ident!("PROG_{}", fn_name.to_string().to_uppercase()); 53 | 54 | let attached_function = if self.function.is_some() { 55 | format!("rex/{}/{}", flavor, self.function.as_ref().unwrap()) 56 | } else { 57 | format!("rex/{}", flavor) 58 | }; 59 | 60 | let function_body_tokens = quote! { 61 | #[inline(always)] 62 | #item 63 | 64 | #[used] 65 | #[unsafe(link_section = #attached_function)] 66 | static #prog_ident: kprobe = 67 | kprobe::new(#fn_name, #function_name); 68 | }; 69 | 70 | Ok(function_body_tokens) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /rex-macros/src/perf_event.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::{format_ident, quote}; 3 | use syn::{ItemFn, Result}; 4 | 5 | pub(crate) struct PerfEvent { 6 | item: ItemFn, 7 | } 8 | 9 | impl PerfEvent { 10 | // parse the argument of function 11 | pub(crate) fn parse( 12 | _: TokenStream, 13 | item: TokenStream, 14 | ) -> Result { 15 | let item = syn::parse2(item)?; 16 | Ok(PerfEvent { item }) 17 | } 18 | 19 | pub(crate) fn expand(&self) -> Result { 20 | // TODO: section may update in the future 21 | let fn_name = self.item.sig.ident.clone(); 22 | let item = &self.item; 23 | let function_name = format!("{}", fn_name); 24 | let prog_ident = 25 | format_ident!("PROG_{}", fn_name.to_string().to_uppercase()); 26 | 27 | let function_body_tokens = quote! { 28 | #[inline(always)] 29 | #item 30 | 31 | #[used] 32 | #[unsafe(link_section = "rex/perf_event")] 33 | static #prog_ident: perf_event = 34 | perf_event::new(#fn_name, #function_name); 35 | }; 36 | Ok(function_body_tokens) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /rex-macros/src/tc.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::{format_ident, quote}; 3 | use syn::{ItemFn, Result}; 4 | 5 | pub(crate) struct SchedCls { 6 | item: ItemFn, 7 | } 8 | 9 | impl SchedCls { 10 | // parse the argument of function 11 | pub(crate) fn parse(_: TokenStream, item: TokenStream) -> Result { 12 | let item = syn::parse2(item)?; 13 | Ok(SchedCls { item }) 14 | } 15 | 16 | // expand the function into two function with original function 17 | // #[entry_link(inner_unikernel/tc)] 18 | // static PROG2: sched_cls = sched_cls::new( 19 | // xdp_tx_filter, 20 | // "xdp_tx_filter", 21 | // BPF_PROG_TYPE_SCHED_CLS as u64, 22 | // ); 23 | pub(crate) fn expand(&self) -> Result { 24 | // TODO: section may update in the future 25 | let fn_name = self.item.sig.ident.clone(); 26 | let item = &self.item; 27 | let function_name = format!("{}", fn_name); 28 | let prog_ident = 29 | format_ident!("PROG_{}", fn_name.to_string().to_uppercase()); 30 | 31 | let function_body_tokens = quote! { 32 | #[inline(always)] 33 | #item 34 | 35 | #[used] 36 | #[unsafe(link_section = "rex/tc")] 37 | static #prog_ident: sched_cls = 38 | sched_cls::new(#fn_name, #function_name); 39 | }; 40 | Ok(function_body_tokens) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /rex-macros/src/xdp.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::{format_ident, quote}; 3 | use syn::{ItemFn, Result}; 4 | 5 | pub(crate) struct Xdp { 6 | item: ItemFn, 7 | } 8 | 9 | impl Xdp { 10 | // parse the argument of function 11 | pub(crate) fn parse(_: TokenStream, item: TokenStream) -> Result { 12 | let item = syn::parse2(item)?; 13 | Ok(Xdp { item }) 14 | } 15 | 16 | // expand the function into two function with original function 17 | // #[entry_link(inner_unikernel/xdp)] 18 | // static PROG1: xdp = 19 | // xdp::new(xdp_rx_filter_fn, "xdp_rx_filter", BPF_PROG_TYPE_XDP as u64); 20 | pub(crate) fn expand(&self) -> Result { 21 | // TODO: section may update in the future 22 | let fn_name = self.item.sig.ident.clone(); 23 | let item = &self.item; 24 | let function_name = format!("{}", fn_name); 25 | let prog_ident = 26 | format_ident!("PROG_{}", fn_name.to_string().to_uppercase()); 27 | 28 | let function_body_tokens = quote! { 29 | #[inline(always)] 30 | #item 31 | 32 | #[used] 33 | #[unsafe(link_section = "rex/xdp")] 34 | static #prog_ident: xdp = 35 | xdp::new(#fn_name, #function_name); 36 | }; 37 | Ok(function_body_tokens) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /rex-native.ini: -------------------------------------------------------------------------------- 1 | [binaries] 2 | c = 'clang' 3 | c_ld = 'mold' 4 | cpp = 'clang++' 5 | cpp_ld = 'mold' 6 | ar = 'llvm-ar' 7 | 8 | -------------------------------------------------------------------------------- /rex/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /rex/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | libiustub/libiustub.so 4 | -------------------------------------------------------------------------------- /rex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rex" 3 | version = "0.2.0" 4 | build = "build.rs" 5 | autotests = false 6 | repository.workspace = true 7 | edition.workspace = true 8 | authors.workspace = true 9 | 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [lib] 14 | test = false 15 | doctest = false 16 | 17 | [dependencies] 18 | paste = { workspace = true } 19 | rex-macros = { workspace = true } 20 | 21 | [features] 22 | default = ["debug_printk"] 23 | debug_printk = [] 24 | 25 | [rex] 26 | uheaders = [ 27 | "linux/bpf.h", 28 | "linux/errno.h", 29 | "linux/in.h", 30 | "linux/perf_event.h", 31 | "linux/pkt_cls.h", 32 | "linux/ptrace.h", 33 | "linux/seccomp.h", 34 | "linux/unistd.h", 35 | ] 36 | 37 | kheaders = [ 38 | "linux/filter.h", 39 | "linux/gfp_types.h", 40 | "linux/if_ether.h", 41 | "linux/ip.h", 42 | "linux/kcsan.h", 43 | "linux/perf_event.h", 44 | "linux/prandom.h", 45 | "linux/sched.h", 46 | "linux/seqlock.h", 47 | "linux/skbuff.h", 48 | "linux/tcp.h", 49 | "linux/timekeeper_internal.h", 50 | "linux/udp.h", 51 | "net/xdp.h", 52 | ] 53 | 54 | kconfigs = ["CONFIG_BPF_KPROBE_OVERRIDE", "CONFIG_KALLSYMS_ALL"] 55 | -------------------------------------------------------------------------------- /rex/build.rs: -------------------------------------------------------------------------------- 1 | #![feature(exit_status_error)] 2 | 3 | use std::io::Result; 4 | use std::path::Path; 5 | use std::process::Command; 6 | use std::string::String; 7 | use std::{env, fs}; 8 | 9 | fn main() -> Result<()> { 10 | let out_dir = env::var("OUT_DIR").unwrap(); 11 | let linux_obj = env::var("LINUX_OBJ").unwrap(); 12 | let linux_src = env::var("LINUX_SRC").unwrap(); 13 | 14 | let output = Command::new("python3") 15 | .arg("build.py") 16 | .arg(&linux_obj) 17 | .arg(&linux_src) 18 | .arg(&out_dir) 19 | .output()?; 20 | 21 | output 22 | .status 23 | .exit_ok() 24 | .map(|_| print!("{}", String::from_utf8_lossy(&output.stdout))) 25 | .map_err(|_| panic!("\n{}", String::from_utf8_lossy(&output.stderr))) 26 | .unwrap(); 27 | 28 | let mut rexstub_outdir = Path::new(&out_dir).join("librexstub"); 29 | if !rexstub_outdir.exists() { 30 | fs::create_dir(&rexstub_outdir)?; 31 | } 32 | 33 | let rexstub_so = rexstub_outdir.join("librexstub.so"); 34 | Command::new("clang") 35 | .arg("-fPIC") 36 | .arg("-nostartfiles") 37 | .arg("-nodefaultlibs") 38 | .arg("--shared") 39 | .arg("-o") 40 | .arg(rexstub_so.to_string_lossy().to_mut()) 41 | .arg("./librexstub/lib.c") 42 | .output()?; 43 | 44 | rexstub_outdir = rexstub_outdir.canonicalize()?; 45 | 46 | println!("cargo:rerun-if-changed=Cargo.toml"); 47 | println!("cargo:rerun-if-changed=./src/*"); 48 | println!("cargo:rerun-if-changed=./librexstub/*"); 49 | println!("cargo:rustc-link-lib=dylib=rexstub"); 50 | println!( 51 | "cargo:rustc-link-search=native={}", 52 | rexstub_outdir.to_string_lossy() 53 | ); 54 | 55 | Ok(()) 56 | } 57 | -------------------------------------------------------------------------------- /rex/librexstub/lib.c: -------------------------------------------------------------------------------- 1 | // Functions 2 | #define KSYM_FUNC(func) \ 3 | int func() { return 0; } 4 | 5 | KSYM_FUNC(bpf_get_current_pid_tgid) 6 | KSYM_FUNC(bpf_trace_printk) 7 | KSYM_FUNC(bpf_map_lookup_elem) 8 | KSYM_FUNC(bpf_map_update_elem) 9 | KSYM_FUNC(bpf_map_delete_elem) 10 | KSYM_FUNC(bpf_map_push_elem) 11 | KSYM_FUNC(bpf_map_pop_elem) 12 | KSYM_FUNC(bpf_map_peek_elem) 13 | KSYM_FUNC(bpf_probe_read_kernel) 14 | KSYM_FUNC(ktime_get_mono_fast_ns) 15 | KSYM_FUNC(ktime_get_boot_fast_ns) 16 | KSYM_FUNC(get_random_u32) 17 | KSYM_FUNC(bpf_snprintf) 18 | KSYM_FUNC(vprintk) 19 | KSYM_FUNC(rex_landingpad) 20 | KSYM_FUNC(bpf_spin_lock) 21 | KSYM_FUNC(bpf_spin_unlock) 22 | KSYM_FUNC(just_return_func) 23 | KSYM_FUNC(bpf_get_stackid_pe) 24 | KSYM_FUNC(bpf_perf_prog_read_value) 25 | KSYM_FUNC(bpf_perf_event_output_tp) 26 | KSYM_FUNC(bpf_perf_event_read_value) 27 | KSYM_FUNC(bpf_skb_event_output) 28 | KSYM_FUNC(bpf_xdp_event_output) 29 | KSYM_FUNC(bpf_xdp_adjust_head) 30 | KSYM_FUNC(bpf_xdp_adjust_tail) 31 | KSYM_FUNC(bpf_clone_redirect) 32 | KSYM_FUNC(bpf_ringbuf_output) 33 | KSYM_FUNC(bpf_ringbuf_reserve) 34 | KSYM_FUNC(bpf_ringbuf_submit) 35 | KSYM_FUNC(bpf_ringbuf_discard) 36 | KSYM_FUNC(bpf_ringbuf_query) 37 | KSYM_FUNC(bpf_ktime_get_ns) 38 | KSYM_FUNC(bpf_ktime_get_boot_ns) 39 | KSYM_FUNC(bpf_ktime_get_coarse_ns) 40 | KSYM_FUNC(rex_trace_printk) 41 | 42 | // Global variables 43 | unsigned long jiffies; 44 | int numa_node; 45 | void *rex_cleanup_entries; 46 | unsigned long rex_stack_ptr; 47 | void *current_task; 48 | int cpu_number; 49 | unsigned char rex_termination_state; 50 | unsigned long this_cpu_off; 51 | char *rex_log_buf; 52 | -------------------------------------------------------------------------------- /rex/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | rex_build = custom_target( 17 | 'rex-build', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'rustc', '-qr', '--', 24 | '-Cenable_rex' 25 | ], 26 | env: env, 27 | console: false, 28 | build_always_stale: true, 29 | build_by_default: false 30 | ) 31 | -------------------------------------------------------------------------------- /rex/src/bindings/linux/kernel.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/linux/kernel.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/linux/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod kernel; 2 | -------------------------------------------------------------------------------- /rex/src/bindings/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals, unused)] 2 | 3 | pub(crate) mod linux; 4 | pub mod uapi; 5 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/bpf.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/bpf.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/errno.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/errno.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/in.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/in.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bpf; 2 | pub mod errno; 3 | pub mod r#in; 4 | pub mod perf_event; 5 | pub mod pkt_cls; 6 | pub mod ptrace; 7 | pub mod seccomp; 8 | pub mod unistd; 9 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/perf_event.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/perf_event.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/pkt_cls.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/pkt_cls.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/ptrace.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/ptrace.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/seccomp.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/seccomp.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/linux/unistd.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/uapi/linux/unistd.rs")); 2 | -------------------------------------------------------------------------------- /rex/src/bindings/uapi/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod linux; 2 | -------------------------------------------------------------------------------- /rex/src/debug.rs: -------------------------------------------------------------------------------- 1 | use core::ffi::{c_int, c_uchar}; 2 | 3 | use crate::ffi; 4 | 5 | // WARN must add "\0" at the end of &str, c_str is different from rust str 6 | #[allow(improper_ctypes_definitions)] 7 | #[unsafe(no_mangle)] 8 | pub(crate) unsafe extern "C" fn printk(fmt: &str, mut ap: ...) -> c_int { 9 | unsafe { ffi::vprintk(fmt.as_ptr() as *const c_uchar, ap.as_va_list()) } 10 | } 11 | -------------------------------------------------------------------------------- /rex/src/kprobe/kprobe_impl.rs: -------------------------------------------------------------------------------- 1 | use crate::bindings::uapi::linux::bpf::{bpf_map_type, BPF_PROG_TYPE_KPROBE}; 2 | use crate::prog_type::rex_prog; 3 | use crate::pt_regs::PtRegs; 4 | use crate::task_struct::TaskStruct; 5 | use crate::{ffi, Result}; 6 | 7 | /// First 3 fields should always be rtti, prog_fn, and name 8 | /// 9 | /// rtti should be u64, therefore after compiling the 10 | /// packed struct type rustc generates for LLVM does 11 | /// not additional padding after rtti 12 | /// 13 | /// prog_fn should have &Self as its first argument 14 | /// 15 | /// name is a &'static str 16 | #[repr(C)] 17 | pub struct kprobe { 18 | rtti: u64, 19 | prog: fn(&Self, &mut PtRegs) -> Result, 20 | name: &'static str, 21 | } 22 | 23 | impl kprobe { 24 | crate::base_helper::base_helper_defs!(); 25 | 26 | pub const fn new( 27 | f: fn(&kprobe, &mut PtRegs) -> Result, 28 | nm: &'static str, 29 | ) -> kprobe { 30 | Self { 31 | rtti: BPF_PROG_TYPE_KPROBE as u64, 32 | prog: f, 33 | name: nm, 34 | } 35 | } 36 | 37 | // Now returns a mutable ref, but since every reg is private the user prog 38 | // cannot change reg contents. The user should not be able to directly 39 | // assign this reference a new value either, given that they will not able 40 | // to create another instance of pt_regs (private fields, no pub ctor) 41 | fn convert_ctx(&self, ctx: *mut ()) -> &'static mut PtRegs { 42 | // ctx has actual type *mut crate::bindings::linux::kernel::pt_regs 43 | // therefore it is safe to just interpret it as a *mut pt_regs 44 | // since the later is #[repr(transparent)] over the former 45 | unsafe { &mut *(ctx as *mut PtRegs) } 46 | } 47 | 48 | #[cfg(CONFIG_BPF_KPROBE_OVERRIDE = "y")] 49 | pub fn bpf_override_return(&self, regs: &mut PtRegs, rc: u64) -> i32 { 50 | regs.regs.ax = rc; 51 | regs.regs.ip = ffi::just_return_func as *const () as u64; 52 | 0 53 | } 54 | 55 | pub fn bpf_get_current_task(&self) -> Option { 56 | TaskStruct::get_current_task() 57 | } 58 | } 59 | 60 | impl rex_prog for kprobe { 61 | fn prog_run(&self, ctx: *mut ()) -> u32 { 62 | let newctx = self.convert_ctx(ctx); 63 | ((self.prog)(self, newctx)).unwrap_or_else(|e| e) as u32 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /rex/src/kprobe/mod.rs: -------------------------------------------------------------------------------- 1 | mod kprobe_impl; 2 | 3 | pub use kprobe_impl::*; 4 | -------------------------------------------------------------------------------- /rex/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature( 3 | array_ptr_get, 4 | auto_traits, 5 | c_variadic, 6 | core_intrinsics, 7 | negative_impls 8 | )] 9 | #![allow(non_camel_case_types, internal_features)] 10 | 11 | pub mod kprobe; 12 | pub mod map; 13 | pub mod perf_event; 14 | pub mod prog_type; 15 | pub mod pt_regs; 16 | pub mod sched_cls; 17 | pub mod spinlock; 18 | pub mod task_struct; 19 | pub mod tracepoint; 20 | pub mod utils; 21 | pub mod xdp; 22 | 23 | mod base_helper; 24 | mod bindings; 25 | mod debug; 26 | mod ffi; 27 | mod log; 28 | mod panic; 29 | mod per_cpu; 30 | mod random32; 31 | 32 | extern crate paste; 33 | 34 | use paste::paste; 35 | pub use rex_macros::*; 36 | 37 | use crate::prog_type::rex_prog; 38 | 39 | #[cfg(not(CONFIG_KALLSYMS_ALL = "y"))] 40 | compile_error!("CONFIG_KALLSYMS_ALL is required for rex"); 41 | 42 | macro_rules! define_prog_entry { 43 | ($prog_ty:ident) => { 44 | paste! { 45 | #[unsafe(no_mangle)] 46 | #[inline(always)] 47 | fn [<__rex_entry_ $prog_ty>]( 48 | prog: &$prog_ty::$prog_ty, 49 | ctx: *mut (), 50 | ) -> u32 { 51 | prog.prog_run(ctx) 52 | } 53 | } 54 | }; 55 | } 56 | 57 | define_prog_entry!(kprobe); 58 | define_prog_entry!(perf_event); 59 | define_prog_entry!(xdp); 60 | define_prog_entry!(sched_cls); 61 | 62 | pub use bindings::uapi::*; 63 | pub use log::rex_trace_printk; 64 | pub use utils::Result; 65 | -------------------------------------------------------------------------------- /rex/src/perf_event/mod.rs: -------------------------------------------------------------------------------- 1 | mod perf_event_impl; 2 | 3 | pub use perf_event_impl::*; 4 | -------------------------------------------------------------------------------- /rex/src/prog_type.rs: -------------------------------------------------------------------------------- 1 | pub trait rex_prog { 2 | fn prog_run(&self, ctx: *mut ()) -> u32; 3 | } 4 | -------------------------------------------------------------------------------- /rex/src/pt_regs.rs: -------------------------------------------------------------------------------- 1 | use paste::paste; 2 | 3 | use crate::bindings::linux::kernel::pt_regs; 4 | 5 | /// Transparently wraps around the kernel-internal `struct pt_regs` and make the 6 | /// fields read-only to prevent user-defined code from modifying the registers 7 | #[repr(transparent)] 8 | pub struct PtRegs { 9 | pub(crate) regs: pt_regs, 10 | } 11 | 12 | macro_rules! decl_reg_accessors_1 { 13 | ($t:ident $($ts:ident)*) => { 14 | #[inline(always)] 15 | pub fn $t(&self) -> u64 { 16 | self.regs.$t 17 | } 18 | decl_reg_accessors_1!($($ts)*); 19 | }; 20 | () => {}; 21 | } 22 | 23 | macro_rules! decl_reg_accessors_2 { 24 | ($t:ident $($ts:ident)*) => { 25 | paste! { 26 | #[inline(always)] 27 | pub fn [](&self) -> u64 { 28 | self.regs.$t 29 | } 30 | } 31 | decl_reg_accessors_2!($($ts)*); 32 | }; 33 | () => {}; 34 | } 35 | 36 | macro_rules! decl_reg_accessors { 37 | ($t1:ident $($ts1:ident)*, $t2:ident $($ts2:ident)*) => { 38 | // regs that does not require special handling 39 | decl_reg_accessors_1!($t1 $($ts1)*); 40 | // regs that does not have the 'r' prefix in kernel pt_regs 41 | decl_reg_accessors_2!($t2 $($ts2)*); 42 | } 43 | } 44 | 45 | impl PtRegs { 46 | decl_reg_accessors!(r15 r14 r13 r12 r11 r10 r9 r8, 47 | bp bx ax cx dx si di ip sp); 48 | 49 | // orig_rax cs eflags ss cannot be batch-processed by macros 50 | #[inline(always)] 51 | pub fn orig_rax(&self) -> u64 { 52 | self.regs.orig_ax 53 | } 54 | 55 | #[inline(always)] 56 | pub fn cs(&self) -> u64 { 57 | unsafe { self.regs.__bindgen_anon_1.cs as u64 } 58 | } 59 | 60 | #[inline(always)] 61 | pub fn eflags(&self) -> u64 { 62 | self.regs.flags 63 | } 64 | 65 | #[inline(always)] 66 | pub fn ss(&self) -> u64 { 67 | unsafe { self.regs.__bindgen_anon_2.ss as u64 } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /rex/src/random32.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi; 2 | 3 | // fn get_cpu_var() 4 | #[inline(always)] 5 | pub(crate) fn bpf_user_rnd_u32() -> u32 { 6 | // directly use get_random_u32 7 | unsafe { ffi::get_random_u32() } 8 | } 9 | -------------------------------------------------------------------------------- /rex/src/sched_cls/mod.rs: -------------------------------------------------------------------------------- 1 | // mod binding; 2 | mod sched_cls_impl; 3 | 4 | pub use sched_cls_impl::*; 5 | -------------------------------------------------------------------------------- /rex/src/spinlock.rs: -------------------------------------------------------------------------------- 1 | use crate::base_helper::termination_check; 2 | pub use crate::bindings::uapi::linux::bpf::bpf_spin_lock; 3 | use crate::ffi; 4 | use crate::panic::CleanupEntries; 5 | 6 | /// An RAII implementation of a "scoped lock" of a bpf spinlock. When this 7 | /// structure is dropped (falls out of scope), the lock will be unlocked. 8 | /// 9 | /// Ref: 10 | #[must_use = "if unused the spinlock will immediately unlock"] 11 | #[clippy::has_significant_drop] 12 | pub struct rex_spinlock_guard<'a> { 13 | lock: &'a mut bpf_spin_lock, 14 | cleanup_idx: usize, 15 | } 16 | 17 | impl<'a> rex_spinlock_guard<'a> { 18 | /// Constructor function that locks the spinlock 19 | pub fn new(lock: &'a mut bpf_spin_lock) -> Self { 20 | termination_check!({ 21 | // Put it before lock so if it panics we will not be holding the 22 | // lock without a valid cleanup entry for it 23 | let cleanup_idx = CleanupEntries::register_cleanup( 24 | Self::panic_cleanup, 25 | lock as *mut bpf_spin_lock as *mut (), 26 | ); 27 | 28 | // Lock 29 | unsafe { ffi::bpf_spin_lock(lock) }; 30 | 31 | Self { lock, cleanup_idx } 32 | }) 33 | } 34 | 35 | /// Function that unlocks the spinlock, used by cleanup list and drop 36 | pub(crate) unsafe fn panic_cleanup(lock: *mut ()) { 37 | unsafe { 38 | ffi::bpf_spin_unlock(lock as *mut bpf_spin_lock); 39 | } 40 | } 41 | } 42 | 43 | impl Drop for rex_spinlock_guard<'_> { 44 | /// Unlock the spinlock when the guard is out-of-scope 45 | fn drop(&mut self) { 46 | termination_check!({ 47 | // Put it before unlock so if it panics we will not unlock twice 48 | // (once here in the drop handler, the other in the 49 | // panic handler triggered by this function) 50 | CleanupEntries::deregister_cleanup(self.cleanup_idx); 51 | 52 | // Unlock 53 | unsafe { ffi::bpf_spin_unlock(self.lock) }; 54 | }) 55 | } 56 | } 57 | 58 | /// Unimplement Send and Sync 59 | /// Ref: 60 | impl !Send for rex_spinlock_guard<'_> {} 61 | impl !Sync for rex_spinlock_guard<'_> {} 62 | -------------------------------------------------------------------------------- /rex/src/task_struct.rs: -------------------------------------------------------------------------------- 1 | use core::ffi::{self as core_ffi, CStr}; 2 | 3 | use crate::bindings::linux::kernel::task_struct; 4 | use crate::ffi; 5 | use crate::per_cpu::this_cpu_read; 6 | use crate::pt_regs::PtRegs; 7 | 8 | // Bindgen has problem generating these constants 9 | const TOP_OF_KERNEL_STACK_PADDING: u64 = 0; 10 | const PAGE_SHIFT: u64 = 12; 11 | const PAGE_SIZE: u64 = 1u64 << PAGE_SHIFT; 12 | const THREAD_SIZE_ORDER: u64 = 2; // assume no kasan 13 | const THREAD_SIZE: u64 = PAGE_SIZE << THREAD_SIZE_ORDER; 14 | 15 | pub struct TaskStruct { 16 | // struct task_struct * should always live longer than program execution 17 | // given the RCU read lock 18 | pub(crate) kptr: &'static task_struct, 19 | } 20 | 21 | impl TaskStruct { 22 | #[inline(always)] 23 | pub(crate) const fn new(kp: &'static task_struct) -> Self { 24 | Self { kptr: kp } 25 | } 26 | 27 | pub(crate) fn get_current_task() -> Option { 28 | let current: *mut task_struct = 29 | unsafe { this_cpu_read(&raw const ffi::current_task) }; 30 | 31 | if current.is_null() { 32 | None 33 | } else { 34 | Some(TaskStruct::new(unsafe { &*current })) 35 | } 36 | } 37 | 38 | #[inline(always)] 39 | pub fn get_pid(&self) -> i32 { 40 | self.kptr.pid 41 | } 42 | 43 | #[inline(always)] 44 | pub fn get_tgid(&self) -> i32 { 45 | self.kptr.tgid 46 | } 47 | 48 | // Design decision: the equivalent BPF helper writes the program name to 49 | // a user-provided buffer, here we can take advantage of Rust's ownership by 50 | // just providing a &CStr instead 51 | pub fn get_comm(&self) -> Result<&CStr, core_ffi::FromBytesUntilNulError> { 52 | // casting from c_char to u8 is sound, see: 53 | // https://doc.rust-lang.org/src/core/ffi/c_str.rs.html#264 54 | let comm_bytes = 55 | unsafe { &*(&self.kptr.comm[..] as *const _ as *const [u8]) }; 56 | CStr::from_bytes_until_nul(comm_bytes) 57 | } 58 | 59 | pub fn get_pt_regs(&self) -> &'static PtRegs { 60 | // X86 specific 61 | // stack_top is actually bottom of the kernel stack, it refers to the 62 | // highest address of the stack pages 63 | let stack_top = 64 | self.kptr.stack as u64 + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING; 65 | let reg_addr = stack_top - core::mem::size_of::() as u64; 66 | // The pt_regs should always be on the top of the stack 67 | unsafe { &*(reg_addr as *const PtRegs) } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /rex/src/tracepoint/binding.rs: -------------------------------------------------------------------------------- 1 | #[repr(C)] 2 | #[derive(Debug, Copy, Clone)] 3 | pub struct SyscallsEnterOpenCtx { 4 | unused: u64, 5 | pub syscall_nr: i64, 6 | pub filename_ptr: i64, 7 | pub flags: i64, 8 | pub mode: i64, 9 | } 10 | 11 | #[repr(C)] 12 | #[derive(Debug, Copy, Clone)] 13 | pub struct SyscallsEnterOpenatCtx { 14 | unused: u64, 15 | pub syscall_nr: i64, 16 | pub dfd: i64, 17 | pub filename_ptr: i64, 18 | pub flags: i64, 19 | pub mode: i64, 20 | } 21 | 22 | #[repr(C)] 23 | #[derive(Debug, Copy, Clone)] 24 | pub struct SyscallsExitOpenCtx { 25 | unused: u64, 26 | pub syscall_nr: i64, 27 | pub ret: i64, 28 | } 29 | 30 | #[repr(C)] 31 | #[derive(Debug, Copy, Clone)] 32 | pub struct SyscallsExitOpenatCtx { 33 | unused: u64, 34 | pub syscall_nr: i64, 35 | pub ret: i64, 36 | } 37 | 38 | #[repr(C)] 39 | #[derive(Debug, Copy, Clone)] 40 | pub struct SyscallsEnterDupCtx { 41 | unused: u64, 42 | pub syscall_nr: i64, 43 | pub fildes: u64, 44 | } 45 | 46 | #[repr(C)] 47 | #[derive(Debug, Copy, Clone)] 48 | pub struct RawSyscallsEnterCtx { 49 | unused: u64, 50 | pub id: i64, 51 | pub args: [u64; 6], 52 | } 53 | 54 | #[repr(C)] 55 | #[derive(Debug, Copy, Clone)] 56 | pub struct RawSyscallsExitCtx { 57 | unused: u64, 58 | pub id: i64, 59 | pub ret: i64, 60 | } 61 | -------------------------------------------------------------------------------- /rex/src/tracepoint/mod.rs: -------------------------------------------------------------------------------- 1 | mod binding; 2 | mod tp_impl; 3 | 4 | pub use binding::*; 5 | pub use tp_impl::*; 6 | -------------------------------------------------------------------------------- /rex/src/xdp/mod.rs: -------------------------------------------------------------------------------- 1 | // mod binding; 2 | mod xdp_impl; 3 | 4 | pub use xdp_impl::*; 5 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/.gitignore: -------------------------------------------------------------------------------- 1 | */loader 2 | */event-trigger 3 | */src/linux 4 | */src/stub.rs 5 | */target 6 | */.gdbinit 7 | */.gdb_history 8 | */syscall_tp 9 | -------------------------------------------------------------------------------- /samples/atomic/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/atomic/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "atomic" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/atomic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "atomic" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/atomic/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/atomic/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int nr_rounds, arg, fd; 10 | 11 | if (argc != 3) 12 | asm volatile("ud2"); 13 | 14 | nr_rounds = atoi(argv[1]); 15 | arg = atoi(argv[2]); 16 | fd = open("/proc/kprobe_target", O_RDONLY); 17 | if (fd < 0) { 18 | perror("open"); 19 | return 1; 20 | } 21 | 22 | for (int i = 0; i < nr_rounds; i++) 23 | ioctl(fd, 1313, arg); 24 | 25 | close(fd); 26 | } 27 | -------------------------------------------------------------------------------- /samples/atomic/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define EXE "./target/x86_64-unknown-none/release/atomic" 15 | 16 | int main(void) 17 | { 18 | struct bpf_object *obj; 19 | struct bpf_program *prog; 20 | struct bpf_link *link = NULL; 21 | 22 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 23 | if (!obj) { 24 | fprintf(stderr, "Object could not be opened\n"); 25 | return 1; 26 | } 27 | 28 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 29 | if (!prog) { 30 | fprintf(stderr, "Program not found\n"); 31 | return 1; 32 | } 33 | 34 | link = bpf_program__attach(prog); 35 | if (libbpf_get_error(link)) { 36 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 37 | link = NULL; 38 | return 1; 39 | } 40 | 41 | bpf_link__pin(link, "/sys/fs/bpf/link"); 42 | bpf_link__destroy(link); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /samples/atomic/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'atomic-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'atomic-build', 32 | output: ['atomic'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | -------------------------------------------------------------------------------- /samples/atomic/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/atomic/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | extern crate rex; 4 | 5 | use core::sync::atomic::{AtomicU64, Ordering}; 6 | 7 | use rex::kprobe::*; 8 | use rex::pt_regs::PtRegs; 9 | use rex::{Result, rex_kprobe, rex_printk}; 10 | 11 | static ATOM: AtomicU64 = AtomicU64::new(42); 12 | 13 | #[rex_kprobe(function = "kprobe_target_func")] 14 | fn rex_prog1(obj: &kprobe, _ctx: &mut PtRegs) -> Result { 15 | let random = obj.bpf_get_prandom_u32() as u64; 16 | ATOM.store(random, Ordering::Relaxed); 17 | 18 | let start = obj.bpf_ktime_get_ns(); 19 | let val = ATOM.load(Ordering::Relaxed); 20 | let end = obj.bpf_ktime_get_ns(); 21 | 22 | rex_printk!("Time elapsed: {} {}", end - start, val)?; 23 | 24 | Ok(0) 25 | } 26 | -------------------------------------------------------------------------------- /samples/bmc/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/bmc/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "bmc" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/bmc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bmc" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | 32 | -------------------------------------------------------------------------------- /samples/bmc/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/bmc/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'bmc-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'bmc-build', 32 | output: ['bmc'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'entry', 48 | 'entry.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | -------------------------------------------------------------------------------- /samples/bmc/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/electrode/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/electrode/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "electrode" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/electrode/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "electrode" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [features] 8 | fast_reply = [] 9 | fast_quorum_prune = [] 10 | default = [] 11 | 12 | [dependencies] 13 | 14 | [dependencies.rex] 15 | path = "../../rex" 16 | 17 | [lints.clippy] 18 | disallowed_methods = "forbid" 19 | disallowed_types = "forbid" 20 | 21 | [lints.rust] 22 | incomplete_features = "forbid" 23 | internal_features = "forbid" 24 | unsafe_code = "forbid" 25 | unstable_features = "forbid" 26 | 27 | [profile.dev] 28 | panic = "abort" 29 | debug = false 30 | 31 | [profile.release] 32 | panic = "abort" 33 | debug = false 34 | lto = true 35 | -------------------------------------------------------------------------------- /samples/electrode/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/electrode/config.txt: -------------------------------------------------------------------------------- 1 | f 1 2 | replica 10.10.1.1:12345 3 | replica 10.10.1.2:12345 4 | replica 10.10.1.3:12345 5 | -------------------------------------------------------------------------------- /samples/electrode/fast_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Software Name : fast-paxos 3 | * SPDX-FileCopyrightText: Copyright (c) 2022 Orange 4 | * SPDX-License-Identifier: LGPL-2.1-only 5 | * 6 | * This software is distributed under the 7 | * GNU Lesser General Public License v2.1 only. 8 | * 9 | * Author: asd123www et al. 10 | */ 11 | 12 | #ifndef _FAST_COMMON_H 13 | #define _FAST_COMMON_H 14 | 15 | #define ETH_ALEN 6 /* Octets in one ethernet addr */ 16 | 17 | #define CLUSTER_SIZE 3 // need 18 | #define FAST_REPLICA_MAX 100 // max # of replicas. 19 | #define NONFRAG_MAGIC 0x20050318 20 | #define FRAG_MAGIC 0x20101010 21 | 22 | #define MAGIC_LEN 4 23 | #define REQUEST_TYPE_LEN 33 24 | #define PREPARE_TYPE_LEN 33 25 | #define PREPAREOK_TYPE_LEN 35 26 | #define MYPREPAREOK_TYPE_LEN 24 27 | 28 | #define FAST_PAXOS_DATA_LEN 12 29 | #define BROADCAST_SIGN_BIT (1 << 31) 30 | #define QUORUM_SIZE ((CLUSTER_SIZE + 1) >> 1) 31 | #define QUORUM_BITSET_ENTRY 1024 // must be 2^t 32 | 33 | enum ReplicaStatus { STATUS_NORMAL, STATUS_VIEW_CHANGE, STATUS_RECOVERING }; 34 | 35 | enum { 36 | FAST_PROG_XDP_HANDLE_PREPARE = 0, 37 | FAST_PROG_XDP_HANDLE_REQUEST, 38 | FAST_PROG_XDP_HANDLE_PREPAREOK, 39 | FAST_PROG_XDP_WRITE_BUFFER, 40 | FAST_PROG_XDP_PREPARE_REPLY, 41 | 42 | FAST_PROG_XDP_MAX 43 | }; 44 | 45 | enum { 46 | FAST_PROG_TC_BROADCAST = 0, 47 | 48 | FAST_PROG_TC_MAX 49 | }; 50 | 51 | struct paxos_configure { 52 | __u32 addr; // ipv4. 53 | __u16 port; 54 | char eth[ETH_ALEN]; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /samples/electrode/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'electrode-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | electrode_config = custom_target( 31 | 'config.txt', 32 | input: 'config.txt', 33 | output: ['config.txt'], 34 | command: ['cp', '@INPUT@', '@OUTPUT@'], 35 | env: env, 36 | console: false, 37 | build_by_default: true 38 | ) 39 | 40 | sample_build = custom_target( 41 | 'electrode-build', 42 | output: ['electrode'], 43 | command: [ 44 | cargo_wrapper, rust_bin, '-Z', 45 | 'unstable-options', 46 | '-C', meson.current_source_dir(), 47 | 'rustc', '-qr', '--', 48 | '-Cenable_rex' 49 | ], 50 | depends: [sample_clippy, electrode_config], 51 | env: env, 52 | console: false, 53 | build_by_default: true 54 | ) 55 | 56 | executable( 57 | 'entry', 58 | 'entry.c', 59 | build_by_default: true, 60 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 61 | pie: true 62 | ) 63 | -------------------------------------------------------------------------------- /samples/electrode/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/electrode/src/common.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | // 3 | // Software Name : fast-paxos 4 | // SPDX-FileCopyrightText: Copyright (c) 2022 Orange 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | // 7 | // This software is distributed under the 8 | // GNU Lesser General Public License v2.1 only. 9 | // 10 | // Author: asd123www et al. 11 | // Author: Ruowen Qin et al. 12 | // 13 | 14 | pub(crate) const ETH_ALEN: usize = 6; // Octets in one ethernet addr 15 | pub(crate) const MTU: u64 = 1500; 16 | pub(crate) const MAX_DATA_LEN: usize = 64; 17 | 18 | pub(crate) const CLUSTER_SIZE: u8 = 3; 19 | pub(crate) const FAST_REPLICA_MAX: u32 = 100; // max # of replicas. 20 | pub(crate) const NONFRAG_MAGIC: u32 = 0x20050318; 21 | pub(crate) const FRAG_MAGIC: u32 = 0x20101010; 22 | 23 | pub(crate) const MAGIC_LEN: usize = 4; 24 | pub(crate) const REQUEST_TYPE_LEN: usize = 33; 25 | pub(crate) const PREPARE_TYPE_LEN: usize = 33; 26 | pub(crate) const PREPAREOK_TYPE_LEN: usize = 35; 27 | pub(crate) const MYPREPAREOK_TYPE_LEN: usize = 24; 28 | 29 | pub(crate) const FAST_PAXOS_DATA_LEN: usize = 12; 30 | pub(crate) const BROADCAST_SIGN_BIT: u32 = 1 << 31; 31 | pub(crate) const QUORUM_SIZE: u32 = (CLUSTER_SIZE as u32 + 1) >> 1; 32 | pub(crate) const QUORUM_BITSET_ENTRY: u32 = 1024; // must be 2^t 33 | 34 | pub(crate) const PAXOS_PORT: u16 = 12345; 35 | pub(crate) const MAGIC_BITS: [u8; MAGIC_LEN] = [0x18, 0x03, 0x05, 0x20]; 36 | 37 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 38 | #[repr(C)] 39 | pub(crate) enum ReplicaStatus { 40 | STATUS_NORMAL = 0, 41 | STATUS_VIEW_CHANGE, 42 | STATUS_RECOVERING, 43 | } 44 | 45 | #[derive(Debug, PartialEq, Eq)] 46 | #[repr(C)] 47 | pub(crate) enum FastProgXdp { 48 | FAILED = -1, 49 | FAST_PROG_XDP_HANDLE_PREPARE = 0, 50 | FAST_PROG_XDP_HANDLE_REQUEST, 51 | FAST_PROG_XDP_HANDLE_PREPAREOK, 52 | FAST_PROG_XDP_WRITE_BUFFER, 53 | FAST_PROG_XDP_PREPARE_REPLY, 54 | FAST_PROG_XDP_MAX, 55 | } 56 | 57 | #[derive(Debug, PartialEq, Eq)] 58 | #[repr(C)] 59 | pub(crate) enum FastProgTc { 60 | FAST_PROG_TC_BROADCAST = 0, 61 | FAST_PROG_TC_MAX, 62 | } 63 | 64 | #[repr(C)] 65 | #[derive(Clone, Copy)] 66 | pub(crate) struct PaxosConfigure { 67 | pub(crate) addr: u32, // ipv4. 68 | pub(crate) port: u16, 69 | pub(crate) eth: [u8; ETH_ALEN], 70 | } 71 | -------------------------------------------------------------------------------- /samples/electrode/src/maps.rs: -------------------------------------------------------------------------------- 1 | use rex::linux::bpf::bpf_spin_lock; 2 | use rex::map::*; 3 | use rex::rex_map; 4 | 5 | use crate::common::*; 6 | 7 | #[repr(C)] 8 | #[derive(Clone, Copy)] 9 | pub(crate) struct paxos_quorum { 10 | pub(crate) view: u32, 11 | pub(crate) opnum: u32, 12 | pub(crate) bitset: u32, 13 | } 14 | 15 | #[repr(C)] 16 | #[derive(Clone, Copy)] 17 | pub(crate) struct paxos_ctr_state { 18 | pub(crate) state: ReplicaStatus, 19 | pub(crate) my_idx: u32, 20 | pub(crate) leader_idx: u32, 21 | pub(crate) batch_size: u32, 22 | pub(crate) view: u64, 23 | pub(crate) last_op: u64, 24 | } 25 | 26 | #[repr(C)] 27 | #[derive(Clone, Copy)] 28 | pub(crate) struct paxos_batch { 29 | counter: u32, 30 | lock: bpf_spin_lock, 31 | } 32 | 33 | #[rex_map] 34 | pub(crate) static map_configure: RexArrayMap = 35 | RexArrayMap::new(FAST_REPLICA_MAX, 0); 36 | 37 | #[rex_map] 38 | pub(crate) static map_ctr_state: RexArrayMap = 39 | RexArrayMap::new(1, 0); 40 | 41 | #[rex_map] 42 | pub(crate) static map_msg_last_op: RexArrayMap = RexArrayMap::new(1, 0); 43 | 44 | #[rex_map] 45 | pub(crate) static map_quorum: RexArrayMap = 46 | RexArrayMap::new(QUORUM_BITSET_ENTRY, 0); 47 | 48 | #[rex_map] 49 | pub(crate) static batch_context: RexArrayMap = 50 | RexArrayMap::new(1, 0); 51 | 52 | #[rex_map] 53 | pub(crate) static map_prepare_buffer: RexRingBuf = RexRingBuf::new(1 << 20, 0); 54 | #[rex_map] 55 | pub(crate) static map_request_buffer: RexRingBuf = RexRingBuf::new(1 << 20, 0); 56 | -------------------------------------------------------------------------------- /samples/error_injector/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/error_injector/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | userapp 3 | -------------------------------------------------------------------------------- /samples/error_injector/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "error_injector" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/error_injector/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "error_injector" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/error_injector/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/error_injector/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #define EXE "./target/x86_64-unknown-none/release/error_injector" 11 | 12 | #define USAGE "./loader \n" 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | struct bpf_object *obj; 17 | struct bpf_program *prog; 18 | struct bpf_link *link = NULL; 19 | struct bpf_map *pid_to_errno; 20 | struct rex_obj *rex_obj; 21 | unsigned long errno_to_inject; 22 | int pid; 23 | LIBBPF_OPTS(bpf_ksyscall_opts, opts); 24 | 25 | if (argc < 3) { 26 | fprintf(stderr, USAGE); 27 | return 1; 28 | } 29 | 30 | errno_to_inject = -strtoul(argv[2], NULL, 10); 31 | 32 | rex_obj = rex_obj_load(EXE); 33 | if (!rex_obj) { 34 | fprintf(stderr, "rex_obj_load failed\n"); 35 | return 1; 36 | } 37 | 38 | obj = rex_obj_get_bpf(rex_obj); 39 | if (!obj) { 40 | fprintf(stderr, "rex_obj_get_bpf failed\n"); 41 | return 1; 42 | } 43 | 44 | prog = bpf_object__find_program_by_name(obj, "err_injector"); 45 | if (!prog) { 46 | fprintf(stderr, "bpf_object__find_program_by_name failed\n"); 47 | return 1; 48 | } 49 | 50 | opts.retprobe = 0; 51 | link = bpf_program__attach_ksyscall(prog, argv[1], &opts); 52 | if (libbpf_get_error(link)) { 53 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 54 | link = NULL; 55 | return 1; 56 | } 57 | 58 | pid_to_errno = bpf_object__find_map_by_name(obj, "pid_to_errno"); 59 | if (libbpf_get_error(pid_to_errno)) { 60 | fprintf(stderr, "ERROR: Could not find map: pid_map\n"); 61 | goto cleanup; 62 | } 63 | 64 | pid = fork(); 65 | 66 | if (pid < 0) { 67 | perror("fork"); 68 | } else if (!pid) { 69 | pid = getpid(); 70 | if (bpf_map__update_elem( 71 | pid_to_errno, &pid, sizeof(pid), &errno_to_inject, 72 | sizeof(errno_to_inject), BPF_ANY) < 0) { 73 | fprintf(stderr, "ERROR: updating pid_map failed\n"); 74 | } 75 | 76 | bpf_link__destroy(link); 77 | 78 | execl("./userapp", "./userapp", NULL); 79 | perror("executing userapp failed"); 80 | return 1; 81 | } 82 | 83 | wait(NULL); 84 | 85 | cleanup: 86 | bpf_link__destroy(link); 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /samples/error_injector/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | error_injector_clippy = custom_target( 17 | 'error_injector-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | error_injector_build = custom_target( 31 | 'error_injector-build', 32 | output: ['error_injector'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: error_injector_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | error_injector_loader = executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | error_injector_userapp = executable( 55 | 'userapp', 56 | 'userapp.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | sanity_test = custom_target( 63 | 'sanity_test', 64 | output: ['runtest.py'], 65 | input: join_paths(meson.current_source_dir(), 'tests/runtest.py'), 66 | command: [ 67 | 'cp', '@INPUT@', '@OUTPUT@', 68 | ] 69 | ) 70 | 71 | runtest_deps += [error_injector_build, error_injector_loader, error_injector_userapp, sanity_test] 72 | 73 | sanity_test_env = environment() 74 | sanity_test_env.set('SAMPLE_PATH', meson.current_build_dir()) 75 | sanity_test_env.set('Q_SCRIPT', 76 | join_paths(meson.project_source_root(), 'scripts/q-script/sanity-test-q') 77 | ) 78 | sanity_test_env.set('KERNEL_PATH', kbuild_dir) 79 | 80 | test('error_injector', 81 | python3_bin, 82 | args: [sanity_test_scripts], 83 | env: sanity_test_env, 84 | depends: runtest_deps, 85 | is_parallel: false, 86 | workdir: meson.current_build_dir() 87 | ) 88 | -------------------------------------------------------------------------------- /samples/error_injector/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use rex::kprobe::kprobe; 5 | use rex::map::RexHashMap; 6 | use rex::pt_regs::PtRegs; 7 | use rex::{Result, rex_kprobe, rex_map}; 8 | 9 | #[allow(non_upper_case_globals)] 10 | #[rex_map] 11 | static pid_to_errno: RexHashMap = RexHashMap::new(1, 0); 12 | 13 | #[rex_kprobe] 14 | pub fn err_injector(obj: &kprobe, ctx: &mut PtRegs) -> Result { 15 | obj.bpf_get_current_task() 16 | .map(|t| t.get_pid()) 17 | .and_then(|p| obj.bpf_map_lookup_elem(&pid_to_errno, &p).cloned()) 18 | .map(|e| obj.bpf_override_return(ctx, e)) 19 | .ok_or(0) 20 | } 21 | -------------------------------------------------------------------------------- /samples/error_injector/tests/runtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import re 5 | import subprocess 6 | from time import sleep 7 | 8 | process = 0 9 | 10 | 11 | def count_bpf_programs(): 12 | try: 13 | # Run bpftool to list all loaded BPF programs 14 | result = subprocess.run( 15 | "bpftool prog show", 16 | capture_output=True, 17 | shell=True, 18 | text=True, 19 | ) 20 | 21 | # Process the output to count programs 22 | if result.stdout: 23 | # Each program details start on a new line 24 | output = result.stdout.strip().split("\n") 25 | programs = [line for line in output if "name" in line] 26 | return len(programs) 27 | else: 28 | return 0 29 | except FileNotFoundError: 30 | print("bpftool is not installed or not found in the PATH.") 31 | return 0 32 | except Exception as e: 33 | print(f"An error occurred: {e}") 34 | return 0 35 | 36 | 37 | def run_loader(): 38 | global process 39 | process = subprocess.Popen( 40 | ["./loader", "dup", "22"], 41 | text=True, 42 | stdout=subprocess.PIPE, 43 | stderr=subprocess.PIPE, 44 | ) 45 | 46 | 47 | def capture_output() -> bool: 48 | try: 49 | global process 50 | 51 | sleep(2) 52 | process.kill() 53 | std_out, std_err = process.communicate(timeout=7) 54 | prog_match = re.findall(r"dup: Invalid argument", std_err, re.M) 55 | if len(prog_match) == 1: 56 | print("Success") 57 | return True 58 | else: 59 | print("Failed") 60 | return False 61 | 62 | except subprocess.CalledProcessError: 63 | return False 64 | except subprocess.TimeoutExpired: 65 | process.kill() 66 | return False 67 | 68 | 69 | def main(): 70 | 71 | old_prog_num = count_bpf_programs() 72 | run_loader() 73 | count = 0 74 | while old_prog_num == count_bpf_programs(): 75 | sleep(1) 76 | count += 1 77 | if count == 5: 78 | break 79 | grade_file = open("auto_grade.txt", "w") 80 | if capture_output(): 81 | grade_file.write("success") 82 | else: 83 | grade_file.write("fail") 84 | 85 | 86 | if __name__ == "__main__": 87 | main() 88 | -------------------------------------------------------------------------------- /samples/error_injector/userapp.c: -------------------------------------------------------------------------------- 1 | #define _DEFAULT_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | if (syscall(__NR_dup, 0) < 0) { 9 | perror("dup"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/hello/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/hello/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /samples/hello/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "hello" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/hello/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/hello/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | return syscall(__NR_dup, 1); 7 | } 8 | -------------------------------------------------------------------------------- /samples/hello/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define EXE "./target/x86_64-unknown-none/release/hello" 15 | 16 | int main(void) 17 | { 18 | int trace_pipe_fd; 19 | struct bpf_object *obj; 20 | struct bpf_program *prog; 21 | struct bpf_link *link = NULL; 22 | 23 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 24 | if (!obj) { 25 | fprintf(stderr, "Object could not be opened\n"); 26 | return 1; 27 | } 28 | 29 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 30 | if (!prog) { 31 | fprintf(stderr, "_start not found\n"); 32 | return 1; 33 | } 34 | 35 | link = bpf_program__attach(prog); 36 | if (libbpf_get_error(link)) { 37 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 38 | link = NULL; 39 | return 1; 40 | } 41 | 42 | trace_pipe_fd = openat(AT_FDCWD, "/sys/kernel/debug/tracing/trace_pipe", 43 | O_RDONLY); 44 | 45 | for (;;) { 46 | char c; 47 | fflush(stdout); 48 | if (read(trace_pipe_fd, &c, 1) == 1) 49 | putchar(c); 50 | } 51 | 52 | bpf_link__destroy(link); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /samples/hello/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | hello_clippy = custom_target( 17 | 'hello-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | hello_build = custom_target( 31 | 'hello-build', 32 | output: ['hello'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | hello_loader = executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | hello_trigger = executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | sanity_test = custom_target( 63 | 'sanity_test', 64 | output: ['runtest.py'], 65 | input: join_paths(meson.current_source_dir(), 'tests/runtest.py'), 66 | command: [ 67 | 'cp', '@INPUT@', '@OUTPUT@', 68 | ] 69 | ) 70 | 71 | runtest_deps += [hello_build, hello_loader, hello_trigger, sanity_test] 72 | 73 | sanity_test_env = environment() 74 | sanity_test_env.set('SAMPLE_PATH', meson.current_build_dir()) 75 | sanity_test_env.set('Q_SCRIPT', 76 | join_paths(meson.project_source_root(), 'scripts/q-script/sanity-test-q') 77 | ) 78 | sanity_test_env.set('KERNEL_PATH', kbuild_dir) 79 | 80 | test('hello_test', 81 | python3_bin, 82 | args: [sanity_test_scripts], 83 | env: sanity_test_env, 84 | depends: runtest_deps, 85 | is_parallel: false, 86 | workdir: meson.current_build_dir() 87 | ) 88 | -------------------------------------------------------------------------------- /samples/hello/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/hello/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate rex; 5 | 6 | use rex::tracepoint::*; 7 | use rex::{Result, rex_printk, rex_tracepoint}; 8 | 9 | #[rex_tracepoint] 10 | fn rex_prog1( 11 | obj: &tracepoint, 12 | _: &'static SyscallsEnterDupCtx, 13 | ) -> Result { 14 | let option_task = obj.bpf_get_current_task(); 15 | if let Some(task) = option_task { 16 | let cpu = obj.bpf_get_smp_processor_id(); 17 | let pid = task.get_pid(); 18 | rex_printk!("Rust triggered from PID {} on CPU {}.\n", pid, cpu)?; 19 | } 20 | Ok(0) 21 | } 22 | -------------------------------------------------------------------------------- /samples/hello/tests/runtest.py: -------------------------------------------------------------------------------- 1 | #!/bin/python 2 | 3 | import re 4 | import subprocess 5 | from time import sleep 6 | 7 | process = 0 8 | 9 | 10 | def count_bpf_programs(): 11 | try: 12 | # Run bpftool to list all loaded BPF programs 13 | result = subprocess.run( 14 | "bpftool prog show", 15 | capture_output=True, 16 | shell=True, 17 | text=True, 18 | ) 19 | 20 | # Process the output to count programs 21 | if result.stdout: 22 | # Each program details start on a new line 23 | output = result.stdout.strip().split("\n") 24 | programs = [line for line in output if "name" in line] 25 | return len(programs) 26 | else: 27 | return 0 28 | except FileNotFoundError: 29 | print("bpftool is not installed or not found in the PATH.") 30 | return 0 31 | except Exception as e: 32 | print(f"An error occurred: {e}") 33 | return 0 34 | 35 | 36 | def run_loader(): 37 | global process 38 | process = subprocess.Popen( 39 | ["./loader"], 40 | text=True, 41 | stdout=subprocess.PIPE, 42 | stderr=subprocess.PIPE, 43 | ) 44 | 45 | 46 | def trigger_prog(): 47 | try: 48 | subprocess.run("./event-trigger", shell=True) 49 | except subprocess.CalledProcessError: 50 | print("CalledProcessError") 51 | 52 | 53 | def capture_output() -> bool: 54 | try: 55 | global process 56 | trigger_prog() 57 | trigger_prog() 58 | 59 | sleep(2) 60 | process.kill() 61 | std_out, std_err = process.communicate(timeout=7) 62 | re_match = re.findall( 63 | r"Rust triggered from PID \d+ on CPU .+", std_out, re.M 64 | ) 65 | if len(re_match) == 2: 66 | print("Success") 67 | return True 68 | else: 69 | print("Failed") 70 | return False 71 | 72 | except subprocess.CalledProcessError: 73 | return False 74 | except subprocess.TimeoutExpired: 75 | process.kill() 76 | return False 77 | 78 | 79 | def main(): 80 | 81 | old_prog_num = count_bpf_programs() 82 | run_loader() 83 | count = 0 84 | while old_prog_num == count_bpf_programs(): 85 | sleep(1) 86 | count += 1 87 | if count == 5: 88 | break 89 | grade_file = open("auto_grade.txt", "w") 90 | if capture_output(): 91 | grade_file.write("success") 92 | else: 93 | grade_file.write("fail") 94 | 95 | 96 | if __name__ == "__main__": 97 | main() 98 | -------------------------------------------------------------------------------- /samples/map_bench/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/map_bench/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "map_bench" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/map_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "map_bench" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/map_bench/bench.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$#" -ne 2 ]; then 4 | echo "Usage: $0 " 5 | exit 1 6 | fi 7 | 8 | mkdir output 9 | echo 8192 > /sys/kernel/debug/tracing/buffer_size_kb 10 | 11 | if [[ "$1" == "rex" ]]; then 12 | ./event-trigger 6000 1 13 | cat /sys/kernel/debug/tracing/trace | tail -5000 >"./output/rex_${2}.txt" 14 | elif [[ "$1" == "bpf" ]]; then 15 | ./event-trigger 6000 1 16 | cat /sys/kernel/debug/tracing/trace | tail -5000 >"./output/bpf_${2}.txt" 17 | fi 18 | 19 | 20 | # clean buffer 21 | echo >/sys/kernel/debug/tracing/trace 22 | 23 | # unlink 24 | rm -rf /sys/fs/bpf/* 25 | -------------------------------------------------------------------------------- /samples/map_bench/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/map_bench/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int nr_rounds, arg, fd; 10 | 11 | if (argc != 3) 12 | asm volatile("ud2"); 13 | 14 | nr_rounds = atoi(argv[1]); 15 | arg = atoi(argv[2]); 16 | fd = open("/proc/kprobe_target", O_RDONLY); 17 | if (fd < 0) { 18 | perror("open"); 19 | return 1; 20 | } 21 | 22 | for (int i = 0; i < nr_rounds; i++) 23 | ioctl(fd, 1313, arg); 24 | 25 | close(fd); 26 | } 27 | -------------------------------------------------------------------------------- /samples/map_bench/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define EXE "./target/x86_64-unknown-none/release/map_bench" 15 | 16 | int main(void) 17 | { 18 | struct bpf_object *obj; 19 | struct bpf_program *prog; 20 | struct bpf_link *link = NULL; 21 | 22 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 23 | if (!obj) { 24 | fprintf(stderr, "Object could not be opened\n"); 25 | return 1; 26 | } 27 | 28 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 29 | if (!prog) { 30 | fprintf(stderr, "Program not found\n"); 31 | return 1; 32 | } 33 | 34 | link = bpf_program__attach(prog); 35 | if (libbpf_get_error(link)) { 36 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 37 | link = NULL; 38 | return 1; 39 | } 40 | 41 | bpf_link__pin(link, "/sys/fs/bpf/link"); 42 | bpf_link__destroy(link); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /samples/map_bench/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'map_bench-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'map_bench-build', 32 | output: ['map_bench'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | -------------------------------------------------------------------------------- /samples/map_bench/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/map_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate rex; 5 | 6 | use rex::kprobe::*; 7 | use rex::linux::bpf::*; 8 | use rex::map::*; 9 | use rex::pt_regs::PtRegs; 10 | use rex::{Result, rex_kprobe, rex_map, rex_printk}; 11 | 12 | #[rex_map] 13 | static MAP_HASH: RexHashMap = RexHashMap::new(5000, 0); 14 | 15 | #[rex_map] 16 | static MAP_ARRAY: RexArrayMap = RexArrayMap::new(5000, 0); 17 | 18 | #[rex_kprobe(function = "kprobe_target_func")] 19 | fn rex_prog1(obj: &kprobe, _ctx: &mut PtRegs) -> Result { 20 | let zero = 2500u32; 21 | 22 | let random = obj.bpf_get_prandom_u32() as u64; 23 | obj.bpf_map_update_elem(&MAP_HASH, &zero, &random, BPF_ANY as u64)?; 24 | 25 | let start = obj.bpf_ktime_get_ns(); 26 | obj.bpf_map_lookup_elem(&MAP_HASH, &zero); 27 | let end = obj.bpf_ktime_get_ns(); 28 | 29 | rex_printk!("Time elapsed: {}", end - start)?; 30 | 31 | // let random = obj.bpf_get_prandom_u32() as u64; 32 | // obj.bpf_map_update_elem(&MAP_ARRAY, &zero, &random, BPF_ANY as u64)?; 33 | // 34 | // let start = obj.bpf_ktime_get_ns(); 35 | // obj.bpf_map_lookup_elem(&MAP_ARRAY, &zero); 36 | // let end = obj.bpf_ktime_get_ns(); 37 | // 38 | // rex_printk!("Time elapsed: {}", end - start)?; 39 | 40 | Ok(0) 41 | } 42 | -------------------------------------------------------------------------------- /samples/map_test/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/map_test/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "map_test" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/map_test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "map_test" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/map_test/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/map_test/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | return syscall(__NR_dup, 1); 7 | } 8 | -------------------------------------------------------------------------------- /samples/map_test/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define EXE "./target/x86_64-unknown-none/release/map_test" 15 | 16 | int main(void) 17 | { 18 | int trace_pipe_fd; 19 | struct bpf_object *obj; 20 | struct bpf_program *prog; 21 | struct bpf_link *link = NULL; 22 | 23 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 24 | if (!obj) { 25 | fprintf(stderr, "Object could not be opened\n"); 26 | return 1; 27 | } 28 | 29 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 30 | if (!prog) { 31 | fprintf(stderr, "Program not found\n"); 32 | return 1; 33 | } 34 | 35 | link = bpf_program__attach(prog); 36 | if (libbpf_get_error(link)) { 37 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 38 | link = NULL; 39 | return 1; 40 | } 41 | 42 | trace_pipe_fd = openat(AT_FDCWD, "/sys/kernel/debug/tracing/trace_pipe", 43 | O_RDONLY); 44 | 45 | for (;;) { 46 | char c; 47 | fflush(stdout); 48 | if (read(trace_pipe_fd, &c, 1) == 1) 49 | putchar(c); 50 | } 51 | 52 | bpf_link__destroy(link); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /samples/map_test/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | map_test_clippy = custom_target( 17 | 'map_test-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | map_test_build = custom_target( 31 | 'map_test-build', 32 | output: ['map_test'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | map_test_loader = executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | map_test_trigger = executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | sanity_test = custom_target( 63 | 'sanity_test', 64 | output: ['runtest.py'], 65 | input: join_paths(meson.current_source_dir(), 'tests/runtest.py'), 66 | command: [ 67 | 'cp', '@INPUT@', '@OUTPUT@', 68 | ] 69 | ) 70 | 71 | runtest_deps = [ 72 | map_test_build, 73 | map_test_loader, 74 | map_test_trigger, 75 | sanity_test 76 | ] 77 | 78 | sanity_test_env = environment() 79 | sanity_test_env.set('SAMPLE_PATH', meson.current_build_dir()) 80 | sanity_test_env.set('Q_SCRIPT', 81 | join_paths(meson.project_source_root(), 'scripts/q-script/sanity-test-q') 82 | ) 83 | sanity_test_env.set('KERNEL_PATH', kbuild_dir) 84 | 85 | test('map_test', 86 | python3_bin, 87 | args: [sanity_test_scripts], 88 | env: sanity_test_env, 89 | depends: runtest_deps, 90 | is_parallel: false, 91 | workdir: meson.current_build_dir() 92 | ) 93 | -------------------------------------------------------------------------------- /samples/map_test/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/map_test_2/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/map_test_2/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "map_test_2" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "rex", 10 | ] 11 | 12 | [[package]] 13 | name = "paste" 14 | version = "1.0.15" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 17 | 18 | [[package]] 19 | name = "proc-macro-error" 20 | version = "1.0.4" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 23 | dependencies = [ 24 | "proc-macro-error-attr", 25 | "proc-macro2", 26 | "quote", 27 | "version_check", 28 | ] 29 | 30 | [[package]] 31 | name = "proc-macro-error-attr" 32 | version = "1.0.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "version_check", 39 | ] 40 | 41 | [[package]] 42 | name = "proc-macro2" 43 | version = "1.0.95" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 46 | dependencies = [ 47 | "unicode-ident", 48 | ] 49 | 50 | [[package]] 51 | name = "quote" 52 | version = "1.0.40" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 55 | dependencies = [ 56 | "proc-macro2", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/map_test_2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "map_test_2" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/map_test_2/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/map_test_2/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | return syscall(__NR_dup, 1); 7 | } 8 | -------------------------------------------------------------------------------- /samples/map_test_2/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define EXE "./target/x86_64-unknown-none/release/map_test_2" 15 | 16 | int main(void) 17 | { 18 | int trace_pipe_fd; 19 | struct bpf_object *obj; 20 | struct bpf_program *prog; 21 | struct bpf_link *link = NULL; 22 | 23 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 24 | if (!obj) { 25 | fprintf(stderr, "Object could not be opened\n"); 26 | return 1; 27 | } 28 | 29 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 30 | if (!prog) { 31 | fprintf(stderr, "Program not found\n"); 32 | return 1; 33 | } 34 | 35 | link = bpf_program__attach(prog); 36 | if (libbpf_get_error(link)) { 37 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 38 | link = NULL; 39 | return 1; 40 | } 41 | 42 | trace_pipe_fd = openat(AT_FDCWD, "/sys/kernel/debug/tracing/trace_pipe", 43 | O_RDONLY); 44 | 45 | for (;;) { 46 | char c; 47 | fflush(stdout); 48 | if (read(trace_pipe_fd, &c, 1) == 1) 49 | putchar(c); 50 | } 51 | 52 | bpf_link__destroy(link); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /samples/map_test_2/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | map_test_2_clippy = custom_target( 17 | 'map_test_2-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | map_test_2_build = custom_target( 31 | 'map_test_2-build', 32 | output: ['map_test_2'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | map_test_2_loader = executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | map_test_2_trigger = executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | sanity_test = custom_target( 63 | 'sanity_test', 64 | output: ['runtest.py'], 65 | input: join_paths(meson.current_source_dir(), 'tests/runtest.py'), 66 | command: [ 67 | 'cp', '@INPUT@', '@OUTPUT@', 68 | ] 69 | ) 70 | 71 | runtest_deps += [ 72 | map_test_2_build, 73 | map_test_2_loader, 74 | map_test_2_trigger, 75 | sanity_test 76 | ] 77 | 78 | sanity_test_env = environment() 79 | sanity_test_env.set('SAMPLE_PATH', meson.current_build_dir()) 80 | sanity_test_env.set('Q_SCRIPT', 81 | join_paths(meson.project_source_root(), 'scripts/q-script/sanity-test-q') 82 | ) 83 | sanity_test_env.set('KERNEL_PATH', kbuild_dir) 84 | 85 | test('map_test_2', 86 | python3_bin, 87 | args: [sanity_test_scripts], 88 | env: sanity_test_env, 89 | depends: runtest_deps, 90 | is_parallel: false, 91 | workdir: meson.current_build_dir() 92 | ) 93 | -------------------------------------------------------------------------------- /samples/map_test_2/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/meson.build: -------------------------------------------------------------------------------- 1 | subdir('atomic') 2 | subdir('bmc') 3 | subdir('electrode') 4 | subdir('error_injector') 5 | subdir('hello') 6 | subdir('map_bench') 7 | subdir('map_test') 8 | subdir('map_test_2') 9 | subdir('recursive') 10 | subdir('spinlock_cleanup_benchmark') 11 | subdir('spinlock_test') 12 | subdir('startup_overhead_benchmark') 13 | subdir('syscall_tp') 14 | subdir('trace_event') 15 | subdir('tracex5') 16 | subdir('xdp_test') 17 | subdir('syscount') 18 | -------------------------------------------------------------------------------- /samples/recursive/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/recursive/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "recursive" 54 | version = "0.1.0" 55 | dependencies = [ 56 | "rex", 57 | ] 58 | 59 | [[package]] 60 | name = "rex" 61 | version = "0.2.0" 62 | dependencies = [ 63 | "paste", 64 | "rex-macros", 65 | ] 66 | 67 | [[package]] 68 | name = "rex-macros" 69 | version = "0.2.0" 70 | dependencies = [ 71 | "proc-macro-error", 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/recursive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "recursive" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/recursive/bench.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$#" -ne 1 ]; then 4 | echo "Usage: $0 " 5 | exit 1 6 | fi 7 | 8 | echo 8192 > /sys/kernel/debug/tracing/buffer_size_kb 9 | mkdir output 10 | 11 | if [[ "$1" == "rex" ]]; then 12 | for i in {0..32}; do 13 | ./event-trigger 5000 $i 14 | cat /sys/kernel/debug/tracing/trace | tail -5000 >"./output/rust_${i}" 15 | echo >/sys/kernel/debug/tracing/trace 16 | echo $i 17 | sleep 0.5 18 | done 19 | elif [[ "$1" == "bpf" ]]; then 20 | for i in {0..32}; do 21 | ./event-trigger 6000 $i 22 | cat /sys/kernel/debug/tracing/trace | tail -5000 >"./output/bpf_${i}" 23 | echo >/sys/kernel/debug/tracing/trace 24 | echo $i 25 | sleep 0.5 26 | done 27 | fi 28 | 29 | # unlink 30 | rm -rf /sys/fs/bpf/* 31 | -------------------------------------------------------------------------------- /samples/recursive/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/recursive/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int nr_rounds, arg, fd; 10 | 11 | if (argc != 3) 12 | asm volatile("ud2"); 13 | 14 | nr_rounds = atoi(argv[1]); 15 | arg = atoi(argv[2]); 16 | fd = open("/proc/kprobe_target", O_RDONLY); 17 | if (fd < 0) { 18 | perror("open"); 19 | return 1; 20 | } 21 | 22 | for (int i = 0; i < nr_rounds; i++) 23 | ioctl(fd, 1313, arg); 24 | 25 | close(fd); 26 | } 27 | -------------------------------------------------------------------------------- /samples/recursive/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define EXE "./target/x86_64-unknown-none/release/recursive" 16 | 17 | int main(void) 18 | { 19 | struct bpf_object *obj; 20 | struct bpf_program *prog; 21 | struct bpf_link *link = NULL; 22 | 23 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 24 | if (!obj) { 25 | fprintf(stderr, "Object could not be opened\n"); 26 | return 1; 27 | } 28 | 29 | prog = bpf_object__find_program_by_name(obj, "rex_recursive"); 30 | if (!prog) { 31 | fprintf(stderr, "_start not found\n"); 32 | return 1; 33 | } 34 | 35 | link = bpf_program__attach(prog); 36 | if (libbpf_get_error(link)) { 37 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 38 | link = NULL; 39 | return 1; 40 | } 41 | 42 | bpf_link__pin(link, "/sys/fs/bpf/recursive_link"); 43 | bpf_link__destroy(link); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /samples/recursive/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'recursive-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'recursive-build', 32 | output: ['recursive'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | -------------------------------------------------------------------------------- /samples/recursive/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/recursive/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | extern crate rex; 4 | 5 | // use rex::tracepoint::*; 6 | use core::hint::black_box; 7 | 8 | use rex::kprobe::*; 9 | use rex::map::RexArrayMap; 10 | use rex::pt_regs::PtRegs; 11 | use rex::{Result, rex_kprobe, rex_map, rex_printk}; 12 | 13 | #[rex_map] 14 | static data_map: RexArrayMap = RexArrayMap::new(2, 0); 15 | 16 | #[rex_kprobe(function = "kprobe_target_func")] 17 | fn rex_recursive(obj: &kprobe, ctx: &mut PtRegs) -> Result { 18 | // let curr_pid: i32 = if let Some(task_struct) = obj.bpf_get_current_task() 19 | // { task_struct.get_pid() 20 | // } else { 21 | // return Err(0); 22 | // }; 23 | 24 | // let stored_pid: u32 = if let Some(val) = 25 | // obj.bpf_map_lookup_elem(&data_map, &0) { *val 26 | // } else { 27 | // return Err(0); 28 | // }; 29 | 30 | let n = ctx.rdi() as u32; 31 | // let n: u32 = if let Some(val) = obj.bpf_map_lookup_elem(&data_map, &1) { 32 | // *val 33 | // } else { 34 | // return Err(0); 35 | // }; 36 | 37 | // rex_printk!("Received n: {}", n)?; 38 | let start_time: u64 = obj.bpf_ktime_get_ns(); 39 | calculate_tail_fib(n); 40 | let end_time: u64 = obj.bpf_ktime_get_ns(); 41 | // rex_printk!("Result: {}", result)?; 42 | 43 | rex_printk!("Time: {}", end_time - start_time)?; 44 | 45 | Ok(0) 46 | } 47 | 48 | #[inline(never)] 49 | fn calculate_tail_fib(n: u32) { 50 | if n == 0 { 51 | return; 52 | } 53 | 54 | black_box(calculate_tail_fib(n - 1)) 55 | } 56 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "spinlock_cleanup_benchmark" 72 | version = "0.1.0" 73 | dependencies = [ 74 | "rex", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spinlock_cleanup_benchmark" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #define EXE "./target/x86_64-unknown-none/release/spinlock_cleanup_benchmark" 20 | 21 | #define __unused __attribute__((__unused__)) 22 | 23 | int main(int __unused argc, char **argv) 24 | { 25 | struct bpf_program *prog; 26 | struct bpf_object *obj; 27 | 28 | int interface_idx = atoi(argv[1]); 29 | unsigned int xdp_flags = 0; 30 | xdp_flags |= XDP_FLAGS_DRV_MODE; 31 | /* xdp_flags |= XDP_FLAGS_SKB_MODE; */ 32 | 33 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 34 | if (!obj) { 35 | fprintf(stderr, "Object could not be opened\n"); 36 | return 1; 37 | } 38 | 39 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 40 | if (!prog) { 41 | printf("finding a prog in obj file failed\n"); 42 | return 1; 43 | } 44 | int xdp_main_prog_fd = bpf_program__fd(prog); 45 | 46 | if (bpf_xdp_attach(interface_idx, xdp_main_prog_fd, xdp_flags, NULL) < 47 | 0) { 48 | fprintf(stderr, "ERROR: xdp failed"); 49 | return 1; 50 | } 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'spinlock_cleanup_benchmark-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'spinlock_cleanup_benchmark-build', 32 | output: ['spinlock_cleanup_benchmark'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/spinlock_cleanup_benchmark/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate rex; 5 | 6 | use rex::linux::bpf::bpf_spin_lock; 7 | use rex::map::RexArrayMap; 8 | use rex::spinlock::rex_spinlock_guard; 9 | use rex::xdp::*; 10 | use rex::{Result, rex_map, rex_printk, rex_xdp}; 11 | 12 | #[repr(C)] 13 | #[derive(Clone, Copy)] 14 | struct MapEntry { 15 | data: u64, 16 | lock: bpf_spin_lock, 17 | } 18 | 19 | #[rex_map] 20 | static MAP_ARRAY: RexArrayMap = RexArrayMap::new(256, 0); 21 | 22 | #[rex_xdp] 23 | fn rex_prog1(obj: &xdp, _: &mut xdp_md) -> Result { 24 | if let Some(entry) = obj.bpf_map_lookup_elem(&MAP_ARRAY, &0) { 25 | let start = obj.bpf_ktime_get_ns(); 26 | { 27 | let _guard = rex_spinlock_guard::new(&mut entry.lock); 28 | } 29 | let end = obj.bpf_ktime_get_ns(); 30 | rex_printk!("Spinlock allocation and cleanup: {} ns", end - start)?; 31 | Ok(XDP_PASS as i32) 32 | } else { 33 | rex_printk!("Unable to look up map")?; 34 | Err(XDP_PASS as i32) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /samples/spinlock_test/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/spinlock_test/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /samples/spinlock_test/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "spinlock_test" 72 | version = "0.1.0" 73 | dependencies = [ 74 | "rex", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/spinlock_test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spinlock_test" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/spinlock_test/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/spinlock_test/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | return syscall(__NR_dup, 1); 7 | } 8 | -------------------------------------------------------------------------------- /samples/spinlock_test/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #define EXE "./target/x86_64-unknown-none/release/spinlock_test" 14 | 15 | int main(void) 16 | { 17 | int trace_pipe_fd; 18 | struct bpf_object *obj; 19 | struct bpf_program *prog; 20 | struct bpf_link *link = NULL; 21 | 22 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 23 | if (!obj) { 24 | fprintf(stderr, "Object could not be opened\n"); 25 | return 1; 26 | } 27 | 28 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 29 | if (!prog) { 30 | fprintf(stderr, "_start not found\n"); 31 | return 1; 32 | } 33 | 34 | link = bpf_program__attach(prog); 35 | if (libbpf_get_error(link)) { 36 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 37 | link = NULL; 38 | return 1; 39 | } 40 | 41 | trace_pipe_fd = openat(AT_FDCWD, "/sys/kernel/debug/tracing/trace_pipe", 42 | O_RDONLY); 43 | 44 | for (;;) { 45 | char c; 46 | if (read(trace_pipe_fd, &c, 1) == 1) 47 | putchar(c); 48 | } 49 | 50 | bpf_link__destroy(link); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /samples/spinlock_test/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'spinlock_test-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'spinlock_test-build', 32 | output: ['spinlock_test'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | -------------------------------------------------------------------------------- /samples/spinlock_test/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/spinlock_test/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate rex; 5 | 6 | use rex::linux::bpf::bpf_spin_lock; 7 | use rex::map::RexArrayMap; 8 | use rex::spinlock::rex_spinlock_guard; 9 | use rex::tracepoint::*; 10 | use rex::{Result, rex_map, rex_tracepoint}; 11 | 12 | #[repr(C)] 13 | #[derive(Clone, Copy)] 14 | struct MapEntry { 15 | data: u64, 16 | lock: bpf_spin_lock, 17 | } 18 | 19 | #[rex_map] 20 | static MAP_ARRAY: RexArrayMap = RexArrayMap::new(256, 0); 21 | 22 | fn test1(obj: &tracepoint) { 23 | if let Some(entry) = obj.bpf_map_lookup_elem(&MAP_ARRAY, &0) { 24 | // entry.lock locked in rex_spinlock_guard::new 25 | let _guard = rex_spinlock_guard::new(&mut entry.lock); 26 | entry.data = 1; 27 | // entry.lock is automatically released when _guard goes out of scope 28 | } 29 | } 30 | 31 | fn test2(obj: &tracepoint) { 32 | if let Some(entry) = obj.bpf_map_lookup_elem(&MAP_ARRAY, &0) { 33 | // entry.lock locked in rex_spinlock_guard::new 34 | let _guard = rex_spinlock_guard::new(&mut entry.lock); 35 | entry.data = 1; 36 | panic!("test\n"); 37 | // entry.lock is automatically released by cleanup mechanism 38 | } 39 | } 40 | 41 | #[rex_tracepoint] 42 | fn rex_prog1( 43 | obj: &tracepoint, 44 | _: &'static SyscallsEnterDupCtx, 45 | ) -> Result { 46 | test1(obj); 47 | test2(obj); 48 | Ok(0) 49 | } 50 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "startup_overhead_benchmark" 72 | version = "0.1.0" 73 | dependencies = [ 74 | "rex", 75 | ] 76 | 77 | [[package]] 78 | name = "syn" 79 | version = "2.0.101" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 82 | dependencies = [ 83 | "proc-macro2", 84 | "quote", 85 | "unicode-ident", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "startup_overhead_benchmark" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/event-trigger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int nr_rounds, arg, fd; 10 | 11 | if (argc != 3) 12 | asm volatile("ud2"); 13 | 14 | nr_rounds = atoi(argv[1]); 15 | arg = atoi(argv[2]); 16 | fd = open("/proc/kprobe_target", O_RDONLY); 17 | if (fd < 0) { 18 | perror("open"); 19 | return 1; 20 | } 21 | 22 | for (int i = 0; i < nr_rounds; i++) 23 | ioctl(fd, 1313, arg); 24 | 25 | close(fd); 26 | } 27 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define EXE "./target/x86_64-unknown-none/release/startup_overhead_benchmark" 15 | 16 | int main(void) 17 | { 18 | struct bpf_object *obj; 19 | struct bpf_program *prog; 20 | struct bpf_link *link = NULL; 21 | 22 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 23 | if (!obj) { 24 | fprintf(stderr, "Object could not be opened\n"); 25 | return 1; 26 | } 27 | 28 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 29 | if (!prog) { 30 | fprintf(stderr, "_start not found\n"); 31 | return 1; 32 | } 33 | 34 | link = bpf_program__attach(prog); 35 | if (libbpf_get_error(link)) { 36 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 37 | link = NULL; 38 | return 1; 39 | } 40 | 41 | bpf_link__pin(link, "/sys/fs/bpf/kprobe_link"); 42 | bpf_link__destroy(link); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'startup_overhead_benchmark-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'startup_overhead_benchmark-build', 32 | output: ['startup_overhead_benchmark'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'loader', 48 | 'loader.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | executable( 55 | 'event-trigger', 56 | 'event-trigger.c', 57 | build_by_default: true, 58 | dependencies: [kernel_dep], 59 | pie: true 60 | ) 61 | 62 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/startup_overhead_benchmark/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate rex; 5 | 6 | use rex::kprobe::*; 7 | use rex::pt_regs::PtRegs; 8 | use rex::{Result, rex_kprobe}; 9 | 10 | #[rex_kprobe(function = "kprobe_target_func")] 11 | fn rex_prog1(_obj: &kprobe, _ctx: &mut PtRegs) -> Result { 12 | Ok(0) 13 | } 14 | -------------------------------------------------------------------------------- /samples/syscall_tp/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/syscall_tp/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "2.0.101" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 75 | dependencies = [ 76 | "proc-macro2", 77 | "quote", 78 | "unicode-ident", 79 | ] 80 | 81 | [[package]] 82 | name = "syscall_tp" 83 | version = "0.1.0" 84 | dependencies = [ 85 | "rex", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/syscall_tp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syscall_tp" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/syscall_tp/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/syscall_tp/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | syscall_tp_clippy = custom_target( 17 | 'syscall_tp-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | syscall_tp_build = custom_target( 31 | 'syscall_tp-build', 32 | output: ['syscall_tp-rex'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | syscall_tp_loader = executable( 47 | 'syscall_tp', 48 | 'syscall_tp_user.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | 54 | 55 | sanity_test = custom_target( 56 | 'sanity_test', 57 | output: ['runtest.py'], 58 | input: join_paths(meson.current_source_dir(), 'tests/runtest.py'), 59 | command: [ 60 | 'cp', '@INPUT@', '@OUTPUT@', 61 | ] 62 | ) 63 | 64 | runtest_deps += [syscall_tp_build, syscall_tp_loader, sanity_test] 65 | 66 | sanity_test_env = environment() 67 | sanity_test_env.set('SAMPLE_PATH', meson.current_build_dir()) 68 | sanity_test_env.set('Q_SCRIPT', 69 | join_paths(meson.project_source_root(), 'scripts/q-script/sanity-test-q') 70 | ) 71 | sanity_test_env.set('KERNEL_PATH', kbuild_dir) 72 | 73 | test('syscall_tp', 74 | python3_bin, 75 | args: [sanity_test_scripts], 76 | env: sanity_test_env, 77 | depends: runtest_deps, 78 | is_parallel: false, 79 | workdir: meson.current_build_dir() 80 | ) 81 | -------------------------------------------------------------------------------- /samples/syscall_tp/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/syscall_tp/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate rex; 5 | 6 | use rex::linux::bpf::BPF_NOEXIST; 7 | use rex::map::RexArrayMap; 8 | use rex::tracepoint::*; 9 | use rex::{Result, rex_map, rex_tracepoint}; 10 | 11 | #[rex_map] 12 | static enter_open_map: RexArrayMap = RexArrayMap::new(1, 0); 13 | 14 | #[rex_map] 15 | static exit_open_map: RexArrayMap = RexArrayMap::new(1, 0); 16 | 17 | type SyscallTpMap = RexArrayMap; 18 | 19 | fn count( 20 | obj: &tracepoint, 21 | map: &'static SyscallTpMap, 22 | ) -> Result { 23 | match obj.bpf_map_lookup_elem(map, &0) { 24 | None => { 25 | obj.bpf_map_update_elem(map, &0, &1, BPF_NOEXIST.into())?; 26 | } 27 | Some(val) => { 28 | *val += 1; 29 | } 30 | } 31 | 32 | Ok(0) 33 | } 34 | 35 | #[rex_tracepoint] 36 | fn trace_enter_open( 37 | obj: &tracepoint, 38 | _: &'static SyscallsEnterOpenCtx, 39 | ) -> Result { 40 | count(obj, &enter_open_map) 41 | } 42 | 43 | #[rex_tracepoint] 44 | fn trace_enter_open_at( 45 | obj: &tracepoint, 46 | _: &'static SyscallsEnterOpenatCtx, 47 | ) -> Result { 48 | count(obj, &enter_open_map) 49 | } 50 | 51 | #[rex_tracepoint] 52 | fn trace_enter_exit( 53 | obj: &tracepoint, 54 | _: &'static SyscallsExitOpenCtx, 55 | ) -> Result { 56 | count(obj, &exit_open_map) 57 | } 58 | 59 | #[rex_tracepoint] 60 | fn trace_enter_exit_at( 61 | obj: &tracepoint, 62 | _: &'static SyscallsExitOpenatCtx, 63 | ) -> Result { 64 | count(obj, &exit_open_map) 65 | } 66 | -------------------------------------------------------------------------------- /samples/syscall_tp/tests/runtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import re 5 | import subprocess 6 | from time import sleep 7 | 8 | process = 0 9 | 10 | 11 | def count_bpf_programs(): 12 | try: 13 | # Run bpftool to list all loaded BPF programs 14 | result = subprocess.run( 15 | "bpftool prog show", 16 | capture_output=True, 17 | shell=True, 18 | text=True, 19 | ) 20 | 21 | # Process the output to count programs 22 | if result.stdout: 23 | # Each program details start on a new line 24 | output = result.stdout.strip().split("\n") 25 | programs = [line for line in output if "name" in line] 26 | return len(programs) 27 | else: 28 | return 0 29 | except FileNotFoundError: 30 | print("bpftool is not installed or not found in the PATH.") 31 | return 0 32 | except Exception as e: 33 | print(f"An error occurred: {e}") 34 | return 0 35 | 36 | 37 | def run_loader(): 38 | global process 39 | process = subprocess.Popen( 40 | ["./syscall_tp"], 41 | text=True, 42 | stdout=subprocess.PIPE, 43 | stderr=subprocess.PIPE, 44 | ) 45 | 46 | 47 | def capture_output() -> bool: 48 | try: 49 | global process 50 | 51 | sleep(2) 52 | process.kill() 53 | std_out, std_err = process.communicate(timeout=7) 54 | prog_match = re.findall(r"prog #0: map ids \d \d", std_out, re.M) 55 | map_match = re.findall(r"verify map:\d val: \d", std_out, re.M) 56 | if len(prog_match) == 1 and len(map_match) == 2: 57 | print("Success") 58 | return True 59 | else: 60 | print("Failed") 61 | return False 62 | 63 | except subprocess.CalledProcessError: 64 | return False 65 | except subprocess.TimeoutExpired: 66 | process.kill() 67 | return False 68 | 69 | 70 | def main(): 71 | 72 | old_prog_num = count_bpf_programs() 73 | run_loader() 74 | count = 0 75 | while old_prog_num == count_bpf_programs(): 76 | sleep(1) 77 | count += 1 78 | if count == 5: 79 | break 80 | grade_file = open("auto_grade.txt", "w") 81 | if capture_output(): 82 | grade_file.write("success") 83 | else: 84 | grade_file.write("fail") 85 | 86 | 87 | if __name__ == "__main__": 88 | main() 89 | -------------------------------------------------------------------------------- /samples/syscount/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/syscount/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "2.0.101" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 75 | dependencies = [ 76 | "proc-macro2", 77 | "quote", 78 | "unicode-ident", 79 | ] 80 | 81 | [[package]] 82 | name = "syscount" 83 | version = "0.1.0" 84 | dependencies = [ 85 | "rex", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/syscount/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syscount" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | 8 | [dependencies.rex] 9 | path = "../../rex" 10 | 11 | [lints.clippy] 12 | disallowed_methods = "forbid" 13 | disallowed_types = "forbid" 14 | 15 | [lints.rust] 16 | incomplete_features = "forbid" 17 | internal_features = "forbid" 18 | unsafe_code = "forbid" 19 | unstable_features = "forbid" 20 | 21 | [profile.dev] 22 | panic = "abort" 23 | debug = false 24 | 25 | [profile.release] 26 | panic = "abort" 27 | debug = false 28 | lto = true 29 | -------------------------------------------------------------------------------- /samples/syscount/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/syscount/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | env = environment() 10 | env.prepend('PATH', rust_bin) 11 | env.set('LINUX_OBJ', kbuild_dir) 12 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 13 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 14 | 15 | syscount_clippy = custom_target( 16 | 'syscount-clippy', 17 | output: ['target'], 18 | command: [ 19 | cargo_wrapper, rust_bin, '-Z', 20 | 'unstable-options', 21 | '-C', meson.current_source_dir(), 22 | 'clippy', '-qr' 23 | ], 24 | env: env, 25 | console: false, 26 | build_by_default: true 27 | ) 28 | 29 | syscount_build = custom_target( 30 | 'syscount-build', 31 | output: ['syscount'], 32 | command: [ 33 | cargo_wrapper, rust_bin, '-Z', 34 | 'unstable-options', 35 | '-C', meson.current_source_dir(), 36 | 'rustc', '-qr', '--', 37 | '-Cenable_rex' 38 | ], 39 | depends: syscount_clippy, 40 | env: env, 41 | console: false, 42 | build_by_default: true 43 | ) 44 | 45 | syscount_loader = executable( 46 | 'loader', 47 | 'loader.c', 48 | build_by_default: true, 49 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 50 | pie: true 51 | ) 52 | -------------------------------------------------------------------------------- /samples/syscount/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/trace_event/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/trace_event/.gitignore: -------------------------------------------------------------------------------- 1 | trace_event 2 | trace_event_user.o 3 | trace_helpers.o 4 | -------------------------------------------------------------------------------- /samples/trace_event/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "2.0.101" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 75 | dependencies = [ 76 | "proc-macro2", 77 | "quote", 78 | "unicode-ident", 79 | ] 80 | 81 | [[package]] 82 | name = "trace_event_kern" 83 | version = "0.1.0" 84 | dependencies = [ 85 | "rex", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/trace_event/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trace_event_kern" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/trace_event/README.md: -------------------------------------------------------------------------------- 1 | # trace\_event 2 | 3 | Credit: Wentao Zhang 4 | 5 | The code does not fully work yet, with some small problems to be fixed. 6 | -------------------------------------------------------------------------------- /samples/trace_event/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/trace_event/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'trace_event-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'trace_event-build', 32 | output: ['trace_event-rex'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'trace_event', 48 | 'trace_event_user.c', 49 | 'trace_helpers.c', 50 | build_by_default: true, 51 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 52 | pie: true 53 | ) 54 | -------------------------------------------------------------------------------- /samples/trace_event/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/trace_event/trace_helpers.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "trace_helpers.h" 7 | 8 | #define MAX_SYMS 300000 9 | static struct ksym syms[MAX_SYMS]; 10 | static int sym_cnt; 11 | 12 | static int ksym_cmp(const void *p1, const void *p2) 13 | { 14 | return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr; 15 | } 16 | 17 | int load_kallsyms(void) 18 | { 19 | FILE *f = fopen("/proc/kallsyms", "r"); 20 | char func[256], buf[256]; 21 | char symbol; 22 | void *addr; 23 | int i = 0; 24 | 25 | if (!f) 26 | return -ENOENT; 27 | 28 | while (fgets(buf, sizeof(buf), f)) { 29 | if (sscanf(buf, "%p %c %s", &addr, &symbol, func) != 3) 30 | break; 31 | if (!addr) 32 | continue; 33 | syms[i].addr = (long)addr; 34 | syms[i].name = strdup(func); 35 | i++; 36 | } 37 | fclose(f); 38 | sym_cnt = i; 39 | qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp); 40 | return 0; 41 | } 42 | 43 | struct ksym *ksym_search(long key) 44 | { 45 | int start = 0, end = sym_cnt; 46 | int result; 47 | 48 | /* kallsyms not loaded. return NULL */ 49 | if (sym_cnt <= 0) 50 | return NULL; 51 | 52 | while (start < end) { 53 | size_t mid = start + (end - start) / 2; 54 | 55 | result = key - syms[mid].addr; 56 | if (result < 0) 57 | end = mid; 58 | else if (result > 0) 59 | start = mid + 1; 60 | else 61 | return &syms[mid]; 62 | } 63 | 64 | if (start >= 1 && syms[start - 1].addr < key && key < syms[start].addr) 65 | /* valid ksym */ 66 | return &syms[start - 1]; 67 | 68 | /* out of range. return _stext */ 69 | return &syms[0]; 70 | } 71 | -------------------------------------------------------------------------------- /samples/trace_event/trace_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef __TRACE_HELPER_H 3 | #define __TRACE_HELPER_H 4 | 5 | struct ksym { 6 | long addr; 7 | char *name; 8 | }; 9 | 10 | int load_kallsyms(void); 11 | struct ksym *ksym_search(long key); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /samples/tracex5/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/tracex5/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | tracex5 3 | -------------------------------------------------------------------------------- /samples/tracex5/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "2.0.101" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 75 | dependencies = [ 76 | "proc-macro2", 77 | "quote", 78 | "unicode-ident", 79 | ] 80 | 81 | [[package]] 82 | name = "tracex5" 83 | version = "0.1.0" 84 | dependencies = [ 85 | "rex", 86 | ] 87 | 88 | [[package]] 89 | name = "unicode-ident" 90 | version = "1.0.18" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 93 | 94 | [[package]] 95 | name = "version_check" 96 | version = "0.9.5" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 99 | -------------------------------------------------------------------------------- /samples/tracex5/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tracex5" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | -------------------------------------------------------------------------------- /samples/tracex5/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/tracex5/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'tracex5-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'tracex5-build', 32 | output: ['tracex5-rex'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'tracex5', 48 | 'tracex5.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | -------------------------------------------------------------------------------- /samples/tracex5/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/tracex5/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(non_upper_case_globals)] 4 | 5 | extern crate rex; 6 | 7 | use rex::kprobe::*; 8 | use rex::linux::seccomp::seccomp_data; 9 | use rex::linux::unistd::*; 10 | use rex::pt_regs::PtRegs; 11 | use rex::{Result, rex_kprobe, rex_printk}; 12 | 13 | pub fn func_sys_write(obj: &kprobe, ctx: &PtRegs) -> Result { 14 | let mut sd: seccomp_data = seccomp_data { 15 | nr: 0, 16 | arch: 0, 17 | instruction_pointer: 0, 18 | args: [0; 6], 19 | }; 20 | 21 | let unsafe_ptr = ctx.rsi() as *const (); 22 | obj.bpf_probe_read_kernel(&mut sd, unsafe_ptr)?; 23 | 24 | if sd.args[2] == 512 { 25 | return rex_printk!( 26 | "write(fd={}, buf={:x}, size={})\n", 27 | sd.args[0], 28 | sd.args[1], 29 | sd.args[2] 30 | ); 31 | } 32 | Ok(0) 33 | } 34 | 35 | pub fn func_sys_read(obj: &kprobe, ctx: &PtRegs) -> Result { 36 | let mut sd: seccomp_data = seccomp_data { 37 | nr: 0, 38 | arch: 0, 39 | instruction_pointer: 0, 40 | args: [0; 6], 41 | }; 42 | 43 | let unsafe_ptr = ctx.rsi() as *const (); 44 | obj.bpf_probe_read_kernel(&mut sd, unsafe_ptr)?; 45 | 46 | if sd.args[2] > 128 && sd.args[2] <= 1024 { 47 | return rex_printk!( 48 | "read(fd={}, buf={:x}, size={})\n", 49 | sd.args[0], 50 | sd.args[1], 51 | sd.args[2] 52 | ); 53 | } 54 | Ok(0) 55 | } 56 | 57 | pub fn func_sys_mmap(_obj: &kprobe, _: &PtRegs) -> Result { 58 | rex_printk!("mmap\n") 59 | } 60 | 61 | #[rex_kprobe(function = "__seccomp_filter")] 62 | fn rex_prog1(obj: &kprobe, ctx: &mut PtRegs) -> Result { 63 | match ctx.rdi() as u32 { 64 | __NR_read => func_sys_read(obj, ctx), 65 | __NR_write => func_sys_write(obj, ctx), 66 | __NR_mmap => func_sys_mmap(obj, ctx), 67 | __NR_getuid..=__NR_getsid => { 68 | rex_printk!("syscall={} (one of get/set uid/pid/gid)\n", ctx.rdi()) 69 | } 70 | _ => Ok(0), 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /samples/tracex5/tracex5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #define EXE "./target/x86_64-unknown-none/release/tracex5" 13 | 14 | /* install fake seccomp program to enable seccomp code path inside the kernel, 15 | * so that our kprobe attached to seccomp_phase1() can be triggered 16 | */ 17 | static void install_accept_all_seccomp(void) 18 | { 19 | struct sock_filter filter[] = { 20 | BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), 21 | }; 22 | struct sock_fprog prog = { 23 | .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), 24 | .filter = filter, 25 | }; 26 | if (prctl(PR_SET_SECCOMP, 2, &prog)) 27 | perror("prctl"); 28 | } 29 | 30 | #define DEBUGFS "/sys/kernel/debug/tracing/" 31 | 32 | static void read_trace_pipe(void) 33 | { 34 | int trace_fd; 35 | 36 | trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0); 37 | if (trace_fd < 0) 38 | return; 39 | 40 | while (1) { 41 | static char buf[4096]; 42 | ssize_t sz; 43 | 44 | sz = read(trace_fd, buf, sizeof(buf) - 1); 45 | if (sz > 0) { 46 | buf[sz] = 0; 47 | puts(buf); 48 | } 49 | } 50 | } 51 | 52 | int main(void) 53 | { 54 | struct bpf_object *obj; 55 | struct bpf_program *prog; 56 | struct bpf_link *link = NULL; 57 | FILE *f; 58 | 59 | obj = rex_obj_get_bpf(rex_obj_load(EXE)); 60 | if (!obj) { 61 | fprintf(stderr, "Object could not be opened\n"); 62 | return 1; 63 | } 64 | 65 | prog = bpf_object__find_program_by_name(obj, "rex_prog1"); 66 | if (!prog) { 67 | fprintf(stderr, "Program not found\n"); 68 | return 1; 69 | } 70 | 71 | link = bpf_program__attach(prog); 72 | if (libbpf_get_error(link)) { 73 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 74 | link = NULL; 75 | return 1; 76 | } 77 | 78 | install_accept_all_seccomp(); 79 | 80 | f = popen("dd if=/dev/zero of=/dev/null count=5", "r"); 81 | (void)f; 82 | 83 | read_trace_pipe(); 84 | 85 | bpf_link__destroy(link); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /samples/xdp_test/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | linker = "ld.mold" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Cforce-frame-pointers=y", 9 | "-Csymbol-mangling-version=v0", 10 | "-Ccodegen-units=1", 11 | "-Crelocation-model=pie", 12 | "-Crelro-level=full", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /samples/xdp_test/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "paste" 7 | version = "1.0.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 10 | 11 | [[package]] 12 | name = "proc-macro-error" 13 | version = "1.0.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 16 | dependencies = [ 17 | "proc-macro-error-attr", 18 | "proc-macro2", 19 | "quote", 20 | "version_check", 21 | ] 22 | 23 | [[package]] 24 | name = "proc-macro-error-attr" 25 | version = "1.0.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 28 | dependencies = [ 29 | "proc-macro2", 30 | "quote", 31 | "version_check", 32 | ] 33 | 34 | [[package]] 35 | name = "proc-macro2" 36 | version = "1.0.95" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 39 | dependencies = [ 40 | "unicode-ident", 41 | ] 42 | 43 | [[package]] 44 | name = "quote" 45 | version = "1.0.40" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 48 | dependencies = [ 49 | "proc-macro2", 50 | ] 51 | 52 | [[package]] 53 | name = "rex" 54 | version = "0.2.0" 55 | dependencies = [ 56 | "paste", 57 | "rex-macros", 58 | ] 59 | 60 | [[package]] 61 | name = "rex-macros" 62 | version = "0.2.0" 63 | dependencies = [ 64 | "proc-macro-error", 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "2.0.101" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 75 | dependencies = [ 76 | "proc-macro2", 77 | "quote", 78 | "unicode-ident", 79 | ] 80 | 81 | [[package]] 82 | name = "unicode-ident" 83 | version = "1.0.18" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 86 | 87 | [[package]] 88 | name = "version_check" 89 | version = "0.9.5" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 92 | 93 | [[package]] 94 | name = "xdp_test" 95 | version = "0.1.0" 96 | dependencies = [ 97 | "rex", 98 | ] 99 | -------------------------------------------------------------------------------- /samples/xdp_test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xdp_test" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | [dependencies.rex] 11 | path = "../../rex" 12 | 13 | [lints.clippy] 14 | disallowed_methods = "forbid" 15 | disallowed_types = "forbid" 16 | 17 | [lints.rust] 18 | incomplete_features = "forbid" 19 | internal_features = "forbid" 20 | unsafe_code = "forbid" 21 | unstable_features = "forbid" 22 | 23 | [profile.dev] 24 | panic = "abort" 25 | debug = false 26 | 27 | [profile.release] 28 | panic = "abort" 29 | debug = false 30 | lto = true 31 | 32 | -------------------------------------------------------------------------------- /samples/xdp_test/clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-methods = [ 2 | "core::mem::forget", 3 | ] 4 | 5 | disallowed-types = [ 6 | "core::mem::ManuallyDrop", 7 | ] 8 | -------------------------------------------------------------------------------- /samples/xdp_test/meson.build: -------------------------------------------------------------------------------- 1 | build_dir = run_command( 2 | realpath, 3 | '--relative-to', 4 | meson.current_source_dir(), 5 | meson.current_build_dir(), 6 | capture: true, 7 | check: true 8 | ).stdout().strip() 9 | 10 | env = environment() 11 | env.prepend('PATH', rust_bin) 12 | env.set('LINUX_OBJ', kbuild_dir) 13 | env.set('LINUX_SRC', join_paths(meson.project_source_root(), './linux')) 14 | env.set('CARGO_TARGET_DIR', join_paths(build_dir, 'target')) 15 | 16 | sample_clippy = custom_target( 17 | 'xdp_test-clippy', 18 | output: ['target'], 19 | command: [ 20 | cargo_wrapper, rust_bin, '-Z', 21 | 'unstable-options', 22 | '-C', meson.current_source_dir(), 23 | 'clippy', '-qr' 24 | ], 25 | env: env, 26 | console: false, 27 | build_by_default: true 28 | ) 29 | 30 | sample_build = custom_target( 31 | 'xdp_test-build', 32 | output: ['xdp_test'], 33 | command: [ 34 | cargo_wrapper, rust_bin, '-Z', 35 | 'unstable-options', 36 | '-C', meson.current_source_dir(), 37 | 'rustc', '-qr', '--', 38 | '-Cenable_rex' 39 | ], 40 | depends: sample_clippy, 41 | env: env, 42 | console: false, 43 | build_by_default: true 44 | ) 45 | 46 | executable( 47 | 'entry', 48 | 'entry.c', 49 | build_by_default: true, 50 | dependencies: [librex_dep, libbpf_dep, kernel_dep], 51 | pie: true 52 | ) 53 | -------------------------------------------------------------------------------- /samples/xdp_test/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /samples/xdp_test/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | #![allow(non_camel_case_types)] 4 | 5 | extern crate rex; 6 | 7 | use core::net::Ipv4Addr; 8 | 9 | use rex::sched_cls::*; 10 | use rex::utils::*; 11 | use rex::xdp::*; 12 | use rex::{rex_printk, rex_tc, rex_xdp}; 13 | 14 | #[rex_xdp] 15 | fn xdp_rx_filter(obj: &xdp, ctx: &mut xdp_md) -> Result { 16 | let mut ip_header = obj.ip_header(ctx); 17 | 18 | rex_printk!("IP saddr {}\n", Ipv4Addr::from_bits(*ip_header.saddr()))?; 19 | rex_printk!("IP daddr {}\n", Ipv4Addr::from_bits(*ip_header.daddr()))?; 20 | 21 | match u8::from_be(ip_header.protocol) as u32 { 22 | IPPROTO_TCP => { 23 | rex_printk!("TCP packet!")?; 24 | } 25 | IPPROTO_UDP => { 26 | rex_printk!("UDP packet!")?; 27 | } 28 | _ => {} 29 | }; 30 | 31 | Ok(XDP_PASS as i32) 32 | } 33 | 34 | #[rex_tc] 35 | fn xdp_tx_filter(obj: &sched_cls, skb: &mut __sk_buff) -> Result { 36 | let mut ip_header = obj.ip_header(skb); 37 | 38 | rex_printk!("IP saddr {}\n", Ipv4Addr::from_bits(*ip_header.saddr()))?; 39 | rex_printk!("IP daddr {}\n", Ipv4Addr::from_bits(*ip_header.daddr()))?; 40 | if u8::from_be(ip_header.protocol) as u32 == IPPROTO_UDP { 41 | return rex_printk!("UDP packet!"); 42 | } 43 | 44 | Ok(TC_ACT_OK as i32) 45 | } 46 | -------------------------------------------------------------------------------- /scripts/cargo-wrapper.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my ($build_dir, @cmd) = @ARGV; 7 | my $cargo_bin = "$build_dir/cargo"; 8 | 9 | exec($cargo_bin, @cmd); 10 | -------------------------------------------------------------------------------- /scripts/sanity_tests/run_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ''':' ; exec "$(command -v python)" "$0" "$@" 4 | ''' 5 | 6 | import os 7 | import subprocess 8 | import sys 9 | 10 | from pathlib import Path 11 | 12 | sample = Path(os.environ.get("SAMPLE_PATH")) 13 | q_script = Path(os.environ.get("Q_SCRIPT")) 14 | 15 | # Set Path env 16 | kernel_path = Path(os.environ.get("KERNEL_PATH")) 17 | 18 | 19 | def main(): 20 | os.chdir(kernel_path) 21 | test_path = sample.joinpath("runtest.py") 22 | cmd = " ".join([str(q_script), "-t", str(test_path)]) 23 | try: 24 | # print(cmd) 25 | subprocess.run( 26 | cmd, timeout=180, shell=True, capture_output=True, text=True 27 | ) 28 | output = subprocess.run( 29 | "cat auto_grade.txt | grep success", 30 | capture_output=True, 31 | text=True, 32 | shell=True, 33 | ) 34 | if output.stdout.strip() != "success": 35 | print("", end="\x1b[1K\r") 36 | print(" \033[91mFailed\033[0m %s" % sample.name) 37 | exit(1) 38 | 39 | except Exception: 40 | print(f"{sample.name} test run failed", file=sys.stderr) 41 | subprocess.run("pkill qemu-system-x86", shell=True) 42 | finally: 43 | subprocess.run("rm auto_grade.txt", shell=True, check=True) 44 | 45 | 46 | if __name__ == "__main__": 47 | main() 48 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | CC = { value = "clang", force = true } 3 | 4 | [target.x86_64-unknown-linux-gnu] 5 | linker = "clang" 6 | rustflags = [ 7 | "-Zthreads=8", 8 | "-Ctarget-cpu=native", 9 | "-Clinker-plugin-lto", 10 | "-Clink-args=-flto=thin -fuse-ld=mold -Wl,-O1 -Wl,--as-needed -Wl,--gc-sections", 11 | ] 12 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | bmc-results.csv 3 | # Devenv 4 | .devenv* 5 | devenv.local.nix 6 | 7 | # direnv 8 | .direnv 9 | 10 | # pre-commit 11 | .pre-commit-config.yaml 12 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memcached_benchmark" 3 | version = "0.2.0" 4 | edition = "2024" 5 | authors = ["Ruowen Qin ruowenq2@illinois.edu"] 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | memcache = { version = "0.18", default-features = false } 10 | rand = "0" 11 | rand_distr = "0" 12 | clap = { version = "4", features = ["derive"] } 13 | rayon = "1" 14 | tokio = { version = "1", features = ["full"] } 15 | zstd = { version = "0", features = ["zstdmt", "thin-lto"] } 16 | serde = { version = "1", features = ["derive"] } 17 | serde_yaml = "0.9" 18 | serde_json = "1" 19 | async-memcached = "0" 20 | tokio-util = { version = "0.7", features = ["rt"] } 21 | rand_chacha = "0" 22 | log = "0" 23 | env_logger = { version = "0" } 24 | mimalloc = "0" 25 | anyhow = "1" 26 | 27 | 28 | [dev-dependencies] 29 | assert_cmd = "2" 30 | predicates = "3" 31 | tempfile = "3" 32 | test-log = "0" 33 | duct = "0" 34 | 35 | [profile.release] 36 | opt-level = 3 37 | debug = false 38 | codegen-units = 1 39 | panic = "abort" 40 | strip = true 41 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Ruowen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/README.md: -------------------------------------------------------------------------------- 1 | # memcached_benchmark -------------------------------------------------------------------------------- /tools/memcached_benchmark/devenv.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, inputs, ... }: 2 | 3 | { 4 | # https://devenv.sh/basics/ 5 | env.GREET = "devenv"; 6 | 7 | # https://devenv.sh/packages/ 8 | packages = with pkgs; [ git mold llvmPackages.clangUseLLVM memcached openssl ]; 9 | 10 | # https://devenv.sh/languages/ 11 | languages.rust = { 12 | channel = "stable"; 13 | components = [ 14 | "cargo" 15 | "rust-src" 16 | "rustc" 17 | "clippy" 18 | "rust-analyzer" 19 | "rustfmt" 20 | ]; 21 | mold.enable = false; 22 | enable = true; 23 | }; 24 | 25 | 26 | # https://devenv.sh/processes/ 27 | # processes.cargo-watch.exec = "cargo-watch"; 28 | 29 | # https://devenv.sh/services/ 30 | # services.postgres.enable = true; 31 | 32 | # https://devenv.sh/scripts/ 33 | scripts.hello.exec = '' 34 | echo hello from $GREET 35 | ''; 36 | 37 | enterShell = '' 38 | export RUSTC_BOOTSTRAP=1 39 | hello 40 | git --version 41 | rustc --version 42 | ''; 43 | 44 | # https://devenv.sh/tasks/ 45 | # tasks = { 46 | # "myproj:setup".exec = "mytool build"; 47 | # "devenv:enterShell".after = [ "myproj:setup" ]; 48 | # }; 49 | 50 | # https://devenv.sh/tests/ 51 | enterTest = '' 52 | echo "Running tests" 53 | git --version | grep --color=auto "${pkgs.git.version}" 54 | ''; 55 | 56 | # https://devenv.sh/pre-commit-hooks/ 57 | # pre-commit.hooks.shellcheck.enable = true; 58 | 59 | # See full reference at https://devenv.sh/reference/options/ 60 | } 61 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/devenv.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | nixpkgs: 3 | url: github:nixos/nixpkgs/nixos-unstable 4 | fenix: 5 | url: github:nix-community/fenix 6 | inputs: 7 | nixpkgs: 8 | follows: nixpkgs 9 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | binop_separator = "Back" 3 | reorder_impl_items = true 4 | wrap_comments = true 5 | imports_granularity = "Module" 6 | group_imports = "StdExternalCrate" 7 | -------------------------------------------------------------------------------- /tools/memcached_benchmark/src/set_values.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::sync::Arc; 3 | 4 | use anyhow::Result; 5 | use async_memcached::AsciiProtocol; 6 | use log::info; 7 | use tokio::sync::Semaphore; 8 | use tokio::task::JoinSet; 9 | 10 | pub(super) async fn set_memcached_value( 11 | test_dict: Arc, Arc>>, 12 | server_address: String, 13 | port: String, 14 | ) -> Result<()> { 15 | info!("Start set memcached value"); 16 | let addr = format!("tcp://{}:{}", server_address, port); 17 | let mut sockets_pool = vec![]; 18 | let concurrency_limit = 64; 19 | 20 | for _ in 0..concurrency_limit { 21 | let client = async_memcached::Client::new(addr.as_str()) 22 | .await 23 | .expect("TCP memcached connection failed"); 24 | sockets_pool.push(tokio::sync::Mutex::new(client)); 25 | } 26 | let sockets_pool = Arc::new(sockets_pool); 27 | 28 | let mut set = JoinSet::new(); 29 | let sem = Arc::new(Semaphore::new(concurrency_limit)); 30 | 31 | for (count, (key, value)) in test_dict.iter().enumerate() { 32 | let sockets_pool_clone = sockets_pool.clone(); 33 | let key_clone = key.clone(); 34 | let value_clone = value.clone(); 35 | let sem = sem.clone(); 36 | set.spawn(async move { 37 | let _permit = sem.acquire_owned().await; 38 | let mut socket = sockets_pool_clone[count & 0x3F].lock().await; 39 | socket 40 | .set(&*key_clone, &*value_clone, None, None) 41 | .await 42 | .expect("memcached set command failed"); 43 | 44 | let ret = socket 45 | .get(&*key_clone) 46 | .await 47 | .expect("memcached get command failed"); 48 | 49 | let get_value = ret.unwrap().data.unwrap(); 50 | assert_eq!(get_value, value_clone.as_bytes()); 51 | }); 52 | } 53 | 54 | while set.join_next().await.is_some() {} 55 | 56 | info!("Done set memcached value"); 57 | 58 | Ok(()) 59 | } 60 | --------------------------------------------------------------------------------