瀏覽代碼

feat: Update rbpf to mainline (#1209)

* feat: Update rbpf to mainline

Enable JIT compilation on x86 platform.

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* fix: remove rbpf test

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* fix: remove rbpf info

Signed-off-by: Godones <chenlinfeng25@outlook.com>

---------

Signed-off-by: Godones <chenlinfeng25@outlook.com>
linfeng 3 周之前
父節點
當前提交
723ac05719
共有 45 個文件被更改,包括 190 次插入22257 次删除
  1. 1 1
      .github/workflows/makefile.yml
  2. 14 567
      kernel/Cargo.lock
  3. 1 1
      kernel/Cargo.toml
  4. 1 4
      kernel/Makefile
  5. 0 21
      kernel/crates/rbpf/.appveyor.yml
  6. 0 2
      kernel/crates/rbpf/.gitignore
  7. 0 78
      kernel/crates/rbpf/Cargo.toml
  8. 0 202
      kernel/crates/rbpf/LICENSE-APACHE
  9. 0 25
      kernel/crates/rbpf/LICENSE-MIT
  10. 0 743
      kernel/crates/rbpf/README.md
  11. 0 1
      kernel/crates/rbpf/clippy.toml
  12. 0 26
      kernel/crates/rbpf/examples/disassemble.rs
  13. 0 3
      kernel/crates/rbpf/examples/helper.rs
  14. 0 115
      kernel/crates/rbpf/examples/load_elf.rs
  15. 0 43
      kernel/crates/rbpf/examples/load_elf__block_a_port.c
  16. 0 126
      kernel/crates/rbpf/examples/rbpf_plugin.rs
  17. 0 74
      kernel/crates/rbpf/examples/to_json.rs
  18. 0 78
      kernel/crates/rbpf/examples/uptime.rs
  19. 0 72
      kernel/crates/rbpf/mk/appveyor.bat
  20. 0 3
      kernel/crates/rbpf/rustfmt.toml
  21. 0 642
      kernel/crates/rbpf/src/asm_parser.rs
  22. 0 277
      kernel/crates/rbpf/src/assembler.rs
  23. 0 1230
      kernel/crates/rbpf/src/cranelift.rs
  24. 0 807
      kernel/crates/rbpf/src/disassembler.rs
  25. 0 635
      kernel/crates/rbpf/src/ebpf.rs
  26. 0 488
      kernel/crates/rbpf/src/helpers.rs
  27. 0 2199
      kernel/crates/rbpf/src/insn_builder.rs
  28. 0 708
      kernel/crates/rbpf/src/interpreter.rs
  29. 0 1054
      kernel/crates/rbpf/src/jit.rs
  30. 0 1782
      kernel/crates/rbpf/src/lib.rs
  31. 0 41
      kernel/crates/rbpf/src/no_std_error.rs
  32. 0 75
      kernel/crates/rbpf/src/stack.rs
  33. 0 386
      kernel/crates/rbpf/src/verifier.rs
  34. 0 655
      kernel/crates/rbpf/tests/assembler.rs
  35. 0 97
      kernel/crates/rbpf/tests/common.rs
  36. 0 2257
      kernel/crates/rbpf/tests/cranelift.rs
  37. 0 377
      kernel/crates/rbpf/tests/disassembler.rs
  38. 0 571
      kernel/crates/rbpf/tests/misc.rs
  39. 0 2891
      kernel/crates/rbpf/tests/ubpf_jit_x86_64.rs
  40. 0 177
      kernel/crates/rbpf/tests/ubpf_verifier.rs
  41. 0 2674
      kernel/crates/rbpf/tests/ubpf_vm.rs
  42. 36 23
      kernel/src/perf/kprobe.rs
  43. 105 2
      kernel/src/perf/mod.rs
  44. 32 22
      kernel/src/perf/tracepoint.rs
  45. 0 2
      triagebot.toml

+ 1 - 1
.github/workflows/makefile.yml

@@ -51,7 +51,7 @@ jobs:
         env:
           ARCH: ${{ matrix.arch }}
           HOME: /root
-        run: bash -c "source /root/.cargo/env && cd kernel && make test && make test-rbpf"
+        run: bash -c "source /root/.cargo/env && cd kernel && make test"
 
   build:
     name: Build ${{ matrix.arch }}

+ 14 - 567
kernel/Cargo.lock

@@ -39,18 +39,6 @@ version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
-[[package]]
-name = "anyhow"
-version = "1.0.97"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
-
-[[package]]
-name = "arbitrary"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
-
 [[package]]
 name = "asm_macros"
 version = "0.1.0"
@@ -83,12 +71,6 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
-[[package]]
-name = "base-x"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
-
 [[package]]
 name = "bindgen"
 version = "0.61.0"
@@ -144,30 +126,12 @@ checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
 name = "bitmap"
 version = "0.1.0"
 
-[[package]]
-name = "bumpalo"
-version = "3.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
-
-[[package]]
-name = "byteorder"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
-
 [[package]]
 name = "byteorder"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
-[[package]]
-name = "bytes"
-version = "1.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
-
 [[package]]
 name = "cc"
 version = "1.2.17"
@@ -221,136 +185,9 @@ version = "4.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
 dependencies = [
- "bytes",
  "memchr",
 ]
 
-[[package]]
-name = "const_fn"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e"
-
-[[package]]
-name = "cranelift-bforest"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a91a1ccf6fb772808742db2f51e2179f25b1ec559cbe39ea080c72ff61caf8f"
-dependencies = [
- "cranelift-entity",
-]
-
-[[package]]
-name = "cranelift-codegen"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "169db1a457791bff4fd1fc585bb5cc515609647e0420a7d5c98d7700c59c2d00"
-dependencies = [
- "bumpalo",
- "cranelift-bforest",
- "cranelift-codegen-meta",
- "cranelift-codegen-shared",
- "cranelift-control",
- "cranelift-entity",
- "cranelift-isle",
- "gimli 0.27.3",
- "hashbrown 0.13.2",
- "log",
- "regalloc2",
- "smallvec",
- "target-lexicon",
-]
-
-[[package]]
-name = "cranelift-codegen-meta"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3486b93751ef19e6d6eef66d2c0e83ed3d2ba01da1919ed2747f2f7bd8ba3419"
-dependencies = [
- "cranelift-codegen-shared",
-]
-
-[[package]]
-name = "cranelift-codegen-shared"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86a1205ab18e7cd25dc4eca5246e56b506ced3feb8d95a8d776195e48d2cd4ef"
-
-[[package]]
-name = "cranelift-control"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b108cae0f724ddfdec1871a0dc193a607e0c2d960f083cfefaae8ccf655eff2"
-dependencies = [
- "arbitrary",
-]
-
-[[package]]
-name = "cranelift-entity"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "720444006240622798665bfc6aa8178e2eed556da342fda62f659c5267c3c659"
-
-[[package]]
-name = "cranelift-frontend"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7a94c4c5508b7407e125af9d5320694b7423322e59a4ac0d07919ae254347ca"
-dependencies = [
- "cranelift-codegen",
- "log",
- "smallvec",
- "target-lexicon",
-]
-
-[[package]]
-name = "cranelift-isle"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef1f888d0845dcd6be4d625b91d9d8308f3d95bed5c5d4072ce38e1917faa505"
-
-[[package]]
-name = "cranelift-jit"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "547845cd12d15167e5458556ee67513bfaff2e05e72eb489edfbabc9f21d9ea2"
-dependencies = [
- "anyhow",
- "cranelift-codegen",
- "cranelift-control",
- "cranelift-entity",
- "cranelift-module",
- "cranelift-native",
- "libc",
- "log",
- "region",
- "target-lexicon",
- "wasmtime-jit-icache-coherence",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "cranelift-module"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c104ed6a4c56c15e1858cc466482373e3c13d022bc1391485769ba384d9b079"
-dependencies = [
- "anyhow",
- "cranelift-codegen",
- "cranelift-control",
-]
-
-[[package]]
-name = "cranelift-native"
-version = "0.99.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ad5966da08f1e96a3ae63be49966a85c9b249fa465f8cf1b66469a82b1004a0"
-dependencies = [
- "cranelift-codegen",
- "libc",
- "target-lexicon",
-]
-
 [[package]]
 name = "crc"
 version = "0.1.0"
@@ -476,12 +313,6 @@ dependencies = [
  "syn 2.0.100",
 ]
 
-[[package]]
-name = "discard"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
-
 [[package]]
 name = "doc-comment"
 version = "0.3.3"
@@ -503,7 +334,7 @@ dependencies = [
  "defer",
  "derive_builder",
  "driver_base_macros",
- "elf 0.7.2",
+ "elf",
  "fdt",
  "hashbrown 0.13.2",
  "ida",
@@ -553,15 +384,6 @@ version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
 
-[[package]]
-name = "elf"
-version = "0.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4841de15dbe0e49b9b62a417589299e3be0d557e0900d36acb87e6dae47197f5"
-dependencies = [
- "byteorder 0.5.3",
-]
-
 [[package]]
 name = "elf"
 version = "0.7.2"
@@ -600,15 +422,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
 dependencies = [
  "libc",
- "windows-sys 0.59.0",
+ "windows-sys",
 ]
 
-[[package]]
-name = "fallible-iterator"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
-
 [[package]]
 name = "fdt"
 version = "0.2.0-alpha1"
@@ -637,17 +453,6 @@ dependencies = [
  "wasi",
 ]
 
-[[package]]
-name = "gimli"
-version = "0.27.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
-dependencies = [
- "fallible-iterator",
- "indexmap 1.9.3",
- "stable_deref_trait",
-]
-
 [[package]]
 name = "gimli"
 version = "0.31.1"
@@ -666,15 +471,9 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
 dependencies = [
- "byteorder 1.5.0",
+ "byteorder",
 ]
 
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
 [[package]]
 name = "hashbrown"
 version = "0.13.2"
@@ -714,19 +513,13 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
 [[package]]
 name = "home"
 version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
 dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -748,16 +541,6 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
-[[package]]
-name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
-]
-
 [[package]]
 name = "indexmap"
 version = "2.8.0"
@@ -817,12 +600,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "json"
-version = "0.11.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92c245af8786f6ac35f95ca14feca9119e71339aaab41e878e7cdd655c97e9e5"
-
 [[package]]
 name = "kcmdline_macros"
 version = "0.1.0"
@@ -956,15 +733,6 @@ dependencies = [
  "hashbrown 0.15.2",
 ]
 
-[[package]]
-name = "mach"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "mach2"
 version = "0.4.2"
@@ -1192,12 +960,6 @@ dependencies = [
  "syn 2.0.100",
 ]
 
-[[package]]
-name = "proc-macro-hack"
-version = "0.5.20+deprecated"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
-
 [[package]]
 name = "proc-macro2"
 version = "1.0.94"
@@ -1286,34 +1048,13 @@ dependencies = [
 
 [[package]]
 name = "rbpf"
-version = "0.2.0"
+version = "0.3.0"
+source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/rbpf?rev=f31e471a29#f31e471a29dea9a0c272626f7b762adba755e6cc"
 dependencies = [
- "byteorder 1.5.0",
+ "byteorder",
  "combine",
- "cranelift-codegen",
- "cranelift-frontend",
- "cranelift-jit",
- "cranelift-module",
- "cranelift-native",
- "elf 0.0.10",
- "hex",
- "json",
- "libc",
- "log",
- "time",
-]
-
-[[package]]
-name = "regalloc2"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6"
-dependencies = [
- "hashbrown 0.13.2",
+ "hashbrown 0.15.2",
  "log",
- "rustc-hash",
- "slice-group-by",
- "smallvec",
 ]
 
 [[package]]
@@ -1345,18 +1086,6 @@ version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
-[[package]]
-name = "region"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0"
-dependencies = [
- "bitflags 1.3.2",
- "libc",
- "mach",
- "winapi",
-]
-
 [[package]]
 name = "ringbuffer"
 version = "0.15.0"
@@ -1378,15 +1107,6 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver",
-]
-
 [[package]]
 name = "rustix"
 version = "0.38.44"
@@ -1397,7 +1117,7 @@ dependencies = [
  "errno",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.59.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -1433,21 +1153,6 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
 [[package]]
 name = "serde"
 version = "1.0.219"
@@ -1489,21 +1194,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "sha1"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
-dependencies = [
- "sha1_smol",
-]
-
-[[package]]
-name = "sha1_smol"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
-
 [[package]]
 name = "shlex"
 version = "1.3.0"
@@ -1520,12 +1210,6 @@ dependencies = [
  "spin 0.9.8",
 ]
 
-[[package]]
-name = "slice-group-by"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
-
 [[package]]
 name = "smallvec"
 version = "1.14.0"
@@ -1539,7 +1223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97"
 dependencies = [
  "bitflags 1.3.2",
- "byteorder 1.5.0",
+ "byteorder",
  "cfg-if",
  "defmt",
  "heapless",
@@ -1567,15 +1251,6 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
-[[package]]
-name = "standback"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
-dependencies = [
- "version_check",
-]
-
 [[package]]
 name = "static-keys"
 version = "0.7.0"
@@ -1588,55 +1263,6 @@ dependencies = [
  "windows 0.59.0",
 ]
 
-[[package]]
-name = "stdweb"
-version = "0.4.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
-dependencies = [
- "discard",
- "rustc_version",
- "stdweb-derive",
- "stdweb-internal-macros",
- "stdweb-internal-runtime",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "stdweb-derive"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "stdweb-internal-macros"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
-dependencies = [
- "base-x",
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "serde_json",
- "sha1",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "stdweb-internal-runtime"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
-
 [[package]]
 name = "strsim"
 version = "0.11.1"
@@ -1677,12 +1303,6 @@ dependencies = [
  "num-traits 0.2.15",
 ]
 
-[[package]]
-name = "target-lexicon"
-version = "0.12.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
-
 [[package]]
 name = "target-triple"
 version = "0.1.4"
@@ -1727,44 +1347,6 @@ dependencies = [
  "syn 2.0.100",
 ]
 
-[[package]]
-name = "time"
-version = "0.2.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
-dependencies = [
- "const_fn",
- "libc",
- "standback",
- "stdweb",
- "time-macros",
- "version_check",
- "winapi",
-]
-
-[[package]]
-name = "time-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
-dependencies = [
- "proc-macro-hack",
- "time-macros-impl",
-]
-
-[[package]]
-name = "time-macros-impl"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
-dependencies = [
- "proc-macro-hack",
- "proc-macro2",
- "quote",
- "standback",
- "syn 1.0.109",
-]
-
 [[package]]
 name = "toml"
 version = "0.8.20"
@@ -1792,7 +1374,7 @@ version = "0.22.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
 dependencies = [
- "indexmap 2.8.0",
+ "indexmap",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -1900,7 +1482,7 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "637d511437df708cee34bdec7ba2f1548d256b7acf3ff20e0a1c559f9bf3a987"
 dependencies = [
- "gimli 0.31.1",
+ "gimli",
 ]
 
 [[package]]
@@ -1944,75 +1526,6 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
-dependencies = [
- "cfg-if",
- "once_cell",
- "rustversion",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
-dependencies = [
- "bumpalo",
- "log",
- "proc-macro2",
- "quote",
- "syn 2.0.100",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.100",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "wasmtime-jit-icache-coherence"
-version = "12.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b59f94b0409221873565419168e20b5aedf18c4bd64de5c38acf8f0634efeee3"
-dependencies = [
- "cfg-if",
- "libc",
- "windows-sys 0.48.0",
-]
-
 [[package]]
 name = "which"
 version = "4.4.2"
@@ -2047,7 +1560,7 @@ version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
 dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -2189,15 +1702,6 @@ dependencies = [
  "windows-link",
 ]
 
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.59.0"
@@ -2207,21 +1711,6 @@ dependencies = [
  "windows-targets 0.52.6",
 ]
 
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
 [[package]]
 name = "windows-targets"
 version = "0.52.6"
@@ -2254,12 +1743,6 @@ dependencies = [
  "windows_x86_64_msvc 0.53.0",
 ]
 
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.52.6"
@@ -2272,12 +1755,6 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
 
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.52.6"
@@ -2290,12 +1767,6 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
 
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
 [[package]]
 name = "windows_i686_gnu"
 version = "0.52.6"
@@ -2320,12 +1791,6 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
 
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
 [[package]]
 name = "windows_i686_msvc"
 version = "0.52.6"
@@ -2338,12 +1803,6 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
 
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.52.6"
@@ -2356,12 +1815,6 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
 
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.52.6"
@@ -2374,12 +1827,6 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
 
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.52.6"
@@ -2458,7 +1905,7 @@ version = "0.7.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
 dependencies = [
- "byteorder 1.5.0",
+ "byteorder",
  "zerocopy-derive 0.7.35",
 ]
 

+ 1 - 1
kernel/Cargo.toml

@@ -75,7 +75,7 @@ log = "0.4.21"
 kprobe = { path = "crates/kprobe" }
 lru = "0.12.3"
 
-rbpf = { path = "crates/rbpf" }
+rbpf = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/rbpf", rev = "f31e471a29", default-features = false }
 printf-compat = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/printf-compat", rev = "5f5c9cc363", default-features = false }
 
 static-keys = { version = "=0.7" }

+ 1 - 4
kernel/Makefile

@@ -41,7 +41,4 @@ check: ECHO
 
 test:
 # 测试内核库
-	RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-11-05 test --workspace --exclude dragonos_kernel rbpf
-
-test-rbpf:
-	cd crates/rbpf && RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-11-05 test --features=std,user,cranelift
+	RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-11-05 test --workspace --exclude dragonos_kernel

+ 0 - 21
kernel/crates/rbpf/.appveyor.yml

@@ -1,21 +0,0 @@
-version: 1.0.{build}
-branches:
-  only:
-    - main
-os:
-  - Visual Studio 2015
-clone_depth: 1
-configuration:
-  - Debug
-platform:
-  - x64
-environment:
-  matrix:
-    - TOOLCHAIN_VERSION: 14.0
-      RUST: 1.76.0
-    - TOOLCHAIN_VERSION: 14.0
-      RUST: beta
-    - TOOLCHAIN_VERSION: 14.0
-      RUST: nightly
-
-build_script: mk/appveyor.bat

+ 0 - 2
kernel/crates/rbpf/.gitignore

@@ -1,2 +0,0 @@
-target
-Cargo.lock

+ 0 - 78
kernel/crates/rbpf/Cargo.toml

@@ -1,78 +0,0 @@
-[package]
-
-# Project metadata
-name = "rbpf"
-version = "0.2.0"
-authors = ["Quentin <quentin@isovalent.com>"]
-
-# Additional metadata for packaging
-description = "Virtual machine and JIT compiler for eBPF programs"
-repository = "https://github.com/qmonnet/rbpf"
-readme = "README.md"
-keywords = ["BPF", "eBPF", "interpreter", "JIT", "filtering"]
-license = "Apache-2.0/MIT"
-edition = "2021"
-
-# Packaging directives
-include = [
-    "src/**",
-    "examples/**",
-    "tests/**",
-    "bench/**",
-    "LICENSE*",
-    "Cargo.toml",
-]
-
-[dependencies]
-
-# Default features (std) are disabled so that the dependencies don't pull in the
-# standard library when the crate is compiled for no_std
-byteorder = { version = "1.2", default-features = false }
-log = {version = "0.4.21", default-features = false }
-combine = { version = "4.6", default-features = false }
-
-# Optional Dependencies when using the standard library
-libc = { version = "0.2", optional = true }
-time = { version = "0.2", optional = true }
-
-# Optional Dependencies for the CraneLift JIT
-cranelift-codegen = { version = "0.99", optional = true }
-cranelift-frontend = { version = "0.99", optional = true }
-cranelift-jit = { version = "0.99", optional = true }
-cranelift-native = { version = "0.99", optional = true }
-cranelift-module = { version = "0.99", optional = true }
-
-[dev-dependencies]
-
-elf = "0.0.10"
-json = "0.11"
-hex = "0.4.3"
-
-[features]
-#default = ["std", "user", "cranelift"]
-cargo-clippy = []
-std = ["dep:time", "dep:libc", "combine/std"]
-cranelift = [
-    "dep:cranelift-codegen",
-    "dep:cranelift-frontend",
-    "dep:cranelift-jit",
-    "dep:cranelift-native",
-    "dep:cranelift-module",
-]
-user = []
-
-# Examples that depend on the standard library should be disabled when
-# testing the `no_std` configuration.
-[[example]]
-name = "disassemble"
-required-features = ["std"]
-
-[[example]]
-name = "uptime"
-required-features = ["std"]
-
-[[example]]
-name = "to_json"
-
-[[example]]
-name = "rbpf_plugin"

+ 0 - 202
kernel/crates/rbpf/LICENSE-APACHE

@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.

+ 0 - 25
kernel/crates/rbpf/LICENSE-MIT

@@ -1,25 +0,0 @@
-Copyright (c) 2016 6WIND S.A.
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.

+ 0 - 743
kernel/crates/rbpf/README.md

@@ -1,743 +0,0 @@
-# rbpf
-
-<picture>
-  <source media="(prefers-color-scheme: dark)" srcset="misc/rbpf_256_border.png">
-  <img src="misc/rbpf_256.png">
-</picture>
-
-Rust (user-space) virtual machine for eBPF
-
-[![Build Status](https://github.com/qmonnet/rbpf/actions/workflows/test.yaml/badge.svg)](https://github.com/qmonnet/rbpf/actions/workflows/test.yaml)
-[![Build status](https://ci.appveyor.com/api/projects/status/ia74coeuhxtrcvsk/branch/main?svg=true)](https://ci.appveyor.com/project/qmonnet/rbpf/branch/main)
-[![Coverage Status](https://coveralls.io/repos/github/qmonnet/rbpf/badge.svg?branch=main)](https://coveralls.io/github/qmonnet/rbpf?branch=main)
-[![Crates.io](https://img.shields.io/crates/v/rbpf.svg)](https://crates.io/crates/rbpf)
-
-* [Description](#description)
-* [Link to the crate](#link-to-the-crate)
-* [API](#api)
-* [Example uses](#example-uses)
-* [Building eBPF programs](#building-ebpf-programs)
-* [Build Features](#build-features)
-* [Feedback welcome!](#feedback-welcome)
-* [Questions / Answers](#questions--answers)
-* [Caveats](#caveats)
-* [_To do_ list](#to-do-list)
-* [License](#license)
-* [Inspired by](#inspired-by)
-* [Other resources](#other-resources)
-
-## Description
-
-This crate contains a virtual machine for eBPF program execution. BPF, as in
-_Berkeley Packet Filter_, is an assembly-like language initially developed for
-BSD systems, in order to filter packets in the kernel with tools such as
-tcpdump so as to avoid useless copies to user-space. It was ported to Linux,
-where it evolved into eBPF (_extended_ BPF), a faster version with more
-features. While BPF programs are originally intended to run in the kernel, the
-virtual machine of this crate enables running it in user-space applications;
-it contains an interpreter, an x86_64 JIT-compiler for eBPF programs, as well as
-a disassembler.
-
-It is based on Rich Lane's [uBPF software](https://github.com/iovisor/ubpf/),
-which does nearly the same, but is written in C.
-
-The crate is supposed to compile and run on Linux, MacOS X, and Windows,
-although the JIT-compiler does not work with Windows at this time.
-
-## Link to the crate
-
-This crate is available from [crates.io](https://crates.io/crates/rbpf), so it
-should work out of the box by adding it as a dependency in your `Cargo.toml`
-file:
-
-```toml
-[dependencies]
-rbpf = "0.2.0"
-```
-
-You can also use the development version from this GitHub repository. This
-should be as simple as putting this inside your `Cargo.toml`:
-
-```toml
-[dependencies]
-rbpf = { git = "https://github.com/qmonnet/rbpf" }
-```
-
-Of course, if you prefer, you can clone it locally, possibly hack the crate,
-and then indicate the path of your local version in `Cargo.toml`:
-
-```toml
-[dependencies]
-rbpf = { path = "path/to/rbpf" }
-```
-
-Then indicate in your source code that you want to use the crate:
-
-```rust,ignore
-extern crate rbpf;
-```
-
-## API
-
-The API is pretty well documented inside the source code. You should also be
-able to access [an online version of the documentation from
-here](https://docs.rs/rbpf/), automatically generated from the
-[crates.io](https://crates.io/crates/rbpf) version (may not be up-to-date with
-the main branch). [Examples](../../tree/main/examples) and [unit
-tests](../../tree/main/tests) should also prove helpful. Here is a summary of
-how to use the crate.
-
-Here are the steps to follow to run an eBPF program with rbpf:
-
-1. Create a virtual machine. There are several kinds of machines, we will come
-   back on this later. When creating the VM, pass the eBPF program as an
-   argument to the constructor.
-2. If you want to use some helper functions, register them into the virtual
-   machine.
-3. If you want a JIT-compiled program, compile it.
-4. Execute your program: either run the interpreter or call the JIT-compiled
-   function.
-
-eBPF has been initially designed to filter packets (now it has some other hooks
-in the Linux kernel, such as kprobes, but this is not covered by rbpf). As a
-consequence, most of the load and store instructions of the program are
-performed on a memory area representing the packet data. However, in the Linux
-kernel, the eBPF program does not immediately access this data area: initially,
-it has access to a C `struct sk_buff` instead, which is a buffer containing
-metadata about the packet—including memory addresses of the beginning and of
-the end of the packet data area. So the program first loads those pointers from
-the `sk_buff`, and then can access the packet data.
-
-This behavior can be replicated with rbpf, but it is not mandatory. For this
-reason, we have several structs representing different kinds of virtual
-machines:
-
-* `struct EbpfVmMbuffer` mimics the kernel. When the program is run, the
-  address provided to its first eBPF register will be the address of a metadata
-  buffer provided by the user, and that is expected to contain pointers to the
-  start and the end of the packet data memory area.
-
-* `struct EbpfVmFixedMbuff` has one purpose: enabling the execution of programs
-  created to be compatible with the kernel, while saving the effort to manually
-  handle the metadata buffer for the user. In fact, this struct has a static
-  internal buffer that is passed to the program. The user has to indicate the
-  offset values at which the eBPF program expects to find the start and the end
-  of packet data in the buffer. On calling the function that runs the program
-  (JITted or not), the struct automatically updates the addresses in this
-  static buffer, at the appointed offsets, for the start and the end of the
-  packet data the program is called upon.
-
-* `struct EbpfVmRaw` is for programs that want to run directly on packet data.
-  No metadata buffer is involved, the eBPF program directly receives the
-  address of the packet data in its first register. This is the behavior of
-  uBPF.
-
-* `struct EbpfVmNoData` does not take any data. The eBPF program takes no
-  argument whatsoever and its return value is deterministic. Not so sure there
-  is a valid use case for that, but if nothing else, this is very useful for
-  unit tests.
-
-All these structs implement the same public functions:
-
-```rust,ignore
-// called with EbpfVmMbuff:: prefix
-pub fn new(prog: &'a [u8]) -> Result<EbpfVmMbuff<'a>, Error>
-
-// called with EbpfVmFixedMbuff:: prefix
-pub fn new(prog: &'a [u8],
-           data_offset: usize,
-           data_end_offset: usize) -> Result<EbpfVmFixedMbuff<'a>, Error>
-
-// called with EbpfVmRaw:: prefix
-pub fn new(prog: &'a [u8]) -> Result<EbpfVmRaw<'a>, Error>
-
-// called with EbpfVmNoData:: prefix
-pub fn new(prog: &'a [u8]) -> Result<EbpfVmNoData<'a>, Error>
-```
-
-This is used to create a new instance of a VM. The return type is dependent of
-the struct from which the function is called. For instance,
-`rbpf::EbpfVmRaw::new(Some(my_program))` would return an instance of `struct
-rbpf::EbpfVmRaw` (wrapped in a `Result`). When a program is loaded, it is
-checked with a very simple verifier (nothing close to the one for Linux
-kernel). Users are also able to replace it with a custom verifier.
-
-For `struct EbpfVmFixedMbuff`, two additional arguments must be passed to the
-constructor: `data_offset` and `data_end_offset`. They are the offset (byte
-number) at which the pointers to the beginning and to the end, respectively, of
-the memory area of packet data are to be stored in the internal metadata buffer
-each time the program is executed. Other structs do not use this mechanism and
-do not need those offsets.
-
-```rust,ignore
-// for struct EbpfVmMbuff, struct EbpfVmRaw and struct EbpfVmRawData
-pub fn set_program(&mut self, prog: &'a [u8]) -> Result<(), Error>
-
-// for struct EbpfVmFixedMbuff
-pub fn set_program(&mut self, prog: &'a [u8],
-                data_offset: usize,
-                data_end_offset: usize) -> Result<(), Error>
-```
-
-You can use for example `my_vm.set_program(my_program);` to change the loaded
-program after the VM instance creation. This program is checked with the
-verifier attached to the VM. The verifying function of the VM can be changed at
-any moment.
-
-```rust,ignore
-pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
-
-pub fn set_verifier(&mut self,
-                    verifier: Verifier) -> Result<(), Error>
-```
-
-Note that if a program has already been loaded into the VM, setting a new
-verifier also immediately runs it on the loaded program. However, the verifier
-is not run if no program has been loaded (if `None` was passed to the `new()`
-method when creating the VM).
-
-```rust,ignore
-pub type Helper = fn (u64, u64, u64, u64, u64) -> u64;
-
-pub fn register_helper(&mut self,
-                       key: u32,
-                       function: Helper) -> Result<(), Error>
-```
-
-This function is used to register a helper function. The VM stores its
-registers in a hashmap, so the key can be any `u32` value you want. It may be
-useful for programs that should be compatible with the Linux kernel and
-therefore must use specific helper numbers.
-
-```rust,ignore
-// for struct EbpfVmMbuff
-pub fn execute_program(&self,
-                 mem: &'a mut [u8],
-                 mbuff: &'a mut [u8]) -> Result<(u64), Error>
-
-// for struct EbpfVmFixedMbuff and struct EbpfVmRaw
-pub fn execute_program(&self,
-                 mem: &'a mut [u8]) -> Result<(u64), Error>
-
-// for struct EbpfVmNoData
-pub fn execute_program(&self) -> Result<(u64), Error>
-```
-
-Interprets the loaded program. The function takes a reference to the packet
-data and the metadata buffer, or only to the packet data, or nothing at all,
-depending on the kind of the VM used. The value returned is the result of the
-eBPF program.
-
-```rust,ignore
-pub fn jit_compile(&mut self) -> Result<(), Error>
-```
-
-JIT-compile the loaded program, for x86_64 architecture. If the program is to
-use helper functions, they must be registered into the VM before this function
-is called. The generated assembly function is internally stored in the VM.
-
-```rust,ignore
-// for struct EbpfVmMbuff
-pub unsafe fn execute_program_jit(&self, mem: &'a mut [u8],
-                            mbuff: &'a mut [u8]) -> Result<(u64), Error>
-
-// for struct EbpfVmFixedMbuff and struct EbpfVmRaw
-pub unsafe fn execute_program_jit(&self, mem: &'a mut [u8]) -> Result<(u64), Error>
-
-// for struct EbpfVmNoData
-pub unsafe fn execute_program_jit(&self) -> Result<(u64), Error>
-```
-
-Calls the JIT-compiled program. The arguments to provide are the same as for
-`execute_program()`, again depending on the kind of VM that is used. The result of
-the JIT-compiled program should be the same as with the interpreter, but it
-should run faster. Note that if errors occur during the program execution, the
-JIT-compiled version does not handle it as well as the interpreter, and the
-program may crash. For this reason, the functions are marked as `unsafe`.
-
-## Example uses
-
-### Simple example
-
-This comes from the unit test `test_vm_add`.
-
-```rust
-extern crate rbpf;
-
-fn main() {
-
-    // This is the eBPF program, in the form of bytecode instructions.
-    let prog = &[
-        0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov32 r0, 0
-        0xb4, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov32 r1, 2
-        0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // add32 r0, 1
-        0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // add32 r0, r1
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    ];
-
-    // Instantiate a struct EbpfVmNoData. This is an eBPF VM for programs that
-    // takes no packet data in argument.
-    // The eBPF program is passed to the constructor.
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-
-    // Execute (interpret) the program. No argument required for this VM.
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-}
-```
-
-### With JIT, on packet data
-
-This comes from the unit test `test_jit_ldxh`.
-
-```rust
-extern crate rbpf;
-
-fn main() {
-    let prog = &[
-        0x71, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxh r0, [r1+2]
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    ];
-
-    // Let's use some data.
-    let mem = &mut [
-        0xaa, 0xbb, 0x11, 0xcc, 0xdd
-    ];
-
-    // This is an eBPF VM for programs reading from a given memory area (it
-    // directly reads from packet data)
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-
-    #[cfg(any(windows, not(feature = "std")))] {
-        assert_eq!(vm.execute_program(mem).unwrap(), 0x11);
-    }
-    #[cfg(all(not(windows), feature = "std"))] {
-        // This time we JIT-compile the program.
-        vm.jit_compile().unwrap();
-
-        // Then we execute it. For this kind of VM, a reference to the packet
-        // data must be passed to the function that executes the program.
-        unsafe { assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11); }
-    }
-}
-```
-### Using a metadata buffer
-
-This comes from the unit test `test_jit_mbuff` and derives from the unit test
-`test_jit_ldxh`.
-
-```rust
-extern crate rbpf;
-
-fn main() {
-    let prog = &[
-        // Load mem from mbuff at offset 8 into R1
-        0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
-        // ldhx r1[2], r0
-        0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-    ];
-    let mem = &mut [
-        0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    ];
-
-    // Just for the example we create our metadata buffer from scratch, and
-    // we store the pointers to packet data start and end in it.
-    let mut mbuff = &mut [0u8; 32];
-    unsafe {
-        let mut data     = mbuff.as_ptr().offset(8)  as *mut u64;
-        let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-        *data     = mem.as_ptr() as u64;
-        *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-    }
-
-    // This eBPF VM is for program that use a metadata buffer.
-    let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-
-    #[cfg(any(windows, not(feature = "std")))] {
-        assert_eq!(vm.execute_program(mem, mbuff).unwrap(), 0x2211);
-    }
-    #[cfg(all(not(windows), feature = "std"))] {
-        // Here again we JIT-compile the program.
-        vm.jit_compile().unwrap();
-
-        // Here we must provide both a reference to the packet data, and to the
-        // metadata buffer we use.
-        unsafe {
-            assert_eq!(vm.execute_program_jit(mem, mbuff).unwrap(), 0x2211);
-        }
-    }
-}
-```
-
-### Loading code from an object file; and using a virtual metadata buffer
-
-This comes from unit test `test_vm_block_port`.
-
-This example requires the following additional crates, you may have to add them
-to your `Cargo.toml` file.
-
-```toml
-[dependencies]
-rbpf = "0.2.0"
-elf = "0.0.10"
-```
-
-It also uses a kind of VM that uses an internal buffer used to simulate the
-`sk_buff` used by eBPF programs in the kernel, without having to manually
-create a new buffer for each packet. It may be useful for programs compiled for
-the kernel and that assumes the data they receive is a `sk_buff` pointing to
-the packet data start and end addresses. So here we just provide the offsets at
-which the eBPF program expects to find those pointers, and the VM handles the
-buffer update so that we only have to provide a reference to the packet data
-for each run of the program.
-
-```rust
-extern crate elf;
-use std::path::PathBuf;
-
-extern crate rbpf;
-use rbpf::helpers;
-
-fn main() {
-    // Load a program from an ELF file, e.g. compiled from C to eBPF with
-    // clang/LLVM. Some minor modification to the bytecode may be required.
-    let filename = "examples/load_elf__block_a_port.elf";
-
-    let path = PathBuf::from(filename);
-    let file = match elf::File::open_path(&path) {
-        Ok(f) => f,
-        Err(e) => panic!("Error: {:?}", e),
-    };
-
-    // Here we assume the eBPF program is in the ELF section called
-    // ".classifier".
-    let text_scn = match file.get_section(".classifier") {
-        Some(s) => s,
-        None => panic!("Failed to look up .classifier section"),
-    };
-
-    let prog = &text_scn.data;
-
-    // This is our data: a real packet, starting with Ethernet header
-    let packet = &mut [
-        0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
-        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
-        0x08, 0x00,             // ethertype
-        0x45, 0x00, 0x00, 0x3b, // start ip_hdr
-        0xa6, 0xab, 0x40, 0x00,
-        0x40, 0x06, 0x96, 0x0f,
-        0x7f, 0x00, 0x00, 0x01,
-        0x7f, 0x00, 0x00, 0x01,
-        0x99, 0x99, 0xc6, 0xcc, // start tcp_hdr
-        0xd1, 0xe5, 0xc4, 0x9d,
-        0xd4, 0x30, 0xb5, 0xd2,
-        0x80, 0x18, 0x01, 0x56,
-        0xfe, 0x2f, 0x00, 0x00,
-        0x01, 0x01, 0x08, 0x0a, // start data
-        0x00, 0x23, 0x75, 0x89,
-        0x00, 0x23, 0x63, 0x2d,
-        0x71, 0x64, 0x66, 0x73,
-        0x64, 0x66, 0x0a
-    ];
-
-    // This is an eBPF VM for programs using a virtual metadata buffer, similar
-    // to the sk_buff that eBPF programs use with tc and in Linux kernel.
-    // We must provide the offsets at which the pointers to packet data start
-    // and end must be stored: these are the offsets at which the program will
-    // load the packet data from the metadata buffer.
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-
-    // We register a helper function, that can be called by the program, into
-    // the VM. The `bpf_trace_printf` is only available when we have access to
-    // the standard library.
-    #[cfg(feature = "std")] {
-        vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX,
-                           helpers::bpf_trace_printf).unwrap();
-    }
-
-    // This kind of VM takes a reference to the packet data, but does not need
-    // any reference to the metadata buffer: a fixed buffer is handled
-    // internally by the VM.
-    let res = vm.execute_program(packet).unwrap();
-    println!("Program returned: {:?} ({:#x})", res, res);
-}
-```
-
-## Building eBPF programs
-
-Besides passing the raw hexadecimal codes for building eBPF programs, two other
-methods are available.
-
-### Assembler
-
-The first method consists in using the assembler provided by the crate.
-
-```rust
-extern crate rbpf;
-use rbpf::assembler::assemble;
-
-let prog = assemble("add64 r1, 0x605
-                     mov64 r2, 0x32
-                     mov64 r1, r0
-                     be16 r0
-                     neg64 r2
-                     exit").unwrap();
-
-#[cfg(feature = "std")] {
-    println!("{:?}", prog);
-}
-```
-
-The above snippet will produce:
-
-```rust,ignore
-Ok([0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
-    0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
-    0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-    0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
-```
-
-Conversely, a disassembler is also available to dump instruction names from
-bytecode in a human-friendly format.
-
-```rust
-extern crate rbpf;
-use rbpf::disassembler::disassemble;
-
-let prog = &[
-    0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
-    0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
-    0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-    0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-];
-
-disassemble(prog);
-```
-
-This will produce the following output:
-
-```txt
-add64 r1, 0x605
-mov64 r2, 0x32
-mov64 r1, r0
-be16 r0
-neg64 r2
-exit
-```
-
-Please refer to [source code](src/assembler.rs) and [tests](tests/assembler.rs)
-for the syntax and the list of instruction names.
-
-### Building API
-
-The other way to build programs is to chain commands from the instruction
-builder API. It looks less like assembly, maybe more like high-level functions.
-What's sure is that the result is more verbose, but if you prefer to build
-programs this way, it works just as well. If we take again the same sample as
-above, it would be constructed as follows.
-
-```rust
-extern crate rbpf;
-use rbpf::insn_builder::*;
-
-let mut program = BpfCode::new();
-program.add(Source::Imm, Arch::X64).set_dst(1).set_imm(0x605).push()
-       .mov(Source::Imm, Arch::X64).set_dst(2).set_imm(0x32).push()
-       .mov(Source::Reg, Arch::X64).set_src(0).set_dst(1).push()
-       .swap_bytes(Endian::Big).set_dst(0).set_imm(0x10).push()
-       .negate(Arch::X64).set_dst(2).push()
-       .exit().push();
-```
-
-Again, please refer to [the source and related tests](src/insn_builder.rs) to
-get more information and examples on how to use it.
-
-## Build features
-
-### `no_std`
-
-The `rbpf` crate has a Cargo feature named "std" that is enabled by default. To
-use `rbpf` in `no_std` environments this feature needs to be disabled. To do
-this, you need to modify your dependency on `rbpf` in Cargo.toml to disable the
-enabled-by-default features.
-
-```toml
-[dependencies]
-rbpf = { version = "1.0", default-features = false }
-```
-
-Note that when using this crate in `no_std` environments, the `jit` module
-isn't available. This is because it depends on functions provided by `libc`
-(`libc::posix_memalign()`, `libc::mprotect()`) which aren't available on
-`no_std`.
-
-The `assembler` module is available, albeit with reduced debugging features. It
-depends on the `combine` crate providing parser combinators. Under `no_std`
-this crate only provides simple parsers which generate less descriptive error
-messages.
-
-## Feedback welcome!
-
-This is the author's first try at writing Rust code. He learned a lot in the
-process, but there remains a feeling that this crate has a kind of C-ish style
-in some places instead of the Rusty look the author would like it to have. So
-feedback (or PRs) are welcome, including about ways you might see to take
-better advantage of Rust features.
-
-Note that the project expects new commits to be covered by the
-[Developer's Certificate of Origin](https://wiki.linuxfoundation.org/dco).
-When contributing Pull Requests, please sign off your commits accordingly.
-
-## Questions / Answers
-
-### Why implementing an eBPF virtual machine in Rust?
-
-As of this writing, there is no particular use case for this crate at the best
-of the author's knowledge. The author happens to work with BPF on Linux and to
-know how uBPF works, and he wanted to learn and experiment with Rust—no more
-than that.
-
-### What are the differences with uBPF?
-
-Other than the language, obviously? Well, there are some differences:
-
-* Some constants, such as the maximum length for programs or the length for the
-  stack, differs between uBPF and rbpf. The latter uses the same values as the
-  Linux kernel, while uBPF has its own values.
-
-* When an error occurs while a program is run by uBPF, the function running the
-  program silently returns the maximum value as an error code, while rbpf
-  returns Rust type `Error`.
-
-* The registration of helper functions, that can be called from within an eBPF
-  program, is not handled in the same way.
-
-* The distinct structs permitting to run program either on packet data, or with
-  a metadata buffer (simulated or not) is a specificity of rbpf.
-
-* As for performance: theoretically the JITted programs are expected to run at
-  the same speed, while the C interpreter of uBPF should go slightly faster
-  than rbpf. But this has not been asserted yet. Benchmarking both programs
-  would be an interesting thing to do.
-
-### Can I use it with the “classic” BPF (a.k.a cBPF) version?
-
-No. This crate only works with extended BPF (eBPF) programs. For cBPF programs,
-such as used by tcpdump (as of this writing) for example, you may be interested
-in the [bpfjit crate](https://crates.io/crates/bpfjit) written by Alexander
-Polakov instead.
-
-### What functionalities are implemented?
-
-Running and JIT-compiling eBPF programs work. There is also a mechanism to
-register user-defined helper functions. The eBPF implementation of the Linux
-kernel comes with [some additional
-features](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md):
-a high number of helpers, several kinds of maps, tail calls.
-
-* Additional helpers should be easy to add, but very few of the existing Linux
-  helpers have been replicated in rbpf so far.
-
-* Tail calls (“long jumps” from an eBPF program into another) are not
-  implemented. This is probably not trivial to design and implement.
-
-* The interaction with maps is done through the use of specific helpers, so
-  this should not be difficult to add. The maps themselves can reuse the maps
-  in the kernel (if on Linux), to communicate with in-kernel eBPF programs for
-  instance; or they can be handled in user space. Rust has arrays and hashmaps,
-  so their implementation should be pretty straightforward (and may be added to
-  rbpf in the future).
-
-### What about program validation?
-
-The ”verifier” of this crate is very short and has nothing to do with the
-kernel verifier, which means that it accepts programs that may not be safe. On
-the other hand, you probably do not run this in a kernel here, so it will not
-crash your system. Implementing a verifier similar to the one in the kernel is
-not trivial, and we cannot “copy” it since it is under GPL license.
-
-### What about safety then?
-
-Rust has a strong emphasis on safety. Yet to have the eBPF VM work, some
-`unsafe` blocks of code are used. The VM, taken as an eBPF interpreter, can
-return an error but should not crash. Please file an issue otherwise.
-
-As for the JIT-compiler, it is a different story, since runtime memory checks
-are more complicated to implement in assembly. It _will_ crash if your
-JIT-compiled program tries to perform unauthorized memory accesses. Usually, it
-could be a good idea to test your program with the interpreter first.
-
-Oh, and if your program has infinite loops, even with the interpreter, you're
-on your own.
-
-## Caveats
-
-* This crate is **under development** and the API may be subject to change.
-
-* The JIT compiler produces an unsafe program: memory access are not tested at
-  runtime (yet). Use with caution.
-
-* A small number of eBPF instructions have not been implemented yet. This
-  should not be a problem for the majority of eBPF programs.
-
-* Beware of turnips. Turnips are disgusting.
-
-## _To do_ list
-
-* Implement some traits (`Clone`, `Drop`, `Debug` are good candidates).
-* Provide built-in support for user-space array and hash BPF maps.
-* Improve safety of JIT-compiled programs with runtime memory checks.
-* Add helpers (some of those supported in the kernel, such as checksum update,
-  could be helpful).
-* Improve verifier. Could we find a way to directly support programs compiled
-  with clang?
-* Maybe one day, tail calls?
-* JIT-compilers for other architectures?
-* …
-
-## License
-
-Following the effort of the Rust language project itself in order to ease
-integration with other projects, the rbpf crate is distributed under the terms
-of both the MIT license and the Apache License (Version 2.0).
-
-See
-[LICENSE-APACHE](https://github.com/qmonnet/rbpf/blob/main/LICENSE-APACHE)
-and [LICENSE-MIT](https://github.com/qmonnet/rbpf/blob/main/LICENSE-MIT) for
-details.
-
-## Version
-[The last commit](https://github.com/qmonnet/rbpf/commit/fe7021b07b08a43b836743a77796d07ce1f4902e)
-
-
-## Inspired by
-
-* [uBPF](https://github.com/iovisor/ubpf), a C user-space implementation of an
-  eBPF virtual machine, with a JIT-compiler and disassembler (and also
-  including the assembler from the human-readable form of the instructions,
-  such as in `mov r0, 0x1337`), by Rich Lane for Big Switch Networks (2015)
-
-* [_Building a simple JIT in
-  Rust_](https://www.sophiajt.com/building-a-simple-jit-in-rust),
-  by Sophia Turner (2015)
-
-* [bpfjit](https://github.com/polachok/bpfjit) (also [on
-  crates.io](https://crates.io/crates/bpfjit)), a Rust crate exporting the cBPF
-  JIT compiler from FreeBSD 10 tree to Rust, by Alexander Polakov (2016)
-
-## Other resources
-
-* Cilium project documentation about BPF: [_BPF and XDP Reference
-  Guide_](http://docs.cilium.io/en/latest/bpf/)
-
-* [Kernel documentation about BPF](https://docs.kernel.org/bpf/)
-
-* [_Dive into BPF: a list of reading
-  material_](https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf),
-  a blog article listing documentation for BPF and related technologies (2016)
-
-* [The Rust programming language](https://www.rust-lang.org)

+ 0 - 1
kernel/crates/rbpf/clippy.toml

@@ -1 +0,0 @@
-doc-valid-idents = ["eBPF", "uBPF"] 

+ 0 - 26
kernel/crates/rbpf/examples/disassemble.rs

@@ -1,26 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 6WIND S.A. <quentin.monnet@6wind.com>
-
-extern crate rbpf;
-use rbpf::disassembler;
-
-// Simply disassemble a program into human-readable instructions.
-fn main() {
-    let prog = &[
-        0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x12, 0x50, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x79, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x13, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2d, 0x23, 0x12, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x69, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x02, 0x10, 0x00,
-        0x08, 0x00, 0x00, 0x00, 0x71, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x02, 0x0e,
-        0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf,
-        0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
-        0x15, 0x02, 0x08, 0x00, 0x99, 0x99, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff,
-        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x21, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x18, 0x02, 0x00, 0x00, 0x00,
-        0x00, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x21, 0x01, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    disassembler::disassemble(prog);
-}

+ 0 - 3
kernel/crates/rbpf/examples/helper.rs

@@ -1,3 +0,0 @@
-fn main() {
-    rbpf::helpers::show_helper();
-}

+ 0 - 115
kernel/crates/rbpf/examples/load_elf.rs

@@ -1,115 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-#![allow(clippy::unreadable_literal)]
-
-extern crate elf;
-use std::path::PathBuf;
-
-extern crate rbpf;
-use rbpf::helpers;
-
-// The following example uses an ELF file that has been compiled from the C program available in
-// `load_elf__block_a_port.c` in the same directory.
-//
-// It was compiled with the following command:
-//
-// ```bash
-// clang -O2 -emit-llvm -c load_elf__block_a_port.c -o - | \
-//     llc -march=bpf -filetype=obj -o load_elf__block_a_port.o
-// ```
-//
-// Once compiled, this program can be injected into Linux kernel, with tc for instance. Sadly, we
-// need to bring some modifications to the generated bytecode in order to run it: the three
-// instructions with opcode 0x61 load data from a packet area as 4-byte words, where we need to
-// load it as 8-bytes double words (0x79). The kernel does the same kind of translation before
-// running the program, but rbpf does not implement this.
-//
-// In addition, the offset at which the pointer to the packet data is stored must be changed: since
-// we use 8 bytes instead of 4 for the start and end addresses of the data packet, we cannot use
-// the offsets produced by clang (0x4c and 0x50), the addresses would overlap. Instead we can use,
-// for example, 0x40 and 0x50.
-//
-// These change were applied with the following script:
-//
-// ```bash
-// xxd load_elf__block_a_port.o | sed '
-//     s/6112 5000 0000 0000/7912 5000 0000 0000/ ;
-//     s/6111 4c00 0000 0000/7911 4000 0000 0000/ ;
-//     s/6111 2200 0000 0000/7911 2200 0000 0000/' | xxd -r > load_elf__block_a_port.tmp
-
-// mv load_elf__block_a_port.tmp load_elf__block_a_port.o
-// ```
-//
-// The eBPF program was placed into the `.classifier` ELF section (see C code above), which means
-// that you can retrieve the raw bytecode with `readelf -x .classifier load_elf__block_a_port.o` or
-// with `objdump -s -j .classifier load_elf__block_a_port.o`.
-//
-// Once the bytecode has been edited, we can load the bytecode directly from the ELF object file.
-
-fn main() {
-    let filename = "examples/load_elf__block_a_port.elf";
-
-    let path = PathBuf::from(filename);
-    let file = match elf::File::open_path(path) {
-        Ok(f) => f,
-        Err(e) => panic!("Error: {:?}", e),
-    };
-
-    let text_scn = match file.get_section(".classifier") {
-        Some(s) => s,
-        None => panic!("Failed to look up .classifier section"),
-    };
-
-    let prog = &text_scn.data;
-
-    let packet1 = &mut [
-        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x08,
-        0x00, // ethertype
-        0x45, 0x00, 0x00, 0x3b, // start ip_hdr
-        0xa6, 0xab, 0x40, 0x00, 0x40, 0x06, 0x96, 0x0f, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00,
-        0x01,
-        // Program matches the next two bytes: 0x9999 returns 0xffffffff, else return 0.
-        0x99, 0x99, 0xc6, 0xcc, // start tcp_hdr
-        0xd1, 0xe5, 0xc4, 0x9d, 0xd4, 0x30, 0xb5, 0xd2, 0x80, 0x18, 0x01, 0x56, 0xfe, 0x2f, 0x00,
-        0x00, 0x01, 0x01, 0x08, 0x0a, // start data
-        0x00, 0x23, 0x75, 0x89, 0x00, 0x23, 0x63, 0x2d, 0x71, 0x64, 0x66, 0x73, 0x64, 0x66, 0x0au8,
-    ];
-
-    let packet2 = &mut [
-        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x08,
-        0x00, // ethertype
-        0x45, 0x00, 0x00, 0x3b, // start ip_hdr
-        0xa6, 0xab, 0x40, 0x00, 0x40, 0x06, 0x96, 0x0f, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00,
-        0x01,
-        // Program matches the next two bytes: 0x9999 returns 0xffffffff, else return 0.
-        0x98, 0x76, 0xc6, 0xcc, // start tcp_hdr
-        0xd1, 0xe5, 0xc4, 0x9d, 0xd4, 0x30, 0xb5, 0xd2, 0x80, 0x18, 0x01, 0x56, 0xfe, 0x2f, 0x00,
-        0x00, 0x01, 0x01, 0x08, 0x0a, // start data
-        0x00, 0x23, 0x75, 0x89, 0x00, 0x23, 0x63, 0x2d, 0x71, 0x64, 0x66, 0x73, 0x64, 0x66, 0x0au8,
-    ];
-
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf)
-        .unwrap();
-
-    let res = vm.execute_program(packet1).unwrap();
-    println!("Packet #1, program returned: {res:?} ({res:#x})");
-    assert_eq!(res, 0xffffffff);
-
-    #[cfg(not(windows))]
-    {
-        vm.jit_compile().unwrap();
-
-        let res = unsafe { vm.execute_program_jit(packet2).unwrap() };
-        println!("Packet #2, program returned: {res:?} ({res:#x})");
-        assert_eq!(res, 0);
-    }
-
-    #[cfg(windows)]
-    {
-        let res = vm.execute_program(packet2).unwrap();
-        println!("Packet #2, program returned: {:?} ({:#x})", res, res);
-        assert_eq!(res, 0);
-    }
-}

+ 0 - 43
kernel/crates/rbpf/examples/load_elf__block_a_port.c

@@ -1,43 +0,0 @@
-// SPDX-License-Identifier: (APACHE-2.0 OR MIT)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-// Block TCP packets on source or destination port 0x9999.
-
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/tcp.h>
-#include <linux/bpf.h>
-
-#define ETH_ALEN 6
-#define ETH_P_IP 0x0008 /* htons(0x0800) */
-#define TCP_HDR_LEN 20
-
-#define BLOCKED_TCP_PORT 0x9999
-
-struct eth_hdr {
-    unsigned char   h_dest[ETH_ALEN];
-    unsigned char   h_source[ETH_ALEN];
-    unsigned short  h_proto;
-};
-
-#define SEC(NAME) __attribute__((section(NAME), used))
-SEC(".classifier")
-int handle_ingress(struct __sk_buff *skb)
-{
-    void *data = (void *)(long)skb->data;
-    void *data_end = (void *)(long)skb->data_end;
-    struct eth_hdr *eth = data;
-    struct iphdr *iph = data + sizeof(*eth);
-    struct tcphdr *tcp = data + sizeof(*eth) + sizeof(*iph);
-
-    /* single length check */
-    if (data + sizeof(*eth) + sizeof(*iph) + sizeof(*tcp) > data_end)
-        return 0;
-    if (eth->h_proto != ETH_P_IP)
-        return 0;
-    if (iph->protocol != IPPROTO_TCP)
-        return 0;
-    if (tcp->source == BLOCKED_TCP_PORT || tcp->dest == BLOCKED_TCP_PORT)
-        return -1;
-    return 0;
-}

+ 0 - 126
kernel/crates/rbpf/examples/rbpf_plugin.rs

@@ -1,126 +0,0 @@
-// Copyright Microsoft Corporation
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-// Path: examples/rbpf_plugin.rs
-use std::io::Read;
-
-// Helper function used by https://github.com/Alan-Jowett/bpf_conformance/blob/main/tests/call_unwind_fail.data
-fn _unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u64 {
-    a
-}
-
-// This is a plugin for the bpf_conformance test suite (https://github.com/Alan-Jowett/bpf_conformance)
-// It accepts a single argument, the memory contents to pass to the VM.
-// It reads the program from stdin.
-fn main() {
-    let mut args: Vec<String> = std::env::args().collect();
-    #[allow(unused_mut)] // In no_std the jit variable isn't mutated.
-    let mut jit: bool = false;
-    let mut cranelift: bool = false;
-    let mut program_text = String::new();
-    let mut memory_text = String::new();
-
-    args.remove(0);
-
-    // Memory is always the first argument.
-    if !args.is_empty() {
-        memory_text.clone_from(&args[0]);
-        // Strip whitespace
-        memory_text.retain(|c| !c.is_whitespace());
-        args.remove(0);
-    }
-
-    // Process the rest of the arguments.
-    while !args.is_empty() {
-        match args[0].as_str() {
-            "--help" => {
-                println!("Usage: rbpf_plugin [memory] < program");
-                return;
-            }
-            "--jit" => {
-                #[cfg(any(windows, not(feature = "std")))]
-                {
-                    println!("JIT not supported");
-                    return;
-                }
-                #[cfg(all(not(windows), feature = "std"))]
-                {
-                    jit = true;
-                }
-            }
-            "--cranelift" => {
-                cranelift = true;
-
-                #[cfg(not(feature = "cranelift"))]
-                {
-                    let _ = cranelift;
-                    println!("Cranelift is not enabled");
-                    return;
-                }
-            }
-            "--program" => {
-                if args.len() < 2 {
-                    println!("Missing argument to --program");
-                    return;
-                }
-                args.remove(0);
-                if !args.is_empty() {
-                    program_text.clone_from(&args[0]);
-                    args.remove(0);
-                }
-            }
-            _ => panic!("Unknown argument {}", args[0]),
-        }
-        args.remove(0);
-    }
-
-    if program_text.is_empty() {
-        // Read program text from stdin
-        std::io::stdin().read_to_string(&mut program_text).unwrap();
-    }
-
-    // Strip whitespace
-    program_text.retain(|c| !c.is_whitespace());
-
-    // Convert program from hex to bytecode
-    let bytecode = hex::decode(program_text).unwrap();
-
-    // Convert memory from hex to bytes
-    let mut memory: Vec<u8> = hex::decode(memory_text).unwrap();
-
-    // Create rbpf vm
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&bytecode)).unwrap();
-
-    // Register the helper function used by call_unwind_fail.data test.
-    vm.register_helper(5, _unwind).unwrap();
-
-    let result: u64;
-    if jit {
-        #[cfg(any(windows, not(feature = "std")))]
-        {
-            println!("JIT not supported");
-            return;
-        }
-        #[cfg(all(not(windows), feature = "std"))]
-        {
-            unsafe {
-                vm.jit_compile().unwrap();
-                result = vm.execute_program_jit(&mut memory).unwrap();
-            }
-        }
-    } else if cranelift {
-        #[cfg(not(feature = "cranelift"))]
-        {
-            println!("Cranelift is not enabled");
-            return;
-        }
-        #[cfg(feature = "cranelift")]
-        {
-            vm.cranelift_compile().unwrap();
-            result = vm.execute_program_cranelift(&mut memory).unwrap();
-        }
-    } else {
-        result = vm.execute_program(&mut memory).unwrap();
-    }
-    println!("{result:x}");
-}

+ 0 - 74
kernel/crates/rbpf/examples/to_json.rs

@@ -1,74 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 6WIND S.A. <quentin.monnet@6wind.com>
-
-#[macro_use]
-extern crate json;
-
-extern crate elf;
-use std::path::PathBuf;
-
-extern crate rbpf;
-use rbpf::disassembler;
-
-// Turn a program into a JSON string.
-//
-// Relies on `json` crate.
-//
-// You may copy this function and adapt it according to your needs. For instance, you may want to:
-//
-// * Remove the "desc" (description) attributes from the output.
-// * Print integers as integers, and not as strings containing their hexadecimal representation
-//   (just replace the relevant `format!()` calls by the commented values.
-fn to_json(prog: &[u8]) -> String {
-    // This call returns a high-level representation of the instructions, with the two parts of
-    // `LD_DW_IMM` instructions merged, and name and descriptions of the instructions.
-    // If you prefer to use a lower-level representation, use `ebpf::to_insn_vec()` function
-    // instead.
-    let insns = disassembler::to_insn_vec(prog);
-    let mut json_insns = vec![];
-    for insn in insns {
-        json_insns.push(object!(
-            "opc"  => format!("{:#x}", insn.opc), // => insn.opc,
-            "dst"  => format!("{:#x}", insn.dst), // => insn.dst,
-            "src"  => format!("{:#x}", insn.src), // => insn.src,
-            "off"  => format!("{:#x}", insn.off), // => insn.off,
-            // Warning: for imm we use a i64 instead of a i32 (to have correct values for
-            // `lddw` operation. If we print a number in the JSON this is not a problem, the
-            // internal i64 has the same value with extended sign on 32 most significant bytes.
-            // If we print the hexadecimal value as a string however, we want to cast as a i32
-            // to prevent all other instructions to print spurious `ffffffff` prefix if the
-            // number is negative. When values takes more than 32 bits with `lddw`, the cast
-            // has no effect and the complete value is printed anyway.
-            "imm"  => format!("{:#x}", insn.imm as i32), // => insn.imm,
-            "desc" => insn.desc
-        ));
-    }
-    json::stringify_pretty(
-        object!(
-        "size"  => json_insns.len(),
-        "insns" => json_insns
-        ),
-        4,
-    )
-}
-
-// Load a program from an object file, and prints it to standard output as a JSON string.
-fn main() {
-    // Let's reuse this file from `load_elf/example`.
-    let filename = "examples/load_elf__block_a_port.elf";
-
-    let path = PathBuf::from(filename);
-    let file = match elf::File::open_path(path) {
-        Ok(f) => f,
-        Err(e) => panic!("Error: {:?}", e),
-    };
-
-    let text_scn = match file.get_section(".classifier") {
-        Some(s) => s,
-        None => panic!("Failed to look up .classifier section"),
-    };
-
-    let prog = &text_scn.data;
-
-    println!("{}", to_json(prog));
-}

+ 0 - 78
kernel/crates/rbpf/examples/uptime.rs

@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 6WIND S.A. <quentin.monnet@6wind.com>
-
-extern crate rbpf;
-use rbpf::helpers;
-
-// The main objectives of this example is to show:
-//
-// * the use of EbpfVmNoData function,
-// * and the use of a helper.
-//
-// The two eBPF programs are independent and are not related to one another.
-fn main() {
-    let prog1 = &[
-        0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov32 r0, 0
-        0xb4, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov32 r1, 2
-        0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // add32 r0, 1
-        0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // add32 r0, r1
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit and return r0
-    ];
-
-    // We use helper `bpf_time_getns()`, which is similar to helper `bpf_ktime_getns()` from Linux
-    // kernel. Hence rbpf::helpers module provides the index of this in-kernel helper as a
-    // constant, so that we can remain compatible with programs for the kernel. Here we also cast
-    // it to a u8 so as to use it directly in program instructions.
-    let hkey = helpers::BPF_KTIME_GETNS_IDX as u8;
-    let prog2 = &[
-        0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r1, 0
-        0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r1, 0
-        0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r1, 0
-        0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r1, 0
-        0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r1, 0
-        0x85, 0x00, 0x00, 0x00, hkey, 0x00, 0x00, 0x00, // call helper <hkey>
-        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit and return r0
-    ];
-
-    // Create a VM: this one takes no data. Load prog1 in it.
-    let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
-    // Execute prog1.
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-
-    // As struct EbpfVmNoData does not takes any memory area, its return value is mostly
-    // deterministic. So we know prog1 will always return 3. There is an exception: when it uses
-    // helpers, the latter may have non-deterministic values, and all calls may not return the same
-    // value.
-    //
-    // In the following example we use a helper to get the elapsed time since boot time: we
-    // reimplement uptime in eBPF, in Rust. Because why not.
-
-    vm.set_program(prog2).unwrap();
-    vm.register_helper(helpers::BPF_KTIME_GETNS_IDX, helpers::bpf_time_getns)
-        .unwrap();
-
-    let time;
-
-    #[cfg(all(not(windows), feature = "std"))]
-    {
-        vm.jit_compile().unwrap();
-
-        time = unsafe { vm.execute_program_jit().unwrap() };
-    }
-
-    #[cfg(any(windows, not(feature = "std")))]
-    {
-        time = vm.execute_program().unwrap();
-    }
-
-    let days = time / 10u64.pow(9) / 60 / 60 / 24;
-    let hours = (time / 10u64.pow(9) / 60 / 60) % 24;
-    let minutes = (time / 10u64.pow(9) / 60) % 60;
-    let seconds = (time / 10u64.pow(9)) % 60;
-    let nanosec = time % 10u64.pow(9);
-
-    println!(
-        "Uptime: {:#x} ns == {} days {:02}:{:02}:{:02}, {} ns",
-        time, days, hours, minutes, seconds, nanosec
-    );
-}

+ 0 - 72
kernel/crates/rbpf/mk/appveyor.bat

@@ -1,72 +0,0 @@
-echo on
-SetLocal EnableDelayedExpansion
-
-REM This is the recommended way to choose the toolchain version, according to
-REM Appveyor's documentation.
-SET PATH=C:\Program Files (x86)\MSBuild\%TOOLCHAIN_VERSION%\Bin;%PATH%
-
-set VCVARSALL="C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN_VERSION%\VC\vcvarsall.bat"
-
-if [%Platform%] NEQ [x64] goto win32
-set TARGET_ARCH=x86_64
-set TARGET_PROGRAM_FILES=%ProgramFiles%
-call %VCVARSALL% amd64
-if %ERRORLEVEL% NEQ 0 exit 1
-goto download
-
-:win32
-echo on
-if [%Platform%] NEQ [Win32] exit 1
-set TARGET_ARCH=i686
-set TARGET_PROGRAM_FILES=%ProgramFiles(x86)%
-call %VCVARSALL% amd64_x86
-if %ERRORLEVEL% NEQ 0 exit 1
-goto download
-
-:download
-REM vcvarsall turns echo off
-echo on
-
-mkdir windows_build_tools
-mkdir windows_build_tools\
-echo Downloading Yasm...
-powershell -Command "(New-Object Net.WebClient).DownloadFile('http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe', 'windows_build_tools\yasm.exe')"
-if %ERRORLEVEL% NEQ 0 (
-  echo ...downloading Yasm failed.
-  exit 1
-)
-
-set RUST_URL=https://static.rust-lang.org/dist/rust-%RUST%-%TARGET_ARCH%-pc-windows-msvc.msi
-echo Downloading %RUST_URL%...
-mkdir build
-powershell -Command "(New-Object Net.WebClient).DownloadFile('%RUST_URL%', 'build\rust-%RUST%-%TARGET_ARCH%-pc-windows-msvc.msi')"
-if %ERRORLEVEL% NEQ 0 (
-  echo ...downloading Rust failed.
-  exit 1
-)
-
-start /wait msiexec /i build\rust-%RUST%-%TARGET_ARCH%-pc-windows-msvc.msi INSTALLDIR="%TARGET_PROGRAM_FILES%\Rust %RUST%" /quiet /qn /norestart
-if %ERRORLEVEL% NEQ 0 exit 1
-
-set PATH="%TARGET_PROGRAM_FILES%\Rust %RUST%\bin";%cd%\windows_build_tools;%PATH%
-
-if [%Configuration%] == [Release] set CARGO_MODE=--release
-
-set
-
-link /?
-cl /?
-rustc --version
-cargo --version
-
-cargo test --all-features -vv %CARGO_MODE%
-if %ERRORLEVEL% NEQ 0 exit 1
-
-REM Verify that `cargo build`, independent from `cargo test`, works; i.e.
-REM verify that non-test builds aren't trying to use test-only features.
-cargo build -vv %CARGO_MODE%
-if %ERRORLEVEL% NEQ 0 exit 1
-
-REM Verify that we can build with all features
-cargo build --all-features -vv %CARGO_MODE%
-if %ERRORLEVEL% NEQ 0 exit 1

+ 0 - 3
kernel/crates/rbpf/rustfmt.toml

@@ -1,3 +0,0 @@
-group_imports="StdExternalCrate"
-reorder_imports=true
-imports_granularity="Crate"

+ 0 - 642
kernel/crates/rbpf/src/asm_parser.rs

@@ -1,642 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 Rich Lane <lanerl@gmail.com>
-
-// Rust-doc comments were left in the module, but it is no longer publicly exposed from the root
-// file of the crate. Do not expect to find those comments in the documentation of the crate.
-
-//! This module parses eBPF assembly language source code.
-
-use alloc::{
-    string::{String, ToString},
-    vec::Vec,
-};
-
-#[cfg(feature = "std")]
-use combine::EasyParser;
-use combine::{
-    attempt, between, eof, many, many1, one_of, optional,
-    parser::char::{alpha_num, char, digit, hex_digit, spaces, string},
-    sep_by,
-    stream::position::{self},
-    ParseError, Parser, Stream,
-};
-
-/// Operand of an instruction.
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum Operand {
-    /// Register number.
-    Register(i64),
-    /// Jump offset or immediate.
-    Integer(i64),
-    /// Register number and offset.
-    Memory(i64, i64),
-    /// Used for pattern matching.
-    Nil,
-}
-
-/// Parsed instruction.
-#[derive(Debug, PartialEq, Eq)]
-pub struct Instruction {
-    /// Instruction name.
-    pub name: String,
-    /// Operands.
-    pub operands: Vec<Operand>,
-}
-
-fn ident<I>() -> impl Parser<I, Output = String>
-where
-    I: Stream<Token = char>,
-    I::Error: ParseError<I::Token, I::Range, I::Position>,
-{
-    many1(alpha_num())
-}
-
-fn integer<I>() -> impl Parser<I, Output = i64>
-where
-    I: Stream<Token = char>,
-    I::Error: ParseError<I::Token, I::Range, I::Position>,
-{
-    let sign = optional(one_of("-+".chars())).map(|x| match x {
-        Some('-') => -1,
-        _ => 1,
-    });
-    let hex = string("0x")
-        .with(many1(hex_digit()))
-        .map(|x: String| u64::from_str_radix(&x, 16).unwrap() as i64);
-    let dec = many1(digit()).map(|x: String| x.parse::<i64>().unwrap());
-    (sign, attempt(hex).or(dec)).map(|(s, x)| s * x)
-}
-
-fn register<I>() -> impl Parser<I, Output = i64>
-where
-    I: Stream<Token = char>,
-    I::Error: ParseError<I::Token, I::Range, I::Position>,
-{
-    char('r')
-        .with(many1(digit()))
-        .map(|x: String| x.parse::<i64>().unwrap())
-}
-
-fn operand<I>() -> impl Parser<I, Output = Operand>
-where
-    I: Stream<Token = char>,
-    I::Error: ParseError<I::Token, I::Range, I::Position>,
-{
-    let register_operand = register().map(Operand::Register);
-    let immediate = integer().map(Operand::Integer);
-    let memory = between(char('['), char(']'), (register(), optional(integer())))
-        .map(|t| Operand::Memory(t.0, t.1.unwrap_or(0)));
-    register_operand.or(immediate).or(memory)
-}
-
-fn instruction<I>() -> impl Parser<I, Output = Instruction>
-where
-    I: Stream<Token = char>,
-    I::Error: ParseError<I::Token, I::Range, I::Position>,
-{
-    let operands = sep_by(operand(), char(',').skip(spaces()));
-    (ident().skip(spaces()), operands, spaces()).map(|t| Instruction {
-        name: t.0,
-        operands: t.1,
-    })
-}
-
-/// Parse a string into a list of instructions.
-///
-/// The instructions are not validated and may have invalid names and operand types.
-pub fn parse(input: &str) -> Result<Vec<Instruction>, String> {
-    let mut with = spaces().with(many(instruction()).skip(eof()));
-
-    #[cfg(feature = "std")]
-    {
-        match with.easy_parse(position::Stream::new(input)) {
-            Ok((insts, _)) => Ok(insts),
-            Err(err) => Err(err.to_string()),
-        }
-    }
-    #[cfg(not(feature = "std"))]
-    {
-        match with.parse(position::Stream::new(input)) {
-            Ok((insts, _)) => Ok(insts),
-            Err(err) => Err(err.to_string()),
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use alloc::{string::ToString, vec};
-
-    use combine::Parser;
-
-    use super::{ident, instruction, integer, operand, parse, register, Instruction, Operand};
-
-    // Unit tests for the different kinds of parsers.
-
-    #[test]
-    fn test_ident() {
-        assert_eq!(ident().parse("nop"), Ok(("nop".to_string(), "")));
-        assert_eq!(ident().parse("add32"), Ok(("add32".to_string(), "")));
-        assert_eq!(ident().parse("add32*"), Ok(("add32".to_string(), "*")));
-    }
-
-    #[test]
-    fn test_integer() {
-        assert_eq!(integer().parse("0"), Ok((0, "")));
-        assert_eq!(integer().parse("42"), Ok((42, "")));
-        assert_eq!(integer().parse("+42"), Ok((42, "")));
-        assert_eq!(integer().parse("-42"), Ok((-42, "")));
-        assert_eq!(integer().parse("0x0"), Ok((0, "")));
-        assert_eq!(
-            integer().parse("0x123456789abcdef0"),
-            Ok((0x123456789abcdef0, ""))
-        );
-        assert_eq!(integer().parse("-0x1f"), Ok((-31, "")));
-    }
-
-    #[test]
-    fn test_register() {
-        assert_eq!(register().parse("r0"), Ok((0, "")));
-        assert_eq!(register().parse("r15"), Ok((15, "")));
-    }
-
-    #[test]
-    fn test_operand() {
-        assert_eq!(operand().parse("r0"), Ok((Operand::Register(0), "")));
-        assert_eq!(operand().parse("r15"), Ok((Operand::Register(15), "")));
-        assert_eq!(operand().parse("0"), Ok((Operand::Integer(0), "")));
-        assert_eq!(operand().parse("42"), Ok((Operand::Integer(42), "")));
-        assert_eq!(operand().parse("[r1]"), Ok((Operand::Memory(1, 0), "")));
-        assert_eq!(operand().parse("[r3+5]"), Ok((Operand::Memory(3, 5), "")));
-        assert_eq!(
-            operand().parse("[r3+0x1f]"),
-            Ok((Operand::Memory(3, 31), ""))
-        );
-        assert_eq!(
-            operand().parse("[r3-0x1f]"),
-            Ok((Operand::Memory(3, -31), ""))
-        );
-    }
-
-    #[test]
-    fn test_instruction() {
-        assert_eq!(
-            instruction().parse("exit"),
-            Ok((
-                Instruction {
-                    name: "exit".to_string(),
-                    operands: vec![],
-                },
-                ""
-            ))
-        );
-
-        assert_eq!(
-            instruction().parse("call 2"),
-            Ok((
-                Instruction {
-                    name: "call".to_string(),
-                    operands: vec![Operand::Integer(2)],
-                },
-                ""
-            ))
-        );
-
-        assert_eq!(
-            instruction().parse("addi r1, 2"),
-            Ok((
-                Instruction {
-                    name: "addi".to_string(),
-                    operands: vec![Operand::Register(1), Operand::Integer(2)],
-                },
-                ""
-            ))
-        );
-
-        assert_eq!(
-            instruction().parse("ldxb r2, [r1+12]"),
-            Ok((
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
-                },
-                ""
-            ))
-        );
-
-        assert_eq!(
-            instruction().parse("lsh r3, 0x8"),
-            Ok((
-                Instruction {
-                    name: "lsh".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Integer(8)],
-                },
-                ""
-            ))
-        );
-
-        assert_eq!(
-            instruction().parse("jne r3, 0x8, +37"),
-            Ok((
-                Instruction {
-                    name: "jne".to_string(),
-                    operands: vec![
-                        Operand::Register(3),
-                        Operand::Integer(8),
-                        Operand::Integer(37)
-                    ],
-                },
-                ""
-            ))
-        );
-
-        // Whitespace between operands is optional.
-        assert_eq!(
-            instruction().parse("jne r3,0x8,+37"),
-            Ok((
-                Instruction {
-                    name: "jne".to_string(),
-                    operands: vec![
-                        Operand::Register(3),
-                        Operand::Integer(8),
-                        Operand::Integer(37)
-                    ],
-                },
-                ""
-            ))
-        );
-    }
-
-    // Other unit tests: try to parse various set of instructions.
-
-    #[test]
-    fn test_empty() {
-        assert_eq!(parse(""), Ok(vec![]));
-    }
-
-    #[test]
-    fn test_exit() {
-        // No operands.
-        assert_eq!(
-            parse("exit"),
-            Ok(vec![Instruction {
-                name: "exit".to_string(),
-                operands: vec![],
-            }])
-        );
-    }
-
-    #[test]
-    fn test_lsh() {
-        // Register and immediate operands.
-        assert_eq!(
-            parse("lsh r3, 0x20"),
-            Ok(vec![Instruction {
-                name: "lsh".to_string(),
-                operands: vec![Operand::Register(3), Operand::Integer(0x20)],
-            }])
-        );
-    }
-
-    #[test]
-    fn test_ja() {
-        // Jump offset operand.
-        assert_eq!(
-            parse("ja +1"),
-            Ok(vec![Instruction {
-                name: "ja".to_string(),
-                operands: vec![Operand::Integer(1)],
-            }])
-        );
-    }
-
-    #[test]
-    fn test_ldxh() {
-        // Register and memory operands.
-        assert_eq!(
-            parse("ldxh r4, [r1+12]"),
-            Ok(vec![Instruction {
-                name: "ldxh".to_string(),
-                operands: vec![Operand::Register(4), Operand::Memory(1, 12)],
-            }])
-        );
-    }
-
-    #[test]
-    fn test_tcp_sack() {
-        // Sample program from ubpf.
-        // We could technically indent the instructions since the parser support white spaces at
-        // the beginning, but there is another test for that.
-        let src = "\
-ldxb r2, [r1+12]
-ldxb r3, [r1+13]
-lsh r3, 0x8
-or r3, r2
-mov r0, 0x0
-jne r3, 0x8, +37
-ldxb r2, [r1+23]
-jne r2, 0x6, +35
-ldxb r2, [r1+14]
-add r1, 0xe
-and r2, 0xf
-lsh r2, 0x2
-add r1, r2
-mov r0, 0x0
-ldxh r4, [r1+12]
-add r1, 0x14
-rsh r4, 0x2
-and r4, 0x3c
-mov r2, r4
-add r2, 0xffffffec
-mov r5, 0x15
-mov r3, 0x0
-jgt r5, r4, +20
-mov r5, r3
-lsh r5, 0x20
-arsh r5, 0x20
-mov r4, r1
-add r4, r5
-ldxb r5, [r4]
-jeq r5, 0x1, +4
-jeq r5, 0x0, +12
-mov r6, r3
-jeq r5, 0x5, +9
-ja +2
-add r3, 0x1
-mov r6, r3
-ldxb r3, [r4+1]
-add r3, r6
-lsh r3, 0x20
-arsh r3, 0x20
-jsgt r2, r3, -18
-ja +1
-mov r0, 0x1
-exit
-";
-
-        assert_eq!(
-            parse(src),
-            Ok(vec![
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
-                },
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Memory(1, 13)],
-                },
-                Instruction {
-                    name: "lsh".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Integer(8)],
-                },
-                Instruction {
-                    name: "or".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Register(2)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(0), Operand::Integer(0)],
-                },
-                Instruction {
-                    name: "jne".to_string(),
-                    operands: vec![
-                        Operand::Register(3),
-                        Operand::Integer(8),
-                        Operand::Integer(37)
-                    ],
-                },
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Memory(1, 23)],
-                },
-                Instruction {
-                    name: "jne".to_string(),
-                    operands: vec![
-                        Operand::Register(2),
-                        Operand::Integer(6),
-                        Operand::Integer(35)
-                    ],
-                },
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Memory(1, 14)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(1), Operand::Integer(14)],
-                },
-                Instruction {
-                    name: "and".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Integer(15)],
-                },
-                Instruction {
-                    name: "lsh".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Integer(2)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(1), Operand::Register(2)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(0), Operand::Integer(0)],
-                },
-                Instruction {
-                    name: "ldxh".to_string(),
-                    operands: vec![Operand::Register(4), Operand::Memory(1, 12)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(1), Operand::Integer(20)],
-                },
-                Instruction {
-                    name: "rsh".to_string(),
-                    operands: vec![Operand::Register(4), Operand::Integer(2)],
-                },
-                Instruction {
-                    name: "and".to_string(),
-                    operands: vec![Operand::Register(4), Operand::Integer(60)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Register(4)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(2), Operand::Integer(4294967276)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(5), Operand::Integer(21)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Integer(0)],
-                },
-                Instruction {
-                    name: "jgt".to_string(),
-                    operands: vec![
-                        Operand::Register(5),
-                        Operand::Register(4),
-                        Operand::Integer(20)
-                    ],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(5), Operand::Register(3)],
-                },
-                Instruction {
-                    name: "lsh".to_string(),
-                    operands: vec![Operand::Register(5), Operand::Integer(32)],
-                },
-                Instruction {
-                    name: "arsh".to_string(),
-                    operands: vec![Operand::Register(5), Operand::Integer(32)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(4), Operand::Register(1)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(4), Operand::Register(5)],
-                },
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(5), Operand::Memory(4, 0)],
-                },
-                Instruction {
-                    name: "jeq".to_string(),
-                    operands: vec![
-                        Operand::Register(5),
-                        Operand::Integer(1),
-                        Operand::Integer(4)
-                    ],
-                },
-                Instruction {
-                    name: "jeq".to_string(),
-                    operands: vec![
-                        Operand::Register(5),
-                        Operand::Integer(0),
-                        Operand::Integer(12)
-                    ],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(6), Operand::Register(3)],
-                },
-                Instruction {
-                    name: "jeq".to_string(),
-                    operands: vec![
-                        Operand::Register(5),
-                        Operand::Integer(5),
-                        Operand::Integer(9)
-                    ],
-                },
-                Instruction {
-                    name: "ja".to_string(),
-                    operands: vec![Operand::Integer(2)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Integer(1)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(6), Operand::Register(3)],
-                },
-                Instruction {
-                    name: "ldxb".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Memory(4, 1)],
-                },
-                Instruction {
-                    name: "add".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Register(6)],
-                },
-                Instruction {
-                    name: "lsh".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Integer(32)],
-                },
-                Instruction {
-                    name: "arsh".to_string(),
-                    operands: vec![Operand::Register(3), Operand::Integer(32)],
-                },
-                Instruction {
-                    name: "jsgt".to_string(),
-                    operands: vec![
-                        Operand::Register(2),
-                        Operand::Register(3),
-                        Operand::Integer(-18)
-                    ],
-                },
-                Instruction {
-                    name: "ja".to_string(),
-                    operands: vec![Operand::Integer(1)],
-                },
-                Instruction {
-                    name: "mov".to_string(),
-                    operands: vec![Operand::Register(0), Operand::Integer(1)],
-                },
-                Instruction {
-                    name: "exit".to_string(),
-                    operands: vec![],
-                }
-            ])
-        );
-    }
-
-    /// When running without `std` the `EasyParser` provided by `combine`
-    /// cannot be used. Because of this we need to use the `Parser` and the
-    /// error messages are different.
-    #[test]
-    fn test_error_eof() {
-        let expected_error;
-        #[cfg(feature = "std")]
-        {
-            expected_error = Err(
-                "Parse error at line: 1, column: 6\nUnexpected end of input\nExpected digit\n"
-                    .to_string(),
-            );
-        }
-        #[cfg(not(feature = "std"))]
-        {
-            expected_error = Err("unexpected parse".to_string());
-        }
-        // Unexpected end of input in a register name.
-        assert_eq!(parse("lsh r"), expected_error);
-    }
-
-    /// When running without `std` the `EasyParser` provided by `combine`
-    /// cannot be used. Because of this we need to use the `Parser` and the
-    /// error messages are different.
-    #[test]
-    fn test_error_unexpected_character() {
-        let expected_error;
-        #[cfg(feature = "std")]
-        {
-            expected_error = Err(
-                "Parse error at line: 2, column: 1\nUnexpected `^`\nExpected letter or digit, whitespaces, `r`, `-`, `+`, `[` or end of input\n".to_string()
-            );
-        }
-        #[cfg(not(feature = "std"))]
-        {
-            expected_error = Err("unexpected parse".to_string());
-        }
-        // Unexpected character at end of input.
-        assert_eq!(parse("exit\n^"), expected_error);
-    }
-
-    #[test]
-    fn test_initial_whitespace() {
-        assert_eq!(
-            parse(
-                " 
-                          exit"
-            ),
-            Ok(vec![Instruction {
-                name: "exit".to_string(),
-                operands: vec![],
-            }])
-        );
-    }
-}

+ 0 - 277
kernel/crates/rbpf/src/assembler.rs

@@ -1,277 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 Rich Lane <lanerl@gmail.com>
-
-//! This module translates eBPF assembly language to binary.
-
-use alloc::{
-    collections::BTreeMap,
-    format,
-    string::{String, ToString},
-    vec,
-    vec::Vec,
-};
-
-use self::InstructionType::{
-    AluBinary, AluUnary, Call, Endian, JumpConditional, JumpUnconditional, LoadAbs, LoadImm,
-    LoadInd, LoadReg, NoOperand, StoreImm, StoreReg,
-};
-use crate::{
-    asm_parser::{
-        parse, Instruction, Operand,
-        Operand::{Integer, Memory, Nil, Register},
-    },
-    ebpf::{self, Insn},
-};
-
-#[derive(Clone, Copy, Debug, PartialEq)]
-enum InstructionType {
-    AluBinary,
-    AluUnary,
-    LoadImm,
-    LoadAbs,
-    LoadInd,
-    LoadReg,
-    StoreImm,
-    StoreReg,
-    JumpUnconditional,
-    JumpConditional,
-    Call,
-    Endian(i64),
-    NoOperand,
-}
-
-fn make_instruction_map() -> BTreeMap<String, (InstructionType, u8)> {
-    let mut result = BTreeMap::new();
-
-    let alu_binary_ops = [
-        ("add", ebpf::BPF_ADD),
-        ("sub", ebpf::BPF_SUB),
-        ("mul", ebpf::BPF_MUL),
-        ("div", ebpf::BPF_DIV),
-        ("or", ebpf::BPF_OR),
-        ("and", ebpf::BPF_AND),
-        ("lsh", ebpf::BPF_LSH),
-        ("rsh", ebpf::BPF_RSH),
-        ("mod", ebpf::BPF_MOD),
-        ("xor", ebpf::BPF_XOR),
-        ("mov", ebpf::BPF_MOV),
-        ("arsh", ebpf::BPF_ARSH),
-    ];
-
-    let mem_sizes = [
-        ("w", ebpf::BPF_W),
-        ("h", ebpf::BPF_H),
-        ("b", ebpf::BPF_B),
-        ("dw", ebpf::BPF_DW),
-    ];
-
-    let jump_conditions = [
-        ("jeq", ebpf::BPF_JEQ),
-        ("jgt", ebpf::BPF_JGT),
-        ("jge", ebpf::BPF_JGE),
-        ("jlt", ebpf::BPF_JLT),
-        ("jle", ebpf::BPF_JLE),
-        ("jset", ebpf::BPF_JSET),
-        ("jne", ebpf::BPF_JNE),
-        ("jsgt", ebpf::BPF_JSGT),
-        ("jsge", ebpf::BPF_JSGE),
-        ("jslt", ebpf::BPF_JSLT),
-        ("jsle", ebpf::BPF_JSLE),
-    ];
-
-    {
-        let mut entry = |name: &str, inst_type: InstructionType, opc: u8| {
-            result.insert(name.to_string(), (inst_type, opc))
-        };
-
-        // Miscellaneous.
-        entry("exit", NoOperand, ebpf::EXIT);
-        entry("ja", JumpUnconditional, ebpf::JA);
-        entry("call", Call, ebpf::CALL);
-        entry("lddw", LoadImm, ebpf::LD_DW_IMM);
-
-        // AluUnary.
-        entry("neg", AluUnary, ebpf::NEG64);
-        entry("neg32", AluUnary, ebpf::NEG32);
-        entry("neg64", AluUnary, ebpf::NEG64);
-
-        // AluBinary.
-        for &(name, opc) in &alu_binary_ops {
-            entry(name, AluBinary, ebpf::BPF_ALU64 | opc);
-            entry(&format!("{name}32"), AluBinary, ebpf::BPF_ALU | opc);
-            entry(&format!("{name}64"), AluBinary, ebpf::BPF_ALU64 | opc);
-        }
-
-        // LoadAbs, LoadInd, LoadReg, StoreImm, and StoreReg.
-        for &(suffix, size) in &mem_sizes {
-            entry(
-                &format!("ldabs{suffix}"),
-                LoadAbs,
-                ebpf::BPF_ABS | ebpf::BPF_LD | size,
-            );
-            entry(
-                &format!("ldind{suffix}"),
-                LoadInd,
-                ebpf::BPF_IND | ebpf::BPF_LD | size,
-            );
-            entry(
-                &format!("ldx{suffix}"),
-                LoadReg,
-                ebpf::BPF_MEM | ebpf::BPF_LDX | size,
-            );
-            entry(
-                &format!("st{suffix}"),
-                StoreImm,
-                ebpf::BPF_MEM | ebpf::BPF_ST | size,
-            );
-            entry(
-                &format!("stx{suffix}"),
-                StoreReg,
-                ebpf::BPF_MEM | ebpf::BPF_STX | size,
-            );
-        }
-
-        // JumpConditional.
-        for &(name, condition) in &jump_conditions {
-            entry(name, JumpConditional, ebpf::BPF_JMP | condition);
-            entry(
-                &format!("{name}32"),
-                JumpConditional,
-                ebpf::BPF_JMP32 | condition,
-            );
-        }
-
-        // Endian.
-        for &size in &[16, 32, 64] {
-            entry(&format!("be{size}"), Endian(size), ebpf::BE);
-            entry(&format!("le{size}"), Endian(size), ebpf::LE);
-        }
-    }
-
-    result
-}
-
-fn insn(opc: u8, dst: i64, src: i64, off: i64, imm: i64) -> Result<Insn, String> {
-    if !(0..16).contains(&dst) {
-        return Err(format!("Invalid destination register {dst}"));
-    }
-    if dst < 0 || src >= 16 {
-        return Err(format!("Invalid source register {src}"));
-    }
-    if !(-32768..32768).contains(&off) {
-        return Err(format!("Invalid offset {off}"));
-    }
-    if !(-2147483648..2147483648).contains(&imm) {
-        return Err(format!("Invalid immediate {imm}"));
-    }
-    Ok(Insn {
-        opc,
-        dst: dst as u8,
-        src: src as u8,
-        off: off as i16,
-        imm: imm as i32,
-    })
-}
-
-// TODO Use slice patterns when available and remove this function.
-fn operands_tuple(operands: &[Operand]) -> Result<(Operand, Operand, Operand), String> {
-    match operands.len() {
-        0 => Ok((Nil, Nil, Nil)),
-        1 => Ok((operands[0], Nil, Nil)),
-        2 => Ok((operands[0], operands[1], Nil)),
-        3 => Ok((operands[0], operands[1], operands[2])),
-        _ => Err("Too many operands".to_string()),
-    }
-}
-
-fn encode(inst_type: InstructionType, opc: u8, operands: &[Operand]) -> Result<Insn, String> {
-    let (a, b, c) = (operands_tuple(operands))?;
-    match (inst_type, a, b, c) {
-        (AluBinary, Register(dst), Register(src), Nil) => insn(opc | ebpf::BPF_X, dst, src, 0, 0),
-        (AluBinary, Register(dst), Integer(imm), Nil) => insn(opc | ebpf::BPF_K, dst, 0, 0, imm),
-        (AluUnary, Register(dst), Nil, Nil) => insn(opc, dst, 0, 0, 0),
-        (LoadAbs, Integer(imm), Nil, Nil) => insn(opc, 0, 0, 0, imm),
-        (LoadInd, Register(src), Integer(imm), Nil) => insn(opc, 0, src, 0, imm),
-        (LoadReg, Register(dst), Memory(src, off), Nil)
-        | (StoreReg, Memory(dst, off), Register(src), Nil) => insn(opc, dst, src, off, 0),
-        (StoreImm, Memory(dst, off), Integer(imm), Nil) => insn(opc, dst, 0, off, imm),
-        (NoOperand, Nil, Nil, Nil) => insn(opc, 0, 0, 0, 0),
-        (JumpUnconditional, Integer(off), Nil, Nil) => insn(opc, 0, 0, off, 0),
-        (JumpConditional, Register(dst), Register(src), Integer(off)) => {
-            insn(opc | ebpf::BPF_X, dst, src, off, 0)
-        }
-        (JumpConditional, Register(dst), Integer(imm), Integer(off)) => {
-            insn(opc | ebpf::BPF_K, dst, 0, off, imm)
-        }
-        (Call, Integer(imm), Nil, Nil) => insn(opc, 0, 0, 0, imm),
-        (Endian(size), Register(dst), Nil, Nil) => insn(opc, dst, 0, 0, size),
-        (LoadImm, Register(dst), Integer(imm), Nil) => insn(opc, dst, 0, 0, (imm << 32) >> 32),
-        _ => Err(format!("Unexpected operands: {operands:?}")),
-    }
-}
-
-fn assemble_internal(parsed: &[Instruction]) -> Result<Vec<Insn>, String> {
-    let instruction_map = make_instruction_map();
-    let mut result: Vec<Insn> = vec![];
-    for instruction in parsed {
-        let name = instruction.name.as_str();
-        match instruction_map.get(name) {
-            Some(&(inst_type, opc)) => {
-                match encode(inst_type, opc, &instruction.operands) {
-                    Ok(insn) => result.push(insn),
-                    Err(msg) => return Err(format!("Failed to encode {name}: {msg}")),
-                }
-                // Special case for lddw.
-                if let LoadImm = inst_type {
-                    if let Integer(imm) = instruction.operands[1] {
-                        result.push(insn(0, 0, 0, 0, imm >> 32).unwrap());
-                    }
-                }
-            }
-            None => return Err(format!("Invalid instruction {name:?}")),
-        }
-    }
-    Ok(result)
-}
-
-/// Parse assembly source and translate to binary.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::assembler::assemble;
-/// let prog = assemble("add64 r1, 0x605
-///                      mov64 r2, 0x32
-///                      mov64 r1, r0
-///                      be16 r0
-///                      neg64 r2
-///                      exit");
-/// println!("{:?}", prog);
-/// # assert_eq!(prog,
-/// #            Ok(vec![0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
-/// #                    0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
-/// #                    0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/// #                    0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-/// #                    0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/// #                    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
-/// ```
-///
-/// This will produce the following output:
-///
-/// ```test
-/// Ok([0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
-///     0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
-///     0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-///     0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
-/// ```
-pub fn assemble(src: &str) -> Result<Vec<u8>, String> {
-    let parsed = (parse(src))?;
-    let insns = (assemble_internal(&parsed))?;
-    let mut result: Vec<u8> = vec![];
-    for insn in insns {
-        result.extend_from_slice(&insn.to_array());
-    }
-    Ok(result)
-}

+ 0 - 1230
kernel/crates/rbpf/src/cranelift.rs

@@ -1,1230 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-use alloc::{collections::BTreeMap, format, vec, vec::Vec};
-use core::{mem, mem::ManuallyDrop};
-use std::io::ErrorKind;
-
-use cranelift_codegen::{
-    entity::EntityRef,
-    ir::{
-        condcodes::IntCC,
-        types::{I16, I32, I64, I8},
-        AbiParam, Block, Endianness, FuncRef, Function, InstBuilder, MemFlags, Signature,
-        SourceLoc, StackSlotData, StackSlotKind, TrapCode, Type, UserFuncName, Value,
-    },
-    isa::OwnedTargetIsa,
-    settings::{self, Configurable},
-};
-use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
-use cranelift_jit::{JITBuilder, JITModule};
-use cranelift_module::{FuncId, Linkage, Module};
-
-use super::{Error, HashMap, HashSet};
-use crate::ebpf::{
-    self, Insn, BPF_ALU_OP_MASK, BPF_IND, BPF_JEQ, BPF_JGE, BPF_JGT, BPF_JLE, BPF_JLT, BPF_JMP32,
-    BPF_JNE, BPF_JSET, BPF_JSGE, BPF_JSGT, BPF_JSLE, BPF_JSLT, BPF_X, STACK_SIZE,
-};
-
-pub type JittedFunction = extern "C" fn(
-    *mut u8, // mem_ptr
-    usize,   // mem_len
-    *mut u8, // mbuff_ptr
-    usize,   // mbuff_len
-) -> u64;
-
-pub(crate) struct CraneliftCompiler {
-    isa: OwnedTargetIsa,
-    module: JITModule,
-
-    helpers: HashMap<u32, ebpf::Helper>,
-    helper_func_refs: HashMap<u32, FuncRef>,
-
-    /// List of blocks corresponding to each instruction.
-    /// We only store the first instruction that observes a new block
-    insn_blocks: BTreeMap<u32, Block>,
-    /// Map of block targets for each jump/branching instruction.
-    insn_targets: BTreeMap<u32, (Block, Block)>,
-    filled_blocks: HashSet<Block>,
-
-    /// Map of register numbers to Cranelift variables.
-    registers: [Variable; 11],
-    /// Other usefull variables used throughout the program.
-    mem_start: Variable,
-    mem_end: Variable,
-    mbuf_start: Variable,
-    mbuf_end: Variable,
-    stack_start: Variable,
-    stack_end: Variable,
-}
-
-impl CraneliftCompiler {
-    pub(crate) fn new(helpers: HashMap<u32, ebpf::Helper>) -> Self {
-        let mut flag_builder = settings::builder();
-
-        flag_builder.set("opt_level", "speed").unwrap();
-
-        // Enable stack probes
-        flag_builder.enable("enable_probestack").unwrap();
-        flag_builder.set("probestack_strategy", "inline").unwrap();
-
-        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
-            panic!("host machine is not supported: {}", msg);
-        });
-        let isa = isa_builder
-            .finish(settings::Flags::new(flag_builder))
-            .unwrap();
-
-        let mut jit_builder =
-            JITBuilder::with_isa(isa.clone(), cranelift_module::default_libcall_names());
-        // Register all the helpers
-        for (k, v) in helpers.iter() {
-            let name = format!("helper_{}", k);
-            jit_builder.symbol(name, (*v) as usize as *const u8);
-        }
-
-        let mut module = JITModule::new(jit_builder);
-
-        let registers = (0..11)
-            .map(|i| Variable::new(i))
-            .collect::<Vec<_>>()
-            .try_into()
-            .unwrap();
-
-        Self {
-            isa,
-            module,
-            helpers,
-            helper_func_refs: HashMap::new(),
-            insn_blocks: BTreeMap::new(),
-            insn_targets: BTreeMap::new(),
-            filled_blocks: HashSet::new(),
-            registers,
-            mem_start: Variable::new(11),
-            mem_end: Variable::new(12),
-            mbuf_start: Variable::new(13),
-            mbuf_end: Variable::new(14),
-            stack_start: Variable::new(15),
-            stack_end: Variable::new(16),
-        }
-    }
-
-    pub(crate) fn compile_function(mut self, prog: &[u8]) -> Result<CraneliftProgram, Error> {
-        let name = "main";
-        // This is not a standard eBPF function! We use an informal ABI with just 4 parameters.
-        // See [JittedFunction] which is the signature of this function.
-        //
-        // Since this function only serves as the entrypoint for the JITed program, it doesen't
-        // really matter.
-        let sig = Signature {
-            params: vec![
-                AbiParam::new(I64),
-                AbiParam::new(I64),
-                AbiParam::new(I64),
-                AbiParam::new(I64),
-            ],
-            returns: vec![AbiParam::new(I64)],
-            call_conv: self.isa.default_call_conv(),
-        };
-
-        let func_id = self
-            .module
-            .declare_function(name, Linkage::Local, &sig)
-            .unwrap();
-
-        let mut ctx = self.module.make_context();
-        ctx.func = Function::with_name_signature(UserFuncName::testcase(name.as_bytes()), sig);
-        let mut func_ctx = FunctionBuilderContext::new();
-
-        {
-            let mut builder: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
-
-            let entry = builder.create_block();
-            builder.append_block_params_for_function_params(entry);
-            builder.switch_to_block(entry);
-
-            self.build_cfg(&mut builder, prog)?;
-            self.build_function_prelude(&mut builder, entry)?;
-            self.translate_program(&mut builder, prog)?;
-
-            builder.seal_all_blocks();
-            builder.finalize();
-        }
-
-        self.module.define_function(func_id, &mut ctx).unwrap();
-        self.module.finalize_definitions().unwrap();
-        self.module.clear_context(&mut ctx);
-
-        Ok(CraneliftProgram::new(self.module, func_id))
-    }
-
-    fn build_function_prelude(
-        &mut self,
-        bcx: &mut FunctionBuilder,
-        entry: Block,
-    ) -> Result<(), Error> {
-        // Register the VM registers as variables
-        for var in self.registers.iter() {
-            bcx.declare_var(*var, I64);
-        }
-
-        // Register the bounds check variables
-        bcx.declare_var(self.mem_start, I64);
-        bcx.declare_var(self.mem_end, I64);
-        bcx.declare_var(self.mbuf_start, I64);
-        bcx.declare_var(self.mbuf_end, I64);
-        bcx.declare_var(self.stack_start, I64);
-        bcx.declare_var(self.stack_end, I64);
-
-        // Register the helpers
-        for (k, _) in self.helpers.iter() {
-            let name = format!("helper_{}", k);
-            let sig = Signature {
-                params: vec![
-                    AbiParam::new(I64),
-                    AbiParam::new(I64),
-                    AbiParam::new(I64),
-                    AbiParam::new(I64),
-                    AbiParam::new(I64),
-                ],
-                returns: vec![AbiParam::new(I64)],
-                call_conv: self.isa.default_call_conv(),
-            };
-            let func_id = self
-                .module
-                .declare_function(&name, Linkage::Import, &sig)
-                .unwrap();
-
-            let func_ref = self.module.declare_func_in_func(func_id, bcx.func);
-            self.helper_func_refs.insert(*k, func_ref);
-        }
-
-        // Register the stack
-        let ss = bcx.create_sized_stack_slot(StackSlotData {
-            kind: StackSlotKind::ExplicitSlot,
-            size: STACK_SIZE as u32,
-        });
-        let addr_ty = self.isa.pointer_type();
-        let stack_addr = bcx.ins().stack_addr(addr_ty, ss, STACK_SIZE as i32);
-        bcx.def_var(self.registers[10], stack_addr);
-
-        // Initialize the bounds check variables
-        let stack_start = bcx.ins().stack_addr(addr_ty, ss, 0);
-        bcx.def_var(self.stack_start, stack_start);
-        let stack_end = bcx.ins().stack_addr(addr_ty, ss, STACK_SIZE as i32);
-        bcx.def_var(self.stack_end, stack_end);
-
-        // This is our internal ABI where the first 2 params are the memory
-        let mem_start = bcx.block_params(entry)[0];
-        let mem_len = bcx.block_params(entry)[1];
-        let mem_end = bcx.ins().iadd(mem_start, mem_len);
-        bcx.def_var(self.mem_start, mem_start);
-        bcx.def_var(self.mem_end, mem_end);
-
-        // And the next 2 are the mbuf
-        let mbuf_start = bcx.block_params(entry)[2];
-        let mbuf_len = bcx.block_params(entry)[3];
-        let mbuf_end = bcx.ins().iadd(mbuf_start, mbuf_len);
-        bcx.def_var(self.mbuf_start, mbuf_start);
-        bcx.def_var(self.mbuf_end, mbuf_end);
-
-        // The ABI for eBPF specifies that R1 must contain either the memory, or mbuff pointer
-        // If the mbuf length is non-zero, then we use that, otherwise we use the memory pointer
-        let mbuf_exists = bcx.ins().icmp_imm(IntCC::NotEqual, mbuf_len, 0);
-        let mem_or_mbuf = bcx.ins().select(mbuf_exists, mbuf_start, mem_start);
-        bcx.def_var(self.registers[1], mem_or_mbuf);
-
-        // R2 should contain the length of the memory or mbuf
-        // At least ebpf-conformance tests expect this
-        let mem_or_mbuf_len = bcx.ins().select(mbuf_exists, mbuf_len, mem_len);
-        bcx.def_var(self.registers[2], mem_or_mbuf_len);
-
-        // Insert the *actual* initial block
-        let program_entry = bcx.create_block();
-        bcx.ins().jump(program_entry, &[]);
-        self.filled_blocks.insert(bcx.current_block().unwrap());
-        self.insn_blocks.insert(0, program_entry);
-
-        Ok(())
-    }
-
-    fn translate_program(&mut self, bcx: &mut FunctionBuilder, prog: &[u8]) -> Result<(), Error> {
-        let mut insn_ptr: usize = 0;
-        while insn_ptr * ebpf::INSN_SIZE < prog.len() {
-            let insn = ebpf::get_insn(prog, insn_ptr);
-
-            // If this instruction is on a new block switch to it.
-            if let Some(block) = self.insn_blocks.get(&(insn_ptr as u32)) {
-                // Blocks must have a terminator instruction at the end before we switch away from them
-                let current_block = bcx.current_block().unwrap();
-                if !self.filled_blocks.contains(&current_block) {
-                    bcx.ins().jump(*block, &[]);
-                }
-
-                bcx.switch_to_block(*block);
-            }
-
-            // Set the source location for the instruction
-            bcx.set_srcloc(SourceLoc::new(insn_ptr as u32));
-
-            match insn.opc {
-                // BPF_LD class
-                // LD_ABS_* and LD_IND_* are supposed to load pointer to data from metadata buffer.
-                // Since this pointer is constant, and since we already know it (mem), do not
-                // bother re-fetching it, just use mem already.
-                ebpf::LD_ABS_B
-                | ebpf::LD_ABS_H
-                | ebpf::LD_ABS_W
-                | ebpf::LD_ABS_DW
-                | ebpf::LD_IND_B
-                | ebpf::LD_IND_H
-                | ebpf::LD_IND_W
-                | ebpf::LD_IND_DW => {
-                    let ty = match insn.opc {
-                        ebpf::LD_ABS_B | ebpf::LD_IND_B => I8,
-                        ebpf::LD_ABS_H | ebpf::LD_IND_H => I16,
-                        ebpf::LD_ABS_W | ebpf::LD_IND_W => I32,
-                        ebpf::LD_ABS_DW | ebpf::LD_IND_DW => I64,
-                        _ => unreachable!(),
-                    };
-
-                    // Both instructions add the imm part of the instruction to the pointer
-                    let ptr = bcx.use_var(self.mem_start);
-                    let offset = bcx
-                        .ins()
-                        .iconst(self.isa.pointer_type(), insn.imm as u32 as i64);
-                    let addr = bcx.ins().iadd(ptr, offset);
-
-                    // IND instructions additionally add the value of the source register
-                    let is_ind = (insn.opc & BPF_IND) != 0;
-                    let addr = if is_ind {
-                        let src_reg = self.insn_src(bcx, &insn);
-                        bcx.ins().iadd(addr, src_reg)
-                    } else {
-                        addr
-                    };
-
-                    // The offset here has already been added to the pointer, so we pass 0
-                    let loaded = self.reg_load(bcx, ty, addr, 0);
-
-                    let ext = if ty != I64 {
-                        bcx.ins().uextend(I64, loaded)
-                    } else {
-                        loaded
-                    };
-
-                    self.set_dst(bcx, &insn, ext);
-                }
-                ebpf::LD_DW_IMM => {
-                    insn_ptr += 1;
-                    let next_insn = ebpf::get_insn(prog, insn_ptr);
-
-                    let imm = (((insn.imm as u32) as u64) + ((next_insn.imm as u64) << 32)) as i64;
-                    let iconst = bcx.ins().iconst(I64, imm);
-                    self.set_dst(bcx, &insn, iconst);
-                }
-
-                // BPF_LDX class
-                ebpf::LD_B_REG | ebpf::LD_H_REG | ebpf::LD_W_REG | ebpf::LD_DW_REG => {
-                    let ty = match insn.opc {
-                        ebpf::LD_B_REG => I8,
-                        ebpf::LD_H_REG => I16,
-                        ebpf::LD_W_REG => I32,
-                        ebpf::LD_DW_REG => I64,
-                        _ => unreachable!(),
-                    };
-
-                    let base = self.insn_src(bcx, &insn);
-                    let loaded = self.reg_load(bcx, ty, base, insn.off);
-
-                    let ext = if ty != I64 {
-                        bcx.ins().uextend(I64, loaded)
-                    } else {
-                        loaded
-                    };
-
-                    self.set_dst(bcx, &insn, ext);
-                }
-
-                // BPF_ST and BPF_STX class
-                ebpf::ST_B_IMM
-                | ebpf::ST_H_IMM
-                | ebpf::ST_W_IMM
-                | ebpf::ST_DW_IMM
-                | ebpf::ST_B_REG
-                | ebpf::ST_H_REG
-                | ebpf::ST_W_REG
-                | ebpf::ST_DW_REG => {
-                    let ty = match insn.opc {
-                        ebpf::ST_B_IMM | ebpf::ST_B_REG => I8,
-                        ebpf::ST_H_IMM | ebpf::ST_H_REG => I16,
-                        ebpf::ST_W_IMM | ebpf::ST_W_REG => I32,
-                        ebpf::ST_DW_IMM | ebpf::ST_DW_REG => I64,
-                        _ => unreachable!(),
-                    };
-                    let is_imm = match insn.opc {
-                        ebpf::ST_B_IMM | ebpf::ST_H_IMM | ebpf::ST_W_IMM | ebpf::ST_DW_IMM => true,
-                        ebpf::ST_B_REG | ebpf::ST_H_REG | ebpf::ST_W_REG | ebpf::ST_DW_REG => false,
-                        _ => unreachable!(),
-                    };
-
-                    let value = if is_imm {
-                        self.insn_imm64(bcx, &insn)
-                    } else {
-                        self.insn_src(bcx, &insn)
-                    };
-
-                    let narrow = if ty != I64 {
-                        bcx.ins().ireduce(ty, value)
-                    } else {
-                        value
-                    };
-
-                    let base = self.insn_dst(bcx, &insn);
-                    self.reg_store(bcx, ty, base, insn.off, narrow);
-                }
-
-                ebpf::ST_W_XADD => unimplemented!(),
-                ebpf::ST_DW_XADD => unimplemented!(),
-
-                // BPF_ALU class
-                // TODO Check how overflow works in kernel. Should we &= U32MAX all src register value
-                // before we do the operation?
-                // Cf ((0x11 << 32) - (0x1 << 32)) as u32 VS ((0x11 << 32) as u32 - (0x1 << 32) as u32
-                ebpf::ADD32_IMM => {
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().iadd(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::ADD32_REG => {
-                    //((reg[_dst] & U32MAX) + (reg[_src] & U32MAX)) & U32MAX,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().iadd(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::SUB32_IMM => {
-                    // reg[_dst] = (reg[_dst] as i32).wrapping_sub(insn.imm)         as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().isub(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::SUB32_REG => {
-                    // reg[_dst] = (reg[_dst] as i32).wrapping_sub(reg[_src] as i32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().isub(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::MUL32_IMM => {
-                    // reg[_dst] = (reg[_dst] as i32).wrapping_mul(insn.imm)         as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().imul(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::MUL32_REG => {
-                    // reg[_dst] = (reg[_dst] as i32).wrapping_mul(reg[_src] as i32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().imul(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::DIV32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32 / insn.imm              as u32) as u64,
-                    let res = if insn.imm == 0 {
-                        bcx.ins().iconst(I32, 0)
-                    } else {
-                        let imm = self.insn_imm32(bcx, &insn);
-                        let src = self.insn_dst32(bcx, &insn);
-                        bcx.ins().udiv(src, imm)
-                    };
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::DIV32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32 / reg[_src]             as u32) as u64,
-                    let zero = bcx.ins().iconst(I32, 0);
-                    let one = bcx.ins().iconst(I32, 1);
-
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-
-                    let rhs_is_zero = bcx.ins().icmp(IntCC::Equal, rhs, zero);
-                    let safe_rhs = bcx.ins().select(rhs_is_zero, one, rhs);
-                    let div_res = bcx.ins().udiv(lhs, safe_rhs);
-
-                    let res = bcx.ins().select(rhs_is_zero, zero, div_res);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::OR32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32             | insn.imm  as u32) as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().bor(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::OR32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32             | reg[_src] as u32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().bor(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::AND32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32             & insn.imm  as u32) as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().band(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::AND32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32             & reg[_src] as u32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().band(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::LSH32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32).wrapping_shl(insn.imm  as u32) as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().ishl(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::LSH32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32).wrapping_shl(reg[_src] as u32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().ishl(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::RSH32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32).wrapping_shr(insn.imm  as u32) as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().ushr(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::RSH32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32).wrapping_shr(reg[_src] as u32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().ushr(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::NEG32 => {
-                    // { reg[_dst] = (reg[_dst] as i32).wrapping_neg()                 as u64; reg[_dst] &= U32MAX; },
-                    let src = self.insn_dst32(bcx, &insn);
-                    let res = bcx.ins().ineg(src);
-                    // TODO: Do we need to mask the result?
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::MOD32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32             % insn.imm  as u32) as u64,
-
-                    if insn.imm != 0 {
-                        let imm = self.insn_imm32(bcx, &insn);
-                        let src = self.insn_dst32(bcx, &insn);
-                        let res = bcx.ins().urem(src, imm);
-                        self.set_dst32(bcx, &insn, res);
-                    }
-                }
-                ebpf::MOD32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32 % reg[_src]             as u32) as u64,
-                    let zero = bcx.ins().iconst(I32, 0);
-                    let one = bcx.ins().iconst(I32, 1);
-
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-
-                    let rhs_is_zero = bcx.ins().icmp(IntCC::Equal, rhs, zero);
-                    let safe_rhs = bcx.ins().select(rhs_is_zero, one, rhs);
-                    let div_res = bcx.ins().urem(lhs, safe_rhs);
-
-                    let res = bcx.ins().select(rhs_is_zero, lhs, div_res);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::XOR32_IMM => {
-                    // reg[_dst] = (reg[_dst] as u32             ^ insn.imm  as u32) as u64,
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().bxor(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::XOR32_REG => {
-                    // reg[_dst] = (reg[_dst] as u32             ^ reg[_src] as u32) as u64,
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().bxor(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::MOV32_IMM => {
-                    let imm = self.insn_imm32(bcx, &insn);
-                    self.set_dst32(bcx, &insn, imm);
-                }
-                ebpf::MOV32_REG => {
-                    // reg[_dst] = (reg[_src] as u32)                                as u64,
-                    let src = self.insn_src32(bcx, &insn);
-                    self.set_dst32(bcx, &insn, src);
-                }
-                ebpf::ARSH32_IMM => {
-                    // { reg[_dst] = (reg[_dst] as i32).wrapping_shr(insn.imm  as u32) as u64; reg[_dst] &= U32MAX; },
-                    let src = self.insn_dst32(bcx, &insn);
-                    let imm = self.insn_imm32(bcx, &insn);
-                    let res = bcx.ins().sshr(src, imm);
-                    self.set_dst32(bcx, &insn, res);
-                }
-                ebpf::ARSH32_REG => {
-                    // { reg[_dst] = (reg[_dst] as i32).wrapping_shr(reg[_src] as u32) as u64; reg[_dst] &= U32MAX; },
-                    let lhs = self.insn_dst32(bcx, &insn);
-                    let rhs = self.insn_src32(bcx, &insn);
-                    let res = bcx.ins().sshr(lhs, rhs);
-                    self.set_dst32(bcx, &insn, res);
-                }
-
-                ebpf::BE | ebpf::LE => {
-                    let should_swap = match insn.opc {
-                        ebpf::BE => self.isa.endianness() == Endianness::Little,
-                        ebpf::LE => self.isa.endianness() == Endianness::Big,
-                        _ => unreachable!(),
-                    };
-
-                    let ty: Type = match insn.imm {
-                        16 => I16,
-                        32 => I32,
-                        64 => I64,
-                        _ => unreachable!(),
-                    };
-
-                    if should_swap {
-                        let src = self.insn_dst(bcx, &insn);
-                        let src_narrow = if ty != I64 {
-                            bcx.ins().ireduce(ty, src)
-                        } else {
-                            src
-                        };
-
-                        let res = bcx.ins().bswap(src_narrow);
-                        let res_wide = if ty != I64 {
-                            bcx.ins().uextend(I64, res)
-                        } else {
-                            res
-                        };
-
-                        self.set_dst(bcx, &insn, res_wide);
-                    }
-                }
-
-                // BPF_ALU64 class
-                ebpf::ADD64_IMM => {
-                    // reg[_dst] = reg[_dst].wrapping_add(insn.imm as u64),
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().iadd(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::ADD64_REG => {
-                    // reg[_dst] = reg[_dst].wrapping_add(reg[_src]),
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().iadd(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::SUB64_IMM => {
-                    // reg[_dst] = reg[_dst].wrapping_sub(insn.imm as u64),
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().isub(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::SUB64_REG => {
-                    // reg[_dst] = reg[_dst].wrapping_sub(reg[_src]),
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().isub(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::MUL64_IMM => {
-                    // reg[_dst] = reg[_dst].wrapping_mul(insn.imm as u64),
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().imul(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::MUL64_REG => {
-                    // reg[_dst] = reg[_dst].wrapping_mul(reg[_src]),
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().imul(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::DIV64_IMM => {
-                    // reg[_dst] /= insn.imm as u64,
-                    let res = if insn.imm == 0 {
-                        bcx.ins().iconst(I64, 0)
-                    } else {
-                        let imm = self.insn_imm64(bcx, &insn);
-                        let src = self.insn_dst(bcx, &insn);
-                        bcx.ins().udiv(src, imm)
-                    };
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::DIV64_REG => {
-                    // reg[_dst] /= reg[_src], if reg[_src] != 0
-                    // reg[_dst] = 0, if reg[_src] == 0
-                    let zero = bcx.ins().iconst(I64, 0);
-                    let one = bcx.ins().iconst(I64, 1);
-
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-
-                    let rhs_is_zero = bcx.ins().icmp(IntCC::Equal, rhs, zero);
-                    let safe_rhs = bcx.ins().select(rhs_is_zero, one, rhs);
-                    let div_res = bcx.ins().udiv(lhs, safe_rhs);
-
-                    let res = bcx.ins().select(rhs_is_zero, zero, div_res);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::MOD64_IMM => {
-                    // reg[_dst] %= insn.imm as u64,
-
-                    if insn.imm != 0 {
-                        let imm = self.insn_imm64(bcx, &insn);
-                        let src = self.insn_dst(bcx, &insn);
-                        let res = bcx.ins().urem(src, imm);
-                        self.set_dst(bcx, &insn, res);
-                    };
-                }
-                ebpf::MOD64_REG => {
-                    // reg[_dst] %= reg[_src], if reg[_src] != 0
-
-                    let zero = bcx.ins().iconst(I64, 0);
-                    let one = bcx.ins().iconst(I64, 1);
-
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-
-                    let rhs_is_zero = bcx.ins().icmp(IntCC::Equal, rhs, zero);
-                    let safe_rhs = bcx.ins().select(rhs_is_zero, one, rhs);
-                    let div_res = bcx.ins().urem(lhs, safe_rhs);
-
-                    let res = bcx.ins().select(rhs_is_zero, lhs, div_res);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::OR64_IMM => {
-                    // reg[_dst] |= insn.imm as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().bor(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::OR64_REG => {
-                    // reg[_dst] |= reg[_src],
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().bor(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::AND64_IMM => {
-                    // reg[_dst] &= insn.imm as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().band(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::AND64_REG => {
-                    // reg[_dst] &= reg[_src],
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().band(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::LSH64_IMM => {
-                    // reg[_dst] <<= insn.imm as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().ishl(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::LSH64_REG => {
-                    // reg[_dst] <<= reg[_src],
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().ishl(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::RSH64_IMM => {
-                    // reg[_dst] >>= insn.imm as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().ushr(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::RSH64_REG => {
-                    // reg[_dst] >>= reg[_src],
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().ushr(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::NEG64 => {
-                    // reg[_dst] = -(reg[_dst] as i64) as u64,
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().ineg(src);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::XOR64_IMM => {
-                    // reg[_dst] ^= insn.imm as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().bxor(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::XOR64_REG => {
-                    // reg[_dst] ^= reg[_src],
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().bxor(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::MOV64_IMM => {
-                    // reg[_dst] = insn.imm as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    bcx.def_var(self.registers[insn.dst as usize], imm);
-                }
-                ebpf::MOV64_REG => {
-                    // reg[_dst] = reg[_src],
-                    let src = self.insn_src(bcx, &insn);
-                    bcx.def_var(self.registers[insn.dst as usize], src);
-                }
-                ebpf::ARSH64_IMM => {
-                    // reg[_dst] = (reg[_dst] as i64 >> insn.imm) as u64,
-                    let imm = self.insn_imm64(bcx, &insn);
-                    let src = self.insn_dst(bcx, &insn);
-                    let res = bcx.ins().sshr(src, imm);
-                    self.set_dst(bcx, &insn, res);
-                }
-                ebpf::ARSH64_REG => {
-                    // reg[_dst] = (reg[_dst] as i64 >> reg[_src]) as u64,
-                    let lhs = self.insn_dst(bcx, &insn);
-                    let rhs = self.insn_src(bcx, &insn);
-                    let res = bcx.ins().sshr(lhs, rhs);
-                    self.set_dst(bcx, &insn, res);
-                }
-
-                // BPF_JMP & BPF_JMP32 class
-                ebpf::JA => {
-                    let (_, target_block) = self.insn_targets[&(insn_ptr as u32)];
-
-                    bcx.ins().jump(target_block, &[]);
-                    self.filled_blocks.insert(bcx.current_block().unwrap());
-                }
-                ebpf::JEQ_IMM
-                | ebpf::JEQ_REG
-                | ebpf::JGT_IMM
-                | ebpf::JGT_REG
-                | ebpf::JGE_IMM
-                | ebpf::JGE_REG
-                | ebpf::JLT_IMM
-                | ebpf::JLT_REG
-                | ebpf::JLE_IMM
-                | ebpf::JLE_REG
-                | ebpf::JNE_IMM
-                | ebpf::JNE_REG
-                | ebpf::JSGT_IMM
-                | ebpf::JSGT_REG
-                | ebpf::JSGE_IMM
-                | ebpf::JSGE_REG
-                | ebpf::JSLT_IMM
-                | ebpf::JSLT_REG
-                | ebpf::JSLE_IMM
-                | ebpf::JSLE_REG
-                | ebpf::JSET_IMM
-                | ebpf::JSET_REG
-                | ebpf::JEQ_IMM32
-                | ebpf::JEQ_REG32
-                | ebpf::JGT_IMM32
-                | ebpf::JGT_REG32
-                | ebpf::JGE_IMM32
-                | ebpf::JGE_REG32
-                | ebpf::JLT_IMM32
-                | ebpf::JLT_REG32
-                | ebpf::JLE_IMM32
-                | ebpf::JLE_REG32
-                | ebpf::JNE_IMM32
-                | ebpf::JNE_REG32
-                | ebpf::JSGT_IMM32
-                | ebpf::JSGT_REG32
-                | ebpf::JSGE_IMM32
-                | ebpf::JSGE_REG32
-                | ebpf::JSLT_IMM32
-                | ebpf::JSLT_REG32
-                | ebpf::JSLE_IMM32
-                | ebpf::JSLE_REG32
-                | ebpf::JSET_IMM32
-                | ebpf::JSET_REG32 => {
-                    let (fallthrough, target) = self.insn_targets[&(insn_ptr as u32)];
-
-                    let is_reg = (insn.opc & BPF_X) != 0;
-                    let is_32 = (insn.opc & BPF_JMP32) != 0;
-                    let intcc = match insn.opc {
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JEQ => IntCC::Equal,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JNE => IntCC::NotEqual,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JGT => IntCC::UnsignedGreaterThan,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JGE => IntCC::UnsignedGreaterThanOrEqual,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JLT => IntCC::UnsignedLessThan,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JLE => IntCC::UnsignedLessThanOrEqual,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JSGT => IntCC::SignedGreaterThan,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JSGE => IntCC::SignedGreaterThanOrEqual,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JSLT => IntCC::SignedLessThan,
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JSLE => IntCC::SignedLessThanOrEqual,
-                        // JSET is handled specially below
-                        c if (c & BPF_ALU_OP_MASK) == BPF_JSET => IntCC::NotEqual,
-                        _ => unreachable!(),
-                    };
-
-                    let lhs = if is_32 {
-                        self.insn_dst32(bcx, &insn)
-                    } else {
-                        self.insn_dst(bcx, &insn)
-                    };
-                    let rhs = match (is_reg, is_32) {
-                        (true, false) => self.insn_src(bcx, &insn),
-                        (true, true) => self.insn_src32(bcx, &insn),
-                        (false, false) => self.insn_imm64(bcx, &insn),
-                        (false, true) => self.insn_imm32(bcx, &insn),
-                    };
-
-                    let cmp_res = if (insn.opc & BPF_ALU_OP_MASK) == BPF_JSET {
-                        bcx.ins().band(lhs, rhs)
-                    } else {
-                        bcx.ins().icmp(intcc, lhs, rhs)
-                    };
-                    bcx.ins().brif(cmp_res, target, &[], fallthrough, &[]);
-                    self.filled_blocks.insert(bcx.current_block().unwrap());
-                }
-
-                // Do not delegate the check to the verifier, since registered functions can be
-                // changed after the program has been verified.
-                ebpf::CALL => {
-                    let func_ref = self
-                        .helper_func_refs
-                        .get(&(insn.imm as u32))
-                        .copied()
-                        .ok_or_else(|| {
-                            Error::new(
-                                ErrorKind::Other,
-                                format!(
-                                    "[CRANELIFT] Error: unknown helper function (id: {:#x})",
-                                    insn.imm as u32
-                                ),
-                            )
-                        })?;
-
-                    let arg0 = bcx.use_var(self.registers[1]);
-                    let arg1 = bcx.use_var(self.registers[2]);
-                    let arg2 = bcx.use_var(self.registers[3]);
-                    let arg3 = bcx.use_var(self.registers[4]);
-                    let arg4 = bcx.use_var(self.registers[5]);
-
-                    let call = bcx.ins().call(func_ref, &[arg0, arg1, arg2, arg3, arg4]);
-                    let ret = bcx.inst_results(call)[0];
-                    self.set_dst(bcx, &insn, ret);
-                }
-                ebpf::TAIL_CALL => unimplemented!(),
-                ebpf::EXIT => {
-                    let ret = bcx.use_var(self.registers[0]);
-                    bcx.ins().return_(&[ret]);
-                    self.filled_blocks.insert(bcx.current_block().unwrap());
-                }
-                _ => unimplemented!("inst: {:?}", insn),
-            }
-
-            insn_ptr += 1;
-        }
-
-        Ok(())
-    }
-
-    fn insn_imm64(&mut self, bcx: &mut FunctionBuilder, insn: &Insn) -> Value {
-        bcx.ins().iconst(I64, insn.imm as u64 as i64)
-    }
-    fn insn_imm32(&mut self, bcx: &mut FunctionBuilder, insn: &Insn) -> Value {
-        bcx.ins().iconst(I32, insn.imm as u32 as u64 as i64)
-    }
-
-    fn insn_dst(&mut self, bcx: &mut FunctionBuilder, insn: &Insn) -> Value {
-        bcx.use_var(self.registers[insn.dst as usize])
-    }
-    fn insn_dst32(&mut self, bcx: &mut FunctionBuilder, insn: &Insn) -> Value {
-        let dst = self.insn_dst(bcx, insn);
-        bcx.ins().ireduce(I32, dst)
-    }
-
-    fn insn_src(&mut self, bcx: &mut FunctionBuilder, insn: &Insn) -> Value {
-        bcx.use_var(self.registers[insn.src as usize])
-    }
-    fn insn_src32(&mut self, bcx: &mut FunctionBuilder, insn: &Insn) -> Value {
-        let src = self.insn_src(bcx, insn);
-        bcx.ins().ireduce(I32, src)
-    }
-
-    fn set_dst(&mut self, bcx: &mut FunctionBuilder, insn: &Insn, val: Value) {
-        bcx.def_var(self.registers[insn.dst as usize], val);
-    }
-    fn set_dst32(&mut self, bcx: &mut FunctionBuilder, insn: &Insn, val: Value) {
-        let val32 = bcx.ins().uextend(I64, val);
-        self.set_dst(bcx, insn, val32);
-    }
-
-    fn reg_load(&mut self, bcx: &mut FunctionBuilder, ty: Type, base: Value, offset: i16) -> Value {
-        self.insert_bounds_check(bcx, ty, base, offset);
-
-        let mut flags = MemFlags::new();
-        flags.set_endianness(Endianness::Little);
-
-        bcx.ins().load(ty, flags, base, offset as i32)
-    }
-    fn reg_store(
-        &mut self,
-        bcx: &mut FunctionBuilder,
-        ty: Type,
-        base: Value,
-        offset: i16,
-        val: Value,
-    ) {
-        self.insert_bounds_check(bcx, ty, base, offset);
-
-        let mut flags = MemFlags::new();
-        flags.set_endianness(Endianness::Little);
-
-        bcx.ins().store(flags, val, base, offset as i32);
-    }
-
-    /// Inserts a bounds check for a memory access
-    ///
-    /// This emits a conditional trap if the access is out of bounds for any of the known
-    /// valid memory regions. These are the stack, the memory, and the mbuf.
-    fn insert_bounds_check(
-        &mut self,
-        bcx: &mut FunctionBuilder,
-        ty: Type,
-        base: Value,
-        offset: i16,
-    ) {
-        let access_size = bcx.ins().iconst(I64, ty.bytes() as i64);
-
-        let offset = bcx.ins().iconst(I64, offset as i64);
-        let start_addr = bcx.ins().iadd(base, offset);
-        let end_addr = bcx.ins().iadd(start_addr, access_size);
-
-        let does_not_overflow =
-            bcx.ins()
-                .icmp(IntCC::UnsignedGreaterThanOrEqual, end_addr, start_addr);
-
-        // Check if it's a valid stack access
-        let stack_start = bcx.use_var(self.stack_start);
-        let stack_end = bcx.use_var(self.stack_end);
-        let stack_start_valid =
-            bcx.ins()
-                .icmp(IntCC::UnsignedGreaterThanOrEqual, start_addr, stack_start);
-        let stack_end_valid = bcx
-            .ins()
-            .icmp(IntCC::UnsignedLessThanOrEqual, end_addr, stack_end);
-        let stack_valid = bcx.ins().band(stack_start_valid, stack_end_valid);
-
-        // Check if it's a valid memory access
-        let mem_start = bcx.use_var(self.mem_start);
-        let mem_end = bcx.use_var(self.mem_end);
-        let has_mem = bcx.ins().icmp_imm(IntCC::NotEqual, mem_start, 0);
-        let mem_start_valid =
-            bcx.ins()
-                .icmp(IntCC::UnsignedGreaterThanOrEqual, start_addr, mem_start);
-        let mem_end_valid = bcx
-            .ins()
-            .icmp(IntCC::UnsignedLessThanOrEqual, end_addr, mem_end);
-
-        let mem_valid = bcx.ins().band(mem_start_valid, mem_end_valid);
-        let mem_valid = bcx.ins().band(mem_valid, has_mem);
-
-        // Check if it's a valid mbuf access
-        let mbuf_start = bcx.use_var(self.mbuf_start);
-        let mbuf_end = bcx.use_var(self.mbuf_end);
-        let has_mbuf = bcx.ins().icmp_imm(IntCC::NotEqual, mbuf_start, 0);
-        let mbuf_start_valid =
-            bcx.ins()
-                .icmp(IntCC::UnsignedGreaterThanOrEqual, start_addr, mbuf_start);
-        let mbuf_end_valid = bcx
-            .ins()
-            .icmp(IntCC::UnsignedLessThanOrEqual, end_addr, mbuf_end);
-        let mbuf_valid = bcx.ins().band(mbuf_start_valid, mbuf_end_valid);
-        let mbuf_valid = bcx.ins().band(mbuf_valid, has_mbuf);
-
-        // Join all of these checks together and trap if any of them fails
-
-        // We need it to be valid to at least one region of memory
-        let valid_region = bcx.ins().bor(stack_valid, mem_valid);
-        let valid_region = bcx.ins().bor(valid_region, mbuf_valid);
-
-        // And that it does not overflow
-        let valid = bcx.ins().band(does_not_overflow, valid_region);
-
-        // TODO: We can potentially throw a custom trap code here to indicate
-        // which check failed.
-        bcx.ins().trapz(valid, TrapCode::HeapOutOfBounds);
-    }
-
-    /// Analyze the program and build the CFG
-    ///
-    /// We do this because cranelift does not allow us to switch back to a previously
-    /// filled block and add instructions to it. So we can't split the program as we
-    /// translate it.
-    fn build_cfg(&mut self, bcx: &mut FunctionBuilder, prog: &[u8]) -> Result<(), Error> {
-        let mut insn_ptr: usize = 0;
-        while insn_ptr * ebpf::INSN_SIZE < prog.len() {
-            let insn = ebpf::get_insn(prog, insn_ptr);
-
-            match insn.opc {
-                // This instruction consumes two opcodes
-                ebpf::LD_DW_IMM => {
-                    insn_ptr += 1;
-                }
-
-                ebpf::JA
-                | ebpf::JEQ_IMM
-                | ebpf::JEQ_REG
-                | ebpf::JGT_IMM
-                | ebpf::JGT_REG
-                | ebpf::JGE_IMM
-                | ebpf::JGE_REG
-                | ebpf::JLT_IMM
-                | ebpf::JLT_REG
-                | ebpf::JLE_IMM
-                | ebpf::JLE_REG
-                | ebpf::JNE_IMM
-                | ebpf::JNE_REG
-                | ebpf::JSGT_IMM
-                | ebpf::JSGT_REG
-                | ebpf::JSGE_IMM
-                | ebpf::JSGE_REG
-                | ebpf::JSLT_IMM
-                | ebpf::JSLT_REG
-                | ebpf::JSLE_IMM
-                | ebpf::JSLE_REG
-                | ebpf::JSET_IMM
-                | ebpf::JSET_REG
-                | ebpf::JEQ_IMM32
-                | ebpf::JEQ_REG32
-                | ebpf::JGT_IMM32
-                | ebpf::JGT_REG32
-                | ebpf::JGE_IMM32
-                | ebpf::JGE_REG32
-                | ebpf::JLT_IMM32
-                | ebpf::JLT_REG32
-                | ebpf::JLE_IMM32
-                | ebpf::JLE_REG32
-                | ebpf::JNE_IMM32
-                | ebpf::JNE_REG32
-                | ebpf::JSGT_IMM32
-                | ebpf::JSGT_REG32
-                | ebpf::JSGE_IMM32
-                | ebpf::JSGE_REG32
-                | ebpf::JSLT_IMM32
-                | ebpf::JSLT_REG32
-                | ebpf::JSLE_IMM32
-                | ebpf::JSLE_REG32
-                | ebpf::JSET_IMM32
-                | ebpf::JSET_REG32
-                | ebpf::EXIT
-                | ebpf::TAIL_CALL => {
-                    self.prepare_jump_blocks(bcx, insn_ptr, &insn);
-                }
-                _ => {}
-            }
-
-            insn_ptr += 1;
-        }
-
-        Ok(())
-    }
-
-    fn prepare_jump_blocks(&mut self, bcx: &mut FunctionBuilder, insn_ptr: usize, insn: &Insn) {
-        let insn_ptr = insn_ptr as u32;
-        let next_pc: u32 = insn_ptr + 1;
-        let target_pc: u32 = (insn_ptr as isize + insn.off as isize + 1)
-            .try_into()
-            .unwrap();
-
-        // This is the fallthrough block
-        let fallthrough_block = *self
-            .insn_blocks
-            .entry(next_pc)
-            .or_insert_with(|| bcx.create_block());
-
-        // Jump Target
-        let target_block = *self
-            .insn_blocks
-            .entry(target_pc)
-            .or_insert_with(|| bcx.create_block());
-
-        // Mark the blocks for this instruction
-        self.insn_targets
-            .insert(insn_ptr, (fallthrough_block, target_block));
-    }
-}
-
-/// Contains the backing memory for a previously compiled function.
-///
-/// Currently this will allways just contain code for a single function, but
-/// in the future we might want to support multiple functions per module.
-///
-/// Ensures that the backing memory is freed when dropped.
-pub struct CraneliftProgram {
-    module: ManuallyDrop<JITModule>,
-
-    main_id: FuncId,
-}
-
-impl CraneliftProgram {
-    pub(crate) fn new(module: JITModule, main_id: FuncId) -> Self {
-        Self {
-            module: ManuallyDrop::new(module),
-            main_id,
-        }
-    }
-
-    /// We shouldn't allow this function pointer to be exposed outside of this
-    /// module, since it's not guaranteed to be valid after the module is dropped.
-    pub(crate) fn get_main_function(&self) -> JittedFunction {
-        let function_ptr = self.module.get_finalized_function(self.main_id);
-        unsafe { mem::transmute(function_ptr) }
-    }
-
-    /// Execute this module by calling the main function
-    pub fn execute(
-        &self,
-        mem_ptr: *mut u8,
-        mem_len: usize,
-        mbuff_ptr: *mut u8,
-        mbuff_len: usize,
-    ) -> u64 {
-        let main = self.get_main_function();
-
-        main(mem_ptr, mem_len, mbuff_ptr, mbuff_len)
-    }
-}
-
-impl Drop for CraneliftProgram {
-    fn drop(&mut self) {
-        // We need to have an owned version of `JITModule` to be able to free
-        // it's memory. Use `ManuallyDrop` to get the owned `JITModule`.
-        //
-        // We can no longer use `module` after this, but since we are `Drop`
-        // it should be safe.
-        unsafe {
-            let module = ManuallyDrop::take(&mut self.module);
-            module.free_memory()
-        };
-    }
-}

+ 0 - 807
kernel/crates/rbpf/src/disassembler.rs

@@ -1,807 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 6WIND S.A. <quentin.monnet@6wind.com>
-
-//! Functions in this module are used to handle eBPF programs with a higher level representation,
-//! for example to disassemble the code into a human-readable format.
-
-use alloc::{
-    format,
-    string::{String, ToString},
-    vec,
-    vec::Vec,
-};
-
-use log::warn;
-
-use crate::ebpf;
-
-#[inline]
-fn alu_imm_str(name: &str, insn: &ebpf::Insn) -> String {
-    format!("{name} r{}, {:#x}", insn.dst, insn.imm)
-}
-
-#[inline]
-fn alu_reg_str(name: &str, insn: &ebpf::Insn) -> String {
-    format!("{name} r{}, r{}", insn.dst, insn.src)
-}
-
-#[inline]
-fn byteswap_str(name: &str, insn: &ebpf::Insn) -> String {
-    match insn.imm {
-        16 | 32 | 64 => {}
-        _ => warn!("[Disassembler] Warning: Invalid offset value for {name} insn"),
-    }
-    format!("{name}{} r{}", insn.imm, insn.dst)
-}
-
-#[inline]
-fn ld_st_imm_str(name: &str, insn: &ebpf::Insn) -> String {
-    if insn.off >= 0 {
-        format!("{name} [r{}+{:#x}], {:#x}", insn.dst, insn.off, insn.imm)
-    } else {
-        format!(
-            "{name} [r{}-{:#x}], {:#x}",
-            insn.dst,
-            -(insn.off as isize),
-            insn.imm
-        )
-    }
-}
-
-#[inline]
-fn ld_reg_str(name: &str, insn: &ebpf::Insn) -> String {
-    if insn.off >= 0 {
-        format!("{name} r{}, [r{}+{:#x}]", insn.dst, insn.src, insn.off)
-    } else {
-        format!(
-            "{name} r{}, [r{}-{:#x}]",
-            insn.dst,
-            insn.src,
-            -(insn.off as isize)
-        )
-    }
-}
-
-#[inline]
-fn st_reg_str(name: &str, insn: &ebpf::Insn) -> String {
-    if insn.off >= 0 {
-        format!("{name} [r{}+{:#x}], r{}", insn.dst, insn.off, insn.src)
-    } else {
-        format!(
-            "{name} [r{}-{:#x}], r{}",
-            insn.dst,
-            -(insn.off as isize),
-            insn.src
-        )
-    }
-}
-
-#[inline]
-fn ldabs_str(name: &str, insn: &ebpf::Insn) -> String {
-    format!("{name} {:#x}", insn.imm)
-}
-
-#[inline]
-fn ldind_str(name: &str, insn: &ebpf::Insn) -> String {
-    format!("{name} r{}, {:#x}", insn.src, insn.imm)
-}
-
-#[inline]
-fn jmp_imm_str(name: &str, insn: &ebpf::Insn) -> String {
-    if insn.off >= 0 {
-        format!("{name} r{}, {:#x}, +{:#x}", insn.dst, insn.imm, insn.off)
-    } else {
-        format!(
-            "{name} r{}, {:#x}, -{:#x}",
-            insn.dst,
-            insn.imm,
-            -(insn.off as isize)
-        )
-    }
-}
-
-#[inline]
-fn jmp_reg_str(name: &str, insn: &ebpf::Insn) -> String {
-    if insn.off >= 0 {
-        format!("{name} r{}, r{}, +{:#x}", insn.dst, insn.src, insn.off)
-    } else {
-        format!(
-            "{name} r{}, r{}, -{:#x}",
-            insn.dst,
-            insn.src,
-            -(insn.off as isize)
-        )
-    }
-}
-
-/// High-level representation of an eBPF instruction.
-///
-/// In addition to standard operation code and various operand, this struct has the following
-/// properties:
-///
-/// * It stores a name, corresponding to a mnemonic for the operation code.
-/// * It also stores a description, which is a mnemonic for the full instruction, using the actual
-///   values of the relevant operands, and that can be used for disassembling the eBPF program for
-///   example.
-/// * Immediate values are stored in an `i64` instead of a traditional i32, in order to merge the
-///   two parts of (otherwise double-length) `LD_DW_IMM` instructions.
-///
-/// See <https://www.kernel.org/doc/Documentation/networking/filter.txt> for the Linux kernel
-/// documentation about eBPF, or <https://github.com/iovisor/bpf-docs/blob/master/eBPF.md> for a
-/// more concise version.
-#[derive(Debug, PartialEq, Eq)]
-pub struct HLInsn {
-    /// Operation code.
-    pub opc: u8,
-    /// Name (mnemonic). This name is not canon.
-    pub name: String,
-    /// Description of the instruction. This is not canon.
-    pub desc: String,
-    /// Destination register operand.
-    pub dst: u8,
-    /// Source register operand.
-    pub src: u8,
-    /// Offset operand.
-    pub off: i16,
-    /// Immediate value operand. For `LD_DW_IMM` instructions, contains the whole value merged from
-    /// the two 8-bytes parts of the instruction.
-    pub imm: i64,
-}
-
-/// Return a vector of `struct HLInsn` built from an eBPF program.
-///
-/// This is made public to provide a way to manipulate a program as a vector of instructions, in a
-/// high-level format, for example for dumping the program instruction after instruction with a
-/// custom format.
-///
-/// Note that the two parts of `LD_DW_IMM` instructions (that have the size of two standard
-/// instructions) are considered as making a single immediate value. As a consequence, the number
-/// of instructions stored in the vector may not be equal to the size in bytes of the program
-/// divided by the length of an instructions.
-///
-/// To do so, the immediate value operand is stored as an `i64` instead as an i32, so be careful
-/// when you use it (see example `examples/to_json.rs`).
-///
-/// This is to oppose to `ebpf::to_insn_vec()` function, that treats instructions on a low-level
-/// ground and do not merge the parts of `LD_DW_IMM`. Also, the version in `ebpf` module does not
-/// use names or descriptions when storing the instructions.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::disassembler;
-///
-/// let prog = &[
-///     0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55,
-///     0x00, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-/// ];
-///
-/// let v = disassembler::to_insn_vec(prog);
-/// assert_eq!(v, vec![
-///     disassembler::HLInsn {
-///         opc: 0x18,
-///         name: "lddw".to_string(),
-///         desc: "lddw r0, 0x1122334455667788".to_string(),
-///         dst: 0,
-///         src: 0,
-///         off: 0,
-///         imm: 0x1122334455667788
-///     },
-///     disassembler::HLInsn {
-///         opc: 0x95,
-///         name: "exit".to_string(),
-///         desc: "exit".to_string(),
-///         dst: 0,
-///         src: 0,
-///         off: 0,
-///         imm: 0
-///     },
-/// ]);
-/// ```
-pub fn to_insn_vec(prog: &[u8]) -> Vec<HLInsn> {
-    if prog.len() % ebpf::INSN_SIZE != 0 {
-        panic!(
-            "[Disassembler] Error: eBPF program length must be a multiple of {:?} octets",
-            ebpf::INSN_SIZE
-        );
-    }
-    if prog.is_empty() {
-        return vec![];
-    }
-
-    let mut res = vec![];
-    let mut insn_ptr: usize = 0;
-
-    while insn_ptr * ebpf::INSN_SIZE < prog.len() {
-        let insn = ebpf::get_insn(prog, insn_ptr);
-
-        let name;
-        let desc;
-        let mut imm = insn.imm as i64;
-        match insn.opc {
-            // BPF_LD class
-            ebpf::LD_ABS_B => {
-                name = "ldabsb";
-                desc = ldabs_str(name, &insn);
-            }
-            ebpf::LD_ABS_H => {
-                name = "ldabsh";
-                desc = ldabs_str(name, &insn);
-            }
-            ebpf::LD_ABS_W => {
-                name = "ldabsw";
-                desc = ldabs_str(name, &insn);
-            }
-            ebpf::LD_ABS_DW => {
-                name = "ldabsdw";
-                desc = ldabs_str(name, &insn);
-            }
-            ebpf::LD_IND_B => {
-                name = "ldindb";
-                desc = ldind_str(name, &insn);
-            }
-            ebpf::LD_IND_H => {
-                name = "ldindh";
-                desc = ldind_str(name, &insn);
-            }
-            ebpf::LD_IND_W => {
-                name = "ldindw";
-                desc = ldind_str(name, &insn);
-            }
-            ebpf::LD_IND_DW => {
-                name = "ldinddw";
-                desc = ldind_str(name, &insn);
-            }
-
-            ebpf::LD_DW_IMM => {
-                insn_ptr += 1;
-                let next_insn = ebpf::get_insn(prog, insn_ptr);
-                imm = ((insn.imm as u32) as u64 + ((next_insn.imm as u64) << 32)) as i64;
-                name = "lddw";
-                desc = format!("{name} r{:}, {imm:#x}", insn.dst);
-            }
-
-            // BPF_LDX class
-            ebpf::LD_B_REG => {
-                name = "ldxb";
-                desc = ld_reg_str(name, &insn);
-            }
-            ebpf::LD_H_REG => {
-                name = "ldxh";
-                desc = ld_reg_str(name, &insn);
-            }
-            ebpf::LD_W_REG => {
-                name = "ldxw";
-                desc = ld_reg_str(name, &insn);
-            }
-            ebpf::LD_DW_REG => {
-                name = "ldxdw";
-                desc = ld_reg_str(name, &insn);
-            }
-
-            // BPF_ST class
-            ebpf::ST_B_IMM => {
-                name = "stb";
-                desc = ld_st_imm_str(name, &insn);
-            }
-            ebpf::ST_H_IMM => {
-                name = "sth";
-                desc = ld_st_imm_str(name, &insn);
-            }
-            ebpf::ST_W_IMM => {
-                name = "stw";
-                desc = ld_st_imm_str(name, &insn);
-            }
-            ebpf::ST_DW_IMM => {
-                name = "stdw";
-                desc = ld_st_imm_str(name, &insn);
-            }
-
-            // BPF_STX class
-            ebpf::ST_B_REG => {
-                name = "stxb";
-                desc = st_reg_str(name, &insn);
-            }
-            ebpf::ST_H_REG => {
-                name = "stxh";
-                desc = st_reg_str(name, &insn);
-            }
-            ebpf::ST_W_REG => {
-                name = "stxw";
-                desc = st_reg_str(name, &insn);
-            }
-            ebpf::ST_DW_REG => {
-                name = "stxdw";
-                desc = st_reg_str(name, &insn);
-            }
-            ebpf::ST_W_XADD => {
-                name = "stxxaddw";
-                desc = st_reg_str(name, &insn);
-            }
-            ebpf::ST_DW_XADD => {
-                name = "stxxadddw";
-                desc = st_reg_str(name, &insn);
-            }
-
-            // BPF_ALU class
-            ebpf::ADD32_IMM => {
-                name = "add32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::ADD32_REG => {
-                name = "add32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::SUB32_IMM => {
-                name = "sub32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::SUB32_REG => {
-                name = "sub32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::MUL32_IMM => {
-                name = "mul32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::MUL32_REG => {
-                name = "mul32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::DIV32_IMM => {
-                name = "div32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::DIV32_REG => {
-                name = "div32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::OR32_IMM => {
-                name = "or32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::OR32_REG => {
-                name = "or32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::AND32_IMM => {
-                name = "and32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::AND32_REG => {
-                name = "and32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::LSH32_IMM => {
-                name = "lsh32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::LSH32_REG => {
-                name = "lsh32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::RSH32_IMM => {
-                name = "rsh32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::RSH32_REG => {
-                name = "rsh32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::NEG32 => {
-                name = "neg32";
-                desc = format!("{name} r{:}", insn.dst);
-            }
-            ebpf::MOD32_IMM => {
-                name = "mod32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::MOD32_REG => {
-                name = "mod32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::XOR32_IMM => {
-                name = "xor32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::XOR32_REG => {
-                name = "xor32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::MOV32_IMM => {
-                name = "mov32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::MOV32_REG => {
-                name = "mov32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::ARSH32_IMM => {
-                name = "arsh32";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::ARSH32_REG => {
-                name = "arsh32";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::LE => {
-                name = "le";
-                desc = byteswap_str(name, &insn);
-            }
-            ebpf::BE => {
-                name = "be";
-                desc = byteswap_str(name, &insn);
-            }
-
-            // BPF_ALU64 class
-            ebpf::ADD64_IMM => {
-                name = "add64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::ADD64_REG => {
-                name = "add64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::SUB64_IMM => {
-                name = "sub64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::SUB64_REG => {
-                name = "sub64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::MUL64_IMM => {
-                name = "mul64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::MUL64_REG => {
-                name = "mul64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::DIV64_IMM => {
-                name = "div64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::DIV64_REG => {
-                name = "div64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::OR64_IMM => {
-                name = "or64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::OR64_REG => {
-                name = "or64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::AND64_IMM => {
-                name = "and64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::AND64_REG => {
-                name = "and64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::LSH64_IMM => {
-                name = "lsh64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::LSH64_REG => {
-                name = "lsh64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::RSH64_IMM => {
-                name = "rsh64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::RSH64_REG => {
-                name = "rsh64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::NEG64 => {
-                name = "neg64";
-                desc = format!("{name} r{:}", insn.dst);
-            }
-            ebpf::MOD64_IMM => {
-                name = "mod64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::MOD64_REG => {
-                name = "mod64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::XOR64_IMM => {
-                name = "xor64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::XOR64_REG => {
-                name = "xor64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::MOV64_IMM => {
-                name = "mov64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::MOV64_REG => {
-                name = "mov64";
-                desc = alu_reg_str(name, &insn);
-            }
-            ebpf::ARSH64_IMM => {
-                name = "arsh64";
-                desc = alu_imm_str(name, &insn);
-            }
-            ebpf::ARSH64_REG => {
-                name = "arsh64";
-                desc = alu_reg_str(name, &insn);
-            }
-
-            // BPF_JMP class
-            ebpf::JA => {
-                name = "ja";
-                desc = if insn.off >= 0 {
-                    format!("{name} +{:#x}", insn.off)
-                } else {
-                    format!("{name} -{:#x}", -insn.off)
-                }
-            }
-            ebpf::JEQ_IMM => {
-                name = "jeq";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JEQ_REG => {
-                name = "jeq";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JGT_IMM => {
-                name = "jgt";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JGT_REG => {
-                name = "jgt";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JGE_IMM => {
-                name = "jge";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JGE_REG => {
-                name = "jge";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JLT_IMM => {
-                name = "jlt";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JLT_REG => {
-                name = "jlt";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JLE_IMM => {
-                name = "jle";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JLE_REG => {
-                name = "jle";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSET_IMM => {
-                name = "jset";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSET_REG => {
-                name = "jset";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JNE_IMM => {
-                name = "jne";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JNE_REG => {
-                name = "jne";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSGT_IMM => {
-                name = "jsgt";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSGT_REG => {
-                name = "jsgt";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSGE_IMM => {
-                name = "jsge";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSGE_REG => {
-                name = "jsge";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSLT_IMM => {
-                name = "jslt";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSLT_REG => {
-                name = "jslt";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSLE_IMM => {
-                name = "jsle";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSLE_REG => {
-                name = "jsle";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::CALL => {
-                name = "call";
-                desc = format!("{name} {:#x}", insn.imm);
-            }
-            ebpf::TAIL_CALL => {
-                name = "tail_call";
-                desc = name.to_string();
-            }
-            ebpf::EXIT => {
-                name = "exit";
-                desc = name.to_string();
-            }
-
-            // BPF_JMP32 class
-            ebpf::JEQ_IMM32 => {
-                name = "jeq32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JEQ_REG32 => {
-                name = "jeq32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JGT_IMM32 => {
-                name = "jgt32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JGT_REG32 => {
-                name = "jgt32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JGE_IMM32 => {
-                name = "jge32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JGE_REG32 => {
-                name = "jge32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JLT_IMM32 => {
-                name = "jlt32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JLT_REG32 => {
-                name = "jlt32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JLE_IMM32 => {
-                name = "jle32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JLE_REG32 => {
-                name = "jle32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSET_IMM32 => {
-                name = "jset32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSET_REG32 => {
-                name = "jset32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JNE_IMM32 => {
-                name = "jne32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JNE_REG32 => {
-                name = "jne32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSGT_IMM32 => {
-                name = "jsgt32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSGT_REG32 => {
-                name = "jsgt32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSGE_IMM32 => {
-                name = "jsge32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSGE_REG32 => {
-                name = "jsge32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSLT_IMM32 => {
-                name = "jslt32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSLT_REG32 => {
-                name = "jslt32";
-                desc = jmp_reg_str(name, &insn);
-            }
-            ebpf::JSLE_IMM32 => {
-                name = "jsle32";
-                desc = jmp_imm_str(name, &insn);
-            }
-            ebpf::JSLE_REG32 => {
-                name = "jsle32";
-                desc = jmp_reg_str(name, &insn);
-            }
-
-            _ => {
-                panic!(
-                    "[Disassembler] Error: unknown eBPF opcode {:#2x} (insn #{:?})",
-                    insn.opc, insn_ptr
-                );
-            }
-        };
-
-        let hl_insn = HLInsn {
-            opc: insn.opc,
-            name: name.to_string(),
-            desc,
-            dst: insn.dst,
-            src: insn.src,
-            off: insn.off,
-            imm,
-        };
-
-        res.push(hl_insn);
-
-        insn_ptr += 1;
-    }
-    res
-}
-
-/// Disassemble an eBPF program into human-readable instructions and prints it to standard output.
-///
-/// The program is not checked for errors or inconsistencies.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::disassembler;
-/// let prog = &[
-///     0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
-///     0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
-///     0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-///     0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-/// ];
-/// disassembler::disassemble(prog);
-/// # // "\nadd64 r1, 0x605\nmov64 r2, 0x32\nmov64 r1, r0\nbe16 r0\nneg64 r2\nexit"
-/// ```
-///
-/// This will produce the following output:
-///
-/// ```test
-/// add64 r1, 0x605
-/// mov64 r2, 0x32
-/// mov64 r1, r0
-/// be16 r0
-/// neg64 r2
-/// exit
-/// ```
-pub fn disassemble(prog: &[u8]) {
-    #[cfg(feature = "std")]
-    {
-        for insn in to_insn_vec(prog) {
-            println!("{}", insn.desc);
-        }
-    }
-    #[cfg(not(feature = "std"))]
-    {
-        for insn in to_insn_vec(prog) {
-            log::info!("{}", insn.desc);
-        }
-    }
-}

+ 0 - 635
kernel/crates/rbpf/src/ebpf.rs

@@ -1,635 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-//! This module contains all the definitions related to eBPF, and some functions permitting to
-//! manipulate eBPF instructions.
-//!
-//! The number of bytes in an instruction, the maximum number of instructions in a program, and
-//! also all operation codes are defined here as constants.
-//!
-//! The structure for an instruction used by this crate, as well as the function to extract it from
-//! a program, is also defined in the module.
-//!
-//! To learn more about these instructions, see the Linux kernel documentation:
-//! <https://www.kernel.org/doc/Documentation/networking/filter.txt>, or for a shorter version of
-//! the list of the operation codes: <https://github.com/iovisor/bpf-docs/blob/master/eBPF.md>
-
-use alloc::{vec, vec::Vec};
-
-use byteorder::{ByteOrder, LittleEndian};
-
-/// The maximum call depth is 8
-pub const RBPF_MAX_CALL_DEPTH: usize = 8;
-
-/// Maximum number of instructions in an eBPF program.
-pub const PROG_MAX_INSNS: usize = 1000000;
-/// Size of an eBPF instructions, in bytes.
-pub const INSN_SIZE: usize = 8;
-/// Maximum size of an eBPF program, in bytes.
-pub const PROG_MAX_SIZE: usize = PROG_MAX_INSNS * INSN_SIZE;
-/// Stack for the eBPF stack, in bytes.
-pub const STACK_SIZE: usize = 512;
-
-// eBPF op codes.
-// See also https://www.kernel.org/doc/Documentation/networking/filter.txt
-
-// Three least significant bits are operation class:
-/// BPF operation class: load from immediate.
-pub const BPF_LD: u8 = 0x00;
-/// BPF operation class: load from register.
-pub const BPF_LDX: u8 = 0x01;
-/// BPF operation class: store immediate.
-pub const BPF_ST: u8 = 0x02;
-/// BPF operation class: store value from register.
-pub const BPF_STX: u8 = 0x03;
-/// BPF operation class: 32 bits arithmetic operation.
-pub const BPF_ALU: u8 = 0x04;
-/// BPF operation class: jump (64-bit wide operands for comparisons).
-pub const BPF_JMP: u8 = 0x05;
-/// BPF operation class: jump (32-bit wide operands for comparisons).
-pub const BPF_JMP32: u8 = 0x06;
-// [ class 6 unused, reserved for future use ]
-/// BPF operation class: 64 bits arithmetic operation.
-pub const BPF_ALU64: u8 = 0x07;
-
-// For load and store instructions:
-// +------------+--------+------------+
-// |   3 bits   | 2 bits |   3 bits   |
-// |    mode    |  size  | insn class |
-// +------------+--------+------------+
-// (MSB)                          (LSB)
-
-// Size modifiers:
-/// BPF size modifier: word (4 bytes).
-pub const BPF_W: u8 = 0x00;
-/// BPF size modifier: half-word (2 bytes).
-pub const BPF_H: u8 = 0x08;
-/// BPF size modifier: byte (1 byte).
-pub const BPF_B: u8 = 0x10;
-/// BPF size modifier: double word (8 bytes).
-pub const BPF_DW: u8 = 0x18;
-
-// Mode modifiers:
-/// BPF mode modifier: immediate value.
-pub const BPF_IMM: u8 = 0x00;
-/// BPF mode modifier: absolute load.
-pub const BPF_ABS: u8 = 0x20;
-/// BPF mode modifier: indirect load.
-pub const BPF_IND: u8 = 0x40;
-/// BPF mode modifier: load from / store to memory.
-pub const BPF_MEM: u8 = 0x60;
-// [ 0x80 reserved ]
-// [ 0xa0 reserved ]
-/// BPF mode modifier: exclusive add.
-pub const BPF_XADD: u8 = 0xc0;
-
-// For arithmetic (BPF_ALU/BPF_ALU64) and jump (BPF_JMP) instructions:
-// +----------------+--------+--------+
-// |     4 bits     |1 b.|   3 bits   |
-// | operation code | src| insn class |
-// +----------------+----+------------+
-// (MSB)                          (LSB)
-
-// Source modifiers:
-/// BPF source operand modifier: 32-bit immediate value.
-pub const BPF_K: u8 = 0x00;
-/// BPF source operand modifier: `src` register.
-pub const BPF_X: u8 = 0x08;
-
-// Operation codes -- BPF_ALU or BPF_ALU64 classes:
-/// BPF ALU/ALU64 operation code: addition.
-pub const BPF_ADD: u8 = 0x00;
-/// BPF ALU/ALU64 operation code: subtraction.
-pub const BPF_SUB: u8 = 0x10;
-/// BPF ALU/ALU64 operation code: multiplication.
-pub const BPF_MUL: u8 = 0x20;
-/// BPF ALU/ALU64 operation code: division.
-pub const BPF_DIV: u8 = 0x30;
-/// BPF ALU/ALU64 operation code: or.
-pub const BPF_OR: u8 = 0x40;
-/// BPF ALU/ALU64 operation code: and.
-pub const BPF_AND: u8 = 0x50;
-/// BPF ALU/ALU64 operation code: left shift.
-pub const BPF_LSH: u8 = 0x60;
-/// BPF ALU/ALU64 operation code: right shift.
-pub const BPF_RSH: u8 = 0x70;
-/// BPF ALU/ALU64 operation code: negation.
-pub const BPF_NEG: u8 = 0x80;
-/// BPF ALU/ALU64 operation code: modulus.
-pub const BPF_MOD: u8 = 0x90;
-/// BPF ALU/ALU64 operation code: exclusive or.
-pub const BPF_XOR: u8 = 0xa0;
-/// BPF ALU/ALU64 operation code: move.
-pub const BPF_MOV: u8 = 0xb0;
-/// BPF ALU/ALU64 operation code: sign extending right shift.
-pub const BPF_ARSH: u8 = 0xc0;
-/// BPF ALU/ALU64 operation code: endianness conversion.
-pub const BPF_END: u8 = 0xd0;
-
-// Operation codes -- BPF_JMP or BPF_JMP32 classes:
-/// BPF JMP operation code: jump.
-pub const BPF_JA: u8 = 0x00;
-/// BPF JMP operation code: jump if equal.
-pub const BPF_JEQ: u8 = 0x10;
-/// BPF JMP operation code: jump if greater than.
-pub const BPF_JGT: u8 = 0x20;
-/// BPF JMP operation code: jump if greater or equal.
-pub const BPF_JGE: u8 = 0x30;
-/// BPF JMP operation code: jump if `src` & `reg`.
-pub const BPF_JSET: u8 = 0x40;
-/// BPF JMP operation code: jump if not equal.
-pub const BPF_JNE: u8 = 0x50;
-/// BPF JMP operation code: jump if greater than (signed).
-pub const BPF_JSGT: u8 = 0x60;
-/// BPF JMP operation code: jump if greater or equal (signed).
-pub const BPF_JSGE: u8 = 0x70;
-/// BPF JMP operation code: helper function call.
-pub const BPF_CALL: u8 = 0x80;
-/// BPF JMP operation code: return from program.
-pub const BPF_EXIT: u8 = 0x90;
-/// BPF JMP operation code: jump if lower than.
-pub const BPF_JLT: u8 = 0xa0;
-/// BPF JMP operation code: jump if lower or equal.
-pub const BPF_JLE: u8 = 0xb0;
-/// BPF JMP operation code: jump if lower than (signed).
-pub const BPF_JSLT: u8 = 0xc0;
-/// BPF JMP operation code: jump if lower or equal (signed).
-pub const BPF_JSLE: u8 = 0xd0;
-
-// Op codes
-// (Following operation names are not “official”, but may be proper to rbpf; Linux kernel only
-// combines above flags and does not attribute a name per operation.)
-
-/// BPF opcode: `ldabsb src, dst, imm`.
-pub const LD_ABS_B: u8 = BPF_LD | BPF_ABS | BPF_B;
-/// BPF opcode: `ldabsh src, dst, imm`.
-pub const LD_ABS_H: u8 = BPF_LD | BPF_ABS | BPF_H;
-/// BPF opcode: `ldabsw src, dst, imm`.
-pub const LD_ABS_W: u8 = BPF_LD | BPF_ABS | BPF_W;
-/// BPF opcode: `ldabsdw src, dst, imm`.
-pub const LD_ABS_DW: u8 = BPF_LD | BPF_ABS | BPF_DW;
-/// BPF opcode: `ldindb src, dst, imm`.
-pub const LD_IND_B: u8 = BPF_LD | BPF_IND | BPF_B;
-/// BPF opcode: `ldindh src, dst, imm`.
-pub const LD_IND_H: u8 = BPF_LD | BPF_IND | BPF_H;
-/// BPF opcode: `ldindw src, dst, imm`.
-pub const LD_IND_W: u8 = BPF_LD | BPF_IND | BPF_W;
-/// BPF opcode: `ldinddw src, dst, imm`.
-pub const LD_IND_DW: u8 = BPF_LD | BPF_IND | BPF_DW;
-
-#[allow(unknown_lints)]
-#[allow(clippy::eq_op)]
-/// BPF opcode: `lddw dst, imm` /// `dst = imm`.
-pub const LD_DW_IMM: u8 = BPF_LD | BPF_IMM | BPF_DW;
-/// BPF opcode: `ldxb dst, [src + off]` /// `dst = (src + off) as u8`.
-pub const LD_B_REG: u8 = BPF_LDX | BPF_MEM | BPF_B;
-/// BPF opcode: `ldxh dst, [src + off]` /// `dst = (src + off) as u16`.
-pub const LD_H_REG: u8 = BPF_LDX | BPF_MEM | BPF_H;
-/// BPF opcode: `ldxw dst, [src + off]` /// `dst = (src + off) as u32`.
-pub const LD_W_REG: u8 = BPF_LDX | BPF_MEM | BPF_W;
-/// BPF opcode: `ldxdw dst, [src + off]` /// `dst = (src + off) as u64`.
-pub const LD_DW_REG: u8 = BPF_LDX | BPF_MEM | BPF_DW;
-/// BPF opcode: `stb [dst + off], imm` /// `(dst + offset) as u8 = imm`.
-pub const ST_B_IMM: u8 = BPF_ST | BPF_MEM | BPF_B;
-/// BPF opcode: `sth [dst + off], imm` /// `(dst + offset) as u16 = imm`.
-pub const ST_H_IMM: u8 = BPF_ST | BPF_MEM | BPF_H;
-/// BPF opcode: `stw [dst + off], imm` /// `(dst + offset) as u32 = imm`.
-pub const ST_W_IMM: u8 = BPF_ST | BPF_MEM | BPF_W;
-/// BPF opcode: `stdw [dst + off], imm` /// `(dst + offset) as u64 = imm`.
-pub const ST_DW_IMM: u8 = BPF_ST | BPF_MEM | BPF_DW;
-/// BPF opcode: `stxb [dst + off], src` /// `(dst + offset) as u8 = src`.
-pub const ST_B_REG: u8 = BPF_STX | BPF_MEM | BPF_B;
-/// BPF opcode: `stxh [dst + off], src` /// `(dst + offset) as u16 = src`.
-pub const ST_H_REG: u8 = BPF_STX | BPF_MEM | BPF_H;
-/// BPF opcode: `stxw [dst + off], src` /// `(dst + offset) as u32 = src`.
-pub const ST_W_REG: u8 = BPF_STX | BPF_MEM | BPF_W;
-/// BPF opcode: `stxdw [dst + off], src` /// `(dst + offset) as u64 = src`.
-pub const ST_DW_REG: u8 = BPF_STX | BPF_MEM | BPF_DW;
-
-/// BPF opcode: `stxxaddw [dst + off], src`.
-pub const ST_W_XADD: u8 = BPF_STX | BPF_XADD | BPF_W;
-/// BPF opcode: `stxxadddw [dst + off], src`.
-pub const ST_DW_XADD: u8 = BPF_STX | BPF_XADD | BPF_DW;
-
-/// BPF opcode: `add32 dst, imm` /// `dst += imm`.
-pub const ADD32_IMM: u8 = BPF_ALU | BPF_K | BPF_ADD;
-/// BPF opcode: `add32 dst, src` /// `dst += src`.
-pub const ADD32_REG: u8 = BPF_ALU | BPF_X | BPF_ADD;
-/// BPF opcode: `sub32 dst, imm` /// `dst -= imm`.
-pub const SUB32_IMM: u8 = BPF_ALU | BPF_K | BPF_SUB;
-/// BPF opcode: `sub32 dst, src` /// `dst -= src`.
-pub const SUB32_REG: u8 = BPF_ALU | BPF_X | BPF_SUB;
-/// BPF opcode: `mul32 dst, imm` /// `dst *= imm`.
-pub const MUL32_IMM: u8 = BPF_ALU | BPF_K | BPF_MUL;
-/// BPF opcode: `mul32 dst, src` /// `dst *= src`.
-pub const MUL32_REG: u8 = BPF_ALU | BPF_X | BPF_MUL;
-/// BPF opcode: `div32 dst, imm` /// `dst /= imm`.
-pub const DIV32_IMM: u8 = BPF_ALU | BPF_K | BPF_DIV;
-/// BPF opcode: `div32 dst, src` /// `dst /= src`.
-pub const DIV32_REG: u8 = BPF_ALU | BPF_X | BPF_DIV;
-/// BPF opcode: `or32 dst, imm` /// `dst |= imm`.
-pub const OR32_IMM: u8 = BPF_ALU | BPF_K | BPF_OR;
-/// BPF opcode: `or32 dst, src` /// `dst |= src`.
-pub const OR32_REG: u8 = BPF_ALU | BPF_X | BPF_OR;
-/// BPF opcode: `and32 dst, imm` /// `dst &= imm`.
-pub const AND32_IMM: u8 = BPF_ALU | BPF_K | BPF_AND;
-/// BPF opcode: `and32 dst, src` /// `dst &= src`.
-pub const AND32_REG: u8 = BPF_ALU | BPF_X | BPF_AND;
-/// BPF opcode: `lsh32 dst, imm` /// `dst <<= imm`.
-pub const LSH32_IMM: u8 = BPF_ALU | BPF_K | BPF_LSH;
-/// BPF opcode: `lsh32 dst, src` /// `dst <<= src`.
-pub const LSH32_REG: u8 = BPF_ALU | BPF_X | BPF_LSH;
-/// BPF opcode: `rsh32 dst, imm` /// `dst >>= imm`.
-pub const RSH32_IMM: u8 = BPF_ALU | BPF_K | BPF_RSH;
-/// BPF opcode: `rsh32 dst, src` /// `dst >>= src`.
-pub const RSH32_REG: u8 = BPF_ALU | BPF_X | BPF_RSH;
-/// BPF opcode: `neg32 dst` /// `dst = -dst`.
-pub const NEG32: u8 = BPF_ALU | BPF_NEG;
-/// BPF opcode: `mod32 dst, imm` /// `dst %= imm`.
-pub const MOD32_IMM: u8 = BPF_ALU | BPF_K | BPF_MOD;
-/// BPF opcode: `mod32 dst, src` /// `dst %= src`.
-pub const MOD32_REG: u8 = BPF_ALU | BPF_X | BPF_MOD;
-/// BPF opcode: `xor32 dst, imm` /// `dst ^= imm`.
-pub const XOR32_IMM: u8 = BPF_ALU | BPF_K | BPF_XOR;
-/// BPF opcode: `xor32 dst, src` /// `dst ^= src`.
-pub const XOR32_REG: u8 = BPF_ALU | BPF_X | BPF_XOR;
-/// BPF opcode: `mov32 dst, imm` /// `dst = imm`.
-pub const MOV32_IMM: u8 = BPF_ALU | BPF_K | BPF_MOV;
-/// BPF opcode: `mov32 dst, src` /// `dst = src`.
-pub const MOV32_REG: u8 = BPF_ALU | BPF_X | BPF_MOV;
-/// BPF opcode: `arsh32 dst, imm` /// `dst >>= imm (arithmetic)`.
-///
-/// <https://en.wikipedia.org/wiki/Arithmetic_shift>
-pub const ARSH32_IMM: u8 = BPF_ALU | BPF_K | BPF_ARSH;
-/// BPF opcode: `arsh32 dst, src` /// `dst >>= src (arithmetic)`.
-///
-/// <https://en.wikipedia.org/wiki/Arithmetic_shift>
-pub const ARSH32_REG: u8 = BPF_ALU | BPF_X | BPF_ARSH;
-
-/// BPF opcode: `le dst` /// `dst = htole<imm>(dst), with imm in {16, 32, 64}`.
-pub const LE: u8 = BPF_ALU | BPF_K | BPF_END;
-/// BPF opcode: `be dst` /// `dst = htobe<imm>(dst), with imm in {16, 32, 64}`.
-pub const BE: u8 = BPF_ALU | BPF_X | BPF_END;
-
-/// BPF opcode: `add64 dst, imm` /// `dst += imm`.
-pub const ADD64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_ADD;
-/// BPF opcode: `add64 dst, src` /// `dst += src`.
-pub const ADD64_REG: u8 = BPF_ALU64 | BPF_X | BPF_ADD;
-/// BPF opcode: `sub64 dst, imm` /// `dst -= imm`.
-pub const SUB64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_SUB;
-/// BPF opcode: `sub64 dst, src` /// `dst -= src`.
-pub const SUB64_REG: u8 = BPF_ALU64 | BPF_X | BPF_SUB;
-/// BPF opcode: `div64 dst, imm` /// `dst /= imm`.
-pub const MUL64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_MUL;
-/// BPF opcode: `div64 dst, src` /// `dst /= src`.
-pub const MUL64_REG: u8 = BPF_ALU64 | BPF_X | BPF_MUL;
-/// BPF opcode: `div64 dst, imm` /// `dst /= imm`.
-pub const DIV64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_DIV;
-/// BPF opcode: `div64 dst, src` /// `dst /= src`.
-pub const DIV64_REG: u8 = BPF_ALU64 | BPF_X | BPF_DIV;
-/// BPF opcode: `or64 dst, imm` /// `dst |= imm`.
-pub const OR64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_OR;
-/// BPF opcode: `or64 dst, src` /// `dst |= src`.
-pub const OR64_REG: u8 = BPF_ALU64 | BPF_X | BPF_OR;
-/// BPF opcode: `and64 dst, imm` /// `dst &= imm`.
-pub const AND64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_AND;
-/// BPF opcode: `and64 dst, src` /// `dst &= src`.
-pub const AND64_REG: u8 = BPF_ALU64 | BPF_X | BPF_AND;
-/// BPF opcode: `lsh64 dst, imm` /// `dst <<= imm`.
-pub const LSH64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_LSH;
-/// BPF opcode: `lsh64 dst, src` /// `dst <<= src`.
-pub const LSH64_REG: u8 = BPF_ALU64 | BPF_X | BPF_LSH;
-/// BPF opcode: `rsh64 dst, imm` /// `dst >>= imm`.
-pub const RSH64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_RSH;
-/// BPF opcode: `rsh64 dst, src` /// `dst >>= src`.
-pub const RSH64_REG: u8 = BPF_ALU64 | BPF_X | BPF_RSH;
-/// BPF opcode: `neg64 dst, imm` /// `dst = -dst`.
-pub const NEG64: u8 = BPF_ALU64 | BPF_NEG;
-/// BPF opcode: `mod64 dst, imm` /// `dst %= imm`.
-pub const MOD64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_MOD;
-/// BPF opcode: `mod64 dst, src` /// `dst %= src`.
-pub const MOD64_REG: u8 = BPF_ALU64 | BPF_X | BPF_MOD;
-/// BPF opcode: `xor64 dst, imm` /// `dst ^= imm`.
-pub const XOR64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_XOR;
-/// BPF opcode: `xor64 dst, src` /// `dst ^= src`.
-pub const XOR64_REG: u8 = BPF_ALU64 | BPF_X | BPF_XOR;
-/// BPF opcode: `mov64 dst, imm` /// `dst = imm`.
-pub const MOV64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_MOV;
-/// BPF opcode: `mov64 dst, src` /// `dst = src`.
-pub const MOV64_REG: u8 = BPF_ALU64 | BPF_X | BPF_MOV;
-/// BPF opcode: `arsh64 dst, imm` /// `dst >>= imm (arithmetic)`.
-///
-/// <https://en.wikipedia.org/wiki/Arithmetic_shift>
-pub const ARSH64_IMM: u8 = BPF_ALU64 | BPF_K | BPF_ARSH;
-/// BPF opcode: `arsh64 dst, src` /// `dst >>= src (arithmetic)`.
-///
-/// <https://en.wikipedia.org/wiki/Arithmetic_shift>
-pub const ARSH64_REG: u8 = BPF_ALU64 | BPF_X | BPF_ARSH;
-
-/// BPF opcode: `ja +off` /// `PC += off`.
-pub const JA: u8 = BPF_JMP | BPF_JA;
-/// BPF opcode: `jeq dst, imm, +off` /// `PC += off if dst == imm`.
-pub const JEQ_IMM: u8 = BPF_JMP | BPF_K | BPF_JEQ;
-/// BPF opcode: `jeq dst, src, +off` /// `PC += off if dst == src`.
-pub const JEQ_REG: u8 = BPF_JMP | BPF_X | BPF_JEQ;
-/// BPF opcode: `jgt dst, imm, +off` /// `PC += off if dst > imm`.
-pub const JGT_IMM: u8 = BPF_JMP | BPF_K | BPF_JGT;
-/// BPF opcode: `jgt dst, src, +off` /// `PC += off if dst > src`.
-pub const JGT_REG: u8 = BPF_JMP | BPF_X | BPF_JGT;
-/// BPF opcode: `jge dst, imm, +off` /// `PC += off if dst >= imm`.
-pub const JGE_IMM: u8 = BPF_JMP | BPF_K | BPF_JGE;
-/// BPF opcode: `jge dst, src, +off` /// `PC += off if dst >= src`.
-pub const JGE_REG: u8 = BPF_JMP | BPF_X | BPF_JGE;
-/// BPF opcode: `jlt dst, imm, +off` /// `PC += off if dst < imm`.
-pub const JLT_IMM: u8 = BPF_JMP | BPF_K | BPF_JLT;
-/// BPF opcode: `jlt dst, src, +off` /// `PC += off if dst < src`.
-pub const JLT_REG: u8 = BPF_JMP | BPF_X | BPF_JLT;
-/// BPF opcode: `jle dst, imm, +off` /// `PC += off if dst <= imm`.
-pub const JLE_IMM: u8 = BPF_JMP | BPF_K | BPF_JLE;
-/// BPF opcode: `jle dst, src, +off` /// `PC += off if dst <= src`.
-pub const JLE_REG: u8 = BPF_JMP | BPF_X | BPF_JLE;
-/// BPF opcode: `jset dst, imm, +off` /// `PC += off if dst & imm`.
-pub const JSET_IMM: u8 = BPF_JMP | BPF_K | BPF_JSET;
-/// BPF opcode: `jset dst, src, +off` /// `PC += off if dst & src`.
-pub const JSET_REG: u8 = BPF_JMP | BPF_X | BPF_JSET;
-/// BPF opcode: `jne dst, imm, +off` /// `PC += off if dst != imm`.
-pub const JNE_IMM: u8 = BPF_JMP | BPF_K | BPF_JNE;
-/// BPF opcode: `jne dst, src, +off` /// `PC += off if dst != src`.
-pub const JNE_REG: u8 = BPF_JMP | BPF_X | BPF_JNE;
-/// BPF opcode: `jsgt dst, imm, +off` /// `PC += off if dst > imm (signed)`.
-pub const JSGT_IMM: u8 = BPF_JMP | BPF_K | BPF_JSGT;
-/// BPF opcode: `jsgt dst, src, +off` /// `PC += off if dst > src (signed)`.
-pub const JSGT_REG: u8 = BPF_JMP | BPF_X | BPF_JSGT;
-/// BPF opcode: `jsge dst, imm, +off` /// `PC += off if dst >= imm (signed)`.
-pub const JSGE_IMM: u8 = BPF_JMP | BPF_K | BPF_JSGE;
-/// BPF opcode: `jsge dst, src, +off` /// `PC += off if dst >= src (signed)`.
-pub const JSGE_REG: u8 = BPF_JMP | BPF_X | BPF_JSGE;
-/// BPF opcode: `jslt dst, imm, +off` /// `PC += off if dst < imm (signed)`.
-pub const JSLT_IMM: u8 = BPF_JMP | BPF_K | BPF_JSLT;
-/// BPF opcode: `jslt dst, src, +off` /// `PC += off if dst < src (signed)`.
-pub const JSLT_REG: u8 = BPF_JMP | BPF_X | BPF_JSLT;
-/// BPF opcode: `jsle dst, imm, +off` /// `PC += off if dst <= imm (signed)`.
-pub const JSLE_IMM: u8 = BPF_JMP | BPF_K | BPF_JSLE;
-/// BPF opcode: `jsle dst, src, +off` /// `PC += off if dst <= src (signed)`.
-pub const JSLE_REG: u8 = BPF_JMP | BPF_X | BPF_JSLE;
-
-/// BPF opcode: `jeq dst, imm, +off` /// `PC += off if (dst as u32) == imm`.
-pub const JEQ_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JEQ;
-/// BPF opcode: `jeq dst, src, +off` /// `PC += off if (dst as u32) == (src as u32)`.
-pub const JEQ_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JEQ;
-/// BPF opcode: `jgt dst, imm, +off` /// `PC += off if (dst as u32) > imm`.
-pub const JGT_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JGT;
-/// BPF opcode: `jgt dst, src, +off` /// `PC += off if (dst as u32) > (src as u32)`.
-pub const JGT_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JGT;
-/// BPF opcode: `jge dst, imm, +off` /// `PC += off if (dst as u32) >= imm`.
-pub const JGE_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JGE;
-/// BPF opcode: `jge dst, src, +off` /// `PC += off if (dst as u32) >= (src as u32)`.
-pub const JGE_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JGE;
-/// BPF opcode: `jlt dst, imm, +off` /// `PC += off if (dst as u32) < imm`.
-pub const JLT_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JLT;
-/// BPF opcode: `jlt dst, src, +off` /// `PC += off if (dst as u32) < (src as u32)`.
-pub const JLT_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JLT;
-/// BPF opcode: `jle dst, imm, +off` /// `PC += off if (dst as u32) <= imm`.
-pub const JLE_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JLE;
-/// BPF opcode: `jle dst, src, +off` /// `PC += off if (dst as u32) <= (src as u32)`.
-pub const JLE_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JLE;
-/// BPF opcode: `jset dst, imm, +off` /// `PC += off if (dst as u32) & imm`.
-pub const JSET_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JSET;
-/// BPF opcode: `jset dst, src, +off` /// `PC += off if (dst as u32) & (src as u32)`.
-pub const JSET_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JSET;
-/// BPF opcode: `jne dst, imm, +off` /// `PC += off if (dst as u32) != imm`.
-pub const JNE_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JNE;
-/// BPF opcode: `jne dst, src, +off` /// `PC += off if (dst as u32) != (src as u32)`.
-pub const JNE_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JNE;
-/// BPF opcode: `jsgt dst, imm, +off` /// `PC += off if (dst as i32) > imm (signed)`.
-pub const JSGT_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JSGT;
-/// BPF opcode: `jsgt dst, src, +off` /// `PC += off if (dst as i32) > (src as i32) (signed)`.
-pub const JSGT_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JSGT;
-/// BPF opcode: `jsge dst, imm, +off` /// `PC += off if (dst as i32) >= imm (signed)`.
-pub const JSGE_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JSGE;
-/// BPF opcode: `jsge dst, src, +off` /// `PC += off if (dst as i32) >= (src as i32) (signed)`.
-pub const JSGE_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JSGE;
-/// BPF opcode: `jslt dst, imm, +off` /// `PC += off if (dst as i32) < imm (signed)`.
-pub const JSLT_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JSLT;
-/// BPF opcode: `jslt dst, src, +off` /// `PC += off if (dst as i32) < (src as i32) (signed)`.
-pub const JSLT_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JSLT;
-/// BPF opcode: `jsle dst, imm, +off` /// `PC += off if (dst as i32) <= imm (signed)`.
-pub const JSLE_IMM32: u8 = BPF_JMP32 | BPF_K | BPF_JSLE;
-/// BPF opcode: `jsle dst, src, +off` /// `PC += off if (dst as i32) <= (src as i32) (signed)`.
-pub const JSLE_REG32: u8 = BPF_JMP32 | BPF_X | BPF_JSLE;
-
-/// BPF opcode: `call imm` /// helper function call to helper with key `imm`.
-pub const CALL: u8 = BPF_JMP | BPF_CALL;
-/// BPF opcode: tail call.
-pub const TAIL_CALL: u8 = BPF_JMP | BPF_X | BPF_CALL;
-/// BPF opcode: `exit` /// `return r0`.
-pub const EXIT: u8 = BPF_JMP | BPF_EXIT;
-
-// Used in JIT
-/// Mask to extract the operation class from an operation code.
-pub const BPF_CLS_MASK: u8 = 0x07;
-/// Mask to extract the arithmetic operation code from an instruction operation code.
-pub const BPF_ALU_OP_MASK: u8 = 0xf0;
-
-/// Prototype of an eBPF helper function.
-pub type Helper = fn(u64, u64, u64, u64, u64) -> u64;
-
-/// An eBPF instruction.
-///
-/// See <https://www.kernel.org/doc/Documentation/networking/filter.txt> for the Linux kernel
-/// documentation about eBPF, or <https://github.com/iovisor/bpf-docs/blob/master/eBPF.md> for a
-/// more concise version.
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub struct Insn {
-    /// Operation code.
-    pub opc: u8,
-    /// Destination register operand.
-    pub dst: u8,
-    /// Source register operand.
-    pub src: u8,
-    /// Offset operand.
-    pub off: i16,
-    /// Immediate value operand.
-    pub imm: i32,
-}
-
-impl Insn {
-    /// Turn an `Insn` back into an array of bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::ebpf;
-    ///
-    /// let prog: &[u8] = &[
-    ///     0xb7, 0x12, 0x56, 0x34, 0xde, 0xbc, 0x9a, 0x78,
-    ///     ];
-    /// let insn = ebpf::Insn {
-    ///     opc: 0xb7,
-    ///     dst: 2,
-    ///     src: 1,
-    ///     off: 0x3456,
-    ///     imm: 0x789abcde
-    /// };
-    /// assert_eq!(insn.to_array(), prog);
-    /// ```
-    pub fn to_array(&self) -> [u8; INSN_SIZE] {
-        [
-            self.opc,
-            self.src.wrapping_shl(4) | self.dst,
-            (self.off & 0xff) as u8,
-            self.off.wrapping_shr(8) as u8,
-            (self.imm & 0xff) as u8,
-            (self.imm & 0xff_00).wrapping_shr(8) as u8,
-            (self.imm as u32 & 0xff_00_00).wrapping_shr(16) as u8,
-            (self.imm as u32 & 0xff_00_00_00).wrapping_shr(24) as u8,
-        ]
-    }
-
-    /// Turn an `Insn` into an vector of bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::ebpf;
-    ///
-    /// let prog: Vec<u8> = vec![
-    ///     0xb7, 0x12, 0x56, 0x34, 0xde, 0xbc, 0x9a, 0x78,
-    ///     ];
-    /// let insn = ebpf::Insn {
-    ///     opc: 0xb7,
-    ///     dst: 2,
-    ///     src: 1,
-    ///     off: 0x3456,
-    ///     imm: 0x789abcde
-    /// };
-    /// assert_eq!(insn.to_vec(), prog);
-    /// ```
-    pub fn to_vec(&self) -> Vec<u8> {
-        vec![
-            self.opc,
-            self.src.wrapping_shl(4) | self.dst,
-            (self.off & 0xff) as u8,
-            self.off.wrapping_shr(8) as u8,
-            (self.imm & 0xff) as u8,
-            (self.imm & 0xff_00).wrapping_shr(8) as u8,
-            (self.imm as u32 & 0xff_00_00).wrapping_shr(16) as u8,
-            (self.imm as u32 & 0xff_00_00_00).wrapping_shr(24) as u8,
-        ]
-    }
-}
-
-/// Get the instruction at `idx` of an eBPF program. `idx` is the index (number) of the
-/// instruction (not a byte offset). The first instruction has index 0.
-///
-/// # Panics
-///
-/// Panics if it is not possible to get the instruction (if idx is too high, or last instruction is
-/// incomplete).
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::ebpf;
-///
-/// let prog = &[
-///     0xb7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-///     ];
-/// let insn = ebpf::get_insn(prog, 1);
-/// assert_eq!(insn.opc, 0x95);
-/// ```
-///
-/// The example below will panic, since the last instruction is not complete and cannot be loaded.
-///
-/// ```rust,should_panic
-/// use rbpf::ebpf;
-///
-/// let prog = &[
-///     0xb7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00              // two bytes missing
-///     ];
-/// let insn = ebpf::get_insn(prog, 1);
-/// ```
-pub fn get_insn(prog: &[u8], idx: usize) -> Insn {
-    // This guard should not be needed in most cases, since the verifier already checks the program
-    // size, and indexes should be fine in the interpreter/JIT. But this function is publicly
-    // available and user can call it with any `idx`, so we have to check anyway.
-    if (idx + 1) * INSN_SIZE > prog.len() {
-        panic!(
-            "Error: cannot reach instruction at index {:?} in program containing {:?} bytes",
-            idx,
-            prog.len()
-        );
-    }
-    Insn {
-        opc: prog[INSN_SIZE * idx],
-        dst: prog[INSN_SIZE * idx + 1] & 0x0f,
-        src: (prog[INSN_SIZE * idx + 1] & 0xf0) >> 4,
-        off: LittleEndian::read_i16(&prog[(INSN_SIZE * idx + 2)..]),
-        imm: LittleEndian::read_i32(&prog[(INSN_SIZE * idx + 4)..]),
-    }
-}
-
-/// Return a vector of `struct Insn` built from a program.
-///
-/// This is provided as a convenience for users wishing to manipulate a vector of instructions, for
-/// example for dumping the program instruction after instruction with a custom format.
-///
-/// Note that the two parts of `LD_DW_IMM` instructions (spanning on 64 bits) are considered as two
-/// distinct instructions.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::ebpf;
-///
-/// let prog = &[
-///     0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55,
-///     0x00, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-/// ];
-///
-/// let v = ebpf::to_insn_vec(prog);
-/// assert_eq!(v, vec![
-///     ebpf::Insn {
-///         opc: 0x18,
-///         dst: 0,
-///         src: 0,
-///         off: 0,
-///         imm: 0x55667788
-///     },
-///     ebpf::Insn {
-///         opc: 0,
-///         dst: 0,
-///         src: 0,
-///         off: 0,
-///         imm: 0x11223344
-///     },
-///     ebpf::Insn {
-///         opc: 0x95,
-///         dst: 0,
-///         src: 0,
-///         off: 0,
-///         imm: 0
-///     },
-/// ]);
-/// ```
-pub fn to_insn_vec(prog: &[u8]) -> Vec<Insn> {
-    if prog.len() % INSN_SIZE != 0 {
-        panic!(
-            "Error: eBPF program length must be a multiple of {:?} octets",
-            INSN_SIZE
-        );
-    }
-
-    let mut res = vec![];
-    let mut insn_ptr: usize = 0;
-
-    while insn_ptr * INSN_SIZE < prog.len() {
-        let insn = get_insn(prog, insn_ptr);
-        res.push(insn);
-        insn_ptr += 1;
-    }
-    res
-}

+ 0 - 488
kernel/crates/rbpf/src/helpers.rs

@@ -1,488 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2015 Big Switch Networks, Inc
-//      (Algorithms for uBPF helpers, originally in C)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-//      (Translation to Rust, other helpers)
-
-//! This module implements some built-in helpers that can be called from within an eBPF program.
-//!
-//! These helpers may originate from several places:
-//!
-//! * Some of them mimic the helpers available in the Linux kernel.
-//! * Some of them were proposed as example helpers in uBPF and they were adapted here.
-//! * Other helpers may be specific to rbpf.
-//!
-//! The prototype for helpers is always the same: five `u64` as arguments, and a `u64` as a return
-//! value. Hence some helpers have unused arguments, or return a 0 value in all cases, in order to
-//! respect this convention.
-
-// Helpers associated to kernel helpers
-// See also linux/include/uapi/linux/bpf.h in Linux kernel sources.
-
-// bpf_ktime_getns()
-
-/// Index of helper `bpf_ktime_getns()`, equivalent to `bpf_time_getns()`, in Linux kernel, see
-/// <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/bpf.h>.
-pub const BPF_KTIME_GETNS_IDX: u32 = 5;
-
-/// Get monotonic time (since boot time) in nanoseconds. All arguments are unused.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::helpers;
-///
-/// let t = helpers::bpf_time_getns(0, 0, 0, 0, 0);
-/// let d =  t / 10u64.pow(9)  / 60   / 60  / 24;
-/// let h = (t / 10u64.pow(9)  / 60   / 60) % 24;
-/// let m = (t / 10u64.pow(9)  / 60 ) % 60;
-/// let s = (t / 10u64.pow(9)) % 60;
-/// let ns = t % 10u64.pow(9);
-/// println!("Uptime: {:#x} == {} days {}:{}:{}, {} ns", t, d, h, m, s, ns);
-/// ```
-#[allow(dead_code)]
-#[allow(unused_variables)]
-#[allow(deprecated)]
-#[cfg(feature = "std")]
-pub fn bpf_time_getns(unused1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
-    time::precise_time_ns()
-}
-
-// bpf_trace_printk()
-
-/// Index of helper `bpf_trace_printk()`, equivalent to `bpf_trace_printf()`, in Linux kernel, see
-/// <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/bpf.h>.
-pub const BPF_TRACE_PRINTK_IDX: u32 = 6;
-
-/// Prints its **last three** arguments to standard output. The **first two** arguments are
-/// **unused**. Returns the number of bytes written.
-///
-/// By ignoring the first two arguments, it creates a helper that will have a behavior similar to
-/// the one of the equivalent helper `bpf_trace_printk()` from Linux kernel.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::helpers;
-///
-/// let res = helpers::bpf_trace_printf(0, 0, 1, 15, 32);
-/// assert_eq!(res as usize, "bpf_trace_printf: 0x1, 0xf, 0x20\n".len());
-/// ```
-///
-/// This will print `bpf_trace_printf: 0x1, 0xf, 0x20`.
-///
-/// The eBPF code needed to perform the call in this example would be nearly identical to the code
-/// obtained by compiling the following code from C to eBPF with clang:
-///
-/// ```c
-/// #include <linux/bpf.h>
-/// #include "path/to/linux/samples/bpf/bpf_helpers.h"
-///
-/// int main(struct __sk_buff *skb)
-/// {
-///     // Only %d %u %x %ld %lu %lx %lld %llu %llx %p %s conversion specifiers allowed.
-///     // See <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/trace/bpf_trace.c>.
-///     char *fmt = "bpf_trace_printk %llx, %llx, %llx\n";
-///     return bpf_trace_printk(fmt, sizeof(fmt), 1, 15, 32);
-/// }
-/// ```
-///
-/// This would equally print the three numbers in `/sys/kernel/debug/tracing` file each time the
-/// program is run.
-#[allow(dead_code)]
-#[allow(unused_variables)]
-#[cfg(feature = "std")]
-pub fn bpf_trace_printf(unused1: u64, unused2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
-    println!("bpf_trace_printf: {arg3:#x}, {arg4:#x}, {arg5:#x}");
-    let size_arg = |x| {
-        if x == 0 {
-            1
-        } else {
-            (x as f64).log(16.0).floor() as u64 + 1
-        }
-    };
-    "bpf_trace_printf: 0x, 0x, 0x\n".len() as u64 + size_arg(arg3) + size_arg(arg4) + size_arg(arg5)
-}
-
-// Helpers coming from uBPF <https://github.com/iovisor/ubpf/blob/master/vm/test.c>
-
-/// The idea is to assemble five bytes into a single `u64`. For compatibility with the helpers API,
-/// each argument must be a `u64`.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::helpers;
-///
-/// let gathered = helpers::gather_bytes(0x11, 0x22, 0x33, 0x44, 0x55);
-/// assert_eq!(gathered, 0x1122334455);
-/// ```
-pub fn gather_bytes(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
-    arg1.wrapping_shl(32)
-        | arg2.wrapping_shl(24)
-        | arg3.wrapping_shl(16)
-        | arg4.wrapping_shl(8)
-        | arg5
-}
-
-/// Same as `void *memfrob(void *s, size_t n);` in `string.h` in C. See the GNU manual page (in
-/// section 3) for `memfrob`. The memory is directly modified, and the helper returns 0 in all
-/// cases. Arguments 3 to 5 are unused.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::helpers;
-///
-/// let val: u64 = 0x112233;
-/// let val_ptr = &val as *const u64;
-///
-/// helpers::memfrob(val_ptr as u64, 8, 0, 0, 0);
-/// assert_eq!(val, 0x2a2a2a2a2a3b0819);
-/// helpers::memfrob(val_ptr as u64, 8, 0, 0, 0);
-/// assert_eq!(val, 0x112233);
-/// ```
-#[allow(unused_variables)]
-pub fn memfrob(ptr: u64, len: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
-    for i in 0..len {
-        unsafe {
-            let mut p = (ptr + i) as *mut u8;
-            *p ^= 0b101010;
-        }
-    }
-    0
-}
-
-// TODO: Try again when asm!() is available in stable Rust.
-// #![feature(asm)]
-// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-// #[allow(unused_variables)]
-// pub fn memfrob (ptr: u64, len: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
-//     unsafe {
-//         asm!(
-//                 "mov $0xf0, %rax"
-//             ::: "mov $0xf1, %rcx"
-//             ::: "mov $0xf2, %rdx"
-//             ::: "mov $0xf3, %rsi"
-//             ::: "mov $0xf4, %rdi"
-//             ::: "mov $0xf5, %r8"
-//             ::: "mov $0xf6, %r9"
-//             ::: "mov $0xf7, %r10"
-//             ::: "mov $0xf8, %r11"
-//         );
-//     }
-//     0
-// }
-
-/// Compute and return the square root of argument 1, cast as a float. Arguments 2 to 5 are
-/// unused.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::helpers;
-///
-/// let x = helpers::sqrti(9, 0, 0, 0, 0);
-/// assert_eq!(x, 3);
-/// ```
-#[allow(dead_code)]
-#[allow(unused_variables)]
-#[cfg(feature = "std")] // sqrt is only available when using `std`
-pub fn sqrti(arg1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
-    (arg1 as f64).sqrt() as u64
-}
-
-/// C-like `strcmp`, return 0 if the strings are equal, and a non-null value otherwise.
-///
-/// # Examples
-///
-/// ```
-/// use rbpf::helpers;
-///
-/// let foo = "This is a string.\0".as_ptr() as u64;
-/// let bar = "This is another sting.\0".as_ptr() as u64;
-///
-/// assert!(helpers::strcmp(foo, foo, 0, 0, 0) == 0);
-/// assert!(helpers::strcmp(foo, bar, 0, 0, 0) != 0);
-/// ```
-#[allow(dead_code)]
-#[allow(unused_variables)]
-pub fn strcmp(arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u64 {
-    // C-like strcmp, maybe shorter than converting the bytes to string and comparing?
-    if arg1 == 0 || arg2 == 0 {
-        return u64::MAX;
-    }
-    let mut a = arg1;
-    let mut b = arg2;
-    unsafe {
-        let mut a_val = *(a as *const u8);
-        let mut b_val = *(b as *const u8);
-        while a_val == b_val && a_val != 0 && b_val != 0 {
-            a += 1;
-            b += 1;
-            a_val = *(a as *const u8);
-            b_val = *(b as *const u8);
-        }
-        if a_val >= b_val {
-            (a_val - b_val) as u64
-        } else {
-            (b_val - a_val) as u64
-        }
-    }
-}
-
-// Some additional helpers
-
-/// Returns a random u64 value comprised between `min` and `max` values (inclusive). Arguments 3 to
-/// 5 are unused.
-///
-/// Relies on `rand()` function from libc, so `libc::srand()` should be called once before this
-/// helper is used.
-///
-/// # Examples
-///
-/// ```
-/// extern crate libc;
-/// extern crate rbpf;
-/// extern crate time;
-///
-/// unsafe {
-///     libc::srand(time::precise_time_ns() as u32)
-/// }
-///
-/// let n = rbpf::helpers::rand(3, 6, 0, 0, 0);
-/// assert!(3 <= n && n <= 6);
-/// ```
-#[allow(dead_code)]
-#[allow(unused_variables)]
-#[cfg(feature = "std")]
-pub fn rand(min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
-    let mut n = unsafe { (libc::rand() as u64).wrapping_shl(32) + libc::rand() as u64 };
-    if min < max {
-        n = n % (max + 1 - min) + min;
-    };
-    n
-}
-/// Prints the helper functions name and it's index.
-#[cfg(feature = "std")]
-pub fn show_helper() {
-    for (index, name) in BPF_FUNC_MAPPER.iter().enumerate() {
-        println!("{}:{}", index, name);
-    }
-}
-
-/// See https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf.h
-pub const BPF_FUNC_MAPPER: &[&str] = &[
-    "unspec",
-    "map_lookup_elem",
-    "map_update_elem",
-    "map_delete_elem",
-    "probe_read",
-    "ktime_get_ns",
-    "trace_printk",
-    "get_prandom_u32",
-    "get_smp_processor_id",
-    "skb_store_bytes",
-    "l3_csum_replace",
-    "l4_csum_replace",
-    "tail_call",
-    "clone_redirect",
-    "get_current_pid_tgid",
-    "get_current_uid_gid",
-    "get_current_comm",
-    "get_cgroup_classid",
-    "skb_vlan_push",
-    "skb_vlan_pop",
-    "skb_get_tunnel_key",
-    "skb_set_tunnel_key",
-    "perf_event_read",
-    "redirect",
-    "get_route_realm",
-    "perf_event_output",
-    "skb_load_bytes",
-    "get_stackid",
-    "csum_diff",
-    "skb_get_tunnel_opt",
-    "skb_set_tunnel_opt",
-    "skb_change_proto",
-    "skb_change_type",
-    "skb_under_cgroup",
-    "get_hash_recalc",
-    "get_current_task",
-    "probe_write_user",
-    "current_task_under_cgroup",
-    "skb_change_tail",
-    "skb_pull_data",
-    "csum_update",
-    "set_hash_invalid",
-    "get_numa_node_id",
-    "skb_change_head",
-    "xdp_adjust_head",
-    "probe_read_str",
-    "get_socket_cookie",
-    "get_socket_uid",
-    "set_hash",
-    "setsockopt",
-    "skb_adjust_room",
-    "redirect_map",
-    "sk_redirect_map",
-    "sock_map_update",
-    "xdp_adjust_meta",
-    "perf_event_read_value",
-    "perf_prog_read_value",
-    "getsockopt",
-    "override_return",
-    "sock_ops_cb_flags_set",
-    "msg_redirect_map",
-    "msg_apply_bytes",
-    "msg_cork_bytes",
-    "msg_pull_data",
-    "bind",
-    "xdp_adjust_tail",
-    "skb_get_xfrm_state",
-    "get_stack",
-    "skb_load_bytes_relative",
-    "fib_lookup",
-    "sock_hash_update",
-    "msg_redirect_hash",
-    "sk_redirect_hash",
-    "lwt_push_encap",
-    "lwt_seg6_store_bytes",
-    "lwt_seg6_adjust_srh",
-    "lwt_seg6_action",
-    "rc_repeat",
-    "rc_keydown",
-    "skb_cgroup_id",
-    "get_current_cgroup_id",
-    "get_local_storage",
-    "sk_select_reuseport",
-    "skb_ancestor_cgroup_id",
-    "sk_lookup_tcp",
-    "sk_lookup_udp",
-    "sk_release",
-    "map_push_elem",
-    "map_pop_elem",
-    "map_peek_elem",
-    "msg_push_data",
-    "msg_pop_data",
-    "rc_pointer_rel",
-    "spin_lock",
-    "spin_unlock",
-    "sk_fullsock",
-    "tcp_sock",
-    "skb_ecn_set_ce",
-    "get_listener_sock",
-    "skc_lookup_tcp",
-    "tcp_check_syncookie",
-    "sysctl_get_name",
-    "sysctl_get_current_value",
-    "sysctl_get_new_value",
-    "sysctl_set_new_value",
-    "strtol",
-    "strtoul",
-    "sk_storage_get",
-    "sk_storage_delete",
-    "send_signal",
-    "tcp_gen_syncookie",
-    "skb_output",
-    "probe_read_user",
-    "probe_read_kernel",
-    "probe_read_user_str",
-    "probe_read_kernel_str",
-    "tcp_send_ack",
-    "send_signal_thread",
-    "jiffies64",
-    "read_branch_records",
-    "get_ns_current_pid_tgid",
-    "xdp_output",
-    "get_netns_cookie",
-    "get_current_ancestor_cgroup_id",
-    "sk_assign",
-    "ktime_get_boot_ns",
-    "seq_printf",
-    "seq_write",
-    "sk_cgroup_id",
-    "sk_ancestor_cgroup_id",
-    "ringbuf_output",
-    "ringbuf_reserve",
-    "ringbuf_submit",
-    "ringbuf_discard",
-    "ringbuf_query",
-    "csum_level",
-    "skc_to_tcp6_sock",
-    "skc_to_tcp_sock",
-    "skc_to_tcp_timewait_sock",
-    "skc_to_tcp_request_sock",
-    "skc_to_udp6_sock",
-    "get_task_stack",
-    "load_hdr_opt",
-    "store_hdr_opt",
-    "reserve_hdr_opt",
-    "inode_storage_get",
-    "inode_storage_delete",
-    "d_path",
-    "copy_from_user",
-    "snprintf_btf",
-    "seq_printf_btf",
-    "skb_cgroup_classid",
-    "redirect_neigh",
-    "per_cpu_ptr",
-    "this_cpu_ptr",
-    "redirect_peer",
-    "task_storage_get",
-    "task_storage_delete",
-    "get_current_task_btf",
-    "bprm_opts_set",
-    "ktime_get_coarse_ns",
-    "ima_inode_hash",
-    "sock_from_file",
-    "check_mtu",
-    "for_each_map_elem",
-    "snprintf",
-    "sys_bpf",
-    "btf_find_by_name_kind",
-    "sys_close",
-    "timer_init",
-    "timer_set_callback",
-    "timer_start",
-    "timer_cancel",
-    "get_func_ip",
-    "get_attach_cookie",
-    "task_pt_regs",
-    "get_branch_snapshot",
-    "trace_vprintk",
-    "skc_to_unix_sock",
-    "kallsyms_lookup_name",
-    "find_vma",
-    "loop",
-    "strncmp",
-    "get_func_arg",
-    "get_func_ret",
-    "get_func_arg_cnt",
-    "get_retval",
-    "set_retval",
-    "xdp_get_buff_len",
-    "xdp_load_bytes",
-    "xdp_store_bytes",
-    "copy_from_user_task",
-    "skb_set_tstamp",
-    "ima_file_hash",
-    "kptr_xchg",
-    "map_lookup_percpu_elem",
-    "skc_to_mptcp_sock",
-    "dynptr_from_mem",
-    "ringbuf_reserve_dynptr",
-    "ringbuf_submit_dynptr",
-    "ringbuf_discard_dynptr",
-    "dynptr_read",
-    "dynptr_write",
-    "dynptr_data",
-    "tcp_raw_gen_syncookie_ipv4",
-    "tcp_raw_gen_syncookie_ipv6",
-    "tcp_raw_check_syncookie_ipv4",
-    "tcp_raw_check_syncookie_ipv6",
-    "ktime_get_tai_ns",
-    "user_ringbuf_drain",
-    "cgrp_storage_get",
-    "cgrp_storage_delete",
-];

+ 0 - 2199
kernel/crates/rbpf/src/insn_builder.rs

@@ -1,2199 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 Alex Dukhno <alex.dukhno@icloud.com>
-
-//! Module provides API to create eBPF programs by Rust programming language
-
-use alloc::{vec, vec::Vec};
-
-use crate::ebpf::*;
-
-/// Represents single eBPF instruction
-pub trait Instruction: Sized {
-    /// returns instruction opt code
-    fn opt_code_byte(&self) -> u8;
-
-    /// returns destination register
-    fn get_dst(&self) -> u8 {
-        self.get_insn().dst
-    }
-
-    /// returns source register
-    fn get_src(&self) -> u8 {
-        self.get_insn().src
-    }
-
-    /// returns offset bytes
-    fn get_off(&self) -> i16 {
-        self.get_insn().off
-    }
-
-    /// returns immediate value
-    fn get_imm(&self) -> i32 {
-        self.get_insn().imm
-    }
-
-    /// sets destination register
-    fn set_dst(mut self, dst: u8) -> Self {
-        self.get_insn_mut().dst = dst;
-        self
-    }
-
-    /// sets source register
-    fn set_src(mut self, src: u8) -> Self {
-        self.get_insn_mut().src = src;
-        self
-    }
-
-    /// sets offset bytes
-    fn set_off(mut self, offset: i16) -> Self {
-        self.get_insn_mut().off = offset;
-        self
-    }
-
-    /// sets immediate value
-    fn set_imm(mut self, imm: i32) -> Self {
-        self.get_insn_mut().imm = imm;
-        self
-    }
-
-    /// get `ebpf::Insn` struct
-    fn get_insn(&self) -> &Insn;
-
-    /// get mutable `ebpf::Insn` struct
-    fn get_insn_mut(&mut self) -> &mut Insn;
-}
-
-/// General trait for `Instruction`s and `BpfCode`.
-/// Provides functionality to transform `struct` into collection of bytes
-pub trait IntoBytes {
-    /// type of targeted transformation
-    type Bytes;
-
-    /// consume `Self` with transformation into `Self::Bytes`
-    fn into_bytes(self) -> Self::Bytes;
-}
-
-/// General implementation of `IntoBytes` for `Instruction`
-impl<I: Instruction> IntoBytes for &'_ I {
-    type Bytes = Vec<u8>;
-
-    /// transform immutable reference of `Instruction` into `Vec<u8>` with size of 8
-    /// [ 1 byte ,      1 byte      , 2 bytes,  4 bytes  ]
-    /// [ OP_CODE, SRC_REG | DST_REG, OFFSET , IMMEDIATE ]
-    fn into_bytes(self) -> Self::Bytes {
-        let buffer = vec![
-            self.opt_code_byte(),
-            self.get_src() << 4 | self.get_dst(),
-            self.get_off() as u8,
-            (self.get_off() >> 8) as u8,
-            self.get_imm() as u8,
-            (self.get_imm() >> 8) as u8,
-            (self.get_imm() >> 16) as u8,
-            (self.get_imm() >> 24) as u8,
-        ];
-        buffer
-    }
-}
-
-/// BPF instruction stack in byte representation
-#[derive(Default)]
-pub struct BpfCode {
-    instructions: Vec<u8>,
-}
-
-impl BpfCode {
-    /// creates new empty BPF instruction stack
-    pub fn new() -> Self {
-        BpfCode {
-            instructions: vec![],
-        }
-    }
-
-    /// create ADD instruction
-    pub fn add(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::Add)
-    }
-
-    /// create SUB instruction
-    pub fn sub(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::Sub)
-    }
-
-    /// create MUL instruction
-    pub fn mul(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::Mul)
-    }
-
-    /// create DIV instruction
-    pub fn div(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::Div)
-    }
-
-    /// create OR instruction
-    pub fn bit_or(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::BitOr)
-    }
-
-    /// create AND instruction
-    pub fn bit_and(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::BitAnd)
-    }
-
-    /// create LSHIFT instruction
-    pub fn left_shift(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::LShift)
-    }
-
-    /// create RSHIFT instruction
-    pub fn right_shift(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::RShift)
-    }
-
-    /// create NEGATE instruction
-    pub fn negate(&mut self, arch: Arch) -> Move {
-        self.mov_internal(Source::Imm, arch, OpBits::Negate)
-    }
-
-    /// create MOD instruction
-    pub fn modulo(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::Mod)
-    }
-
-    /// create XOR instruction
-    pub fn bit_xor(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::BitXor)
-    }
-
-    /// create MOV instruction
-    pub fn mov(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::Mov)
-    }
-
-    /// create SIGNED RSHIFT instruction
-    pub fn signed_right_shift(&mut self, source: Source, arch: Arch) -> Move {
-        self.mov_internal(source, arch, OpBits::SignRShift)
-    }
-
-    #[inline]
-    fn mov_internal(&mut self, source: Source, arch_bits: Arch, op_bits: OpBits) -> Move {
-        Move {
-            bpf_code: self,
-            src_bit: source,
-            op_bits,
-            arch_bits,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-
-    /// create byte swap instruction
-    pub fn swap_bytes(&mut self, endian: Endian) -> SwapBytes {
-        SwapBytes {
-            bpf_code: self,
-            endian,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-
-    /// create LOAD instruction, IMMEDIATE is the source
-    pub fn load(&mut self, mem_size: MemSize) -> Load {
-        self.load_internal(mem_size, Addressing::Imm, BPF_LD)
-    }
-
-    /// create ABSOLUTE LOAD instruction
-    pub fn load_abs(&mut self, mem_size: MemSize) -> Load {
-        self.load_internal(mem_size, Addressing::Abs, BPF_LD)
-    }
-
-    /// create INDIRECT LOAD instruction
-    pub fn load_ind(&mut self, mem_size: MemSize) -> Load {
-        self.load_internal(mem_size, Addressing::Ind, BPF_LD)
-    }
-
-    /// create LOAD instruction, MEMORY is the source
-    pub fn load_x(&mut self, mem_size: MemSize) -> Load {
-        self.load_internal(mem_size, Addressing::Mem, BPF_LDX)
-    }
-
-    #[inline]
-    fn load_internal(&mut self, mem_size: MemSize, addressing: Addressing, source: u8) -> Load {
-        Load {
-            bpf_code: self,
-            addressing,
-            mem_size,
-            source,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-
-    /// creates STORE instruction, IMMEDIATE is the source
-    pub fn store(&mut self, mem_size: MemSize) -> Store {
-        self.store_internal(mem_size, BPF_IMM)
-    }
-
-    /// creates STORE instruction, MEMORY is the source
-    pub fn store_x(&mut self, mem_size: MemSize) -> Store {
-        self.store_internal(mem_size, BPF_MEM | BPF_STX)
-    }
-
-    #[inline]
-    fn store_internal(&mut self, mem_size: MemSize, source: u8) -> Store {
-        Store {
-            bpf_code: self,
-            mem_size,
-            source,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-
-    /// create unconditional JMP instruction
-    pub fn jump_unconditional(&mut self) -> Jump {
-        self.jump_conditional(Cond::Abs, Source::Imm)
-    }
-
-    /// create conditional JMP instruction
-    pub fn jump_conditional(&mut self, cond: Cond, src_bit: Source) -> Jump {
-        Jump {
-            bpf_code: self,
-            cond,
-            src_bit,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-
-    /// create CALL instruction
-    pub fn call(&mut self) -> FunctionCall {
-        FunctionCall {
-            bpf_code: self,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-
-    /// create EXIT instruction
-    pub fn exit(&mut self) -> Exit {
-        Exit {
-            bpf_code: self,
-            insn: Insn {
-                opc: 0x00,
-                dst: 0x00,
-                src: 0x00,
-                off: 0x00_00,
-                imm: 0x00_00_00_00,
-            },
-        }
-    }
-}
-
-/// Transform `BpfCode` into assemble representation
-impl<'a> IntoBytes for &'a BpfCode {
-    type Bytes = &'a [u8];
-
-    /// returns `BpfCode` instruction stack as `&[u8]`
-    fn into_bytes(self) -> Self::Bytes {
-        self.instructions.as_slice()
-    }
-}
-
-/// struct to represent `MOV ALU` instructions
-pub struct Move<'i> {
-    bpf_code: &'i mut BpfCode,
-    src_bit: Source,
-    op_bits: OpBits,
-    arch_bits: Arch,
-    insn: Insn,
-}
-
-impl<'i> Move<'i> {
-    /// push MOV instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for Move<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        let op_bits = self.op_bits as u8;
-        let src_bit = self.src_bit as u8;
-        let arch_bits = self.arch_bits as u8;
-        op_bits | src_bit | arch_bits
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-/// The source of ALU and JMP instructions
-pub enum Source {
-    /// immediate field will be used as a source
-    Imm = BPF_IMM as isize,
-    /// src register will be used as a source
-    Reg = BPF_X as isize,
-}
-
-#[derive(Copy, Clone)]
-enum OpBits {
-    Add = BPF_ADD as isize,
-    Sub = BPF_SUB as isize,
-    Mul = BPF_MUL as isize,
-    Div = BPF_DIV as isize,
-    BitOr = BPF_OR as isize,
-    BitAnd = BPF_AND as isize,
-    LShift = BPF_LSH as isize,
-    RShift = BPF_RSH as isize,
-    Negate = BPF_NEG as isize,
-    Mod = BPF_MOD as isize,
-    BitXor = BPF_XOR as isize,
-    Mov = BPF_MOV as isize,
-    SignRShift = BPF_ARSH as isize,
-}
-
-#[derive(Copy, Clone)]
-/// Architecture of instructions
-pub enum Arch {
-    /// 64-bit instructions
-    X64 = BPF_ALU64 as isize,
-    /// 32-bit instructions
-    X32 = BPF_ALU as isize,
-}
-
-/// struct representation of byte swap operation
-pub struct SwapBytes<'i> {
-    bpf_code: &'i mut BpfCode,
-    endian: Endian,
-    insn: Insn,
-}
-
-impl<'i> SwapBytes<'i> {
-    /// push bytes swap instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for SwapBytes<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        self.endian as u8
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-}
-
-#[derive(Copy, Clone)]
-/// Bytes endian
-pub enum Endian {
-    /// Little endian
-    Little = LE as isize,
-    /// Big endian
-    Big = BE as isize,
-}
-
-/// struct representation of LOAD instructions
-pub struct Load<'i> {
-    bpf_code: &'i mut BpfCode,
-    addressing: Addressing,
-    mem_size: MemSize,
-    source: u8,
-    insn: Insn,
-}
-
-impl<'i> Load<'i> {
-    /// push LOAD instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for Load<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        let size = self.mem_size as u8;
-        let addressing = self.addressing as u8;
-        addressing | size | self.source
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-}
-
-/// struct representation of STORE instructions
-pub struct Store<'i> {
-    bpf_code: &'i mut BpfCode,
-    mem_size: MemSize,
-    source: u8,
-    insn: Insn,
-}
-
-impl<'i> Store<'i> {
-    /// push STORE instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for Store<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        let size = self.mem_size as u8;
-        BPF_MEM | BPF_ST | size | self.source
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-}
-
-#[derive(Copy, Clone)]
-/// Memory size for LOAD and STORE instructions
-pub enum MemSize {
-    /// 8-bit size
-    Byte = BPF_B as isize,
-    /// 16-bit size
-    HalfWord = BPF_H as isize,
-    /// 32-bit size
-    Word = BPF_W as isize,
-    /// 64-bit size
-    DoubleWord = BPF_DW as isize,
-}
-
-#[derive(Copy, Clone)]
-enum Addressing {
-    Imm = BPF_IMM as isize,
-    Abs = BPF_ABS as isize,
-    Ind = BPF_IND as isize,
-    Mem = BPF_MEM as isize,
-}
-
-/// struct representation of JMP instructions
-pub struct Jump<'i> {
-    bpf_code: &'i mut BpfCode,
-    cond: Cond,
-    src_bit: Source,
-    insn: Insn,
-}
-
-impl<'i> Jump<'i> {
-    /// push JMP instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for Jump<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        let cmp: u8 = self.cond as u8;
-        let src_bit = self.src_bit as u8;
-        cmp | src_bit | BPF_JMP
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-/// Conditions for JMP instructions
-pub enum Cond {
-    /// Absolute or unconditional
-    Abs = BPF_JA as isize,
-    /// Jump if `==`
-    Equals = BPF_JEQ as isize,
-    /// Jump if `>`
-    Greater = BPF_JGT as isize,
-    /// Jump if `>=`
-    GreaterEquals = BPF_JGE as isize,
-    /// Jump if `<`
-    Lower = BPF_JLT as isize,
-    /// Jump if `<=`
-    LowerEquals = BPF_JLE as isize,
-    /// Jump if `src` & `dst`
-    BitAnd = BPF_JSET as isize,
-    /// Jump if `!=`
-    NotEquals = BPF_JNE as isize,
-    /// Jump if `>` (signed)
-    GreaterSigned = BPF_JSGT as isize,
-    /// Jump if `>=` (signed)
-    GreaterEqualsSigned = BPF_JSGE as isize,
-    /// Jump if `<` (signed)
-    LowerSigned = BPF_JSLT as isize,
-    /// Jump if `<=` (signed)
-    LowerEqualsSigned = BPF_JSLE as isize,
-}
-
-/// struct representation of CALL instruction
-pub struct FunctionCall<'i> {
-    bpf_code: &'i mut BpfCode,
-    insn: Insn,
-}
-
-impl<'i> FunctionCall<'i> {
-    /// push CALL instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for FunctionCall<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        BPF_CALL | BPF_JMP
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-}
-
-/// struct representation of EXIT instruction
-pub struct Exit<'i> {
-    bpf_code: &'i mut BpfCode,
-    insn: Insn,
-}
-
-impl<'i> Exit<'i> {
-    /// push EXIT instruction into BpfCode instruction stack
-    pub fn push(self) -> &'i mut BpfCode {
-        let mut asm = self.into_bytes();
-        self.bpf_code.instructions.append(&mut asm);
-        self.bpf_code
-    }
-}
-
-impl Instruction for Exit<'_> {
-    fn opt_code_byte(&self) -> u8 {
-        BPF_EXIT | BPF_JMP
-    }
-
-    fn get_insn_mut(&mut self) -> &mut Insn {
-        &mut self.insn
-    }
-
-    fn get_insn(&self) -> &Insn {
-        &self.insn
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    #[cfg(test)]
-    mod special {
-        use super::super::*;
-
-        #[test]
-        fn call_immediate() {
-            let mut program = BpfCode::new();
-            program.call().set_imm(0x11_22_33_44).push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x85, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
-            );
-        }
-
-        #[test]
-        fn exit_operation() {
-            let mut program = BpfCode::new();
-            program.exit().push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-    }
-
-    #[cfg(test)]
-    mod jump_instructions {
-        #[cfg(test)]
-        mod register {
-            use super::super::super::*;
-
-            #[test]
-            fn jump_on_dst_equals_src() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::Equals, Source::Reg)
-                    .set_dst(0x01)
-                    .set_src(0x02)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x1d, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_than_src() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::Greater, Source::Reg)
-                    .set_dst(0x03)
-                    .set_src(0x02)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x2d, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_or_equals_to_src() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::GreaterEquals, Source::Reg)
-                    .set_dst(0x04)
-                    .set_src(0x01)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x3d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_than_src() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::Lower, Source::Reg)
-                    .set_dst(0x03)
-                    .set_src(0x02)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xad, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_or_equals_to_src() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::LowerEquals, Source::Reg)
-                    .set_dst(0x04)
-                    .set_src(0x01)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xbd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_bit_and_with_src_not_equal_zero() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::BitAnd, Source::Reg)
-                    .set_dst(0x05)
-                    .set_src(0x02)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x4d, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_not_equals_src() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::NotEquals, Source::Reg)
-                    .set_dst(0x03)
-                    .set_src(0x05)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x5d, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_than_src_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::GreaterSigned, Source::Reg)
-                    .set_dst(0x04)
-                    .set_src(0x01)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x6d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_or_equals_src_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::GreaterEqualsSigned, Source::Reg)
-                    .set_dst(0x01)
-                    .set_src(0x03)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x7d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_than_src_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::LowerSigned, Source::Reg)
-                    .set_dst(0x04)
-                    .set_src(0x01)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xcd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_or_equals_src_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::LowerEqualsSigned, Source::Reg)
-                    .set_dst(0x01)
-                    .set_src(0x03)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xdd, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-        }
-
-        #[cfg(test)]
-        mod immediate {
-            use super::super::super::*;
-
-            #[test]
-            fn jump_to_label() {
-                let mut program = BpfCode::new();
-                program.jump_unconditional().set_off(0x00_11).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_equals_const() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::Equals, Source::Imm)
-                    .set_dst(0x01)
-                    .set_imm(0x00_11_22_33)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x15, 0x01, 0x00, 0x00, 0x33, 0x22, 0x11, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_than_const() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::Greater, Source::Imm)
-                    .set_dst(0x02)
-                    .set_imm(0x00_11_00_11)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x25, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_or_equals_to_const() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::GreaterEquals, Source::Imm)
-                    .set_dst(0x04)
-                    .set_imm(0x00_22_11_00)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x35, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_than_const() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::Lower, Source::Imm)
-                    .set_dst(0x02)
-                    .set_imm(0x00_11_00_11)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xa5, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_or_equals_to_const() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::LowerEquals, Source::Imm)
-                    .set_dst(0x04)
-                    .set_imm(0x00_22_11_00)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xb5, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_bit_and_with_const_not_equal_zero() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::BitAnd, Source::Imm)
-                    .set_dst(0x05)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_not_equals_const() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::NotEquals, Source::Imm)
-                    .set_dst(0x03)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_than_const_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::GreaterSigned, Source::Imm)
-                    .set_dst(0x04)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x65, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_greater_or_equals_src_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::GreaterEqualsSigned, Source::Imm)
-                    .set_dst(0x01)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_than_const_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::LowerSigned, Source::Imm)
-                    .set_dst(0x04)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xc5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn jump_on_dst_lower_or_equals_src_signed() {
-                let mut program = BpfCode::new();
-                program
-                    .jump_conditional(Cond::LowerEqualsSigned, Source::Imm)
-                    .set_dst(0x01)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-        }
-    }
-
-    #[cfg(test)]
-    mod store_instructions {
-        use super::super::*;
-
-        #[test]
-        fn store_word_from_dst_into_immediate_address() {
-            let mut program = BpfCode::new();
-            program
-                .store(MemSize::Word)
-                .set_dst(0x01)
-                .set_off(0x00_11)
-                .set_imm(0x11_22_33_44)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x62, 0x01, 0x11, 0x00, 0x44, 0x33, 0x22, 0x11]
-            );
-        }
-
-        #[test]
-        fn store_half_word_from_dst_into_immediate_address() {
-            let mut program = BpfCode::new();
-            program
-                .store(MemSize::HalfWord)
-                .set_dst(0x02)
-                .set_off(0x11_22)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x6a, 0x02, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn store_byte_from_dst_into_immediate_address() {
-            let mut program = BpfCode::new();
-            program.store(MemSize::Byte).push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn store_double_word_from_dst_into_immediate_address() {
-            let mut program = BpfCode::new();
-            program.store(MemSize::DoubleWord).push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn store_word_from_dst_into_src_address() {
-            let mut program = BpfCode::new();
-            program
-                .store_x(MemSize::Word)
-                .set_dst(0x01)
-                .set_src(0x02)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x63, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn store_half_word_from_dst_into_src_address() {
-            let mut program = BpfCode::new();
-            program.store_x(MemSize::HalfWord).push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn store_byte_from_dst_into_src_address() {
-            let mut program = BpfCode::new();
-            program.store_x(MemSize::Byte).push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn store_double_word_from_dst_into_src_address() {
-            let mut program = BpfCode::new();
-            program.store_x(MemSize::DoubleWord).push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-            );
-        }
-    }
-
-    #[cfg(test)]
-    mod load_instructions {
-        #[cfg(test)]
-        mod register {
-            use super::super::super::*;
-
-            #[test]
-            fn load_word_from_set_src_with_offset() {
-                let mut program = BpfCode::new();
-                program
-                    .load_x(MemSize::Word)
-                    .set_dst(0x01)
-                    .set_src(0x02)
-                    .set_off(0x00_02)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x61, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_half_word_from_set_src_with_offset() {
-                let mut program = BpfCode::new();
-                program
-                    .load_x(MemSize::HalfWord)
-                    .set_dst(0x02)
-                    .set_src(0x01)
-                    .set_off(0x11_22)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x69, 0x12, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_byte_from_set_src_with_offset() {
-                let mut program = BpfCode::new();
-                program
-                    .load_x(MemSize::Byte)
-                    .set_dst(0x01)
-                    .set_src(0x04)
-                    .set_off(0x00_11)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x71, 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_double_word_from_set_src_with_offset() {
-                let mut program = BpfCode::new();
-                program
-                    .load_x(MemSize::DoubleWord)
-                    .set_dst(0x04)
-                    .set_src(0x05)
-                    .set_off(0x44_55)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x79, 0x54, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-        }
-
-        #[cfg(test)]
-        mod immediate {
-            use super::super::super::*;
-
-            #[test]
-            fn load_double_word() {
-                let mut program = BpfCode::new();
-                program
-                    .load(MemSize::DoubleWord)
-                    .set_dst(0x01)
-                    .set_imm(0x00_01_02_03)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x18, 0x01, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_abs_word() {
-                let mut program = BpfCode::new();
-                program.load_abs(MemSize::Word).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_abs_half_word() {
-                let mut program = BpfCode::new();
-                program.load_abs(MemSize::HalfWord).set_dst(0x05).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x28, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_abs_byte() {
-                let mut program = BpfCode::new();
-                program.load_abs(MemSize::Byte).set_dst(0x01).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_abs_double_word() {
-                let mut program = BpfCode::new();
-                program
-                    .load_abs(MemSize::DoubleWord)
-                    .set_dst(0x01)
-                    .set_imm(0x01_02_03_04)
-                    .push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x38, 0x01, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
-                );
-            }
-
-            #[test]
-            fn load_indirect_word() {
-                let mut program = BpfCode::new();
-                program.load_ind(MemSize::Word).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_indirect_half_word() {
-                let mut program = BpfCode::new();
-                program.load_ind(MemSize::HalfWord).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_indirect_byte() {
-                let mut program = BpfCode::new();
-                program.load_ind(MemSize::Byte).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-
-            #[test]
-            fn load_indirect_double_word() {
-                let mut program = BpfCode::new();
-                program.load_ind(MemSize::DoubleWord).push();
-
-                assert_eq!(
-                    program.into_bytes(),
-                    &[0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                );
-            }
-        }
-    }
-
-    #[cfg(test)]
-    mod byte_swap_instructions {
-        use super::super::*;
-
-        #[test]
-        fn convert_host_to_little_endian_16bits() {
-            let mut program = BpfCode::new();
-            program
-                .swap_bytes(Endian::Little)
-                .set_dst(0x01)
-                .set_imm(0x00_00_00_10)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0xd4, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn convert_host_to_little_endian_32bits() {
-            let mut program = BpfCode::new();
-            program
-                .swap_bytes(Endian::Little)
-                .set_dst(0x02)
-                .set_imm(0x00_00_00_20)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0xd4, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn convert_host_to_little_endian_64bit() {
-            let mut program = BpfCode::new();
-            program
-                .swap_bytes(Endian::Little)
-                .set_dst(0x03)
-                .set_imm(0x00_00_00_40)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0xd4, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn convert_host_to_big_endian_16bits() {
-            let mut program = BpfCode::new();
-            program
-                .swap_bytes(Endian::Big)
-                .set_dst(0x01)
-                .set_imm(0x00_00_00_10)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn convert_host_to_big_endian_32bits() {
-            let mut program = BpfCode::new();
-            program
-                .swap_bytes(Endian::Big)
-                .set_dst(0x02)
-                .set_imm(0x00_00_00_20)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0xdc, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
-            );
-        }
-
-        #[test]
-        fn convert_host_to_big_endian_64bit() {
-            let mut program = BpfCode::new();
-            program
-                .swap_bytes(Endian::Big)
-                .set_dst(0x03)
-                .set_imm(0x00_00_00_40)
-                .push();
-
-            assert_eq!(
-                program.into_bytes(),
-                &[0xdc, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]
-            );
-        }
-    }
-
-    #[cfg(test)]
-    mod moves_instructions {
-        #[cfg(test)]
-        mod arch_x64 {
-            #[cfg(test)]
-            mod immediate {
-                use super::super::super::super::*;
-
-                #[test]
-                fn move_and_add_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .add(Source::Imm, Arch::X64)
-                        .set_dst(0x02)
-                        .set_imm(0x01_02_03_04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x07, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
-                    );
-                }
-
-                #[test]
-                fn move_sub_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .sub(Source::Imm, Arch::X64)
-                        .set_dst(0x04)
-                        .set_imm(0x00_01_02_03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x17, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mul_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mul(Source::Imm, Arch::X64)
-                        .set_dst(0x05)
-                        .set_imm(0x04_03_02_01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x27, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
-                    );
-                }
-
-                #[test]
-                fn move_div_constant_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .div(Source::Imm, Arch::X64)
-                        .set_dst(0x02)
-                        .set_imm(0x00_ff_00_ff)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x37, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_or_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_or(Source::Imm, Arch::X64)
-                        .set_dst(0x02)
-                        .set_imm(0x00_11_00_22)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x47, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_and_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_and(Source::Imm, Arch::X64)
-                        .set_dst(0x02)
-                        .set_imm(0x11_22_33_44)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x57, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
-                    );
-                }
-
-                #[test]
-                fn move_left_shift_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .left_shift(Source::Imm, Arch::X64)
-                        .set_dst(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_logical_right_shift_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .right_shift(Source::Imm, Arch::X64)
-                        .set_dst(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_negate_register() {
-                    let mut program = BpfCode::new();
-                    program.negate(Arch::X64).set_dst(0x02).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mod_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program.modulo(Source::Imm, Arch::X64).set_dst(0x02).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x97, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_xor_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program.bit_xor(Source::Imm, Arch::X64).set_dst(0x03).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xa7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mov(Source::Imm, Arch::X64)
-                        .set_dst(0x01)
-                        .set_imm(0x00_00_00_FF)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xb7, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_signed_right_shift_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .signed_right_shift(Source::Imm, Arch::X64)
-                        .set_dst(0x05)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xc7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-            }
-
-            #[cfg(test)]
-            mod register {
-                use super::super::super::super::*;
-
-                #[test]
-                fn move_and_add_from_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .add(Source::Reg, Arch::X64)
-                        .set_dst(0x03)
-                        .set_src(0x02)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x0f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_sub_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .sub(Source::Reg, Arch::X64)
-                        .set_dst(0x03)
-                        .set_src(0x04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x1f, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mul_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mul(Source::Reg, Arch::X64)
-                        .set_dst(0x04)
-                        .set_src(0x03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x2f, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_div_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .div(Source::Reg, Arch::X64)
-                        .set_dst(0x01)
-                        .set_src(0x00)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_or_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_or(Source::Reg, Arch::X64)
-                        .set_dst(0x03)
-                        .set_src(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x4f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_and_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_and(Source::Reg, Arch::X64)
-                        .set_dst(0x03)
-                        .set_src(0x02)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x5f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_left_shift_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .left_shift(Source::Reg, Arch::X64)
-                        .set_dst(0x02)
-                        .set_src(0x03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x6f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_logical_right_shift_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .right_shift(Source::Reg, Arch::X64)
-                        .set_dst(0x02)
-                        .set_src(0x04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x7f, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mod_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .modulo(Source::Reg, Arch::X64)
-                        .set_dst(0x01)
-                        .set_src(0x02)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x9f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_xor_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_xor(Source::Reg, Arch::X64)
-                        .set_dst(0x02)
-                        .set_src(0x04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xaf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_from_register_to_another_register() {
-                    let mut program = BpfCode::new();
-                    program.mov(Source::Reg, Arch::X64).set_src(0x01).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_signed_right_shift_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .signed_right_shift(Source::Reg, Arch::X64)
-                        .set_dst(0x02)
-                        .set_src(0x03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xcf, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-            }
-        }
-
-        #[cfg(test)]
-        mod arch_x32 {
-            #[cfg(test)]
-            mod immediate {
-                use super::super::super::super::*;
-
-                #[test]
-                fn move_and_add_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .add(Source::Imm, Arch::X32)
-                        .set_dst(0x02)
-                        .set_imm(0x01_02_03_04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x04, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
-                    );
-                }
-
-                #[test]
-                fn move_sub_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .sub(Source::Imm, Arch::X32)
-                        .set_dst(0x04)
-                        .set_imm(0x00_01_02_03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x14, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mul_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mul(Source::Imm, Arch::X32)
-                        .set_dst(0x05)
-                        .set_imm(0x04_03_02_01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x24, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
-                    );
-                }
-
-                #[test]
-                fn move_div_constant_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .div(Source::Imm, Arch::X32)
-                        .set_dst(0x02)
-                        .set_imm(0x00_ff_00_ff)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x34, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_or_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_or(Source::Imm, Arch::X32)
-                        .set_dst(0x02)
-                        .set_imm(0x00_11_00_22)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x44, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_and_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_and(Source::Imm, Arch::X32)
-                        .set_dst(0x02)
-                        .set_imm(0x11_22_33_44)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x54, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
-                    );
-                }
-
-                #[test]
-                fn move_left_shift_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .left_shift(Source::Imm, Arch::X32)
-                        .set_dst(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_logical_right_shift_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .right_shift(Source::Imm, Arch::X32)
-                        .set_dst(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_negate_register() {
-                    let mut program = BpfCode::new();
-                    program.negate(Arch::X32).set_dst(0x02).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mod_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program.modulo(Source::Imm, Arch::X32).set_dst(0x02).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_xor_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program.bit_xor(Source::Imm, Arch::X32).set_dst(0x03).push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mov(Source::Imm, Arch::X32)
-                        .set_dst(0x01)
-                        .set_imm(0x00_00_00_FF)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xb4, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_signed_right_shift_const_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .signed_right_shift(Source::Imm, Arch::X32)
-                        .set_dst(0x05)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xc4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-            }
-
-            #[cfg(test)]
-            mod register {
-                use super::super::super::super::*;
-
-                #[test]
-                fn move_and_add_from_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .add(Source::Reg, Arch::X32)
-                        .set_dst(0x03)
-                        .set_src(0x02)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x0c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_sub_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .sub(Source::Reg, Arch::X32)
-                        .set_dst(0x03)
-                        .set_src(0x04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x1c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mul_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mul(Source::Reg, Arch::X32)
-                        .set_dst(0x04)
-                        .set_src(0x03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x2c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_div_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .div(Source::Reg, Arch::X32)
-                        .set_dst(0x01)
-                        .set_src(0x00)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_or_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_or(Source::Reg, Arch::X32)
-                        .set_dst(0x03)
-                        .set_src(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x4c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_and_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_and(Source::Reg, Arch::X32)
-                        .set_dst(0x03)
-                        .set_src(0x02)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x5c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_left_shift_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .left_shift(Source::Reg, Arch::X32)
-                        .set_dst(0x02)
-                        .set_src(0x03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x6c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_logical_right_shift_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .right_shift(Source::Reg, Arch::X32)
-                        .set_dst(0x02)
-                        .set_src(0x04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x7c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_mod_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .modulo(Source::Reg, Arch::X32)
-                        .set_dst(0x01)
-                        .set_src(0x02)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0x9c, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_bit_xor_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .bit_xor(Source::Reg, Arch::X32)
-                        .set_dst(0x02)
-                        .set_src(0x04)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xac, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_from_register_to_another_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .mov(Source::Reg, Arch::X32)
-                        .set_dst(0x00)
-                        .set_src(0x01)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-
-                #[test]
-                fn move_signed_right_shift_from_register_to_register() {
-                    let mut program = BpfCode::new();
-                    program
-                        .signed_right_shift(Source::Reg, Arch::X32)
-                        .set_dst(0x02)
-                        .set_src(0x03)
-                        .push();
-
-                    assert_eq!(
-                        program.into_bytes(),
-                        &[0xcc, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-                    );
-                }
-            }
-        }
-    }
-
-    #[cfg(test)]
-    mod programs {
-        use super::super::*;
-
-        #[test]
-        fn example_from_assembler() {
-            let mut program = BpfCode::new();
-            program
-                .add(Source::Imm, Arch::X64)
-                .set_dst(1)
-                .set_imm(0x605)
-                .push()
-                .mov(Source::Imm, Arch::X64)
-                .set_dst(2)
-                .set_imm(0x32)
-                .push()
-                .mov(Source::Reg, Arch::X64)
-                .set_src(0)
-                .set_dst(1)
-                .push()
-                .swap_bytes(Endian::Big)
-                .set_dst(0)
-                .set_imm(0x10)
-                .push()
-                .negate(Arch::X64)
-                .set_dst(2)
-                .push()
-                .exit()
-                .push();
-
-            let bytecode = program.into_bytes();
-            let ref_prog = &[
-                0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xb7, 0x02, 0x00, 0x00, 0x32, 0x00,
-                0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
-                0x10, 0x00, 0x00, 0x00, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            ];
-            // cargo says: "`[{integer}; 48]` cannot be formatted using `{:?}`
-            //              because it doesn't implement `std::fmt::Debug`"
-            // So let's check in two steps.
-            assert_eq!(bytecode[..32], ref_prog[..32]);
-            assert_eq!(bytecode[33..], ref_prog[33..]);
-        }
-    }
-}

+ 0 - 708
kernel/crates/rbpf/src/interpreter.rs

@@ -1,708 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Derived from uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-//      (uBPF: VM architecture, parts of the interpreter, originally in C)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-//      (Translation to Rust, MetaBuff/multiple classes addition, hashmaps for helpers)
-
-use crate::{
-    ebpf::{self, Insn},
-    helpers::BPF_FUNC_MAPPER,
-    stack::StackFrame,
-    *,
-};
-
-#[cfg(not(feature = "user"))]
-#[allow(unused)]
-fn check_mem(
-    addr: u64,
-    len: usize,
-    access_type: &str,
-    insn_ptr: usize,
-    mbuff: &[u8],
-    mem: &[u8],
-    stack: &[u8],
-) -> Result<(), Error> {
-    log::trace!(
-        "check_mem: addr {:#x}, len {}, access_type {}, insn_ptr {}",
-        addr,
-        len,
-        access_type,
-        insn_ptr
-    );
-    log::trace!(
-        "check_mem: mbuff: {:#x}/{:#x}, mem: {:#x}/{:#x}, stack: {:#x}/{:#x}",
-        mbuff.as_ptr() as u64,
-        mbuff.len(),
-        mem.as_ptr() as u64,
-        mem.len(),
-        stack.as_ptr() as u64,
-        stack.len()
-    );
-    Ok(())
-}
-
-#[cfg(feature = "user")]
-fn check_mem(
-    addr: u64,
-    len: usize,
-    access_type: &str,
-    insn_ptr: usize,
-    mbuff: &[u8],
-    mem: &[u8],
-    stack: &[u8],
-) -> Result<(), Error> {
-    if let Some(addr_end) = addr.checked_add(len as u64) {
-        if mbuff.as_ptr() as u64 <= addr && addr_end <= mbuff.as_ptr() as u64 + mbuff.len() as u64 {
-            return Ok(());
-        }
-        if mem.as_ptr() as u64 <= addr && addr_end <= mem.as_ptr() as u64 + mem.len() as u64 {
-            return Ok(());
-        }
-        if stack.as_ptr() as u64 <= addr && addr_end <= stack.as_ptr() as u64 + stack.len() as u64 {
-            return Ok(());
-        }
-    }
-
-    Err(Error::new(ErrorKind::Other, format!(
-        "Error: out of bounds memory {} (insn #{:?}), addr {:#x}, size {:?}\nmbuff: {:#x}/{:#x}, mem: {:#x}/{:#x}, stack: {:#x}/{:#x}",
-        access_type, insn_ptr, addr, len,
-        mbuff.as_ptr() as u64, mbuff.len(),
-        mem.as_ptr() as u64, mem.len(),
-        stack.as_ptr() as u64, stack.len()
-    )))
-}
-
-#[inline]
-fn do_jump(insn_ptr: &mut usize, insn: &Insn) {
-    *insn_ptr = (*insn_ptr as i16 + insn.off) as usize;
-}
-
-#[allow(unknown_lints)]
-#[allow(cyclomatic_complexity)]
-pub fn execute_program(
-    prog_: Option<&[u8]>,
-    mem: &[u8],
-    mbuff: &[u8],
-    helpers: &HashMap<u32, ebpf::Helper>,
-) -> Result<u64, Error> {
-    const U32MAX: u64 = u32::MAX as u64;
-    const SHIFT_MASK_64: u64 = 0x3f;
-
-    let prog = match prog_ {
-        Some(prog) => prog,
-        None => Err(Error::new(
-            ErrorKind::Other,
-            "Error: No program set, call prog_set() to load one",
-        ))?,
-    };
-    let mut stacks = Vec::new();
-    let stack = StackFrame::new();
-    // R1 points to beginning of memory area, R10 to stack
-    let mut reg: [u64; 11] = [
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        stack.as_ptr() as u64 + stack.len() as u64,
-    ];
-    stacks.push(stack);
-    if !mbuff.is_empty() {
-        reg[1] = mbuff.as_ptr() as u64;
-    } else if !mem.is_empty() {
-        reg[1] = mem.as_ptr() as u64;
-    }
-    let check_mem_load =
-        |stack: &[u8], addr: u64, len: usize, insn_ptr: usize| -> Result<(), Error> {
-            check_mem(addr, len, "load", insn_ptr, mbuff, mem, stack)
-        };
-    let check_mem_store =
-        |stack: &[u8], addr: u64, len: usize, insn_ptr: usize| -> Result<(), Error> {
-            check_mem(addr, len, "store", insn_ptr, mbuff, mem, stack)
-        };
-
-    // Loop on instructions
-    let mut insn_ptr: usize = 0;
-    while insn_ptr * ebpf::INSN_SIZE < prog.len() {
-        let insn = ebpf::get_insn(prog, insn_ptr);
-        insn_ptr += 1;
-        let _dst = insn.dst as usize;
-        let _src = insn.src as usize;
-
-        match insn.opc {
-            // BPF_LD class
-            // LD_ABS_* and LD_IND_* are supposed to load pointer to data from metadata buffer.
-            // Since this pointer is constant, and since we already know it (mem), do not
-            // bother re-fetching it, just use mem already.
-            ebpf::LD_ABS_B => {
-                reg[0] = unsafe {
-                    let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u8;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_ABS_H => {
-                reg[0] = unsafe {
-                    let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u16;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_ABS_W => {
-                reg[0] = unsafe {
-                    let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u32;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_ABS_DW => {
-                log::info!("executing LD_ABS_DW, set reg[{}] to {:#x}", _dst, insn.imm);
-                reg[0] = unsafe {
-                    let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u64;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned()
-                }
-            }
-            ebpf::LD_IND_B => {
-                reg[0] = unsafe {
-                    let x =
-                        (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u8;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_IND_H => {
-                reg[0] = unsafe {
-                    let x =
-                        (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u16;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_IND_W => {
-                reg[0] = unsafe {
-                    let x =
-                        (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u32;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_IND_DW => {
-                reg[0] = unsafe {
-                    let x =
-                        (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u64;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned()
-                }
-            }
-
-            ebpf::LD_DW_IMM => {
-                let next_insn = ebpf::get_insn(prog, insn_ptr);
-                insn_ptr += 1;
-                // log::warn!(
-                //     "executing LD_DW_IMM, set reg[{}] to {:#x}",
-                //     _dst,
-                //     ((insn.imm as u32) as u64) + ((next_insn.imm as u64) << 32)
-                // );
-                reg[_dst] = ((insn.imm as u32) as u64) + ((next_insn.imm as u64) << 32);
-            }
-
-            // BPF_LDX class
-            ebpf::LD_B_REG => {
-                reg[_dst] = unsafe {
-                    #[allow(clippy::cast_ptr_alignment)]
-                    let x = (reg[_src] as *const u8).offset(insn.off as isize);
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 1, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_H_REG => {
-                reg[_dst] = unsafe {
-                    #[allow(clippy::cast_ptr_alignment)]
-                    let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u16;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 2, insn_ptr)?;
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_W_REG => {
-                reg[_dst] = unsafe {
-                    #[allow(clippy::cast_ptr_alignment)]
-                    let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u32;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 4, insn_ptr)?;
-                    // log::warn!(
-                    //     "executing LD_W_REG, the ptr is REG:{} -> [{:#x}] + {:#x}",
-                    //     _src,
-                    //     reg[_src],
-                    //     insn.off
-                    // );
-                    x.read_unaligned() as u64
-                }
-            }
-            ebpf::LD_DW_REG => {
-                reg[_dst] = unsafe {
-                    #[allow(clippy::cast_ptr_alignment)]
-                    let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u64;
-                    check_mem_load(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                    x.read_unaligned()
-                }
-            }
-
-            // BPF_ST class
-            ebpf::ST_B_IMM => unsafe {
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 1, insn_ptr)?;
-                x.write_unaligned(insn.imm as u8);
-            },
-            ebpf::ST_H_IMM => unsafe {
-                #[allow(clippy::cast_ptr_alignment)]
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 2, insn_ptr)?;
-                x.write_unaligned(insn.imm as u16);
-            },
-            ebpf::ST_W_IMM => unsafe {
-                #[allow(clippy::cast_ptr_alignment)]
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 4, insn_ptr)?;
-                x.write_unaligned(insn.imm as u32);
-            },
-            ebpf::ST_DW_IMM => unsafe {
-                #[allow(clippy::cast_ptr_alignment)]
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                x.write_unaligned(insn.imm as u64);
-            },
-
-            // BPF_STX class
-            ebpf::ST_B_REG => unsafe {
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 1, insn_ptr)?;
-                x.write_unaligned(reg[_src] as u8);
-            },
-            ebpf::ST_H_REG => unsafe {
-                #[allow(clippy::cast_ptr_alignment)]
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 2, insn_ptr)?;
-                x.write_unaligned(reg[_src] as u16);
-            },
-            ebpf::ST_W_REG => unsafe {
-                #[allow(clippy::cast_ptr_alignment)]
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 4, insn_ptr)?;
-                x.write_unaligned(reg[_src] as u32);
-            },
-            ebpf::ST_DW_REG => unsafe {
-                #[allow(clippy::cast_ptr_alignment)]
-                let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
-                check_mem_store(stacks.last().unwrap().as_slice(), x as u64, 8, insn_ptr)?;
-                x.write_unaligned(reg[_src]);
-            },
-            ebpf::ST_W_XADD => unimplemented!(),
-            ebpf::ST_DW_XADD => unimplemented!(),
-
-            // BPF_ALU class
-            // TODO Check how overflow works in kernel. Should we &= U32MAX all src register value
-            // before we do the operation?
-            // Cf ((0x11 << 32) - (0x1 << 32)) as u32 VS ((0x11 << 32) as u32 - (0x1 << 32) as u32
-            ebpf::ADD32_IMM => reg[_dst] = (reg[_dst] as i32).wrapping_add(insn.imm) as u64, //((reg[_dst] & U32MAX) + insn.imm  as u64)     & U32MAX,
-            ebpf::ADD32_REG => reg[_dst] = (reg[_dst] as i32).wrapping_add(reg[_src] as i32) as u64, //((reg[_dst] & U32MAX) + (reg[_src] & U32MAX)) & U32MAX,
-            ebpf::SUB32_IMM => reg[_dst] = (reg[_dst] as i32).wrapping_sub(insn.imm) as u64,
-            ebpf::SUB32_REG => reg[_dst] = (reg[_dst] as i32).wrapping_sub(reg[_src] as i32) as u64,
-            ebpf::MUL32_IMM => reg[_dst] = (reg[_dst] as i32).wrapping_mul(insn.imm) as u64,
-            ebpf::MUL32_REG => reg[_dst] = (reg[_dst] as i32).wrapping_mul(reg[_src] as i32) as u64,
-            ebpf::DIV32_IMM if insn.imm as u32 == 0 => reg[_dst] = 0,
-            ebpf::DIV32_IMM => reg[_dst] = (reg[_dst] as u32 / insn.imm as u32) as u64,
-            ebpf::DIV32_REG if reg[_src] as u32 == 0 => reg[_dst] = 0,
-            ebpf::DIV32_REG => reg[_dst] = (reg[_dst] as u32 / reg[_src] as u32) as u64,
-            ebpf::OR32_IMM => reg[_dst] = (reg[_dst] as u32 | insn.imm as u32) as u64,
-            ebpf::OR32_REG => reg[_dst] = (reg[_dst] as u32 | reg[_src] as u32) as u64,
-            ebpf::AND32_IMM => reg[_dst] = (reg[_dst] as u32 & insn.imm as u32) as u64,
-            ebpf::AND32_REG => reg[_dst] = (reg[_dst] as u32 & reg[_src] as u32) as u64,
-            // As for the 64-bit version, we should mask the number of bits to shift with
-            // 0x1f, but .wrappping_shr() already takes care of it for us.
-            ebpf::LSH32_IMM => reg[_dst] = (reg[_dst] as u32).wrapping_shl(insn.imm as u32) as u64,
-            ebpf::LSH32_REG => reg[_dst] = (reg[_dst] as u32).wrapping_shl(reg[_src] as u32) as u64,
-            ebpf::RSH32_IMM => reg[_dst] = (reg[_dst] as u32).wrapping_shr(insn.imm as u32) as u64,
-            ebpf::RSH32_REG => reg[_dst] = (reg[_dst] as u32).wrapping_shr(reg[_src] as u32) as u64,
-            ebpf::NEG32 => {
-                reg[_dst] = (reg[_dst] as i32).wrapping_neg() as u64;
-                reg[_dst] &= U32MAX;
-            }
-            ebpf::MOD32_IMM if insn.imm as u32 == 0 => (),
-            ebpf::MOD32_IMM => reg[_dst] = (reg[_dst] as u32 % insn.imm as u32) as u64,
-            ebpf::MOD32_REG if reg[_src] as u32 == 0 => (),
-            ebpf::MOD32_REG => reg[_dst] = (reg[_dst] as u32 % reg[_src] as u32) as u64,
-            ebpf::XOR32_IMM => reg[_dst] = (reg[_dst] as u32 ^ insn.imm as u32) as u64,
-            ebpf::XOR32_REG => reg[_dst] = (reg[_dst] as u32 ^ reg[_src] as u32) as u64,
-            ebpf::MOV32_IMM => reg[_dst] = insn.imm as u32 as u64,
-            ebpf::MOV32_REG => reg[_dst] = (reg[_src] as u32) as u64,
-            // As for the 64-bit version, we should mask the number of bits to shift with
-            // 0x1f, but .wrappping_shr() already takes care of it for us.
-            ebpf::ARSH32_IMM => {
-                reg[_dst] = (reg[_dst] as i32).wrapping_shr(insn.imm as u32) as u64;
-                reg[_dst] &= U32MAX;
-            }
-            ebpf::ARSH32_REG => {
-                reg[_dst] = (reg[_dst] as i32).wrapping_shr(reg[_src] as u32) as u64;
-                reg[_dst] &= U32MAX;
-            }
-            ebpf::LE => {
-                reg[_dst] = match insn.imm {
-                    16 => (reg[_dst] as u16).to_le() as u64,
-                    32 => (reg[_dst] as u32).to_le() as u64,
-                    64 => reg[_dst].to_le(),
-                    _ => unreachable!(),
-                };
-            }
-            ebpf::BE => {
-                reg[_dst] = match insn.imm {
-                    16 => (reg[_dst] as u16).to_be() as u64,
-                    32 => (reg[_dst] as u32).to_be() as u64,
-                    64 => reg[_dst].to_be(),
-                    _ => unreachable!(),
-                };
-            }
-
-            // BPF_ALU64 class
-            ebpf::ADD64_IMM => reg[_dst] = reg[_dst].wrapping_add(insn.imm as u64),
-            ebpf::ADD64_REG => reg[_dst] = reg[_dst].wrapping_add(reg[_src]),
-            ebpf::SUB64_IMM => reg[_dst] = reg[_dst].wrapping_sub(insn.imm as u64),
-            ebpf::SUB64_REG => reg[_dst] = reg[_dst].wrapping_sub(reg[_src]),
-            ebpf::MUL64_IMM => reg[_dst] = reg[_dst].wrapping_mul(insn.imm as u64),
-            ebpf::MUL64_REG => reg[_dst] = reg[_dst].wrapping_mul(reg[_src]),
-            ebpf::DIV64_IMM if insn.imm == 0 => reg[_dst] = 0,
-            ebpf::DIV64_IMM => reg[_dst] /= insn.imm as u64,
-            ebpf::DIV64_REG if reg[_src] == 0 => reg[_dst] = 0,
-            ebpf::DIV64_REG => reg[_dst] /= reg[_src],
-            ebpf::OR64_IMM => reg[_dst] |= insn.imm as u64,
-            ebpf::OR64_REG => reg[_dst] |= reg[_src],
-            ebpf::AND64_IMM => reg[_dst] &= insn.imm as u64,
-            ebpf::AND64_REG => reg[_dst] &= reg[_src],
-            ebpf::LSH64_IMM => reg[_dst] <<= insn.imm as u64 & SHIFT_MASK_64,
-            ebpf::LSH64_REG => reg[_dst] <<= reg[_src] & SHIFT_MASK_64,
-            ebpf::RSH64_IMM => reg[_dst] >>= insn.imm as u64 & SHIFT_MASK_64,
-            ebpf::RSH64_REG => reg[_dst] >>= reg[_src] & SHIFT_MASK_64,
-            ebpf::NEG64 => reg[_dst] = -(reg[_dst] as i64) as u64,
-            ebpf::MOD64_IMM if insn.imm == 0 => (),
-            ebpf::MOD64_IMM => reg[_dst] %= insn.imm as u64,
-            ebpf::MOD64_REG if reg[_src] == 0 => (),
-            ebpf::MOD64_REG => reg[_dst] %= reg[_src],
-            ebpf::XOR64_IMM => reg[_dst] ^= insn.imm as u64,
-            ebpf::XOR64_REG => reg[_dst] ^= reg[_src],
-            ebpf::MOV64_IMM => reg[_dst] = insn.imm as u64,
-            ebpf::MOV64_REG => reg[_dst] = reg[_src],
-            ebpf::ARSH64_IMM => {
-                reg[_dst] = (reg[_dst] as i64 >> (insn.imm as u64 & SHIFT_MASK_64)) as u64
-            }
-            ebpf::ARSH64_REG => {
-                reg[_dst] = (reg[_dst] as i64 >> (reg[_src] as u64 & SHIFT_MASK_64)) as u64
-            }
-
-            // BPF_JMP class
-            // TODO: check this actually works as expected for signed / unsigned ops
-            ebpf::JA => do_jump(&mut insn_ptr, &insn),
-            ebpf::JEQ_IMM => {
-                if reg[_dst] == insn.imm as u64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JEQ_REG => {
-                if reg[_dst] == reg[_src] {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGT_IMM => {
-                if reg[_dst] > insn.imm as u64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGT_REG => {
-                if reg[_dst] > reg[_src] {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGE_IMM => {
-                if reg[_dst] >= insn.imm as u64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGE_REG => {
-                if reg[_dst] >= reg[_src] {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLT_IMM => {
-                if reg[_dst] < insn.imm as u64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLT_REG => {
-                if reg[_dst] < reg[_src] {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLE_IMM => {
-                if reg[_dst] <= insn.imm as u64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLE_REG => {
-                if reg[_dst] <= reg[_src] {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSET_IMM => {
-                if reg[_dst] & insn.imm as u64 != 0 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSET_REG => {
-                if reg[_dst] & reg[_src] != 0 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JNE_IMM => {
-                if reg[_dst] != insn.imm as u64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JNE_REG => {
-                if reg[_dst] != reg[_src] {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGT_IMM => {
-                if reg[_dst] as i64 > insn.imm as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGT_REG => {
-                if reg[_dst] as i64 > reg[_src] as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGE_IMM => {
-                if reg[_dst] as i64 >= insn.imm as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGE_REG => {
-                if reg[_dst] as i64 >= reg[_src] as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLT_IMM => {
-                if (reg[_dst] as i64) < insn.imm as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLT_REG => {
-                if (reg[_dst] as i64) < reg[_src] as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLE_IMM => {
-                if reg[_dst] as i64 <= insn.imm as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLE_REG => {
-                if reg[_dst] as i64 <= reg[_src] as i64 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-
-            // BPF_JMP32 class
-            ebpf::JEQ_IMM32 => {
-                if reg[_dst] as u32 == insn.imm as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JEQ_REG32 => {
-                if reg[_dst] as u32 == reg[_src] as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGT_IMM32 => {
-                if reg[_dst] as u32 > insn.imm as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGT_REG32 => {
-                if reg[_dst] as u32 > reg[_src] as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGE_IMM32 => {
-                if reg[_dst] as u32 >= insn.imm as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JGE_REG32 => {
-                if reg[_dst] as u32 >= reg[_src] as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLT_IMM32 => {
-                if (reg[_dst] as u32) < insn.imm as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLT_REG32 => {
-                if (reg[_dst] as u32) < reg[_src] as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLE_IMM32 => {
-                if reg[_dst] as u32 <= insn.imm as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JLE_REG32 => {
-                if reg[_dst] as u32 <= reg[_src] as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSET_IMM32 => {
-                if reg[_dst] as u32 & insn.imm as u32 != 0 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSET_REG32 => {
-                if reg[_dst] as u32 & reg[_src] as u32 != 0 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JNE_IMM32 => {
-                if reg[_dst] as u32 != insn.imm as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JNE_REG32 => {
-                if reg[_dst] as u32 != reg[_src] as u32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGT_IMM32 => {
-                if reg[_dst] as i32 > insn.imm {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGT_REG32 => {
-                if reg[_dst] as i32 > reg[_src] as i32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGE_IMM32 => {
-                if reg[_dst] as i32 >= insn.imm {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSGE_REG32 => {
-                if reg[_dst] as i32 >= reg[_src] as i32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLT_IMM32 => {
-                if (reg[_dst] as i32) < insn.imm {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLT_REG32 => {
-                if (reg[_dst] as i32) < reg[_src] as i32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLE_IMM32 => {
-                if reg[_dst] as i32 <= insn.imm {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-            ebpf::JSLE_REG32 => {
-                if reg[_dst] as i32 <= reg[_src] as i32 {
-                    do_jump(&mut insn_ptr, &insn);
-                }
-            }
-
-            // Do not delegate the check to the verifier, since registered functions can be
-            // changed after the program has been verified.
-            ebpf::CALL => {
-                // See https://www.kernel.org/doc/html/latest/bpf/standardization/instruction-set.html#id16
-                let src_reg = _src;
-                let call_func_res = match src_reg {
-                    0 => {
-                        // Handle call by address to external function.
-                        if let Some(function) = helpers.get(&(insn.imm as u32)) {
-                            reg[0] = function(reg[1], reg[2], reg[3], reg[4], reg[5]);
-                            Ok(())
-                        }else {
-                            Err(format!(
-                                "Error: unknown helper function (id: {:#x}) [{}], (instruction #{})",
-                                insn.imm as u32,BPF_FUNC_MAPPER[insn.imm as usize],insn_ptr
-                            ))
-                        }
-                    }
-                    1 => {
-                        // bpf to bpf call
-                        // The function is in the same program, so we can just jump to the address
-                        if stacks.len() >= ebpf::RBPF_MAX_CALL_DEPTH{
-                            Err(format!(
-                                "Error: bpf to bpf call stack limit reached (instruction #{}) max depth: {}",
-                                insn_ptr, ebpf::RBPF_MAX_CALL_DEPTH
-                            ))
-                        }else {
-                            let mut pre_stack = stacks.last_mut().unwrap();
-                            // Save the callee saved registers
-                            pre_stack.save_registers(&reg[6..=9]);
-                            // Save the return address
-                            pre_stack.save_return_address(insn_ptr as u64);
-                            // save the stack pointer
-                            pre_stack.save_sp(reg[10]);
-                            let mut stack = StackFrame::new();
-                            log::trace!("BPF TO BPF CALL: new pc: {} + {} = {}",insn_ptr ,insn.imm,insn_ptr + insn.imm as usize);
-                            reg[10] = stack.as_ptr() as u64 + stack.len() as u64;
-                            stacks.push(stack);
-                            insn_ptr += insn.imm as usize;
-                            Ok(())
-                        }
-                    }
-                    _ =>{
-                        Err(format!(
-                            "Error: the function call type (id: {:#x}) [{}], (instruction #{}) not supported",
-                            insn.imm as u32,BPF_FUNC_MAPPER[insn.imm as usize],insn_ptr
-                        ))
-                    }
-                };
-                if let Err(e) = call_func_res {
-                    Err(Error::new(ErrorKind::Other, e))?;
-                }
-            }
-            ebpf::TAIL_CALL => unimplemented!(),
-            ebpf::EXIT => {
-                if stacks.len() == 1 {
-                    return Ok(reg[0]);
-                } else {
-                    // Pop the stack
-                    stacks.pop();
-                    let stack = stacks.last().unwrap();
-                    // Restore the callee saved registers
-                    reg[6..=9].copy_from_slice(&stack.get_registers());
-                    // Restore the return address
-                    insn_ptr = stack.get_return_address() as usize;
-                    // Restore the stack pointer
-                    reg[10] = stack.get_sp();
-                    log::trace!("EXIT: new pc: {}", insn_ptr);
-                }
-            }
-
-            _ => unreachable!(),
-        }
-    }
-
-    unreachable!()
-}

+ 0 - 1054
kernel/crates/rbpf/src/jit.rs

@@ -1,1054 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Derived from uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-//      (uBPF: JIT algorithm, originally in C)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-//      (Translation to Rust, MetaBuff addition)
-
-use std::{
-    fmt::{Error as FormatterError, Formatter},
-    io::{Error, ErrorKind},
-    mem,
-    ops::{Index, IndexMut},
-};
-
-use crate::{ebpf, HashMap};
-
-extern crate libc;
-
-type MachineCode = unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64;
-
-const PAGE_SIZE: usize = 4096;
-// TODO: check how long the page must be to be sure to support an eBPF program of maximum possible
-// length
-const NUM_PAGES: usize = 1;
-
-// Special values for target_pc in struct Jump
-const TARGET_OFFSET: isize = ebpf::PROG_MAX_INSNS as isize;
-const TARGET_PC_EXIT: isize = TARGET_OFFSET + 1;
-
-#[derive(Copy, Clone)]
-enum OperandSize {
-    S8 = 8,
-    S16 = 16,
-    S32 = 32,
-    S64 = 64,
-}
-
-// Registers
-const RAX: u8 = 0;
-const RCX: u8 = 1;
-const RDX: u8 = 2;
-const RBX: u8 = 3;
-const RSP: u8 = 4;
-const RBP: u8 = 5;
-const RSI: u8 = 6;
-const RDI: u8 = 7;
-const R8: u8 = 8;
-const R9: u8 = 9;
-const R10: u8 = 10;
-const R11: u8 = 11;
-//const R12: u8 = 12;
-const R13: u8 = 13;
-const R14: u8 = 14;
-const R15: u8 = 15;
-
-const REGISTER_MAP_SIZE: usize = 11;
-const REGISTER_MAP: [u8; REGISTER_MAP_SIZE] = [
-    RAX, // 0  return value
-    RDI, // 1  arg 1
-    RSI, // 2  arg 2
-    RDX, // 3  arg 3
-    R9,  // 4  arg 4
-    R8,  // 5  arg 5
-    RBX, // 6  callee-saved
-    R13, // 7  callee-saved
-    R14, // 8  callee-saved
-    R15, // 9  callee-saved
-    RBP, // 10 stack pointer
-         // R10 and R11 are used to compute store a constant pointer to mem and to compute offset for
-         // LD_ABS_* and LD_IND_* operations, so they are not mapped to any eBPF register.
-];
-
-// Return the x86 register for the given eBPF register
-fn map_register(r: u8) -> u8 {
-    assert!(r < REGISTER_MAP_SIZE as u8);
-    REGISTER_MAP[(r % REGISTER_MAP_SIZE as u8) as usize]
-}
-
-macro_rules! emit_bytes {
-    ( $mem:ident, $data:tt, $t:ty ) => {{
-        let size = mem::size_of::<$t>() as usize;
-        assert!($mem.offset + size <= $mem.contents.len());
-        unsafe {
-            let mut ptr = $mem.contents.as_ptr().add($mem.offset) as *mut $t;
-            ptr.write_unaligned($data);
-        }
-        $mem.offset += size;
-    }};
-}
-
-#[derive(Debug)]
-struct Jump {
-    offset_loc: usize,
-    target_pc: isize,
-}
-
-#[derive(Debug)]
-struct JitCompiler {
-    pc_locs: Vec<usize>,
-    special_targets: HashMap<isize, usize>,
-    jumps: Vec<Jump>,
-}
-
-impl JitCompiler {
-    fn new() -> JitCompiler {
-        JitCompiler {
-            pc_locs: vec![],
-            jumps: vec![],
-            special_targets: HashMap::new(),
-        }
-    }
-
-    fn emit1(&self, mem: &mut JitMemory, data: u8) {
-        emit_bytes!(mem, data, u8);
-    }
-
-    fn emit2(&self, mem: &mut JitMemory, data: u16) {
-        emit_bytes!(mem, data, u16);
-    }
-
-    fn emit4(&self, mem: &mut JitMemory, data: u32) {
-        emit_bytes!(mem, data, u32);
-    }
-
-    fn emit8(&self, mem: &mut JitMemory, data: u64) {
-        emit_bytes!(mem, data, u64);
-    }
-
-    fn emit_modrm(&self, mem: &mut JitMemory, modrm: u8, r: u8, m: u8) {
-        assert_eq!((modrm | 0xc0), 0xc0);
-        self.emit1(mem, (modrm & 0xc0) | ((r & 0b111) << 3) | (m & 0b111));
-    }
-
-    fn emit_modrm_reg2reg(&self, mem: &mut JitMemory, r: u8, m: u8) {
-        self.emit_modrm(mem, 0xc0, r, m);
-    }
-
-    fn emit_modrm_and_displacement(&self, mem: &mut JitMemory, r: u8, m: u8, d: i32) {
-        if d == 0 && (m & 0b111) != RBP {
-            self.emit_modrm(mem, 0x00, r, m);
-        } else if (-128..=127).contains(&d) {
-            self.emit_modrm(mem, 0x40, r, m);
-            self.emit1(mem, d as u8);
-        } else {
-            self.emit_modrm(mem, 0x80, r, m);
-            self.emit4(mem, d as u32);
-        }
-    }
-
-    fn basix_rex_would_set_bits(&self, w: u8, src: u8, dst: u8) -> bool {
-        w != 0 || (src & 0b1000) != 0 || (dst & 0b1000) != 0
-    }
-
-    fn emit_rex(&self, mem: &mut JitMemory, w: u8, r: u8, x: u8, b: u8) {
-        assert_eq!((w | 1), 1);
-        assert_eq!((r | 1), 1);
-        assert_eq!((x | 1), 1);
-        assert_eq!((b | 1), 1);
-        self.emit1(mem, 0x40 | (w << 3) | (r << 2) | (x << 1) | b);
-    }
-
-    // Emits a REX prefix with the top bit of src and dst.
-    // Skipped if no bits would be set.
-    fn emit_basic_rex(&self, mem: &mut JitMemory, w: u8, src: u8, dst: u8) {
-        if self.basix_rex_would_set_bits(w, src, dst) {
-            let is_masked = |val, mask| match val & mask {
-                0 => 0,
-                _ => 1,
-            };
-            self.emit_rex(mem, w, is_masked(src, 8), 0, is_masked(dst, 8));
-        }
-    }
-
-    fn emit_push(&self, mem: &mut JitMemory, r: u8) {
-        self.emit_basic_rex(mem, 0, 0, r);
-        self.emit1(mem, 0x50 | (r & 0b111));
-    }
-
-    fn emit_pop(&self, mem: &mut JitMemory, r: u8) {
-        self.emit_basic_rex(mem, 0, 0, r);
-        self.emit1(mem, 0x58 | (r & 0b111));
-    }
-
-    // REX prefix and ModRM byte
-    // We use the MR encoding when there is a choice
-    // 'src' is often used as an opcode extension
-    fn emit_alu32(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8) {
-        self.emit_basic_rex(mem, 0, src, dst);
-        self.emit1(mem, op);
-        self.emit_modrm_reg2reg(mem, src, dst);
-    }
-
-    // REX prefix, ModRM byte, and 32-bit immediate
-    fn emit_alu32_imm32(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
-        self.emit_alu32(mem, op, src, dst);
-        self.emit4(mem, imm as u32);
-    }
-
-    // REX prefix, ModRM byte, and 8-bit immediate
-    fn emit_alu32_imm8(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
-        self.emit_alu32(mem, op, src, dst);
-        self.emit1(mem, imm as u8);
-    }
-
-    // REX.W prefix and ModRM byte
-    // We use the MR encoding when there is a choice
-    // 'src' is often used as an opcode extension
-    fn emit_alu64(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8) {
-        self.emit_basic_rex(mem, 1, src, dst);
-        self.emit1(mem, op);
-        self.emit_modrm_reg2reg(mem, src, dst);
-    }
-
-    // REX.W prefix, ModRM byte, and 32-bit immediate
-    fn emit_alu64_imm32(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
-        self.emit_alu64(mem, op, src, dst);
-        self.emit4(mem, imm as u32);
-    }
-
-    // REX.W prefix, ModRM byte, and 8-bit immediate
-    fn emit_alu64_imm8(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
-        self.emit_alu64(mem, op, src, dst);
-        self.emit1(mem, imm as u8);
-    }
-
-    // Register to register mov
-    fn emit_mov(&self, mem: &mut JitMemory, src: u8, dst: u8) {
-        self.emit_alu64(mem, 0x89, src, dst);
-    }
-
-    fn emit_cmp_imm32(&self, mem: &mut JitMemory, dst: u8, imm: i32) {
-        self.emit_alu64_imm32(mem, 0x81, 7, dst, imm);
-    }
-
-    fn emit_cmp(&self, mem: &mut JitMemory, src: u8, dst: u8) {
-        self.emit_alu64(mem, 0x39, src, dst);
-    }
-
-    fn emit_cmp32_imm32(&self, mem: &mut JitMemory, dst: u8, imm: i32) {
-        self.emit_alu32_imm32(mem, 0x81, 7, dst, imm);
-    }
-
-    fn emit_cmp32(&self, mem: &mut JitMemory, src: u8, dst: u8) {
-        self.emit_alu32(mem, 0x39, src, dst);
-    }
-
-    // Load [src + offset] into dst
-    fn emit_load(&self, mem: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
-        let data = match size {
-            OperandSize::S64 => 1,
-            _ => 0,
-        };
-        self.emit_basic_rex(mem, data, dst, src);
-
-        match size {
-            OperandSize::S8 => {
-                // movzx
-                self.emit1(mem, 0x0f);
-                self.emit1(mem, 0xb6);
-            }
-            OperandSize::S16 => {
-                // movzx
-                self.emit1(mem, 0x0f);
-                self.emit1(mem, 0xb7);
-            }
-            OperandSize::S32 | OperandSize::S64 => {
-                // mov
-                self.emit1(mem, 0x8b);
-            }
-        }
-
-        self.emit_modrm_and_displacement(mem, dst, src, offset);
-    }
-
-    // Load sign-extended immediate into register
-    fn emit_load_imm(&self, mem: &mut JitMemory, dst: u8, imm: i64) {
-        if imm >= i32::MIN as i64 && imm <= i32::MAX as i64 {
-            self.emit_alu64_imm32(mem, 0xc7, 0, dst, imm as i32);
-        } else {
-            // movabs $imm,dst
-            self.emit_basic_rex(mem, 1, 0, dst);
-            self.emit1(mem, 0xb8 | (dst & 0b111));
-            self.emit8(mem, imm as u64);
-        }
-    }
-
-    // Store register src to [dst + offset]
-    fn emit_store(&self, mem: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
-        match size {
-            OperandSize::S16 => self.emit1(mem, 0x66), // 16-bit override
-            _ => {}
-        };
-        let (is_s8, is_u64, rexw) = match size {
-            OperandSize::S8 => (true, false, 0),
-            OperandSize::S64 => (false, true, 1),
-            _ => (false, false, 0),
-        };
-        if is_u64 || (src & 0b1000) != 0 || (dst & 0b1000) != 0 || is_s8 {
-            let is_masked = |val, mask| match val & mask {
-                0 => 0,
-                _ => 1,
-            };
-            self.emit_rex(mem, rexw, is_masked(src, 8), 0, is_masked(dst, 8));
-        }
-        match size {
-            OperandSize::S8 => self.emit1(mem, 0x88),
-            _ => self.emit1(mem, 0x89),
-        };
-        self.emit_modrm_and_displacement(mem, src, dst, offset);
-    }
-
-    // Store immediate to [dst + offset]
-    fn emit_store_imm32(
-        &self,
-        mem: &mut JitMemory,
-        size: OperandSize,
-        dst: u8,
-        offset: i32,
-        imm: i32,
-    ) {
-        match size {
-            OperandSize::S16 => self.emit1(mem, 0x66), // 16-bit override
-            _ => {}
-        };
-        match size {
-            OperandSize::S64 => self.emit_basic_rex(mem, 1, 0, dst),
-            _ => self.emit_basic_rex(mem, 0, 0, dst),
-        };
-        match size {
-            OperandSize::S8 => self.emit1(mem, 0xc6),
-            _ => self.emit1(mem, 0xc7),
-        };
-        self.emit_modrm_and_displacement(mem, 0, dst, offset);
-        match size {
-            OperandSize::S8 => self.emit1(mem, imm as u8),
-            OperandSize::S16 => self.emit2(mem, imm as u16),
-            _ => self.emit4(mem, imm as u32),
-        };
-    }
-
-    fn emit_direct_jcc(&self, mem: &mut JitMemory, code: u8, offset: u32) {
-        self.emit1(mem, 0x0f);
-        self.emit1(mem, code);
-        emit_bytes!(mem, offset, u32);
-    }
-
-    fn emit_call(&self, mem: &mut JitMemory, target: usize) {
-        // TODO use direct call when possible
-        self.emit_load_imm(mem, RAX, target as i64);
-        // callq *%rax
-        self.emit1(mem, 0xff);
-        self.emit1(mem, 0xd0);
-    }
-
-    fn emit_jump_offset(&mut self, mem: &mut JitMemory, target_pc: isize) {
-        let jump = Jump {
-            offset_loc: mem.offset,
-            target_pc,
-        };
-        self.jumps.push(jump);
-        self.emit4(mem, 0);
-    }
-
-    fn emit_jcc(&mut self, mem: &mut JitMemory, code: u8, target_pc: isize) {
-        self.emit1(mem, 0x0f);
-        self.emit1(mem, code);
-        self.emit_jump_offset(mem, target_pc);
-    }
-
-    fn emit_jmp(&mut self, mem: &mut JitMemory, target_pc: isize) {
-        self.emit1(mem, 0xe9);
-        self.emit_jump_offset(mem, target_pc);
-    }
-
-    fn set_anchor(&mut self, mem: &mut JitMemory, target: isize) {
-        self.special_targets.insert(target, mem.offset);
-    }
-
-    fn emit_muldivmod(
-        &mut self,
-        mem: &mut JitMemory,
-        pc: u16,
-        opc: u8,
-        src: u8,
-        dst: u8,
-        imm: i32,
-    ) {
-        let mul = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MUL32_IMM & ebpf::BPF_ALU_OP_MASK);
-        let div = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::DIV32_IMM & ebpf::BPF_ALU_OP_MASK);
-        let modrm = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MOD32_IMM & ebpf::BPF_ALU_OP_MASK);
-        let is64 = (opc & ebpf::BPF_CLS_MASK) == ebpf::BPF_ALU64;
-        let is_reg = (opc & ebpf::BPF_X) == ebpf::BPF_X;
-
-        if (div || mul) && !is_reg && imm == 0 {
-            // Division by zero returns 0
-            // Set register to 0: xor with itself
-            self.emit_alu32(mem, 0x31, dst, dst);
-            return;
-        }
-        if modrm && !is_reg && imm == 0 {
-            // Modulo remainder of division by zero keeps destination register unchanged
-            return;
-        }
-        if (div || modrm) && is_reg {
-            self.emit_load_imm(mem, RCX, pc as i64);
-
-            // test src,src
-            if is64 {
-                self.emit_alu64(mem, 0x85, src, src);
-            } else {
-                self.emit_alu32(mem, 0x85, src, src);
-            }
-
-            if div {
-                // No division by 0: skip next instructions
-                // Jump offset: emit_alu32 adds 2 to 3 bytes, emit_jmp adds 5
-                let offset = match self.basix_rex_would_set_bits(0, dst, dst) {
-                    true => 3 + 5,
-                    false => 2 + 5,
-                };
-                self.emit_direct_jcc(mem, 0x85, offset);
-                // Division by 0: set dst to 0 then go to next instruction
-                // Set register to 0: xor with itself
-                self.emit_alu32(mem, 0x31, dst, dst);
-                self.emit_jmp(mem, (pc + 1) as isize);
-            }
-            if modrm {
-                // Modulo by zero: keep destination register unchanged
-                self.emit_jcc(mem, 0x84, (pc + 1) as isize);
-            }
-        }
-
-        if dst != RAX {
-            self.emit_push(mem, RAX);
-        }
-        if dst != RDX {
-            self.emit_push(mem, RDX);
-        }
-        if imm != 0 {
-            self.emit_load_imm(mem, RCX, imm as i64);
-        } else {
-            self.emit_mov(mem, src, RCX);
-        }
-
-        self.emit_mov(mem, dst, RAX);
-
-        if div || modrm {
-            // Set register to 0: xor %edx,%edx
-            self.emit_alu32(mem, 0x31, RDX, RDX);
-        }
-
-        if is64 {
-            self.emit_rex(mem, 1, 0, 0, 0);
-        }
-
-        // mul %ecx or div %ecx
-        self.emit_alu32(mem, 0xf7, if mul { 4 } else { 6 }, RCX);
-
-        if dst != RDX {
-            if modrm {
-                self.emit_mov(mem, RDX, dst);
-            }
-            self.emit_pop(mem, RDX);
-        }
-        if dst != RAX {
-            if div || mul {
-                self.emit_mov(mem, RAX, dst);
-            }
-            self.emit_pop(mem, RAX);
-        }
-    }
-
-    fn jit_compile(
-        &mut self,
-        mem: &mut JitMemory,
-        prog: &[u8],
-        use_mbuff: bool,
-        update_data_ptr: bool,
-        helpers: &HashMap<u32, ebpf::Helper>,
-    ) -> Result<(), Error> {
-        self.emit_push(mem, RBP);
-        self.emit_push(mem, RBX);
-        self.emit_push(mem, R13);
-        self.emit_push(mem, R14);
-        self.emit_push(mem, R15);
-
-        // RDI: mbuff
-        // RSI: mbuff_len
-        // RDX: mem
-        // RCX: mem_len
-        // R8:  mem_offset
-        // R9:  mem_end_offset
-
-        // Save mem pointer for use with LD_ABS_* and LD_IND_* instructions
-        self.emit_mov(mem, RDX, R10);
-
-        match (use_mbuff, update_data_ptr) {
-            (false, _) => {
-                // We do not use any mbuff. Move mem pointer into register 1.
-                if map_register(1) != RDX {
-                    self.emit_mov(mem, RDX, map_register(1));
-                }
-            }
-            (true, false) => {
-                // We use a mbuff already pointing to mem and mem_end: move it to register 1.
-                if map_register(1) != RDI {
-                    self.emit_mov(mem, RDI, map_register(1));
-                }
-            }
-            (true, true) => {
-                // We have a fixed (simulated) mbuff: update mem and mem_end offset values in it.
-                // Store mem at mbuff + mem_offset. Trash R8.
-                self.emit_alu64(mem, 0x01, RDI, R8); // add mbuff to mem_offset in R8
-                self.emit_store(mem, OperandSize::S64, RDX, R8, 0); // set mem at mbuff + mem_offset
-                                                                    // Store mem_end at mbuff + mem_end_offset. Trash R9.
-                self.emit_load(mem, OperandSize::S64, RDX, R8, 0); // load mem into R8
-                self.emit_alu64(mem, 0x01, RCX, R8); // add mem_len to mem (= mem_end)
-                self.emit_alu64(mem, 0x01, RDI, R9); // add mbuff to mem_end_offset
-                self.emit_store(mem, OperandSize::S64, R8, R9, 0); // store mem_end
-
-                // Move rdi into register 1
-                if map_register(1) != RDI {
-                    self.emit_mov(mem, RDI, map_register(1));
-                }
-            }
-        }
-
-        // Copy stack pointer to R10
-        self.emit_mov(mem, RSP, map_register(10));
-
-        // Allocate stack space
-        self.emit_alu64_imm32(mem, 0x81, 5, RSP, ebpf::STACK_SIZE as i32);
-
-        self.pc_locs = vec![0; prog.len() / ebpf::INSN_SIZE + 1];
-
-        let mut insn_ptr: usize = 0;
-        while insn_ptr * ebpf::INSN_SIZE < prog.len() {
-            let insn = ebpf::get_insn(prog, insn_ptr);
-
-            self.pc_locs[insn_ptr] = mem.offset;
-
-            let dst = map_register(insn.dst);
-            let src = map_register(insn.src);
-            let target_pc = insn_ptr as isize + insn.off as isize + 1;
-
-            match insn.opc {
-                // BPF_LD class
-                // R10 is a constant pointer to mem.
-                ebpf::LD_ABS_B => self.emit_load(mem, OperandSize::S8, R10, RAX, insn.imm),
-                ebpf::LD_ABS_H => self.emit_load(mem, OperandSize::S16, R10, RAX, insn.imm),
-                ebpf::LD_ABS_W => self.emit_load(mem, OperandSize::S32, R10, RAX, insn.imm),
-                ebpf::LD_ABS_DW => self.emit_load(mem, OperandSize::S64, R10, RAX, insn.imm),
-                ebpf::LD_IND_B => {
-                    self.emit_mov(mem, R10, R11); // load mem into R11
-                    self.emit_alu64(mem, 0x01, src, R11); // add src to R11
-                    self.emit_load(mem, OperandSize::S8, R11, RAX, insn.imm); // ld R0, mem[src+imm]
-                }
-                ebpf::LD_IND_H => {
-                    self.emit_mov(mem, R10, R11); // load mem into R11
-                    self.emit_alu64(mem, 0x01, src, R11); // add src to R11
-                    self.emit_load(mem, OperandSize::S16, R11, RAX, insn.imm); // ld R0, mem[src+imm]
-                }
-                ebpf::LD_IND_W => {
-                    self.emit_mov(mem, R10, R11); // load mem into R11
-                    self.emit_alu64(mem, 0x01, src, R11); // add src to R11
-                    self.emit_load(mem, OperandSize::S32, R11, RAX, insn.imm); // ld R0, mem[src+imm]
-                }
-                ebpf::LD_IND_DW => {
-                    self.emit_mov(mem, R10, R11); // load mem into R11
-                    self.emit_alu64(mem, 0x01, src, R11); // add src to R11
-                    self.emit_load(mem, OperandSize::S64, R11, RAX, insn.imm); // ld R0, mem[src+imm]
-                }
-
-                ebpf::LD_DW_IMM => {
-                    insn_ptr += 1;
-                    let second_part = ebpf::get_insn(prog, insn_ptr).imm as u64;
-                    let imm = (insn.imm as u32) as u64 | second_part.wrapping_shl(32);
-                    self.emit_load_imm(mem, dst, imm as i64);
-                }
-
-                // BPF_LDX class
-                ebpf::LD_B_REG => self.emit_load(mem, OperandSize::S8, src, dst, insn.off as i32),
-                ebpf::LD_H_REG => self.emit_load(mem, OperandSize::S16, src, dst, insn.off as i32),
-                ebpf::LD_W_REG => self.emit_load(mem, OperandSize::S32, src, dst, insn.off as i32),
-                ebpf::LD_DW_REG => self.emit_load(mem, OperandSize::S64, src, dst, insn.off as i32),
-
-                // BPF_ST class
-                ebpf::ST_B_IMM => {
-                    self.emit_store_imm32(mem, OperandSize::S8, dst, insn.off as i32, insn.imm)
-                }
-                ebpf::ST_H_IMM => {
-                    self.emit_store_imm32(mem, OperandSize::S16, dst, insn.off as i32, insn.imm)
-                }
-                ebpf::ST_W_IMM => {
-                    self.emit_store_imm32(mem, OperandSize::S32, dst, insn.off as i32, insn.imm)
-                }
-                ebpf::ST_DW_IMM => {
-                    self.emit_store_imm32(mem, OperandSize::S64, dst, insn.off as i32, insn.imm)
-                }
-
-                // BPF_STX class
-                ebpf::ST_B_REG => self.emit_store(mem, OperandSize::S8, src, dst, insn.off as i32),
-                ebpf::ST_H_REG => self.emit_store(mem, OperandSize::S16, src, dst, insn.off as i32),
-                ebpf::ST_W_REG => self.emit_store(mem, OperandSize::S32, src, dst, insn.off as i32),
-                ebpf::ST_DW_REG => {
-                    self.emit_store(mem, OperandSize::S64, src, dst, insn.off as i32)
-                }
-                ebpf::ST_W_XADD => unimplemented!(),
-                ebpf::ST_DW_XADD => unimplemented!(),
-
-                // BPF_ALU class
-                ebpf::ADD32_IMM => self.emit_alu32_imm32(mem, 0x81, 0, dst, insn.imm),
-                ebpf::ADD32_REG => self.emit_alu32(mem, 0x01, src, dst),
-                ebpf::SUB32_IMM => self.emit_alu32_imm32(mem, 0x81, 5, dst, insn.imm),
-                ebpf::SUB32_REG => self.emit_alu32(mem, 0x29, src, dst),
-                ebpf::MUL32_IMM
-                | ebpf::MUL32_REG
-                | ebpf::DIV32_IMM
-                | ebpf::DIV32_REG
-                | ebpf::MOD32_IMM
-                | ebpf::MOD32_REG => {
-                    self.emit_muldivmod(mem, insn_ptr as u16, insn.opc, src, dst, insn.imm)
-                }
-                ebpf::OR32_IMM => self.emit_alu32_imm32(mem, 0x81, 1, dst, insn.imm),
-                ebpf::OR32_REG => self.emit_alu32(mem, 0x09, src, dst),
-                ebpf::AND32_IMM => self.emit_alu32_imm32(mem, 0x81, 4, dst, insn.imm),
-                ebpf::AND32_REG => self.emit_alu32(mem, 0x21, src, dst),
-                ebpf::LSH32_IMM => self.emit_alu32_imm8(mem, 0xc1, 4, dst, insn.imm as i8),
-                ebpf::LSH32_REG => {
-                    self.emit_mov(mem, src, RCX);
-                    self.emit_alu32(mem, 0xd3, 4, dst);
-                }
-                ebpf::RSH32_IMM => self.emit_alu32_imm8(mem, 0xc1, 5, dst, insn.imm as i8),
-                ebpf::RSH32_REG => {
-                    self.emit_mov(mem, src, RCX);
-                    self.emit_alu32(mem, 0xd3, 5, dst);
-                }
-                ebpf::NEG32 => self.emit_alu32(mem, 0xf7, 3, dst),
-                ebpf::XOR32_IMM => self.emit_alu32_imm32(mem, 0x81, 6, dst, insn.imm),
-                ebpf::XOR32_REG => self.emit_alu32(mem, 0x31, src, dst),
-                ebpf::MOV32_IMM => self.emit_alu32_imm32(mem, 0xc7, 0, dst, insn.imm),
-                ebpf::MOV32_REG => self.emit_mov(mem, src, dst),
-                ebpf::ARSH32_IMM => self.emit_alu32_imm8(mem, 0xc1, 7, dst, insn.imm as i8),
-                ebpf::ARSH32_REG => {
-                    self.emit_mov(mem, src, RCX);
-                    self.emit_alu32(mem, 0xd3, 7, dst);
-                }
-                ebpf::LE => {} // No-op
-                ebpf::BE => {
-                    match insn.imm {
-                        16 => {
-                            // rol
-                            self.emit1(mem, 0x66); // 16-bit override
-                            self.emit_alu32_imm8(mem, 0xc1, 0, dst, 8);
-                            // and
-                            self.emit_alu32_imm32(mem, 0x81, 4, dst, 0xffff);
-                        }
-                        32 | 64 => {
-                            // bswap
-                            let bit = match insn.imm {
-                                64 => 1,
-                                _ => 0,
-                            };
-                            self.emit_basic_rex(mem, bit, 0, dst);
-                            self.emit1(mem, 0x0f);
-                            self.emit1(mem, 0xc8 | (dst & 0b111));
-                        }
-                        _ => unreachable!(), // Should have been caught by verifier
-                    }
-                }
-
-                // BPF_ALU64 class
-                ebpf::ADD64_IMM => self.emit_alu64_imm32(mem, 0x81, 0, dst, insn.imm),
-                ebpf::ADD64_REG => self.emit_alu64(mem, 0x01, src, dst),
-                ebpf::SUB64_IMM => self.emit_alu64_imm32(mem, 0x81, 5, dst, insn.imm),
-                ebpf::SUB64_REG => self.emit_alu64(mem, 0x29, src, dst),
-                ebpf::MUL64_IMM
-                | ebpf::MUL64_REG
-                | ebpf::DIV64_IMM
-                | ebpf::DIV64_REG
-                | ebpf::MOD64_IMM
-                | ebpf::MOD64_REG => {
-                    self.emit_muldivmod(mem, insn_ptr as u16, insn.opc, src, dst, insn.imm)
-                }
-                ebpf::OR64_IMM => self.emit_alu64_imm32(mem, 0x81, 1, dst, insn.imm),
-                ebpf::OR64_REG => self.emit_alu64(mem, 0x09, src, dst),
-                ebpf::AND64_IMM => self.emit_alu64_imm32(mem, 0x81, 4, dst, insn.imm),
-                ebpf::AND64_REG => self.emit_alu64(mem, 0x21, src, dst),
-                ebpf::LSH64_IMM => self.emit_alu64_imm8(mem, 0xc1, 4, dst, insn.imm as i8),
-                ebpf::LSH64_REG => {
-                    self.emit_mov(mem, src, RCX);
-                    self.emit_alu64(mem, 0xd3, 4, dst);
-                }
-                ebpf::RSH64_IMM => self.emit_alu64_imm8(mem, 0xc1, 5, dst, insn.imm as i8),
-                ebpf::RSH64_REG => {
-                    self.emit_mov(mem, src, RCX);
-                    self.emit_alu64(mem, 0xd3, 5, dst);
-                }
-                ebpf::NEG64 => self.emit_alu64(mem, 0xf7, 3, dst),
-                ebpf::XOR64_IMM => self.emit_alu64_imm32(mem, 0x81, 6, dst, insn.imm),
-                ebpf::XOR64_REG => self.emit_alu64(mem, 0x31, src, dst),
-                ebpf::MOV64_IMM => self.emit_load_imm(mem, dst, insn.imm as i64),
-                ebpf::MOV64_REG => self.emit_mov(mem, src, dst),
-                ebpf::ARSH64_IMM => self.emit_alu64_imm8(mem, 0xc1, 7, dst, insn.imm as i8),
-                ebpf::ARSH64_REG => {
-                    self.emit_mov(mem, src, RCX);
-                    self.emit_alu64(mem, 0xd3, 7, dst);
-                }
-
-                // BPF_JMP class
-                ebpf::JA => self.emit_jmp(mem, target_pc),
-                ebpf::JEQ_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x84, target_pc);
-                }
-                ebpf::JEQ_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x84, target_pc);
-                }
-                ebpf::JGT_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x87, target_pc);
-                }
-                ebpf::JGT_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x87, target_pc);
-                }
-                ebpf::JGE_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x83, target_pc);
-                }
-                ebpf::JGE_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x83, target_pc);
-                }
-                ebpf::JLT_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x82, target_pc);
-                }
-                ebpf::JLT_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x82, target_pc);
-                }
-                ebpf::JLE_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x86, target_pc);
-                }
-                ebpf::JLE_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x86, target_pc);
-                }
-                ebpf::JSET_IMM => {
-                    self.emit_alu64_imm32(mem, 0xf7, 0, dst, insn.imm);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JSET_REG => {
-                    self.emit_alu64(mem, 0x85, src, dst);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JNE_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JNE_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JSGT_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8f, target_pc);
-                }
-                ebpf::JSGT_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x8f, target_pc);
-                }
-                ebpf::JSGE_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8d, target_pc);
-                }
-                ebpf::JSGE_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x8d, target_pc);
-                }
-                ebpf::JSLT_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8c, target_pc);
-                }
-                ebpf::JSLT_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x8c, target_pc);
-                }
-                ebpf::JSLE_IMM => {
-                    self.emit_cmp_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8e, target_pc);
-                }
-                ebpf::JSLE_REG => {
-                    self.emit_cmp(mem, src, dst);
-                    self.emit_jcc(mem, 0x8e, target_pc);
-                }
-
-                // BPF_JMP32 class
-                ebpf::JEQ_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x84, target_pc);
-                }
-                ebpf::JEQ_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x84, target_pc);
-                }
-                ebpf::JGT_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x87, target_pc);
-                }
-                ebpf::JGT_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x87, target_pc);
-                }
-                ebpf::JGE_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x83, target_pc);
-                }
-                ebpf::JGE_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x83, target_pc);
-                }
-                ebpf::JLT_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x82, target_pc);
-                }
-                ebpf::JLT_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x82, target_pc);
-                }
-                ebpf::JLE_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x86, target_pc);
-                }
-                ebpf::JLE_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x86, target_pc);
-                }
-                ebpf::JSET_IMM32 => {
-                    self.emit_alu32_imm32(mem, 0xf7, 0, dst, insn.imm);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JSET_REG32 => {
-                    self.emit_alu32(mem, 0x85, src, dst);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JNE_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JNE_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x85, target_pc);
-                }
-                ebpf::JSGT_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8f, target_pc);
-                }
-                ebpf::JSGT_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x8f, target_pc);
-                }
-                ebpf::JSGE_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8d, target_pc);
-                }
-                ebpf::JSGE_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x8d, target_pc);
-                }
-                ebpf::JSLT_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8c, target_pc);
-                }
-                ebpf::JSLT_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x8c, target_pc);
-                }
-                ebpf::JSLE_IMM32 => {
-                    self.emit_cmp32_imm32(mem, dst, insn.imm);
-                    self.emit_jcc(mem, 0x8e, target_pc);
-                }
-                ebpf::JSLE_REG32 => {
-                    self.emit_cmp32(mem, src, dst);
-                    self.emit_jcc(mem, 0x8e, target_pc);
-                }
-
-                ebpf::CALL => {
-                    // For JIT, helpers in use MUST be registered at compile time. They can be
-                    // updated later, but not created after compiling (we need the address of the
-                    // helper function in the JIT-compiled program).
-                    if let Some(helper) = helpers.get(&(insn.imm as u32)) {
-                        // We reserve RCX for shifts
-                        self.emit_mov(mem, R9, RCX);
-                        self.emit_call(mem, *helper as usize);
-                    } else {
-                        Err(Error::new(
-                            ErrorKind::Other,
-                            format!(
-                                "[JIT] Error: unknown helper function (id: {:#x})",
-                                insn.imm as u32
-                            ),
-                        ))?;
-                    };
-                }
-                ebpf::TAIL_CALL => {
-                    unimplemented!()
-                }
-                ebpf::EXIT => {
-                    if insn_ptr != prog.len() / ebpf::INSN_SIZE - 1 {
-                        self.emit_jmp(mem, TARGET_PC_EXIT);
-                    };
-                }
-
-                _ => {
-                    Err(Error::new(
-                        ErrorKind::Other,
-                        format!(
-                            "[JIT] Error: unknown eBPF opcode {:#2x} (insn #{insn_ptr:?})",
-                            insn.opc
-                        ),
-                    ))?;
-                }
-            }
-
-            insn_ptr += 1;
-        }
-
-        // Epilogue
-        self.set_anchor(mem, TARGET_PC_EXIT);
-
-        // Move register 0 into rax
-        if map_register(0) != RAX {
-            self.emit_mov(mem, map_register(0), RAX);
-        }
-
-        // Deallocate stack space
-        self.emit_alu64_imm32(mem, 0x81, 0, RSP, ebpf::STACK_SIZE as i32);
-
-        self.emit_pop(mem, R15);
-        self.emit_pop(mem, R14);
-        self.emit_pop(mem, R13);
-        self.emit_pop(mem, RBX);
-        self.emit_pop(mem, RBP);
-
-        self.emit1(mem, 0xc3); // ret
-
-        Ok(())
-    }
-
-    fn resolve_jumps(&mut self, mem: &mut JitMemory) -> Result<(), Error> {
-        for jump in &self.jumps {
-            let target_loc = match self.special_targets.get(&jump.target_pc) {
-                Some(target) => *target,
-                None => self.pc_locs[jump.target_pc as usize],
-            };
-
-            // Assumes jump offset is at end of instruction
-            unsafe {
-                let offset_loc = jump.offset_loc as i32 + std::mem::size_of::<i32>() as i32;
-                let rel = &(target_loc as i32 - offset_loc) as *const i32;
-
-                let offset_ptr = mem.contents.as_ptr().add(jump.offset_loc);
-
-                libc::memcpy(
-                    offset_ptr as *mut libc::c_void,
-                    rel as *const libc::c_void,
-                    std::mem::size_of::<i32>(),
-                );
-            }
-        }
-        Ok(())
-    }
-} // impl JitCompiler
-
-pub struct JitMemory<'a> {
-    contents: &'a mut [u8],
-    offset: usize,
-}
-
-impl<'a> JitMemory<'a> {
-    pub fn new(
-        prog: &[u8],
-        helpers: &HashMap<u32, ebpf::Helper>,
-        use_mbuff: bool,
-        update_data_ptr: bool,
-    ) -> Result<JitMemory<'a>, Error> {
-        let contents: &mut [u8];
-        let mut raw: mem::MaybeUninit<*mut libc::c_void> = mem::MaybeUninit::uninit();
-        unsafe {
-            let size = NUM_PAGES * PAGE_SIZE;
-            libc::posix_memalign(raw.as_mut_ptr(), PAGE_SIZE, size);
-            libc::mprotect(
-                *raw.as_mut_ptr(),
-                size,
-                libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE,
-            );
-            std::ptr::write_bytes(*raw.as_mut_ptr(), 0xc3, size); // for now, prepopulate with 'RET' calls
-            contents =
-                std::slice::from_raw_parts_mut(*raw.as_mut_ptr() as *mut u8, NUM_PAGES * PAGE_SIZE);
-            raw.assume_init();
-        }
-
-        let mut mem = JitMemory {
-            contents,
-            offset: 0,
-        };
-
-        let mut jit = JitCompiler::new();
-        jit.jit_compile(&mut mem, prog, use_mbuff, update_data_ptr, helpers)?;
-        jit.resolve_jumps(&mut mem)?;
-
-        Ok(mem)
-    }
-
-    pub fn get_prog(&self) -> MachineCode {
-        unsafe { mem::transmute(self.contents.as_ptr()) }
-    }
-}
-
-impl<'a> Index<usize> for JitMemory<'a> {
-    type Output = u8;
-
-    fn index(&self, _index: usize) -> &u8 {
-        &self.contents[_index]
-    }
-}
-
-impl<'a> IndexMut<usize> for JitMemory<'a> {
-    fn index_mut(&mut self, _index: usize) -> &mut u8 {
-        &mut self.contents[_index]
-    }
-}
-
-impl<'a> Drop for JitMemory<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            libc::free(self.contents.as_mut_ptr() as *mut libc::c_void);
-        }
-    }
-}
-
-impl<'a> std::fmt::Debug for JitMemory<'a> {
-    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatterError> {
-        fmt.write_str("JIT contents: [")?;
-        fmt.write_str(" ] | ")?;
-        fmt.debug_struct("JIT memory")
-            .field("offset", &self.offset)
-            .finish()
-    }
-}

+ 0 - 1782
kernel/crates/rbpf/src/lib.rs

@@ -1,1782 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Derived from uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-// Copyright 2023 Isovalent, Inc. <quentin@isovalent.com>
-
-//! Virtual machine and JIT compiler for eBPF programs.
-#![doc(
-    html_logo_url = "https://raw.githubusercontent.com/qmonnet/rbpf/main/misc/rbpf.png",
-    html_favicon_url = "https://raw.githubusercontent.com/qmonnet/rbpf/main/misc/rbpf.ico"
-)]
-#![warn(missing_docs)]
-// There are unused mut warnings due to unsafe code.
-#![allow(unused_mut)]
-// Allows old-style clippy
-#![allow(renamed_and_removed_lints)]
-#![cfg_attr(
-    clippy,
-    allow(
-        redundant_field_names,
-        single_match,
-        cast_lossless,
-        doc_markdown,
-        match_same_arms,
-        unreadable_literal
-    )
-)]
-// Configures the crate to be `no_std` when `std` feature is disabled.
-#![cfg_attr(not(feature = "std"), no_std)]
-extern crate alloc;
-use alloc::{collections::BTreeMap, format, vec, vec::Vec};
-
-use byteorder::{ByteOrder, LittleEndian};
-
-type HashMap<K, V> = BTreeMap<K, V>;
-#[cfg(feature = "cranelift")]
-type HashSet<T> = alloc::collections::BTreeSet<T>;
-mod asm_parser;
-pub mod assembler;
-#[cfg(feature = "cranelift")]
-mod cranelift;
-pub mod disassembler;
-pub mod ebpf;
-pub mod helpers;
-pub mod insn_builder;
-mod interpreter;
-#[cfg(all(not(windows), feature = "std"))]
-mod jit;
-#[cfg(not(feature = "std"))]
-mod no_std_error;
-mod stack;
-mod verifier;
-
-#[cfg(feature = "std")]
-pub use std::io::{Error, ErrorKind};
-
-/// In no_std we use a custom implementation of the error which acts as a
-/// replacement for the io Error.
-#[cfg(not(feature = "std"))]
-pub use crate::no_std_error::{Error, ErrorKind};
-
-/// eBPF verification function that returns an error if the program does not meet its requirements.
-///
-/// Some examples of things the verifier may reject the program for:
-///
-///   - Program does not terminate.
-///   - Unknown instructions.
-///   - Bad formed instruction.
-///   - Unknown eBPF helper index.
-pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
-
-/// eBPF helper function.
-pub type Helper = fn(u64, u64, u64, u64, u64) -> u64;
-
-// A metadata buffer with two offset indications. It can be used in one kind of eBPF VM to simulate
-// the use of a metadata buffer each time the program is executed, without the user having to
-// actually handle it. The offsets are used to tell the VM where in the buffer the pointers to
-// packet data start and end should be stored each time the program is run on a new packet.
-struct MetaBuff {
-    data_offset: usize,
-    data_end_offset: usize,
-    buffer: Vec<u8>,
-}
-
-/// A virtual machine to run eBPF program. This kind of VM is used for programs expecting to work
-/// on a metadata buffer containing pointers to packet data.
-///
-/// # Examples
-///
-/// ```
-/// let prog = &[
-///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff at offset 8 into R1.
-///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-/// ];
-/// let mem = &mut [
-///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-/// ];
-///
-/// // Just for the example we create our metadata buffer from scratch, and we store the pointers
-/// // to packet data start and end in it.
-/// let mut mbuff = [0u8; 32];
-/// unsafe {
-///     let mut data     = mbuff.as_ptr().offset(8)  as *mut u64;
-///     let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-///     *data     = mem.as_ptr() as u64;
-///     *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-/// }
-///
-/// // Instantiate a VM.
-/// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-///
-/// // Provide both a reference to the packet data, and to the metadata buffer.
-/// let res = vm.execute_program(mem, &mut mbuff).unwrap();
-/// assert_eq!(res, 0x2211);
-/// ```
-pub struct EbpfVmMbuff<'a> {
-    prog: Option<&'a [u8]>,
-    verifier: Verifier,
-    #[cfg(all(not(windows), feature = "std"))]
-    jit: Option<jit::JitMemory<'a>>,
-    #[cfg(feature = "cranelift")]
-    cranelift_prog: Option<cranelift::CraneliftProgram>,
-    helpers: HashMap<u32, ebpf::Helper>,
-}
-
-impl<'a> EbpfVmMbuff<'a> {
-    /// Create a new virtual machine instance, and load an eBPF program into that instance.
-    /// When attempting to load the program, it passes through a simple verifier.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    /// ```
-    pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmMbuff<'a>, Error> {
-        if let Some(prog) = prog {
-            verifier::check(prog)?;
-        }
-
-        Ok(EbpfVmMbuff {
-            prog,
-            verifier: verifier::check,
-            #[cfg(all(not(windows), feature = "std"))]
-            jit: None,
-            #[cfg(feature = "cranelift")]
-            cranelift_prog: None,
-            helpers: HashMap::new(),
-        })
-    }
-
-    /// Load a new eBPF program into the virtual machine instance.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let prog2 = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
-    /// vm.set_program(prog2).unwrap();
-    /// ```
-    pub fn set_program(&mut self, prog: &'a [u8]) -> Result<(), Error> {
-        (self.verifier)(prog)?;
-        self.prog = Some(prog);
-        Ok(())
-    }
-
-    /// Set a new verifier function. The function should return an `Error` if the program should be
-    /// rejected by the virtual machine. If a program has been loaded to the VM already, the
-    /// verifier is immediately run.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::{Error, ErrorKind};
-    /// use rbpf::ebpf;
-    ///
-    /// // Define a simple verifier function.
-    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
-    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
-    ///     if last_insn.opc != ebpf::EXIT {
-    ///         return Err(Error::new(ErrorKind::Other,
-    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
-    ///     }
-    ///     Ok(())
-    /// }
-    ///
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
-    /// // Change the verifier.
-    /// vm.set_verifier(verifier).unwrap();
-    /// ```
-    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
-        if let Some(prog) = self.prog {
-            verifier(prog)?;
-        }
-        self.verifier = verifier;
-        Ok(())
-    }
-
-    /// Register a built-in or user-defined helper function in order to use it later from within
-    /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
-    ///
-    /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
-    /// program. You should be able to change registered helpers after compiling, but not to add
-    /// new ones (i.e. with new keys).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::helpers;
-    ///
-    /// // This program was compiled with clang, from a C program containing the following single
-    /// // instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);`
-    /// let prog = &[
-    ///     0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load 0 as u64 into r1 (That would be
-    ///     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // replaced by tc by the address of
-    ///                                                     // the format string, in the .map
-    ///                                                     // section of the ELF file).
-    ///     0xb7, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // mov r2, 10
-    ///     0xb7, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r3, 1
-    ///     0xb7, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r4, 2
-    ///     0xb7, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r5, 3
-    ///     0x85, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // call helper with key 6
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    ///
-    /// // Register a helper.
-    /// // On running the program this helper will print the content of registers r3, r4 and r5 to
-    /// // standard output.
-    /// # #[cfg(feature = "std")]
-    /// vm.register_helper(6, helpers::bpf_trace_printf).unwrap();
-    /// ```
-    pub fn register_helper(&mut self, key: u32, function: Helper) -> Result<(), Error> {
-        self.helpers.insert(key, function);
-        Ok(())
-    }
-
-    /// Execute the program loaded, with the given packet data and metadata buffer.
-    ///
-    /// If the program is made to be compatible with Linux kernel, it is expected to load the
-    /// address of the beginning and of the end of the memory area used for packet data from the
-    /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
-    /// pointers are correctly stored in the buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    /// ];
-    ///
-    /// // Just for the example we create our metadata buffer from scratch, and we store the
-    /// // pointers to packet data start and end in it.
-    /// let mut mbuff = [0u8; 32];
-    /// unsafe {
-    ///     let mut data     = mbuff.as_ptr().offset(8)  as *mut u64;
-    ///     let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-    ///     *data     = mem.as_ptr() as u64;
-    ///     *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-    /// }
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    ///
-    /// // Provide both a reference to the packet data, and to the metadata buffer.
-    /// let res = vm.execute_program(mem, &mut mbuff).unwrap();
-    /// assert_eq!(res, 0x2211);
-    /// ```
-    pub fn execute_program(&self, mem: &[u8], mbuff: &[u8]) -> Result<u64, Error> {
-        interpreter::execute_program(self.prog, mem, mbuff, &self.helpers)
-    }
-
-    /// JIT-compile the loaded program. No argument required for this.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    ///
-    /// vm.jit_compile();
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub fn jit_compile(&mut self) -> Result<(), Error> {
-        let prog = match self.prog {
-            Some(prog) => prog,
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: No program set, call prog_set() to load one",
-            ))?,
-        };
-        self.jit = Some(jit::JitMemory::new(prog, &self.helpers, true, false)?);
-        Ok(())
-    }
-
-    /// Execute the previously JIT-compiled program, with the given packet data and metadata
-    /// buffer, in a manner very similar to `execute_program()`.
-    ///
-    /// If the program is made to be compatible with Linux kernel, it is expected to load the
-    /// address of the beginning and of the end of the memory area used for packet data from the
-    /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
-    /// pointers are correctly stored in the buffer.
-    ///
-    /// # Safety
-    ///
-    /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
-    /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
-    /// very bad (program may segfault). It may be wise to check that the program works with the
-    /// interpreter before running the JIT-compiled version of it.
-    ///
-    /// For this reason the function should be called from within an `unsafe` bloc.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into r1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    /// ];
-    ///
-    /// // Just for the example we create our metadata buffer from scratch, and we store the
-    /// // pointers to packet data start and end in it.
-    /// let mut mbuff = [0u8; 32];
-    /// unsafe {
-    ///     let mut data     = mbuff.as_ptr().offset(8)  as *mut u64;
-    ///     let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-    ///     *data     = mem.as_ptr() as u64;
-    ///     *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-    /// }
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    ///
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// vm.jit_compile();
-    ///
-    /// // Provide both a reference to the packet data, and to the metadata buffer.
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// unsafe {
-    ///     let res = vm.execute_program_jit(mem, &mut mbuff).unwrap();
-    ///     assert_eq!(res, 0x2211);
-    /// }
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub unsafe fn execute_program_jit(
-        &self,
-        mem: &mut [u8],
-        mbuff: &'a mut [u8],
-    ) -> Result<u64, Error> {
-        // If packet data is empty, do not send the address of an empty slice; send a null pointer
-        //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
-        //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
-        //  See `mul_loop` test.
-        let mem_ptr = match mem.len() {
-            0 => std::ptr::null_mut(),
-            _ => mem.as_ptr() as *mut u8,
-        };
-        // The last two arguments are not used in this function. They would be used if there was a
-        // need to indicate to the JIT at which offset in the mbuff mem_ptr and mem_ptr + mem.len()
-        // should be stored; this is what happens with struct EbpfVmFixedMbuff.
-        match &self.jit {
-            Some(jit) => Ok(jit.get_prog()(
-                mbuff.as_ptr() as *mut u8,
-                mbuff.len(),
-                mem_ptr,
-                mem.len(),
-                0,
-                0,
-            )),
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: program has not been JIT-compiled",
-            )),
-        }
-    }
-
-    /// Compile the loaded program using the Cranelift JIT.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into R1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn cranelift_compile(&mut self) -> Result<(), Error> {
-        use crate::cranelift::CraneliftCompiler;
-
-        let prog = match self.prog {
-            Some(prog) => prog,
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: No program set, call prog_set() to load one",
-            ))?,
-        };
-
-        let mut compiler = CraneliftCompiler::new(self.helpers.clone());
-        let program = compiler.compile_function(prog)?;
-
-        self.cranelift_prog = Some(program);
-        Ok(())
-    }
-
-    /// Execute the previously compiled program, with the given packet data and metadata
-    /// buffer, in a manner very similar to `execute_program()`.
-    ///
-    /// If the program is made to be compatible with Linux kernel, it is expected to load the
-    /// address of the beginning and of the end of the memory area used for packet data from the
-    /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
-    /// pointers are correctly stored in the buffer.
-    ///
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Load mem from mbuff into r1.
-    ///     0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    /// ];
-    ///
-    /// // Just for the example we create our metadata buffer from scratch, and we store the
-    /// // pointers to packet data start and end in it.
-    /// let mut mbuff = [0u8; 32];
-    /// unsafe {
-    ///     let mut data     = mbuff.as_ptr().offset(8)  as *mut u64;
-    ///     let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-    ///     *data     = mem.as_ptr() as u64;
-    ///     *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-    /// }
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    ///
-    /// // Provide both a reference to the packet data, and to the metadata buffer.
-    /// let res = vm.execute_program_cranelift(mem, &mut mbuff).unwrap();
-    /// assert_eq!(res, 0x2211);
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn execute_program_cranelift(
-        &self,
-        mem: &mut [u8],
-        mbuff: &'a mut [u8],
-    ) -> Result<u64, Error> {
-        // If packet data is empty, do not send the address of an empty slice; send a null pointer
-        //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
-        //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
-        //  See `mul_loop` test.
-        let mem_ptr = match mem.len() {
-            0 => core::ptr::null_mut(),
-            _ => mem.as_ptr() as *mut u8,
-        };
-
-        // The last two arguments are not used in this function. They would be used if there was a
-        // need to indicate to the JIT at which offset in the mbuff mem_ptr and mem_ptr + mem.len()
-        // should be stored; this is what happens with struct EbpfVmFixedMbuff.
-        match &self.cranelift_prog {
-            Some(prog) => {
-                Ok(prog.execute(mem_ptr, mem.len(), mbuff.as_ptr() as *mut u8, mbuff.len()))
-            }
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: program has not been compiled with cranelift",
-            )),
-        }
-    }
-}
-
-/// A virtual machine to run eBPF program. This kind of VM is used for programs expecting to work
-/// on a metadata buffer containing pointers to packet data, but it internally handles the buffer
-/// so as to save the effort to manually handle the metadata buffer for the user.
-///
-/// This struct implements a static internal buffer that is passed to the program. The user has to
-/// indicate the offset values at which the eBPF program expects to find the start and the end of
-/// packet data in the buffer. On calling the `execute_program()` or `execute_program_jit()` functions, the
-/// struct automatically updates the addresses in this static buffer, at the appointed offsets, for
-/// the start and the end of the packet data the program is called upon.
-///
-/// # Examples
-///
-/// This was compiled with clang from the following program, in C:
-///
-/// ```c
-/// #include <linux/bpf.h>
-/// #include "path/to/linux/samples/bpf/bpf_helpers.h"
-///
-/// SEC(".classifier")
-/// int classifier(struct __sk_buff *skb)
-/// {
-///   void *data = (void *)(long)skb->data;
-///   void *data_end = (void *)(long)skb->data_end;
-///
-///   // Check program is long enough.
-///   if (data + 5 > data_end)
-///     return 0;
-///
-///   return *((char *)data + 5);
-/// }
-/// ```
-///
-/// Some small modifications have been brought to have it work, see comments.
-///
-/// ```
-/// let prog = &[
-///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-///     // Here opcode 0x61 had to be replace by 0x79 so as to load a 8-bytes long address.
-///     // Also, offset 0x4c had to be replace with e.g. 0x40 so as to prevent the two pointers
-///     // from overlapping in the buffer.
-///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load pointer to mem from r1[0x40] to r2
-///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-///     // Here opcode 0x61 had to be replace by 0x79 so as to load a 8-bytes long address.
-///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load ptr to mem_end from r1[0x50] to r1
-///     0x2d, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-///     0x67, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 >>= 56
-///     0xc7, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 <<= 56 (arsh) extend byte sign to u64
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-/// ];
-/// let mem1 = &mut [
-///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-/// ];
-/// let mem2 = &mut [
-///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
-/// ];
-///
-/// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-/// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-///
-/// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-/// let res = vm.execute_program(mem1).unwrap();
-/// assert_eq!(res, 0xffffffffffffffdd);
-///
-/// let res = vm.execute_program(mem2).unwrap();
-/// assert_eq!(res, 0x27);
-/// ```
-pub struct EbpfVmFixedMbuff<'a> {
-    parent: EbpfVmMbuff<'a>,
-    mbuff: MetaBuff,
-}
-
-impl<'a> EbpfVmFixedMbuff<'a> {
-    /// Create a new virtual machine instance, and load an eBPF program into that instance.
-    /// When attempting to load the program, it passes through a simple verifier.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    /// ```
-    pub fn new(
-        prog: Option<&'a [u8]>,
-        data_offset: usize,
-        data_end_offset: usize,
-    ) -> Result<EbpfVmFixedMbuff<'a>, Error> {
-        let parent = EbpfVmMbuff::new(prog)?;
-        let get_buff_len = |x: usize, y: usize| if x >= y { x + 8 } else { y + 8 };
-        let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
-        let mbuff = MetaBuff {
-            data_offset,
-            data_end_offset,
-            buffer,
-        };
-        Ok(EbpfVmFixedMbuff { parent, mbuff })
-    }
-
-    /// Load a new eBPF program into the virtual machine instance.
-    ///
-    /// At the same time, load new offsets for storing pointers to start and end of packet data in
-    /// the internal metadata buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let prog2 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog1), 0, 0).unwrap();
-    /// vm.set_program(prog2, 0x40, 0x50);
-    ///
-    /// let res = vm.execute_program(mem).unwrap();
-    /// assert_eq!(res, 0x27);
-    /// ```
-    pub fn set_program(
-        &mut self,
-        prog: &'a [u8],
-        data_offset: usize,
-        data_end_offset: usize,
-    ) -> Result<(), Error> {
-        let get_buff_len = |x: usize, y: usize| if x >= y { x + 8 } else { y + 8 };
-        let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
-        self.mbuff.buffer = buffer;
-        self.mbuff.data_offset = data_offset;
-        self.mbuff.data_end_offset = data_end_offset;
-        self.parent.set_program(prog)?;
-        Ok(())
-    }
-
-    /// Set a new verifier function. The function should return an `Error` if the program should be
-    /// rejected by the virtual machine. If a program has been loaded to the VM already, the
-    /// verifier is immediately run.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::{Error, ErrorKind};
-    /// use rbpf::ebpf;
-    ///
-    /// // Define a simple verifier function.
-    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
-    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
-    ///     if last_insn.opc != ebpf::EXIT {
-    ///         return Err(Error::new(ErrorKind::Other,
-    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
-    ///     }
-    ///     Ok(())
-    /// }
-    ///
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
-    /// // Change the verifier.
-    /// vm.set_verifier(verifier).unwrap();
-    /// ```
-    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
-        self.parent.set_verifier(verifier)
-    }
-
-    /// Register a built-in or user-defined helper function in order to use it later from within
-    /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
-    ///
-    /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
-    /// program. You should be able to change registered helpers after compiling, but not to add
-    /// new ones (i.e. with new keys).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #[cfg(feature = "std")] {
-    ///     use rbpf::helpers;
-    ///
-    ///     // This program was compiled with clang, from a C program containing the following single
-    ///     // instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);`
-    ///     let prog = &[
-    ///         0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///         0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///         0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///         0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///         0x2d, 0x12, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 6 instructions
-    ///         0x71, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r1
-    ///         0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0
-    ///         0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0
-    ///         0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0
-    ///         0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0
-    ///         0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1
-    ///         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    ///     ];
-    ///
-    ///     let mem = &mut [
-    ///         0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x09,
-    ///     ];
-    ///
-    ///     // Instantiate a VM.
-    ///     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    ///
-    ///     // Register a helper. This helper will store the result of the square root of r1 into r0.
-    ///     vm.register_helper(1, helpers::sqrti);
-    ///
-    ///     let res = vm.execute_program(mem).unwrap();
-    ///     assert_eq!(res, 3);
-    /// }
-    /// ```
-    pub fn register_helper(
-        &mut self,
-        key: u32,
-        function: fn(u64, u64, u64, u64, u64) -> u64,
-    ) -> Result<(), Error> {
-        self.parent.register_helper(key, function)
-    }
-
-    /// Execute the program loaded, with the given packet data.
-    ///
-    /// If the program is made to be compatible with Linux kernel, it is expected to load the
-    /// address of the beginning and of the end of the memory area used for packet data from some
-    /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
-    /// the addresses should be placed should have be set at the creation of the VM.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    /// ];
-    ///
-    /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    ///
-    /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-    /// let res = vm.execute_program(mem).unwrap();
-    /// assert_eq!(res, 0xdd);
-    /// ```
-    pub fn execute_program(&mut self, mem: &'a mut [u8]) -> Result<u64, Error> {
-        let l = self.mbuff.buffer.len();
-        // Can this ever happen? Probably not, should be ensured at mbuff creation.
-        if self.mbuff.data_offset + 8 > l || self.mbuff.data_end_offset + 8 > l {
-            Err(Error::new(ErrorKind::Other, format!("Error: buffer too small ({:?}), cannot use data_offset {:?} and data_end_offset {:?}",
-            l, self.mbuff.data_offset, self.mbuff.data_end_offset)))?;
-        }
-        LittleEndian::write_u64(
-            &mut self.mbuff.buffer[(self.mbuff.data_offset)..],
-            mem.as_ptr() as u64,
-        );
-        LittleEndian::write_u64(
-            &mut self.mbuff.buffer[(self.mbuff.data_end_offset)..],
-            mem.as_ptr() as u64 + mem.len() as u64,
-        );
-        self.parent.execute_program(mem, &self.mbuff.buffer)
-    }
-
-    /// JIT-compile the loaded program. No argument required for this.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    ///
-    /// vm.jit_compile();
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub fn jit_compile(&mut self) -> Result<(), Error> {
-        let prog = match self.parent.prog {
-            Some(prog) => prog,
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: No program set, call prog_set() to load one",
-            ))?,
-        };
-        self.parent.jit = Some(jit::JitMemory::new(prog, &self.parent.helpers, true, true)?);
-        Ok(())
-    }
-
-    /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
-    /// similar to `execute_program()`.
-    ///
-    /// If the program is made to be compatible with Linux kernel, it is expected to load the
-    /// address of the beginning and of the end of the memory area used for packet data from some
-    /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
-    /// the addresses should be placed should have be set at the creation of the VM.
-    ///
-    /// # Safety
-    ///
-    /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
-    /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
-    /// very bad (program may segfault). It may be wise to check that the program works with the
-    /// interpreter before running the JIT-compiled version of it.
-    ///
-    /// For this reason the function should be called from within an `unsafe` bloc.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    /// ];
-    ///
-    /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    ///
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// vm.jit_compile();
-    ///
-    /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// unsafe {
-    ///     let res = vm.execute_program_jit(mem).unwrap();
-    ///     assert_eq!(res, 0xdd);
-    /// }
-    /// ```
-    // This struct redefines the `execute_program_jit()` function, in order to pass the offsets
-    // associated with the fixed mbuff.
-    #[cfg(all(not(windows), feature = "std"))]
-    pub unsafe fn execute_program_jit(&mut self, mem: &'a mut [u8]) -> Result<u64, Error> {
-        // If packet data is empty, do not send the address of an empty slice; send a null pointer
-        //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
-        //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
-        //  See `mul_loop` test.
-        let mem_ptr = match mem.len() {
-            0 => core::ptr::null_mut(),
-            _ => mem.as_ptr() as *mut u8,
-        };
-
-        match &self.parent.jit {
-            Some(jit) => Ok(jit.get_prog()(
-                self.mbuff.buffer.as_ptr() as *mut u8,
-                self.mbuff.buffer.len(),
-                mem_ptr,
-                mem.len(),
-                self.mbuff.data_offset,
-                self.mbuff.data_end_offset,
-            )),
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: program has not been JIT-compiled",
-            )),
-        }
-    }
-
-    /// Compile the loaded program using the Cranelift JIT.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn cranelift_compile(&mut self) -> Result<(), Error> {
-        use crate::cranelift::CraneliftCompiler;
-
-        let prog = match self.parent.prog {
-            Some(prog) => prog,
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: No program set, call prog_set() to load one",
-            ))?,
-        };
-
-        let mut compiler = CraneliftCompiler::new(self.parent.helpers.clone());
-        let program = compiler.compile_function(prog)?;
-
-        self.parent.cranelift_prog = Some(program);
-        Ok(())
-    }
-
-    /// Execute the previously compiled program, with the given packet data and metadata
-    /// buffer, in a manner very similar to `execute_program()`.
-    ///
-    /// If the program is made to be compatible with Linux kernel, it is expected to load the
-    /// address of the beginning and of the end of the memory area used for packet data from some
-    /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
-    /// the addresses should be placed should have be set at the creation of the VM.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem from r1[0x40] to r2
-    ///     0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
-    ///     0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load mem_end from r1[0x50] to r1
-    ///     0x2d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
-    ///     0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    /// ];
-    ///
-    /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    ///
-    /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-    /// let res = vm.execute_program_cranelift(mem).unwrap();
-    /// assert_eq!(res, 0xdd);
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn execute_program_cranelift(&mut self, mem: &'a mut [u8]) -> Result<u64, Error> {
-        // If packet data is empty, do not send the address of an empty slice; send a null pointer
-        //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
-        //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
-        //  See `mul_loop` test.
-        let mem_ptr = match mem.len() {
-            0 => core::ptr::null_mut(),
-            _ => mem.as_ptr() as *mut u8,
-        };
-
-        let l = self.mbuff.buffer.len();
-        // Can this ever happen? Probably not, should be ensured at mbuff creation.
-        if self.mbuff.data_offset + 8 > l || self.mbuff.data_end_offset + 8 > l {
-            Err(Error::new(ErrorKind::Other, format!("Error: buffer too small ({:?}), cannot use data_offset {:?} and data_end_offset {:?}",
-            l, self.mbuff.data_offset, self.mbuff.data_end_offset)))?;
-        }
-        LittleEndian::write_u64(
-            &mut self.mbuff.buffer[(self.mbuff.data_offset)..],
-            mem.as_ptr() as u64,
-        );
-        LittleEndian::write_u64(
-            &mut self.mbuff.buffer[(self.mbuff.data_end_offset)..],
-            mem.as_ptr() as u64 + mem.len() as u64,
-        );
-
-        match &self.parent.cranelift_prog {
-            Some(prog) => Ok(prog.execute(
-                mem_ptr,
-                mem.len(),
-                self.mbuff.buffer.as_ptr() as *mut u8,
-                self.mbuff.buffer.len(),
-            )),
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: program has not been compiled with cranelift",
-            )),
-        }
-    }
-}
-
-/// A virtual machine to run eBPF program. This kind of VM is used for programs expecting to work
-/// directly on the memory area representing packet data.
-///
-/// # Examples
-///
-/// ```
-/// let prog = &[
-///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-/// ];
-/// let mem = &mut [
-///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-/// ];
-///
-/// // Instantiate a VM.
-/// let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-///
-/// // Provide only a reference to the packet data.
-/// let res = vm.execute_program(mem).unwrap();
-/// assert_eq!(res, 0x22cc);
-/// ```
-pub struct EbpfVmRaw<'a> {
-    parent: EbpfVmMbuff<'a>,
-}
-
-impl<'a> EbpfVmRaw<'a> {
-    /// Create a new virtual machine instance, and load an eBPF program into that instance.
-    /// When attempting to load the program, it passes through a simple verifier.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    /// ```
-    pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmRaw<'a>, Error> {
-        let parent = EbpfVmMbuff::new(prog)?;
-        Ok(EbpfVmRaw { parent })
-    }
-
-    /// Load a new eBPF program into the virtual machine instance.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let prog2 = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog1)).unwrap();
-    /// vm.set_program(prog2);
-    ///
-    /// let res = vm.execute_program(mem).unwrap();
-    /// assert_eq!(res, 0x22cc);
-    /// ```
-    pub fn set_program(&mut self, prog: &'a [u8]) -> Result<(), Error> {
-        self.parent.set_program(prog)?;
-        Ok(())
-    }
-
-    /// Set a new verifier function. The function should return an `Error` if the program should be
-    /// rejected by the virtual machine. If a program has been loaded to the VM already, the
-    /// verifier is immediately run.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::{Error, ErrorKind};
-    /// use rbpf::ebpf;
-    ///
-    /// // Define a simple verifier function.
-    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
-    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
-    ///     if last_insn.opc != ebpf::EXIT {
-    ///         return Err(Error::new(ErrorKind::Other,
-    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
-    ///     }
-    ///     Ok(())
-    /// }
-    ///
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
-    /// // Change the verifier.
-    /// vm.set_verifier(verifier).unwrap();
-    /// ```
-    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
-        self.parent.set_verifier(verifier)
-    }
-
-    /// Register a built-in or user-defined helper function in order to use it later from within
-    /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
-    ///
-    /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
-    /// program. You should be able to change registered helpers after compiling, but not to add
-    /// new ones (i.e. with new keys).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #[cfg(feature = "std")] {
-    ///     use rbpf::helpers;
-    ///
-    ///     let prog = &[
-    ///         0x79, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxdw r1, r1[0x00]
-    ///         0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0
-    ///         0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0
-    ///         0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0
-    ///         0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0
-    ///         0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1
-    ///         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    ///     ];
-    ///
-    ///     let mem = &mut [
-    ///         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
-    ///     ];
-    ///
-    ///     // Instantiate a VM.
-    ///     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    ///
-    ///     // Register a helper. This helper will store the result of the square root of r1 into r0.
-    ///     vm.register_helper(1, helpers::sqrti);
-    ///
-    ///     let res = vm.execute_program(mem).unwrap();
-    ///     assert_eq!(res, 0x10000000);
-    /// }
-    /// ```
-    pub fn register_helper(
-        &mut self,
-        key: u32,
-        function: fn(u64, u64, u64, u64, u64) -> u64,
-    ) -> Result<(), Error> {
-        self.parent.register_helper(key, function)
-    }
-
-    /// Register a set of built-in or user-defined helper functions in order to use them later from
-    /// within the eBPF program. The helpers are registered into a hashmap, so the `key` can be any
-    /// `u32`.
-    #[allow(clippy::type_complexity)]
-    pub fn register_helper_set(
-        &mut self,
-        helpers: &HashMap<u32, fn(u64, u64, u64, u64, u64) -> u64>,
-    ) -> Result<(), Error> {
-        for (key, function) in helpers {
-            self.parent.register_helper(*key, *function)?;
-        }
-        Ok(())
-    }
-
-    /// Execute the program loaded, with the given packet data.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    ///
-    /// let res = vm.execute_program(mem).unwrap();
-    /// assert_eq!(res, 0x22cc);
-    /// ```
-    pub fn execute_program(&self, mem: &'a mut [u8]) -> Result<u64, Error> {
-        self.parent.execute_program(mem, &[])
-    }
-
-    /// JIT-compile the loaded program. No argument required for this.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    ///
-    /// vm.jit_compile();
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub fn jit_compile(&mut self) -> Result<(), Error> {
-        let prog = match self.parent.prog {
-            Some(prog) => prog,
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: No program set, call prog_set() to load one",
-            ))?,
-        };
-        self.parent.jit = Some(jit::JitMemory::new(
-            prog,
-            &self.parent.helpers,
-            false,
-            false,
-        )?);
-        Ok(())
-    }
-
-    /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
-    /// similar to `execute_program()`.
-    ///
-    /// # Safety
-    ///
-    /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
-    /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
-    /// very bad (program may segfault). It may be wise to check that the program works with the
-    /// interpreter before running the JIT-compiled version of it.
-    ///
-    /// For this reason the function should be called from within an `unsafe` bloc.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    ///
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// vm.jit_compile();
-    ///
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// unsafe {
-    ///     let res = vm.execute_program_jit(mem).unwrap();
-    ///     assert_eq!(res, 0x22cc);
-    /// }
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub unsafe fn execute_program_jit(&self, mem: &'a mut [u8]) -> Result<u64, Error> {
-        let mut mbuff = vec![];
-        self.parent.execute_program_jit(mem, &mut mbuff)
-    }
-
-    /// Compile the loaded program using the Cranelift JIT.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn cranelift_compile(&mut self) -> Result<(), Error> {
-        use crate::cranelift::CraneliftCompiler;
-
-        let prog = match self.parent.prog {
-            Some(prog) => prog,
-            None => Err(Error::new(
-                ErrorKind::Other,
-                "Error: No program set, call prog_set() to load one",
-            ))?,
-        };
-
-        let mut compiler = CraneliftCompiler::new(self.parent.helpers.clone());
-        let program = compiler.compile_function(prog)?;
-
-        self.parent.cranelift_prog = Some(program);
-        Ok(())
-    }
-
-    /// Execute the previously compiled program, with the given packet data, in a manner very
-    /// similar to `execute_program()`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0x71, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ldxb r1[0x04], r1
-    ///     0x07, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, // add r1, 0x22
-    ///     0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, r1
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mem = &mut [
-    ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    ///
-    /// let res = vm.execute_program_cranelift(mem).unwrap();
-    /// assert_eq!(res, 0x22cc);
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn execute_program_cranelift(&self, mem: &'a mut [u8]) -> Result<u64, Error> {
-        let mut mbuff = vec![];
-        self.parent.execute_program_cranelift(mem, &mut mbuff)
-    }
-}
-
-/// A virtual machine to run eBPF program. This kind of VM is used for programs that do not work
-/// with any memory area—no metadata buffer, no packet data either.
-///
-/// # Examples
-///
-/// ```
-/// let prog = &[
-///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-///     0xb7, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r1, 1
-///     0xb7, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r2, 2
-///     0xb7, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r3, 3
-///     0xb7, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, // mov r4, 4
-///     0xb7, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // mov r5, 5
-///     0xb7, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // mov r6, 6
-///     0xb7, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // mov r7, 7
-///     0xb7, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // mov r8, 8
-///     0x4f, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // or r0, r5
-///     0x47, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, // or r0, 0xa0
-///     0x57, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, // and r0, 0xa3
-///     0xb7, 0x09, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, // mov r9, 0x91
-///     0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // and r0, r9
-///     0x67, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // lsh r0, 32
-///     0x67, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, // lsh r0, 22
-///     0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // lsh r0, r8
-///     0x77, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // rsh r0, 32
-///     0x77, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, // rsh r0, 19
-///     0x7f, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // rsh r0, r7
-///     0xa7, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // xor r0, 0x03
-///     0xaf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xor r0, r2
-///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-/// ];
-///
-/// // Instantiate a VM.
-/// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-///
-/// // Provide only a reference to the packet data.
-/// let res = vm.execute_program().unwrap();
-/// assert_eq!(res, 0x11);
-/// ```
-pub struct EbpfVmNoData<'a> {
-    parent: EbpfVmRaw<'a>,
-}
-
-impl<'a> EbpfVmNoData<'a> {
-    /// Create a new virtual machine instance, and load an eBPF program into that instance.
-    /// When attempting to load the program, it passes through a simple verifier.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let vm = rbpf::EbpfVmNoData::new(Some(prog));
-    /// ```
-    pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmNoData<'a>, Error> {
-        let parent = EbpfVmRaw::new(prog)?;
-        Ok(EbpfVmNoData { parent })
-    }
-
-    /// Load a new eBPF program into the virtual machine instance.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    /// let prog2 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
-    ///
-    /// let res = vm.execute_program().unwrap();
-    /// assert_eq!(res, 0x2211);
-    ///
-    /// vm.set_program(prog2);
-    ///
-    /// let res = vm.execute_program().unwrap();
-    /// assert_eq!(res, 0x1122);
-    /// ```
-    pub fn set_program(&mut self, prog: &'a [u8]) -> Result<(), Error> {
-        self.parent.set_program(prog)?;
-        Ok(())
-    }
-
-    /// Set a new verifier function. The function should return an `Error` if the program should be
-    /// rejected by the virtual machine. If a program has been loaded to the VM already, the
-    /// verifier is immediately run.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use rbpf::{Error, ErrorKind};
-    /// use rbpf::ebpf;
-    ///
-    /// // Define a simple verifier function.
-    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
-    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
-    ///     if last_insn.opc != ebpf::EXIT {
-    ///         return Err(Error::new(ErrorKind::Other,
-    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
-    ///     }
-    ///     Ok(())
-    /// }
-    ///
-    /// let prog1 = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
-    /// // Change the verifier.
-    /// vm.set_verifier(verifier).unwrap();
-    /// ```
-    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
-        self.parent.set_verifier(verifier)
-    }
-
-    /// Register a built-in or user-defined helper function in order to use it later from within
-    /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
-    ///
-    /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the
-    /// program. You should be able to change registered helpers after compiling, but not to add
-    /// new ones (i.e. with new keys).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #[cfg(feature = "std")] {
-    ///     use rbpf::helpers;
-    ///
-    ///     let prog = &[
-    ///         0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // mov r1, 0x010000000
-    ///         0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0
-    ///         0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0
-    ///         0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0
-    ///         0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0
-    ///         0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1
-    ///         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    ///     ];
-    ///
-    ///     let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    ///
-    ///     // Register a helper. This helper will store the result of the square root of r1 into r0.
-    ///     vm.register_helper(1, helpers::sqrti).unwrap();
-    ///
-    ///     let res = vm.execute_program().unwrap();
-    ///     assert_eq!(res, 0x1000);
-    /// }
-    /// ```
-    pub fn register_helper(
-        &mut self,
-        key: u32,
-        function: fn(u64, u64, u64, u64, u64) -> u64,
-    ) -> Result<(), Error> {
-        self.parent.register_helper(key, function)
-    }
-
-    /// JIT-compile the loaded program. No argument required for this.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    ///
-    ///
-    /// vm.jit_compile();
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub fn jit_compile(&mut self) -> Result<(), Error> {
-        self.parent.jit_compile()
-    }
-
-    /// Execute the program loaded, without providing pointers to any memory area whatsoever.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    ///
-    /// // For this kind of VM, the `execute_program()` function needs no argument.
-    /// let res = vm.execute_program().unwrap();
-    /// assert_eq!(res, 0x1122);
-    /// ```
-    pub fn execute_program(&self) -> Result<u64, Error> {
-        self.parent.execute_program(&mut [])
-    }
-
-    /// Execute the previously JIT-compiled program, without providing pointers to any memory area
-    /// whatsoever, in a manner very similar to `execute_program()`.
-    ///
-    /// # Safety
-    ///
-    /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
-    /// check for memory access; so if the eBPF program attempts erroneous accesses, this may end
-    /// very bad (program may segfault). It may be wise to check that the program works with the
-    /// interpreter before running the JIT-compiled version of it.
-    ///
-    /// For this reason the function should be called from within an `unsafe` bloc.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    ///
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// vm.jit_compile();
-    ///
-    /// # #[cfg(all(not(windows), feature = "std"))]
-    /// unsafe {
-    ///     let res = vm.execute_program_jit().unwrap();
-    ///     assert_eq!(res, 0x1122);
-    /// }
-    /// ```
-    #[cfg(all(not(windows), feature = "std"))]
-    pub unsafe fn execute_program_jit(&self) -> Result<u64, Error> {
-        self.parent.execute_program_jit(&mut [])
-    }
-
-    /// Compile the loaded program using the Cranelift JIT.
-    ///
-    /// If using helper functions, be sure to register them into the VM before calling this
-    /// function.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    ///
-    ///
-    /// vm.cranelift_compile();
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn cranelift_compile(&mut self) -> Result<(), Error> {
-        self.parent.cranelift_compile()
-    }
-
-    /// Execute the previously JIT-compiled program, without providing pointers to any memory area
-    /// whatsoever, in a manner very similar to `execute_program()`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let prog = &[
-    ///     0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211
-    ///     0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0
-    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
-    /// ];
-    ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    ///
-    /// vm.cranelift_compile();
-    ///
-    /// let res = vm.execute_program_cranelift().unwrap();
-    /// assert_eq!(res, 0x1122);
-    /// ```
-    #[cfg(feature = "cranelift")]
-    pub fn execute_program_cranelift(&self) -> Result<u64, Error> {
-        self.parent.execute_program_cranelift(&mut [])
-    }
-}
-
-/// EbpfVm with Owned data
-pub struct EbpfVmRawOwned {
-    parent: EbpfVmRaw<'static>,
-    data_len: usize,
-    data_cap: usize,
-}
-
-impl EbpfVmRawOwned {
-    /// Create a new virtual machine instance, and load an eBPF program into that instance.
-    /// When attempting to load the program, it passes through a simple verifier.
-    pub fn new(prog: Option<Vec<u8>>) -> Result<EbpfVmRawOwned, Error> {
-        let (prog, data_len, data_cap) = match prog {
-            Some(prog) => {
-                let data_len = prog.len();
-                let data_cap = prog.capacity();
-                let slice = prog.leak();
-                let slice = unsafe { core::slice::from_raw_parts(slice.as_ptr(), data_len) };
-                (Some(slice), data_len, data_cap)
-            }
-            None => (None, 0, 0),
-        };
-        let parent = EbpfVmRaw::new(prog)?;
-        Ok(Self {
-            parent,
-            data_len,
-            data_cap,
-        })
-    }
-    /// Load a new eBPF program into the virtual machine instance
-    pub fn set_program(&mut self, prog: Vec<u8>) -> Result<(), Error> {
-        self.data_len = prog.len();
-        self.data_cap = prog.capacity();
-        let slice = prog.leak();
-        self.parent.set_program(slice)?;
-        Ok(())
-    }
-
-    /// Set a new verifier function. The function should return an Error if the program should be rejected by the virtual machine.
-    /// If a program has been loaded to the VM already, the verifier is immediately run.
-    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
-        self.parent.set_verifier(verifier)
-    }
-
-    /// Register a built-in or user-defined helper function in order to use it later from within the eBPF program.
-    /// The helper is registered into a hashmap, so the key can be any u32.
-    /// If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the program.
-    /// You should be able to change registered helpers after compiling, but not to add new ones (i. e. with new keys).
-    pub fn register_helper(
-        &mut self,
-        key: u32,
-        function: fn(u64, u64, u64, u64, u64) -> u64,
-    ) -> Result<(), Error> {
-        self.parent.register_helper(key, function)
-    }
-
-    /// Register a set of built-in or user-defined helper functions in order to use them later from
-    /// within the eBPF program. The helpers are registered into a hashmap, so the `key` can be any
-    /// `u32`.
-    #[allow(clippy::type_complexity)]
-    pub fn register_helper_set(
-        &mut self,
-        helpers: &HashMap<u32, fn(u64, u64, u64, u64, u64) -> u64>,
-    ) -> Result<(), Error> {
-        for (key, function) in helpers {
-            self.parent.register_helper(*key, *function)?;
-        }
-        Ok(())
-    }
-
-    /// Execute the previously JIT-compiled program, with the given packet data, in a manner very similar to execute_program().
-    ///
-    /// Safety
-    ///
-    /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime check for memory access;
-    /// so if the eBPF program attempts erroneous accesses, this may end very bad (program may segfault).
-    /// It may be wise to check that the program works with the interpreter before running the JIT-compiled version of it.
-    ///
-    /// For this reason the function should be called from within an unsafe bloc.
-    pub fn execute_program(&self, mem: &mut [u8]) -> Result<u64, Error> {
-        self.parent.execute_program(mem)
-    }
-}
-
-impl Drop for EbpfVmRawOwned {
-    fn drop(&mut self) {
-        match self.parent.parent.prog {
-            Some(prog) => unsafe {
-                let ptr = prog.as_ptr();
-                let _prog = Vec::from_raw_parts(ptr as *mut u8, self.data_len, self.data_cap);
-            },
-            None => {}
-        };
-    }
-}

+ 0 - 41
kernel/crates/rbpf/src/no_std_error.rs

@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-//! This module provides a simple implementation of the Error struct that is
-//! used as a drop-in replacement for `std::io::Error` when using `rbpf` in `no_std`.
-
-use alloc::string::String;
-
-/// Implementation of Error for no_std applications.
-/// Ensures that the existing code can use it with the same interface
-/// as the Error from std::io::Error.
-#[derive(Debug)]
-pub struct Error {
-    #[allow(dead_code)]
-    kind: ErrorKind,
-    #[allow(dead_code)]
-    error: String,
-}
-
-impl Error {
-    /// New function exposing the same signature as `std::io::Error::new`.
-    #[allow(dead_code)]
-    pub fn new<S: Into<String>>(kind: ErrorKind, error: S) -> Error {
-        Error {
-            kind,
-            error: error.into(),
-        }
-    }
-}
-
-/// The current version of `rbpf` only uses the [`Other`](ErrorKind::Other) variant
-/// from the [std::io::ErrorKind] enum. If a dependency on other variants were
-/// introduced in the future, this enum needs to be updated accordingly to maintain
-/// compatibility with the real `ErrorKind`. The reason all available variants
-/// aren't included in the first place is that [std::io::ErrorKind] exposes
-/// 40 variants, and not all of them are meaningful under `no_std`.
-#[derive(Debug)]
-pub enum ErrorKind {
-    /// The no_std code only uses this variant.
-    #[allow(dead_code)]
-    Other,
-}

+ 0 - 75
kernel/crates/rbpf/src/stack.rs

@@ -1,75 +0,0 @@
-use crate::{ebpf::STACK_SIZE, vec, Vec};
-
-pub struct StackFrame {
-    return_address: u64,
-    saved_registers: [u64; 4],
-    sp: u64,
-    frame: Vec<u8>,
-}
-
-impl StackFrame {
-    /// Create a new stack frame
-    ///
-    /// The stack frame is created with a capacity of `STACK_SIZE` == 512 bytes
-    pub fn new() -> Self {
-        Self {
-            sp: 0,
-            return_address: 0,
-            saved_registers: [0; 4],
-            frame: vec![0; STACK_SIZE],
-        }
-    }
-
-    /// Create a new stack frame with a given capacity
-    #[allow(unused)]
-    pub fn with_capacity(capacity: usize) -> Self {
-        Self {
-            sp: 0,
-            return_address: 0,
-            saved_registers: [0; 4],
-            frame: vec![0; capacity],
-        }
-    }
-
-    /// The capacity of the stack frame
-    pub fn len(&self) -> usize {
-        self.frame.len()
-    }
-
-    pub fn as_ptr(&self) -> *const u8 {
-        self.frame.as_ptr()
-    }
-
-    pub fn as_slice(&self) -> &[u8] {
-        self.frame.as_slice()
-    }
-    /// Save the callee-saved registers
-    pub fn save_registers(&mut self, regs: &[u64]) {
-        self.saved_registers.copy_from_slice(regs);
-    }
-
-    /// Get the callee-saved registers
-    pub fn get_registers(&self) -> [u64; 4] {
-        self.saved_registers
-    }
-
-    /// Save the return address
-    pub fn save_return_address(&mut self, address: u64) {
-        self.return_address = address;
-    }
-
-    /// Get the return address
-    pub fn get_return_address(&self) -> u64 {
-        self.return_address
-    }
-
-    /// Save the stack pointer
-    pub fn save_sp(&mut self, sp: u64) {
-        self.sp = sp;
-    }
-
-    /// Get the stack pointer
-    pub fn get_sp(&self) -> u64 {
-        self.sp
-    }
-}

+ 0 - 386
kernel/crates/rbpf/src/verifier.rs

@@ -1,386 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Derived from uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-//      (uBPF: safety checks, originally in C)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-//      (Translation to Rust)
-
-// This “verifier” performs simple checks when the eBPF program is loaded into the VM (before it is
-// interpreted or JIT-compiled). It has nothing to do with the much more elaborated verifier inside
-// Linux kernel. There is no verification regarding the program flow control (should be a Direct
-// Acyclic Graph) or the consistency for registers usage (the verifier of the kernel assigns types
-// to the registers and is much stricter).
-//
-// On the other hand, rbpf is not expected to run in kernel space.
-//
-// Improving the verifier would be nice, but this is not trivial (and Linux kernel is under GPL
-// license, so we cannot copy it).
-//
-// Contrary to the verifier of the Linux kernel, this one does not modify the bytecode at all.
-
-use alloc::format;
-
-use crate::{ebpf, Error, ErrorKind};
-
-fn reject<S: AsRef<str>>(msg: S) -> Result<(), Error> {
-    let full_msg = format!("[Verifier] Error: {}", msg.as_ref());
-    Err(Error::new(ErrorKind::Other, full_msg))
-}
-
-fn check_prog_len(prog: &[u8]) -> Result<(), Error> {
-    if prog.len() % ebpf::INSN_SIZE != 0 {
-        reject(format!(
-            "eBPF program length must be a multiple of {:?} octets",
-            ebpf::INSN_SIZE
-        ))?;
-    }
-    if prog.len() > ebpf::PROG_MAX_SIZE {
-        reject(format!(
-            "eBPF program length limited to {:?}, here {:?}",
-            ebpf::PROG_MAX_INSNS,
-            prog.len() / ebpf::INSN_SIZE
-        ))?;
-    }
-
-    if prog.is_empty() {
-        reject("no program set, call set_program() to load one")?;
-    }
-    let last_opc = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1).opc;
-    if last_opc & ebpf::BPF_CLS_MASK != ebpf::BPF_JMP {
-        reject("program does not end with “EXIT” instruction")?;
-    }
-
-    Ok(())
-}
-
-fn check_imm_endian(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), Error> {
-    match insn.imm {
-        16 | 32 | 64 => Ok(()),
-        _ => reject(format!(
-            "unsupported argument for LE/BE (insn #{insn_ptr:?})"
-        )),
-    }
-}
-
-fn check_load_dw(prog: &[u8], insn_ptr: usize) -> Result<(), Error> {
-    // We know we can reach next insn since we enforce an EXIT insn at the end of program, while
-    // this function should be called only for LD_DW insn, that cannot be last in program.
-    let next_insn = ebpf::get_insn(prog, insn_ptr + 1);
-    if next_insn.opc != 0 {
-        reject(format!("incomplete LD_DW instruction (insn #{insn_ptr:?})"))?;
-    }
-
-    Ok(())
-}
-
-fn check_jmp_offset(prog: &[u8], insn_ptr: usize) -> Result<(), Error> {
-    let insn = ebpf::get_insn(prog, insn_ptr);
-    if insn.off == -1 {
-        reject(format!("infinite loop (insn #{insn_ptr:?})"))?;
-    }
-
-    let dst_insn_ptr = insn_ptr as isize + 1 + insn.off as isize;
-    if dst_insn_ptr < 0 || dst_insn_ptr as usize >= (prog.len() / ebpf::INSN_SIZE) {
-        reject(format!(
-            "jump out of code to #{dst_insn_ptr:?} (insn #{insn_ptr:?})"
-        ))?;
-    }
-
-    let dst_insn = ebpf::get_insn(prog, dst_insn_ptr as usize);
-    if dst_insn.opc == 0 {
-        reject(format!(
-            "jump to middle of LD_DW at #{dst_insn_ptr:?} (insn #{insn_ptr:?})"
-        ))?;
-    }
-
-    Ok(())
-}
-
-fn check_registers(insn: &ebpf::Insn, store: bool, insn_ptr: usize) -> Result<(), Error> {
-    if insn.src > 10 {
-        reject(format!("invalid source register (insn #{insn_ptr:?})"))?;
-    }
-
-    match (insn.dst, store) {
-        (0..=9, _) | (10, true) => Ok(()),
-        (10, false) => reject(format!(
-            "cannot write into register r10 (insn #{insn_ptr:?})"
-        )),
-        (_, _) => reject(format!("invalid destination register (insn #{insn_ptr:?})")),
-    }
-}
-
-pub fn check(prog: &[u8]) -> Result<(), Error> {
-    check_prog_len(prog)?;
-
-    let mut insn_ptr: usize = 0;
-    while insn_ptr * ebpf::INSN_SIZE < prog.len() {
-        let insn = ebpf::get_insn(prog, insn_ptr);
-        let mut store = false;
-
-        match insn.opc {
-            // BPF_LD class
-            ebpf::LD_ABS_B => {}
-            ebpf::LD_ABS_H => {}
-            ebpf::LD_ABS_W => {}
-            ebpf::LD_ABS_DW => {}
-            ebpf::LD_IND_B => {}
-            ebpf::LD_IND_H => {}
-            ebpf::LD_IND_W => {}
-            ebpf::LD_IND_DW => {}
-
-            ebpf::LD_DW_IMM => {
-                store = true;
-                check_load_dw(prog, insn_ptr)?;
-                insn_ptr += 1;
-            }
-
-            // BPF_LDX class
-            ebpf::LD_B_REG => {}
-            ebpf::LD_H_REG => {}
-            ebpf::LD_W_REG => {}
-            ebpf::LD_DW_REG => {}
-
-            // BPF_ST class
-            ebpf::ST_B_IMM => store = true,
-            ebpf::ST_H_IMM => store = true,
-            ebpf::ST_W_IMM => store = true,
-            ebpf::ST_DW_IMM => store = true,
-
-            // BPF_STX class
-            ebpf::ST_B_REG => store = true,
-            ebpf::ST_H_REG => store = true,
-            ebpf::ST_W_REG => store = true,
-            ebpf::ST_DW_REG => store = true,
-            ebpf::ST_W_XADD => {
-                unimplemented!();
-            }
-            ebpf::ST_DW_XADD => {
-                unimplemented!();
-            }
-
-            // BPF_ALU class
-            ebpf::ADD32_IMM => {}
-            ebpf::ADD32_REG => {}
-            ebpf::SUB32_IMM => {}
-            ebpf::SUB32_REG => {}
-            ebpf::MUL32_IMM => {}
-            ebpf::MUL32_REG => {}
-            ebpf::DIV32_IMM => {}
-            ebpf::DIV32_REG => {}
-            ebpf::OR32_IMM => {}
-            ebpf::OR32_REG => {}
-            ebpf::AND32_IMM => {}
-            ebpf::AND32_REG => {}
-            ebpf::LSH32_IMM => {}
-            ebpf::LSH32_REG => {}
-            ebpf::RSH32_IMM => {}
-            ebpf::RSH32_REG => {}
-            ebpf::NEG32 => {}
-            ebpf::MOD32_IMM => {}
-            ebpf::MOD32_REG => {}
-            ebpf::XOR32_IMM => {}
-            ebpf::XOR32_REG => {}
-            ebpf::MOV32_IMM => {}
-            ebpf::MOV32_REG => {}
-            ebpf::ARSH32_IMM => {}
-            ebpf::ARSH32_REG => {}
-            ebpf::LE => {
-                check_imm_endian(&insn, insn_ptr)?;
-            }
-            ebpf::BE => {
-                check_imm_endian(&insn, insn_ptr)?;
-            }
-
-            // BPF_ALU64 class
-            ebpf::ADD64_IMM => {}
-            ebpf::ADD64_REG => {}
-            ebpf::SUB64_IMM => {}
-            ebpf::SUB64_REG => {}
-            ebpf::MUL64_IMM => {}
-            ebpf::MUL64_REG => {}
-            ebpf::DIV64_IMM => {}
-            ebpf::DIV64_REG => {}
-            ebpf::OR64_IMM => {}
-            ebpf::OR64_REG => {}
-            ebpf::AND64_IMM => {}
-            ebpf::AND64_REG => {}
-            ebpf::LSH64_IMM => {}
-            ebpf::LSH64_REG => {}
-            ebpf::RSH64_IMM => {}
-            ebpf::RSH64_REG => {}
-            ebpf::NEG64 => {}
-            ebpf::MOD64_IMM => {}
-            ebpf::MOD64_REG => {}
-            ebpf::XOR64_IMM => {}
-            ebpf::XOR64_REG => {}
-            ebpf::MOV64_IMM => {}
-            ebpf::MOV64_REG => {}
-            ebpf::ARSH64_IMM => {}
-            ebpf::ARSH64_REG => {}
-
-            // BPF_JMP class
-            ebpf::JA => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JEQ_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JEQ_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGT_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGT_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGE_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGE_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLT_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLT_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLE_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLE_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSET_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSET_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JNE_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JNE_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGT_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGT_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGE_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGE_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLT_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLT_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLE_IMM => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLE_REG => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-
-            // BPF_JMP32 class
-            ebpf::JEQ_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JEQ_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGT_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGT_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGE_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JGE_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLT_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLT_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLE_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JLE_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSET_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSET_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JNE_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JNE_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGT_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGT_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGE_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSGE_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLT_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLT_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLE_IMM32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-            ebpf::JSLE_REG32 => {
-                check_jmp_offset(prog, insn_ptr)?;
-            }
-
-            ebpf::CALL => {}
-            ebpf::TAIL_CALL => {
-                unimplemented!()
-            }
-            ebpf::EXIT => {}
-
-            _ => {
-                reject(format!(
-                    "unknown eBPF opcode {:#2x} (insn #{insn_ptr:?})",
-                    insn.opc
-                ))?;
-            }
-        }
-
-        check_registers(&insn, store, insn_ptr)?;
-
-        insn_ptr += 1;
-    }
-
-    // insn_ptr should now be equal to number of instructions.
-    if insn_ptr != prog.len() / ebpf::INSN_SIZE {
-        reject(format!("jumped out of code to #{insn_ptr:?}"))?;
-    }
-
-    Ok(())
-}

+ 0 - 655
kernel/crates/rbpf/tests/assembler.rs

@@ -1,655 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 Rich Lane <lanerl@gmail.com>
-
-#![allow(clippy::unreadable_literal)]
-
-extern crate rbpf;
-mod common;
-
-use common::{TCP_SACK_ASM, TCP_SACK_BIN};
-use rbpf::{assembler::assemble, ebpf};
-
-fn asm(src: &str) -> Result<Vec<ebpf::Insn>, String> {
-    Ok(ebpf::to_insn_vec(&(assemble(src))?))
-}
-
-fn insn(opc: u8, dst: u8, src: u8, off: i16, imm: i32) -> ebpf::Insn {
-    ebpf::Insn {
-        opc,
-        dst,
-        src,
-        off,
-        imm,
-    }
-}
-
-#[test]
-fn test_empty() {
-    assert_eq!(asm(""), Ok(vec![]));
-}
-
-// Example for InstructionType::NoOperand.
-#[test]
-fn test_exit() {
-    assert_eq!(asm("exit"), Ok(vec![insn(ebpf::EXIT, 0, 0, 0, 0)]));
-}
-
-// Example for InstructionType::AluBinary.
-#[test]
-fn test_add64() {
-    assert_eq!(
-        asm("add64 r1, r3"),
-        Ok(vec![insn(ebpf::ADD64_REG, 1, 3, 0, 0)])
-    );
-    assert_eq!(
-        asm("add64 r1, 5"),
-        Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 5)])
-    );
-}
-
-// Example for InstructionType::AluUnary.
-#[test]
-fn test_neg64() {
-    assert_eq!(asm("neg64 r1"), Ok(vec![insn(ebpf::NEG64, 1, 0, 0, 0)]));
-}
-
-// Example for InstructionType::LoadReg.
-#[test]
-fn test_ldxw() {
-    assert_eq!(
-        asm("ldxw r1, [r2+5]"),
-        Ok(vec![insn(ebpf::LD_W_REG, 1, 2, 5, 0)])
-    );
-}
-
-// Example for InstructionType::StoreImm.
-#[test]
-fn test_stw() {
-    assert_eq!(
-        asm("stw [r2+5], 7"),
-        Ok(vec![insn(ebpf::ST_W_IMM, 2, 0, 5, 7)])
-    );
-}
-
-// Example for InstructionType::StoreReg.
-#[test]
-fn test_stxw() {
-    assert_eq!(
-        asm("stxw [r2+5], r8"),
-        Ok(vec![insn(ebpf::ST_W_REG, 2, 8, 5, 0)])
-    );
-}
-
-// Example for InstructionType::JumpUnconditional.
-#[test]
-fn test_ja() {
-    assert_eq!(asm("ja +8"), Ok(vec![insn(ebpf::JA, 0, 0, 8, 0)]));
-    assert_eq!(asm("ja -3"), Ok(vec![insn(ebpf::JA, 0, 0, -3, 0)]));
-}
-
-// Example for InstructionType::JumpConditional.
-#[test]
-fn test_jeq() {
-    assert_eq!(
-        asm("jeq r1, 4, +8"),
-        Ok(vec![insn(ebpf::JEQ_IMM, 1, 0, 8, 4)])
-    );
-    assert_eq!(
-        asm("jeq r1, r3, +8"),
-        Ok(vec![insn(ebpf::JEQ_REG, 1, 3, 8, 0)])
-    );
-}
-
-// Example for InstructionType::Call.
-#[test]
-fn test_call() {
-    assert_eq!(asm("call 300"), Ok(vec![insn(ebpf::CALL, 0, 0, 0, 300)]));
-}
-
-// Example for InstructionType::Endian.
-#[test]
-fn test_be32() {
-    assert_eq!(asm("be32 r1"), Ok(vec![insn(ebpf::BE, 1, 0, 0, 32)]));
-}
-
-// Example for InstructionType::LoadImm.
-#[test]
-fn test_lddw() {
-    assert_eq!(
-        asm("lddw r1, 0x1234abcd5678eeff"),
-        Ok(vec![
-            insn(ebpf::LD_DW_IMM, 1, 0, 0, 0x5678eeff),
-            insn(0, 0, 0, 0, 0x1234abcd)
-        ])
-    );
-    assert_eq!(
-        asm("lddw r1, 0xff11ee22dd33cc44"),
-        Ok(vec![
-            insn(ebpf::LD_DW_IMM, 1, 0, 0, 0xdd33cc44u32 as i32),
-            insn(0, 0, 0, 0, 0xff11ee22u32 as i32)
-        ])
-    );
-}
-
-// Example for InstructionType::LoadAbs.
-#[test]
-fn test_ldabsw() {
-    assert_eq!(asm("ldabsw 1"), Ok(vec![insn(ebpf::LD_ABS_W, 0, 0, 0, 1)]));
-}
-
-// Example for InstructionType::LoadInd.
-#[test]
-fn test_ldindw() {
-    assert_eq!(
-        asm("ldindw r1, 2"),
-        Ok(vec![insn(ebpf::LD_IND_W, 0, 1, 0, 2)])
-    );
-}
-
-// Example for InstructionType::LoadReg.
-#[test]
-fn test_ldxdw() {
-    assert_eq!(
-        asm("ldxdw r1, [r2+3]"),
-        Ok(vec![insn(ebpf::LD_DW_REG, 1, 2, 3, 0)])
-    );
-}
-
-// Example for InstructionType::StoreImm.
-#[test]
-fn test_sth() {
-    assert_eq!(
-        asm("sth [r1+2], 3"),
-        Ok(vec![insn(ebpf::ST_H_IMM, 1, 0, 2, 3)])
-    );
-}
-
-// Example for InstructionType::StoreReg.
-#[test]
-fn test_stxh() {
-    assert_eq!(
-        asm("stxh [r1+2], r3"),
-        Ok(vec![insn(ebpf::ST_H_REG, 1, 3, 2, 0)])
-    );
-}
-
-// Test all supported AluBinary mnemonics.
-#[test]
-fn test_alu_binary() {
-    assert_eq!(
-        asm("add r1, r2
-                    sub r1, r2
-                    mul r1, r2
-                    div r1, r2
-                    or r1, r2
-                    and r1, r2
-                    lsh r1, r2
-                    rsh r1, r2
-                    mod r1, r2
-                    xor r1, r2
-                    mov r1, r2
-                    arsh r1, r2"),
-        Ok(vec![
-            insn(ebpf::ADD64_REG, 1, 2, 0, 0),
-            insn(ebpf::SUB64_REG, 1, 2, 0, 0),
-            insn(ebpf::MUL64_REG, 1, 2, 0, 0),
-            insn(ebpf::DIV64_REG, 1, 2, 0, 0),
-            insn(ebpf::OR64_REG, 1, 2, 0, 0),
-            insn(ebpf::AND64_REG, 1, 2, 0, 0),
-            insn(ebpf::LSH64_REG, 1, 2, 0, 0),
-            insn(ebpf::RSH64_REG, 1, 2, 0, 0),
-            insn(ebpf::MOD64_REG, 1, 2, 0, 0),
-            insn(ebpf::XOR64_REG, 1, 2, 0, 0),
-            insn(ebpf::MOV64_REG, 1, 2, 0, 0),
-            insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
-        ])
-    );
-
-    assert_eq!(
-        asm("add r1, 2
-                    sub r1, 2
-                    mul r1, 2
-                    div r1, 2
-                    or r1, 2
-                    and r1, 2
-                    lsh r1, 2
-                    rsh r1, 2
-                    mod r1, 2
-                    xor r1, 2
-                    mov r1, 2
-                    arsh r1, 2"),
-        Ok(vec![
-            insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
-            insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
-            insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
-            insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
-            insn(ebpf::OR64_IMM, 1, 0, 0, 2),
-            insn(ebpf::AND64_IMM, 1, 0, 0, 2),
-            insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
-            insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
-            insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
-            insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
-            insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
-            insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
-        ])
-    );
-
-    assert_eq!(
-        asm("add64 r1, r2
-                    sub64 r1, r2
-                    mul64 r1, r2
-                    div64 r1, r2
-                    or64 r1, r2
-                    and64 r1, r2
-                    lsh64 r1, r2
-                    rsh64 r1, r2
-                    mod64 r1, r2
-                    xor64 r1, r2
-                    mov64 r1, r2
-                    arsh64 r1, r2"),
-        Ok(vec![
-            insn(ebpf::ADD64_REG, 1, 2, 0, 0),
-            insn(ebpf::SUB64_REG, 1, 2, 0, 0),
-            insn(ebpf::MUL64_REG, 1, 2, 0, 0),
-            insn(ebpf::DIV64_REG, 1, 2, 0, 0),
-            insn(ebpf::OR64_REG, 1, 2, 0, 0),
-            insn(ebpf::AND64_REG, 1, 2, 0, 0),
-            insn(ebpf::LSH64_REG, 1, 2, 0, 0),
-            insn(ebpf::RSH64_REG, 1, 2, 0, 0),
-            insn(ebpf::MOD64_REG, 1, 2, 0, 0),
-            insn(ebpf::XOR64_REG, 1, 2, 0, 0),
-            insn(ebpf::MOV64_REG, 1, 2, 0, 0),
-            insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
-        ])
-    );
-
-    assert_eq!(
-        asm("add64 r1, 2
-                    sub64 r1, 2
-                    mul64 r1, 2
-                    div64 r1, 2
-                    or64 r1, 2
-                    and64 r1, 2
-                    lsh64 r1, 2
-                    rsh64 r1, 2
-                    mod64 r1, 2
-                    xor64 r1, 2
-                    mov64 r1, 2
-                    arsh64 r1, 2"),
-        Ok(vec![
-            insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
-            insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
-            insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
-            insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
-            insn(ebpf::OR64_IMM, 1, 0, 0, 2),
-            insn(ebpf::AND64_IMM, 1, 0, 0, 2),
-            insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
-            insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
-            insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
-            insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
-            insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
-            insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
-        ])
-    );
-
-    assert_eq!(
-        asm("add32 r1, r2
-                    sub32 r1, r2
-                    mul32 r1, r2
-                    div32 r1, r2
-                    or32 r1, r2
-                    and32 r1, r2
-                    lsh32 r1, r2
-                    rsh32 r1, r2
-                    mod32 r1, r2
-                    xor32 r1, r2
-                    mov32 r1, r2
-                    arsh32 r1, r2"),
-        Ok(vec![
-            insn(ebpf::ADD32_REG, 1, 2, 0, 0),
-            insn(ebpf::SUB32_REG, 1, 2, 0, 0),
-            insn(ebpf::MUL32_REG, 1, 2, 0, 0),
-            insn(ebpf::DIV32_REG, 1, 2, 0, 0),
-            insn(ebpf::OR32_REG, 1, 2, 0, 0),
-            insn(ebpf::AND32_REG, 1, 2, 0, 0),
-            insn(ebpf::LSH32_REG, 1, 2, 0, 0),
-            insn(ebpf::RSH32_REG, 1, 2, 0, 0),
-            insn(ebpf::MOD32_REG, 1, 2, 0, 0),
-            insn(ebpf::XOR32_REG, 1, 2, 0, 0),
-            insn(ebpf::MOV32_REG, 1, 2, 0, 0),
-            insn(ebpf::ARSH32_REG, 1, 2, 0, 0)
-        ])
-    );
-
-    assert_eq!(
-        asm("add32 r1, 2
-                    sub32 r1, 2
-                    mul32 r1, 2
-                    div32 r1, 2
-                    or32 r1, 2
-                    and32 r1, 2
-                    lsh32 r1, 2
-                    rsh32 r1, 2
-                    mod32 r1, 2
-                    xor32 r1, 2
-                    mov32 r1, 2
-                    arsh32 r1, 2"),
-        Ok(vec![
-            insn(ebpf::ADD32_IMM, 1, 0, 0, 2),
-            insn(ebpf::SUB32_IMM, 1, 0, 0, 2),
-            insn(ebpf::MUL32_IMM, 1, 0, 0, 2),
-            insn(ebpf::DIV32_IMM, 1, 0, 0, 2),
-            insn(ebpf::OR32_IMM, 1, 0, 0, 2),
-            insn(ebpf::AND32_IMM, 1, 0, 0, 2),
-            insn(ebpf::LSH32_IMM, 1, 0, 0, 2),
-            insn(ebpf::RSH32_IMM, 1, 0, 0, 2),
-            insn(ebpf::MOD32_IMM, 1, 0, 0, 2),
-            insn(ebpf::XOR32_IMM, 1, 0, 0, 2),
-            insn(ebpf::MOV32_IMM, 1, 0, 0, 2),
-            insn(ebpf::ARSH32_IMM, 1, 0, 0, 2)
-        ])
-    );
-}
-
-// Test all supported AluUnary mnemonics.
-#[test]
-fn test_alu_unary() {
-    assert_eq!(
-        asm("neg r1
-                    neg64 r1
-                    neg32 r1"),
-        Ok(vec![
-            insn(ebpf::NEG64, 1, 0, 0, 0),
-            insn(ebpf::NEG64, 1, 0, 0, 0),
-            insn(ebpf::NEG32, 1, 0, 0, 0)
-        ])
-    );
-}
-
-// Test all supported LoadAbs mnemonics.
-#[test]
-fn test_load_abs() {
-    assert_eq!(
-        asm("ldabsw 1
-                    ldabsh 1
-                    ldabsb 1
-                    ldabsdw 1"),
-        Ok(vec![
-            insn(ebpf::LD_ABS_W, 0, 0, 0, 1),
-            insn(ebpf::LD_ABS_H, 0, 0, 0, 1),
-            insn(ebpf::LD_ABS_B, 0, 0, 0, 1),
-            insn(ebpf::LD_ABS_DW, 0, 0, 0, 1)
-        ])
-    );
-}
-
-// Test all supported LoadInd mnemonics.
-#[test]
-fn test_load_ind() {
-    assert_eq!(
-        asm("ldindw r1, 2
-                    ldindh r1, 2
-                    ldindb r1, 2
-                    ldinddw r1, 2"),
-        Ok(vec![
-            insn(ebpf::LD_IND_W, 0, 1, 0, 2),
-            insn(ebpf::LD_IND_H, 0, 1, 0, 2),
-            insn(ebpf::LD_IND_B, 0, 1, 0, 2),
-            insn(ebpf::LD_IND_DW, 0, 1, 0, 2)
-        ])
-    );
-}
-
-// Test all supported LoadReg mnemonics.
-#[test]
-fn test_load_reg() {
-    assert_eq!(
-        asm("ldxw r1, [r2+3]
-                    ldxh r1, [r2+3]
-                    ldxb r1, [r2+3]
-                    ldxdw r1, [r2+3]"),
-        Ok(vec![
-            insn(ebpf::LD_W_REG, 1, 2, 3, 0),
-            insn(ebpf::LD_H_REG, 1, 2, 3, 0),
-            insn(ebpf::LD_B_REG, 1, 2, 3, 0),
-            insn(ebpf::LD_DW_REG, 1, 2, 3, 0)
-        ])
-    );
-}
-
-// Test all supported StoreImm mnemonics.
-#[test]
-fn test_store_imm() {
-    assert_eq!(
-        asm("stw [r1+2], 3
-                    sth [r1+2], 3
-                    stb [r1+2], 3
-                    stdw [r1+2], 3"),
-        Ok(vec![
-            insn(ebpf::ST_W_IMM, 1, 0, 2, 3),
-            insn(ebpf::ST_H_IMM, 1, 0, 2, 3),
-            insn(ebpf::ST_B_IMM, 1, 0, 2, 3),
-            insn(ebpf::ST_DW_IMM, 1, 0, 2, 3)
-        ])
-    );
-}
-
-// Test all supported StoreReg mnemonics.
-#[test]
-fn test_store_reg() {
-    assert_eq!(
-        asm("stxw [r1+2], r3
-                    stxh [r1+2], r3
-                    stxb [r1+2], r3
-                    stxdw [r1+2], r3"),
-        Ok(vec![
-            insn(ebpf::ST_W_REG, 1, 3, 2, 0),
-            insn(ebpf::ST_H_REG, 1, 3, 2, 0),
-            insn(ebpf::ST_B_REG, 1, 3, 2, 0),
-            insn(ebpf::ST_DW_REG, 1, 3, 2, 0)
-        ])
-    );
-}
-
-// Test all supported JumpConditional mnemonics.
-#[test]
-fn test_jump_conditional() {
-    assert_eq!(
-        asm("jeq r1, r2, +3
-                    jgt r1, r2, +3
-                    jge r1, r2, +3
-                    jlt r1, r2, +3
-                    jle r1, r2, +3
-                    jset r1, r2, +3
-                    jne r1, r2, +3
-                    jsgt r1, r2, +3
-                    jsge r1, r2, +3
-                    jslt r1, r2, +3
-                    jsle r1, r2, +3"),
-        Ok(vec![
-            insn(ebpf::JEQ_REG, 1, 2, 3, 0),
-            insn(ebpf::JGT_REG, 1, 2, 3, 0),
-            insn(ebpf::JGE_REG, 1, 2, 3, 0),
-            insn(ebpf::JLT_REG, 1, 2, 3, 0),
-            insn(ebpf::JLE_REG, 1, 2, 3, 0),
-            insn(ebpf::JSET_REG, 1, 2, 3, 0),
-            insn(ebpf::JNE_REG, 1, 2, 3, 0),
-            insn(ebpf::JSGT_REG, 1, 2, 3, 0),
-            insn(ebpf::JSGE_REG, 1, 2, 3, 0),
-            insn(ebpf::JSLT_REG, 1, 2, 3, 0),
-            insn(ebpf::JSLE_REG, 1, 2, 3, 0)
-        ])
-    );
-
-    assert_eq!(
-        asm("jeq r1, 2, +3
-                    jgt r1, 2, +3
-                    jge r1, 2, +3
-                    jlt r1, 2, +3
-                    jle r1, 2, +3
-                    jset r1, 2, +3
-                    jne r1, 2, +3
-                    jsgt r1, 2, +3
-                    jsge r1, 2, +3
-                    jslt r1, 2, +3
-                    jsle r1, 2, +3"),
-        Ok(vec![
-            insn(ebpf::JEQ_IMM, 1, 0, 3, 2),
-            insn(ebpf::JGT_IMM, 1, 0, 3, 2),
-            insn(ebpf::JGE_IMM, 1, 0, 3, 2),
-            insn(ebpf::JLT_IMM, 1, 0, 3, 2),
-            insn(ebpf::JLE_IMM, 1, 0, 3, 2),
-            insn(ebpf::JSET_IMM, 1, 0, 3, 2),
-            insn(ebpf::JNE_IMM, 1, 0, 3, 2),
-            insn(ebpf::JSGT_IMM, 1, 0, 3, 2),
-            insn(ebpf::JSGE_IMM, 1, 0, 3, 2),
-            insn(ebpf::JSLT_IMM, 1, 0, 3, 2),
-            insn(ebpf::JSLE_IMM, 1, 0, 3, 2)
-        ])
-    );
-
-    assert_eq!(
-        asm("jeq32 r1, r2, +3
-                    jgt32 r1, r2, +3
-                    jge32 r1, r2, +3
-                    jlt32 r1, r2, +3
-                    jle32 r1, r2, +3
-                    jset32 r1, r2, +3
-                    jne32 r1, r2, +3
-                    jsgt32 r1, r2, +3
-                    jsge32 r1, r2, +3
-                    jslt32 r1, r2, +3
-                    jsle32 r1, r2, +3"),
-        Ok(vec![
-            insn(ebpf::JEQ_REG32, 1, 2, 3, 0),
-            insn(ebpf::JGT_REG32, 1, 2, 3, 0),
-            insn(ebpf::JGE_REG32, 1, 2, 3, 0),
-            insn(ebpf::JLT_REG32, 1, 2, 3, 0),
-            insn(ebpf::JLE_REG32, 1, 2, 3, 0),
-            insn(ebpf::JSET_REG32, 1, 2, 3, 0),
-            insn(ebpf::JNE_REG32, 1, 2, 3, 0),
-            insn(ebpf::JSGT_REG32, 1, 2, 3, 0),
-            insn(ebpf::JSGE_REG32, 1, 2, 3, 0),
-            insn(ebpf::JSLT_REG32, 1, 2, 3, 0),
-            insn(ebpf::JSLE_REG32, 1, 2, 3, 0)
-        ])
-    );
-
-    assert_eq!(
-        asm("jeq32 r1, 2, +3
-                    jgt32 r1, 2, +3
-                    jge32 r1, 2, +3
-                    jlt32 r1, 2, +3
-                    jle32 r1, 2, +3
-                    jset32 r1, 2, +3
-                    jne32 r1, 2, +3
-                    jsgt32 r1, 2, +3
-                    jsge32 r1, 2, +3
-                    jslt32 r1, 2, +3
-                    jsle32 r1, 2, +3"),
-        Ok(vec![
-            insn(ebpf::JEQ_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JGT_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JGE_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JLT_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JLE_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JSET_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JNE_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JSGT_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JSGE_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JSLT_IMM32, 1, 0, 3, 2),
-            insn(ebpf::JSLE_IMM32, 1, 0, 3, 2)
-        ])
-    );
-}
-
-// Test all supported Endian mnemonics.
-#[test]
-fn test_endian() {
-    assert_eq!(
-        asm("be16 r1
-                    be32 r1
-                    be64 r1
-                    le16 r1
-                    le32 r1
-                    le64 r1"),
-        Ok(vec![
-            insn(ebpf::BE, 1, 0, 0, 16),
-            insn(ebpf::BE, 1, 0, 0, 32),
-            insn(ebpf::BE, 1, 0, 0, 64),
-            insn(ebpf::LE, 1, 0, 0, 16),
-            insn(ebpf::LE, 1, 0, 0, 32),
-            insn(ebpf::LE, 1, 0, 0, 64)
-        ])
-    );
-}
-
-#[test]
-fn test_large_immediate() {
-    assert_eq!(
-        asm("add64 r1, 2147483647"),
-        Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2147483647)])
-    );
-    assert_eq!(
-        asm("add64 r1, -2147483648"),
-        Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, -2147483648)])
-    );
-}
-
-#[test]
-fn test_tcp_sack() {
-    assert_eq!(assemble(TCP_SACK_ASM), Ok(TCP_SACK_BIN.to_vec()));
-}
-
-#[test]
-fn test_error_invalid_instruction() {
-    assert_eq!(asm("abcd"), Err("Invalid instruction \"abcd\"".to_string()));
-}
-
-#[test]
-fn test_error_unexpected_operands() {
-    assert_eq!(
-        asm("add 1, 2"),
-        Err("Failed to encode add: Unexpected operands: [Integer(1), Integer(2)]".to_string())
-    );
-}
-
-#[test]
-fn test_error_too_many_operands() {
-    assert_eq!(
-        asm("add 1, 2, 3, 4"),
-        Err("Failed to encode add: Too many operands".to_string())
-    );
-}
-
-#[test]
-fn test_error_operands_out_of_range() {
-    assert_eq!(
-        asm("add r16, r2"),
-        Err("Failed to encode add: Invalid destination register 16".to_string())
-    );
-    assert_eq!(
-        asm("add r1, r16"),
-        Err("Failed to encode add: Invalid source register 16".to_string())
-    );
-    assert_eq!(
-        asm("ja -32769"),
-        Err("Failed to encode ja: Invalid offset -32769".to_string())
-    );
-    assert_eq!(
-        asm("ja 32768"),
-        Err("Failed to encode ja: Invalid offset 32768".to_string())
-    );
-    assert_eq!(
-        asm("add r1, 4294967296"),
-        Err("Failed to encode add: Invalid immediate 4294967296".to_string())
-    );
-    assert_eq!(
-        asm("add r1, 2147483648"),
-        Err("Failed to encode add: Invalid immediate 2147483648".to_string())
-    );
-    assert_eq!(
-        asm("add r1, -2147483649"),
-        Err("Failed to encode add: Invalid immediate -2147483649".to_string())
-    );
-}

+ 0 - 97
kernel/crates/rbpf/tests/common.rs

@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Converted from the tests for uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-// Assembly code and data for tcp_sack testcases.
-
-#[allow(dead_code)]
-pub const TCP_SACK_ASM: &str = "
-    ldxb r2, [r1+12]
-    ldxb r3, [r1+13]
-    lsh r3, 0x8
-    or r3, r2
-    mov r0, 0x0
-    jne r3, 0x8, +37
-    ldxb r2, [r1+23]
-    jne r2, 0x6, +35
-    ldxb r2, [r1+14]
-    add r1, 0xe
-    and r2, 0xf
-    lsh r2, 0x2
-    add r1, r2
-    mov r0, 0x0
-    ldxh r4, [r1+12]
-    add r1, 0x14
-    rsh r4, 0x2
-    and r4, 0x3c
-    mov r2, r4
-    add r2, -20
-    mov r5, 0x15
-    mov r3, 0x0
-    jgt r5, r4, +20
-    mov r5, r3
-    lsh r5, 0x20
-    arsh r5, 0x20
-    mov r4, r1
-    add r4, r5
-    ldxb r5, [r4]
-    jeq r5, 0x1, +4
-    jeq r5, 0x0, +12
-    mov r6, r3
-    jeq r5, 0x5, +9
-    ja +2
-    add r3, 0x1
-    mov r6, r3
-    ldxb r3, [r4+1]
-    add r3, r6
-    lsh r3, 0x20
-    arsh r3, 0x20
-    jsgt r2, r3, -18
-    ja +1
-    mov r0, 0x1
-    exit";
-
-#[allow(dead_code)]
-pub const TCP_SACK_BIN: [u8; 352] = [
-    0x71, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x13, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x67, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x25, 0x00, 0x08, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x02, 0x23, 0x00, 0x06, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-    0x57, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x0f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x69, 0x14, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
-    0x77, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x57, 0x04, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
-    0xbf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xec, 0xff, 0xff, 0xff,
-    0xb7, 0x05, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x2d, 0x45, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x67, 0x05, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc7, 0x05, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-    0xbf, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x71, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x15, 0x05, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x15, 0x05, 0x09, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x07, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x71, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x67, 0x03, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc7, 0x03, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-    0x6d, 0x32, 0xee, 0xff, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-];
-
-#[allow(dead_code)]
-pub const TCP_SACK_MATCH: [u8; 78] = [
-    0x00, 0x26, 0x62, 0x2f, 0x47, 0x87, 0x00, 0x1d, 0x60, 0xb3, 0x01, 0x84, 0x08, 0x00, 0x45, 0x00,
-    0x00, 0x40, 0xa8, 0xde, 0x40, 0x00, 0x40, 0x06, 0x9d, 0x58, 0xc0, 0xa8, 0x01, 0x03, 0x3f, 0x74,
-    0xf3, 0x61, 0xe5, 0xc0, 0x00, 0x50, 0xe5, 0x94, 0x3f, 0x77, 0xa3, 0xc4, 0xc4, 0x80, 0xb0, 0x10,
-    0x01, 0x3e, 0x34, 0xb6, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x17, 0x95, 0x6f, 0x8d, 0x9d,
-    0x9e, 0x27, 0x01, 0x01, 0x05, 0x0a, 0xa3, 0xc4, 0xca, 0x28, 0xa3, 0xc4, 0xcf, 0xd0,
-];
-
-#[allow(dead_code)]
-pub const TCP_SACK_NOMATCH: [u8; 66] = [
-    0x00, 0x26, 0x62, 0x2f, 0x47, 0x87, 0x00, 0x1d, 0x60, 0xb3, 0x01, 0x84, 0x08, 0x00, 0x45, 0x00,
-    0x00, 0x40, 0xa8, 0xde, 0x40, 0x00, 0x40, 0x06, 0x9d, 0x58, 0xc0, 0xa8, 0x01, 0x03, 0x3f, 0x74,
-    0xf3, 0x61, 0xe5, 0xc0, 0x00, 0x50, 0xe5, 0x94, 0x3f, 0x77, 0xa3, 0xc4, 0xc4, 0x80, 0x80, 0x10,
-    0x01, 0x3e, 0x34, 0xb6, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x17, 0x95, 0x6f, 0x8d, 0x9d,
-    0x9e, 0x27,
-];

+ 0 - 2257
kernel/crates/rbpf/tests/cranelift.rs

@@ -1,2257 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-#![allow(clippy::unreadable_literal)]
-#![cfg(feature = "cranelift")]
-
-extern crate rbpf;
-mod common;
-
-use rbpf::{assembler::assemble, helpers};
-
-use crate::common::{TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH};
-
-macro_rules! test_cranelift {
-    ($name:ident, $prog:expr, $expected:expr) => {
-        #[test]
-        fn $name() {
-            let prog = assemble($prog).unwrap();
-            let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-            vm.cranelift_compile().unwrap();
-            assert_eq!(vm.execute_program_cranelift().unwrap(), $expected);
-        }
-    };
-    ($name:ident, $prog:expr, $mem:expr, $expected:expr) => {
-        #[test]
-        fn $name() {
-            let prog = assemble($prog).unwrap();
-            let mem = &mut $mem;
-            let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-            vm.cranelift_compile().unwrap();
-            assert_eq!(vm.execute_program_cranelift(mem).unwrap(), $expected);
-        }
-    };
-}
-
-test_cranelift!(
-    test_cranelift_add,
-    "
-    mov32 r0, 0
-    mov32 r1, 2
-    add32 r0, 1
-    add32 r0, r1
-    exit
-    ",
-    0x3
-);
-
-test_cranelift!(
-    test_cranelift_alu64_arith,
-    "
-    mov r0, 0
-    mov r1, 1
-    mov r2, 2
-    mov r3, 3
-    mov r4, 4
-    mov r5, 5
-    mov r6, 6
-    mov r7, 7
-    mov r8, 8
-    mov r9, 9
-    add r0, 23
-    add r0, r7
-    sub r0, 13
-    sub r0, r1
-    mul r0, 7
-    mul r0, r3
-    div r0, 2
-    div r0, r4
-    exit
-    ",
-    0x2a
-);
-
-test_cranelift!(
-    test_cranelift_alu64_bit,
-    "
-    mov r0, 0
-    mov r1, 1
-    mov r2, 2
-    mov r3, 3
-    mov r4, 4
-    mov r5, 5
-    mov r6, 6
-    mov r7, 7
-    mov r8, 8
-    or r0, r5
-    or r0, 0xa0
-    and r0, 0xa3
-    mov r9, 0x91
-    and r0, r9
-    lsh r0, 32
-    lsh r0, 22
-    lsh r0, r8
-    rsh r0, 32
-    rsh r0, 19
-    rsh r0, r7
-    xor r0, 0x03
-    xor r0, r2
-    exit
-    ",
-    0x11
-);
-
-test_cranelift!(
-    test_cranelift_alu_arith,
-    "
-    mov32 r0, 0
-    mov32 r1, 1
-    mov32 r2, 2
-    mov32 r3, 3
-    mov32 r4, 4
-    mov32 r5, 5
-    mov32 r6, 6
-    mov32 r7, 7
-    mov32 r8, 8
-    mov32 r9, 9
-    add32 r0, 23
-    add32 r0, r7
-    sub32 r0, 13
-    sub32 r0, r1
-    mul32 r0, 7
-    mul32 r0, r3
-    div32 r0, 2
-    div32 r0, r4
-    exit
-    ",
-    0x2a
-);
-
-test_cranelift!(
-    test_cranelift_alu_bit,
-    "
-    mov32 r0, 0
-    mov32 r1, 1
-    mov32 r2, 2
-    mov32 r3, 3
-    mov32 r4, 4
-    mov32 r5, 5
-    mov32 r6, 6
-    mov32 r7, 7
-    mov32 r8, 8
-    or32 r0, r5
-    or32 r0, 0xa0
-    and32 r0, 0xa3
-    mov32 r9, 0x91
-    and32 r0, r9
-    lsh32 r0, 22
-    lsh32 r0, r8
-    rsh32 r0, 19
-    rsh32 r0, r7
-    xor32 r0, 0x03
-    xor32 r0, r2
-    exit
-    ",
-    0x11
-);
-
-test_cranelift!(
-    test_cranelift_arsh32_high_shift,
-    "
-    mov r0, 8
-    lddw r1, 0x100000001
-    arsh32 r0, r1
-    exit
-    ",
-    0x4
-);
-
-test_cranelift!(
-    test_cranelift_arsh,
-    "
-    mov32 r0, 0xf8
-    lsh32 r0, 28
-    arsh32 r0, 16
-    exit
-    ",
-    0xffff8000
-);
-
-test_cranelift!(
-    test_cranelift_arsh64,
-    "
-    mov32 r0, 1
-    lsh r0, 63
-    arsh r0, 55
-    mov32 r1, 5
-    arsh r0, r1
-    exit
-    ",
-    0xfffffffffffffff8
-);
-
-test_cranelift!(
-    test_cranelift_arsh_reg,
-    "
-    mov32 r0, 0xf8
-    mov32 r1, 16
-    lsh32 r0, 28
-    arsh32 r0, r1
-    exit
-    ",
-    0xffff8000
-);
-
-test_cranelift!(
-    test_cranelift_be16,
-    "
-    ldxh r0, [r1]
-    be16 r0
-    exit
-    ",
-    [0x11, 0x22],
-    0x1122
-);
-
-test_cranelift!(
-    test_cranelift_be16_high,
-    "
-    ldxdw r0, [r1]
-    be16 r0
-    exit
-    ",
-    [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
-    0x1122
-);
-
-test_cranelift!(
-    test_cranelift_be32,
-    "
-    ldxw r0, [r1]
-    be32 r0
-    exit
-    ",
-    [0x11, 0x22, 0x33, 0x44],
-    0x11223344
-);
-
-test_cranelift!(
-    test_cranelift_be32_high,
-    "
-    ldxdw r0, [r1]
-    be32 r0
-    exit
-    ",
-    [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
-    0x11223344
-);
-
-test_cranelift!(
-    test_cranelift_be64,
-    "
-    ldxdw r0, [r1]
-    be64 r0
-    exit
-    ",
-    [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
-    0x1122334455667788
-);
-
-#[test]
-fn test_cranelift_call() {
-    let prog = assemble(
-        "
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        call 0
-        exit",
-    )
-    .unwrap();
-
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift().unwrap(), 0x0102030405);
-}
-
-#[test]
-#[should_panic(expected = "[CRANELIFT] Error: unknown helper function (id: 0x3f)")]
-fn test_cranelift_err_call_unreg() {
-    let prog = assemble(
-        "
-         mov r1, 1
-         mov r2, 2
-         mov r3, 3
-         mov r4, 4
-         mov r5, 5
-         call 63
-         exit
-    ",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-}
-
-#[test]
-fn test_cranelift_call_memfrob() {
-    let prog = assemble(
-        "
-        mov r6, r1
-        add r1, 2
-        mov r2, 4
-        call 1
-        ldxdw r0, [r6]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.register_helper(1, helpers::memfrob).unwrap();
-    let mem = &mut [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
-    vm.cranelift_compile().unwrap();
-    assert_eq!(
-        vm.execute_program_cranelift(mem).unwrap(),
-        0x102292e2f2c0708
-    );
-}
-
-test_cranelift!(
-    test_cranelift_div32_high_divisor,
-    "
-    mov r0, 12
-    lddw r1, 0x100000004
-    div32 r0, r1
-    exit
-    ",
-    0x3
-);
-
-test_cranelift!(
-    test_cranelift_div32_imm,
-    "
-    lddw r0, 0x10000000c
-    div32 r0, 4
-    exit
-    ",
-    0x3
-);
-
-test_cranelift!(
-    test_cranelift_div32_reg,
-    "
-    lddw r0, 0x10000000c
-    mov r1, 4
-    div32 r0, r1
-    exit
-    ",
-    0x3
-);
-
-test_cranelift!(
-    test_cranelift_div64_imm,
-    "
-    mov r0, 0xc
-    lsh r0, 32
-    div r0, 4
-    exit
-    ",
-    0x300000000
-);
-
-test_cranelift!(
-    test_cranelift_div64_reg,
-    "
-    mov r0, 0xc
-    lsh r0, 32
-    mov r1, 4
-    div r0, r1
-    exit
-    ",
-    0x300000000
-);
-
-test_cranelift!(
-    test_cranelift_early_exit,
-    "
-    mov r0, 3
-    exit
-    mov r0, 4
-    exit
-    ",
-    0x3
-);
-
-test_cranelift!(
-    test_cranelift_div64_by_zero_imm,
-    "
-    mov32 r0, 1
-    div r0, 0
-    exit
-    ",
-    0x0
-);
-
-test_cranelift!(
-    test_cranelift_div_by_zero_imm,
-    "
-    mov32 r0, 1
-    div32 r0, 0
-    exit
-    ",
-    0x0
-);
-
-test_cranelift!(
-    test_cranelift_mod64_by_zero_imm,
-    "
-    mov32 r0, 1
-    mod r0, 0
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_mod_by_zero_imm,
-    "
-    mov32 r0, 1
-    mod32 r0, 0
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_div64_by_zero_reg,
-    "
-    mov32 r0, 1
-    mov32 r1, 0
-    div r0, r1
-    exit
-    ",
-    0x0
-);
-
-test_cranelift!(
-    test_cranelift_div_by_zero_reg,
-    "
-    mov32 r0, 1
-    mov32 r1, 0
-    div32 r0, r1
-    exit
-    ",
-    0x0
-);
-
-test_cranelift!(
-    test_cranelift_mod64_by_zero_reg,
-    "
-    mov32 r0, 1
-    mov32 r1, 0
-    mod r0, r1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_mod_by_zero_reg,
-    "
-    mov32 r0, 1
-    mov32 r1, 0
-    mod32 r0, r1
-    exit
-    ",
-    0x1
-);
-
-#[test]
-// #[should_panic(expected = "Error: out of bounds memory store (insn #1)")]
-#[ignore = "We have stack OOB checks, but we don't yet catch the trap code and convert it into a panic"]
-fn test_cranelift_err_stack_out_of_bound() {
-    let prog = [
-        0x72, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    vm.execute_program_cranelift().unwrap();
-}
-
-test_cranelift!(
-    test_cranelift_exit,
-    "
-    mov r0, 0
-    exit
-    ",
-    0x0
-);
-
-test_cranelift!(
-    test_cranelift_ja,
-    "
-    mov r0, 1
-    ja +1
-    mov r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jeq_imm,
-    "
-    mov32 r0, 0
-    mov32 r1, 0xa
-    jeq r1, 0xb, +4
-    mov32 r0, 1
-    mov32 r1, 0xb
-    jeq r1, 0xb, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jeq_reg,
-    "
-    mov32 r0, 0
-    mov32 r1, 0xa
-    mov32 r2, 0xb
-    jeq r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0xb
-    jeq r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jge_imm,
-    "
-    mov32 r0, 0
-    mov32 r1, 0xa
-    jge r1, 0xb, +4
-    mov32 r0, 1
-    mov32 r1, 0xc
-    jge r1, 0xb, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jle_imm,
-    "
-    mov32 r0, 0
-    mov32 r1, 5
-    jle r1, 4, +1
-    jle r1, 6, +1
-    exit
-    jle r1, 5, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jle_reg,
-    "
-    mov r0, 0
-    mov r1, 5
-    mov r2, 4
-    mov r3, 6
-    jle r1, r2, +2
-    jle r1, r1, +1
-    exit
-    jle r1, r3, +1
-    exit
-    mov r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jgt_imm,
-    "
-    mov32 r0, 0
-    mov32 r1, 5
-    jgt r1, 6, +2
-    jgt r1, 5, +1
-    jgt r1, 4, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jgt_reg,
-    "
-    mov r0, 0
-    mov r1, 5
-    mov r2, 6
-    mov r3, 4
-    jgt r1, r2, +2
-    jgt r1, r1, +1
-    jgt r1, r3, +1
-    exit
-    mov r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jlt_imm,
-    "
-    mov32 r0, 0
-    mov32 r1, 5
-    jlt r1, 4, +2
-    jlt r1, 5, +1
-    jlt r1, 6, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jlt_reg,
-    "
-    mov r0, 0
-    mov r1, 5
-    mov r2, 4
-    mov r3, 6
-    jlt r1, r2, +2
-    jlt r1, r1, +1
-    jlt r1, r3, +1
-    exit
-    mov r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jit_bounce,
-    "
-    mov r0, 1
-    mov r6, r0
-    mov r7, r6
-    mov r8, r7
-    mov r9, r8
-    mov r0, r9
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jne_reg,
-    "
-    mov32 r0, 0
-    mov32 r1, 0xb
-    mov32 r2, 0xb
-    jne r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0xa
-    jne r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jset_imm,
-    "
-    mov32 r0, 0
-    mov32 r1, 0x7
-    jset r1, 0x8, +4
-    mov32 r0, 1
-    mov32 r1, 0x9
-    jset r1, 0x8, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jset_reg,
-    "
-    mov32 r0, 0
-    mov32 r1, 0x7
-    mov32 r2, 0x8
-    jset r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0x9
-    jset r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsge_imm,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    jsge r1, -1, +5
-    jsge r1, 0, +4
-    mov32 r0, 1
-    mov r1, -1
-    jsge r1, -1, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsge_reg,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    mov r2, -1
-    mov32 r3, 0
-    jsge r1, r2, +5
-    jsge r1, r3, +4
-    mov32 r0, 1
-    mov r1, r2
-    jsge r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsle_imm,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    jsle r1, -3, +1
-    jsle r1, -1, +1
-    exit
-    mov32 r0, 1
-    jsle r1, -2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsle_reg,
-    "
-    mov32 r0, 0
-    mov r1, -1
-    mov r2, -2
-    mov32 r3, 0
-    jsle r1, r2, +1
-    jsle r1, r3, +1
-    exit
-    mov32 r0, 1
-    mov r1, r2
-    jsle r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsgt_imm,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    jsgt r1, -1, +4
-    mov32 r0, 1
-    mov32 r1, 0
-    jsgt r1, -1, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsgt_reg,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    mov r2, -1
-    jsgt r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0
-    jsgt r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jslt_imm,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    jslt r1, -3, +2
-    jslt r1, -2, +1
-    jslt r1, -1, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jslt_reg,
-    "
-    mov32 r0, 0
-    mov r1, -2
-    mov r2, -3
-    mov r3, -1
-    jslt r1, r1, +2
-    jslt r1, r2, +1
-    jslt r1, r3, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jeq32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0x0
-    mov32 r1, 0xa
-    jeq32 r1, 0xb, +5
-    mov32 r0, 1
-    mov r1, 0xb
-    or r1, r9
-    jeq32 r1, 0xb, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jeq32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0xa
-    mov32 r2, 0xb
-    jeq32 r1, r2, +5
-    mov32 r0, 1
-    mov32 r1, 0xb
-    or r1, r9
-    jeq32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jge32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0xa
-    jge32 r1, 0xb, +5
-    mov32 r0, 1
-    or r1, r9
-    mov32 r1, 0xc
-    jge32 r1, 0xb, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jge32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0xa
-    mov32 r2, 0xb
-    jge32 r1, r2, +5
-    mov32 r0, 1
-    or r1, r9
-    mov32 r1, 0xc
-    jge32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jgt32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 5
-    or r1, r9
-    jgt32 r1, 6, +4
-    jgt32 r1, 5, +3
-    jgt32 r1, 4, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jgt32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov r0, 0
-    mov r1, 5
-    mov32 r1, 5
-    or r1, r9
-    mov r2, 6
-    mov r3, 4
-    jgt32 r1, r2, +4
-    jgt32 r1, r1, +3
-    jgt32 r1, r3, +1
-    exit
-    mov r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jle32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 5
-    or r1, r9
-    jle32 r1, 4, +5
-    jle32 r1, 6, +1
-    exit
-    jle32 r1, 5, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jle32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov r0, 0
-    mov r1, 5
-    mov r2, 4
-    mov r3, 6
-    or r1, r9
-    jle32 r1, r2, +5
-    jle32 r1, r1, +1
-    exit
-    jle32 r1, r3, +1
-    exit
-    mov r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jlt32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 5
-    or r1, r9
-    jlt32 r1, 4, +4
-    jlt32 r1, 5, +3
-    jlt32 r1, 6, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jlt32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov r0, 0
-    mov r1, 5
-    mov r2, 4
-    mov r3, 6
-    or r1, r9
-    jlt32 r1, r2, +4
-    jlt32 r1, r1, +3
-    jlt32 r1, r3, +1
-    exit
-    mov r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jne32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0xb
-    or r1, r9
-    jne32 r1, 0xb, +4
-    mov32 r0, 1
-    mov32 r1, 0xa
-    or r1, r9
-    jne32 r1, 0xb, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jne32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0xb
-    or r1, r9
-    mov32 r2, 0xb
-    jne32 r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0xa
-    or r1, r9
-    jne32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jset32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0x7
-    or r1, r9
-    jset32 r1, 0x8, +4
-    mov32 r0, 1
-    mov32 r1, 0x9
-    jset32 r1, 0x8, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jset32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, 0x7
-    or r1, r9
-    mov32 r2, 0x8
-    jset32 r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0x9
-    jset32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsge32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    jsge32 r1, -1, +5
-    jsge32 r1, 0, +4
-    mov32 r0, 1
-    mov r1, -1
-    jsge32 r1, -1, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsge32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    mov r2, -1
-    mov32 r3, 0
-    jsge32 r1, r2, +5
-    jsge32 r1, r3, +4
-    mov32 r0, 1
-    mov r1, r2
-    jsge32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsgt32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    jsgt32 r1, -1, +4
-    mov32 r0, 1
-    mov32 r1, 0
-    jsgt32 r1, -1, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsgt32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    mov r2, -1
-    jsgt32 r1, r2, +4
-    mov32 r0, 1
-    mov32 r1, 0
-    jsgt32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsle32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    jsle32 r1, -3, +5
-    jsle32 r1, -1, +1
-    exit
-    mov32 r0, 1
-    jsle32 r1, -2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jsle32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    mov r2, -3
-    mov32 r3, 0
-    jsle32 r1, r2, +6
-    jsle32 r1, r3, +1
-    exit
-    mov32 r0, 1
-    mov r1, r2
-    jsle32 r1, r2, +1
-    mov32 r0, 2
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jslt32_imm,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    jslt32 r1, -3, +4
-    jslt32 r1, -2, +3
-    jslt32 r1, -1, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_jslt32_reg,
-    "
-    mov r9, 1
-    lsh r9, 32
-    mov32 r0, 0
-    mov32 r1, -2
-    or r1, r9
-    mov r2, -3
-    mov r3, -1
-    jslt32 r1, r1, +4
-    jslt32 r1, r2, +3
-    jslt32 r1, r3, +1
-    exit
-    mov32 r0, 1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_lddw,
-    "
-    lddw r0, 0x1122334455667788
-    exit
-    ",
-    0x1122334455667788
-);
-
-test_cranelift!(
-    test_cranelift_lddw2,
-    "
-    lddw r0, 0x0000000080000000
-    exit
-    ",
-    0x80000000
-);
-
-test_cranelift!(
-    test_cranelift_ldxb_all,
-    "
-    mov r0, r1
-    ldxb r9, [r0+0]
-    lsh r9, 0
-    ldxb r8, [r0+1]
-    lsh r8, 4
-    ldxb r7, [r0+2]
-    lsh r7, 8
-    ldxb r6, [r0+3]
-    lsh r6, 12
-    ldxb r5, [r0+4]
-    lsh r5, 16
-    ldxb r4, [r0+5]
-    lsh r4, 20
-    ldxb r3, [r0+6]
-    lsh r3, 24
-    ldxb r2, [r0+7]
-    lsh r2, 28
-    ldxb r1, [r0+8]
-    lsh r1, 32
-    ldxb r0, [r0+9]
-    lsh r0, 36
-    or r0, r1
-    or r0, r2
-    or r0, r3
-    or r0, r4
-    or r0, r5
-    or r0, r6
-    or r0, r7
-    or r0, r8
-    or r0, r9
-    exit
-    ",
-    [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09],
-    0x9876543210
-);
-
-test_cranelift!(
-    test_cranelift_ldxb,
-    "
-    ldxb r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0x11, 0xcc, 0xdd],
-    0x11
-);
-
-test_cranelift!(
-    test_cranelift_ldxdw,
-    "
-    ldxdw r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xcc, 0xdd],
-    0x8877665544332211
-);
-
-test_cranelift!(
-    test_cranelift_ldxh_all,
-    "
-    mov r0, r1
-    ldxh r9, [r0+0]
-    be16 r9
-    lsh r9, 0
-    ldxh r8, [r0+2]
-    be16 r8
-    lsh r8, 4
-    ldxh r7, [r0+4]
-    be16 r7
-    lsh r7, 8
-    ldxh r6, [r0+6]
-    be16 r6
-    lsh r6, 12
-    ldxh r5, [r0+8]
-    be16 r5
-    lsh r5, 16
-    ldxh r4, [r0+10]
-    be16 r4
-    lsh r4, 20
-    ldxh r3, [r0+12]
-    be16 r3
-    lsh r3, 24
-    ldxh r2, [r0+14]
-    be16 r2
-    lsh r2, 28
-    ldxh r1, [r0+16]
-    be16 r1
-    lsh r1, 32
-    ldxh r0, [r0+18]
-    be16 r0
-    lsh r0, 36
-    or r0, r1
-    or r0, r2
-    or r0, r3
-    or r0, r4
-    or r0, r5
-    or r0, r6
-    or r0, r7
-    or r0, r8
-    or r0, r9
-    exit
-    ",
-    [
-        0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00,
-        0x07, 0x00, 0x08, 0x00, 0x09
-    ],
-    0x9876543210
-);
-
-test_cranelift!(
-    test_cranelift_ldxh_all2,
-    "
-    mov r0, r1
-    ldxh r9, [r0+0]
-    be16 r9
-    ldxh r8, [r0+2]
-    be16 r8
-    ldxh r7, [r0+4]
-    be16 r7
-    ldxh r6, [r0+6]
-    be16 r6
-    ldxh r5, [r0+8]
-    be16 r5
-    ldxh r4, [r0+10]
-    be16 r4
-    ldxh r3, [r0+12]
-    be16 r3
-    ldxh r2, [r0+14]
-    be16 r2
-    ldxh r1, [r0+16]
-    be16 r1
-    ldxh r0, [r0+18]
-    be16 r0
-    or r0, r1
-    or r0, r2
-    or r0, r3
-    or r0, r4
-    or r0, r5
-    or r0, r6
-    or r0, r7
-    or r0, r8
-    or r0, r9
-    exit
-    ",
-    [
-        0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00,
-        0x80, 0x01, 0x00, 0x02, 0x00
-    ],
-    0x3ff
-);
-
-test_cranelift!(
-    test_cranelift_ldxh,
-    "
-    ldxh r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd],
-    0x2211
-);
-
-test_cranelift!(
-    test_cranelift_ldxh_same_reg,
-    "
-    mov r0, r1
-    sth [r0], 0x1234
-    ldxh r0, [r0]
-    exit
-    ",
-    [0xff, 0xff],
-    0x1234
-);
-
-test_cranelift!(
-    test_cranelift_ldxw_all,
-    "
-    mov r0, r1
-    ldxw r9, [r0+0]
-    be32 r9
-    ldxw r8, [r0+4]
-    be32 r8
-    ldxw r7, [r0+8]
-    be32 r7
-    ldxw r6, [r0+12]
-    be32 r6
-    ldxw r5, [r0+16]
-    be32 r5
-    ldxw r4, [r0+20]
-    be32 r4
-    ldxw r3, [r0+24]
-    be32 r3
-    ldxw r2, [r0+28]
-    be32 r2
-    ldxw r1, [r0+32]
-    be32 r1
-    ldxw r0, [r0+36]
-    be32 r0
-    or r0, r1
-    or r0, r2
-    or r0, r3
-    or r0, r4
-    or r0, r5
-    or r0, r6
-    or r0, r7
-    or r0, r8
-    or r0, r9
-    exit
-    ",
-    [
-        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
-    ],
-    0x030f0f
-);
-
-test_cranelift!(
-    test_cranelift_ldxw,
-    "
-    ldxw r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd],
-    0x44332211
-);
-
-test_cranelift!(
-    test_cranelift_le16,
-    "
-    ldxh r0, [r1]
-    le16 r0
-    exit
-    ",
-    [0x22, 0x11],
-    0x1122
-);
-
-test_cranelift!(
-    test_cranelift_le32,
-    "
-    ldxw r0, [r1]
-    le32 r0
-    exit
-    ",
-    [0x44, 0x33, 0x22, 0x11],
-    0x11223344
-);
-
-test_cranelift!(
-    test_cranelift_le64,
-    "
-    ldxdw r0, [r1]
-    le64 r0
-    exit
-    ",
-    [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11],
-    0x1122334455667788
-);
-
-test_cranelift!(
-    test_cranelift_lsh_reg,
-    "
-    mov r0, 0x1
-    mov r7, 4
-    lsh r0, r7
-    exit
-    ",
-    0x10
-);
-
-test_cranelift!(
-    test_cranelift_mod,
-    "
-    mov32 r0, 5748
-    mod32 r0, 92
-    mov32 r1, 13
-    mod32 r0, r1
-    exit
-    ",
-    0x5
-);
-
-test_cranelift!(
-    test_cranelift_mod32,
-    "
-    lddw r0, 0x100000003
-    mod32 r0, 3
-    exit
-    ",
-    0x0
-);
-
-test_cranelift!(
-    test_cranelift_mod64,
-    "
-    mov32 r0, -1316649930
-    lsh r0, 32
-    or r0, 0x100dc5c8
-    mov32 r1, 0xdde263e
-    lsh r1, 32
-    or r1, 0x3cbef7f3
-    mod r0, r1
-    mod r0, 0x658f1778
-    exit
-    ",
-    0x30ba5a04
-);
-
-test_cranelift!(
-    test_cranelift_mov,
-    "
-    mov32 r1, 1
-    mov32 r0, r1
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_mul32_imm,
-    "
-    mov r0, 3
-    mul32 r0, 4
-    exit
-    ",
-    0xc
-);
-
-test_cranelift!(
-    test_cranelift_mul32_reg,
-    "
-    mov r0, 3
-    mov r1, 4
-    mul32 r0, r1
-    exit
-    ",
-    0xc
-);
-
-test_cranelift!(
-    test_cranelift_mul32_reg_overflow,
-    "
-    mov r0, 0x40000001
-    mov r1, 4
-    mul32 r0, r1
-    exit
-    ",
-    0x4
-);
-
-test_cranelift!(
-    test_cranelift_mul64_imm,
-    "
-    mov r0, 0x40000001
-    mul r0, 4
-    exit
-    ",
-    0x100000004
-);
-
-test_cranelift!(
-    test_cranelift_mul64_reg,
-    "
-    mov r0, 0x40000001
-    mov r1, 4
-    mul r0, r1
-    exit
-    ",
-    0x100000004
-);
-
-test_cranelift!(
-    test_cranelift_mul_loop,
-    "
-    mov r0, 0x7
-    add r1, 0xa
-    lsh r1, 0x20
-    rsh r1, 0x20
-    jeq r1, 0x0, +4
-    mov r0, 0x7
-    mul r0, 0x7
-    add r1, -1
-    jne r1, 0x0, -3
-    exit
-    ",
-    0x75db9c97
-);
-
-test_cranelift!(
-    test_cranelift_neg64,
-    "
-    mov32 r0, 2
-    neg r0
-    exit
-    ",
-    0xfffffffffffffffe
-);
-
-test_cranelift!(
-    test_cranelift_neg,
-    "
-    mov32 r0, 2
-    neg32 r0
-    exit
-    ",
-    0xfffffffe
-);
-
-test_cranelift!(
-    test_cranelift_prime,
-    "
-    mov r1, 67
-    mov r0, 0x1
-    mov r2, 0x2
-    jgt r1, 0x2, +4
-    ja +10
-    add r2, 0x1
-    mov r0, 0x1
-    jge r2, r1, +7
-    mov r3, r1
-    div r3, r2
-    mul r3, r2
-    mov r4, r1
-    sub r4, r3
-    mov r0, 0x0
-    jne r4, 0x0, -10
-    exit
-    ",
-    1
-);
-
-test_cranelift!(
-    test_cranelift_rhs32,
-    "
-    xor r0, r0
-    sub r0, 1
-    rsh32 r0, 8
-    exit
-    ",
-    0x00ffffff
-);
-
-test_cranelift!(
-    test_cranelift_rsh_reg,
-    "
-    mov r0, 0x10
-    mov r7, 4
-    rsh r0, r7
-    exit
-    ",
-    0x1
-);
-
-test_cranelift!(
-    test_cranelift_stack,
-    "
-    mov r1, 51
-    stdw [r10-16], 0xab
-    stdw [r10-8], 0xcd
-    and r1, 1
-    lsh r1, 3
-    mov r2, r10
-    add r2, r1
-    ldxdw r0, [r2-16]
-    exit
-    ",
-    0xcd
-);
-
-#[test]
-fn test_cranelift_stack2() {
-    let prog = assemble(
-        "
-        stb [r10-4], 0x01
-        stb [r10-3], 0x02
-        stb [r10-2], 0x03
-        stb [r10-1], 0x04
-        mov r1, r10
-        mov r2, 0x4
-        sub r1, r2
-        call 1
-        mov r1, 0
-        ldxb r2, [r10-4]
-        ldxb r3, [r10-3]
-        ldxb r4, [r10-2]
-        ldxb r5, [r10-1]
-        call 0
-        xor r0, 0x2a2a2a2a
-        exit",
-    )
-    .unwrap();
-
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes).unwrap();
-    vm.register_helper(1, helpers::memfrob).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift().unwrap(), 0x01020304);
-}
-
-test_cranelift!(
-    test_cranelift_stb,
-    "
-    stb [r1+2], 0x11
-    ldxb r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xcc, 0xdd],
-    0x11
-);
-
-test_cranelift!(
-    test_cranelift_stdw,
-    "
-    stdw [r1+2], 0x44332211
-    ldxdw r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
-    0x44332211
-);
-
-test_cranelift!(
-    test_cranelift_sth,
-    "
-    sth [r1+2], 0x2211
-    ldxh r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd],
-    0x2211
-);
-
-#[test]
-#[ignore]
-fn test_cranelift_string_stack() {
-    let prog = assemble(
-        "
-        mov r1, 0x78636261
-        stxw [r10-8], r1
-        mov r6, 0x0
-        stxb [r10-4], r6
-        stxb [r10-12], r6
-        mov r1, 0x79636261
-        stxw [r10-16], r1
-        mov r1, r10
-        add r1, -8
-        mov r2, r1
-        call 0x4
-        mov r1, r0
-        mov r0, 0x1
-        lsh r1, 0x20
-        rsh r1, 0x20
-        jne r1, 0x0, +11
-        mov r1, r10
-        add r1, -8
-        mov r2, r10
-        add r2, -16
-        call 0x4
-        mov r1, r0
-        lsh r1, 0x20
-        rsh r1, 0x20
-        mov r0, 0x1
-        jeq r1, r6, +1
-        mov r0, 0x0
-        exit",
-    )
-    .unwrap();
-
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(4, helpers::strcmp).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift().unwrap(), 0x0);
-}
-
-test_cranelift!(
-    test_cranelift_stw,
-    "
-    stw [r1+2], 0x44332211
-    ldxw r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
-    0x44332211
-);
-
-test_cranelift!(
-    test_cranelift_stxb,
-    "
-    mov32 r2, 0x11
-    stxb [r1+2], r2
-    ldxb r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xcc, 0xdd],
-    0x11
-);
-
-test_cranelift!(
-    test_cranelift_stxb_all,
-    "
-    mov r0, 0xf0
-    mov r2, 0xf2
-    mov r3, 0xf3
-    mov r4, 0xf4
-    mov r5, 0xf5
-    mov r6, 0xf6
-    mov r7, 0xf7
-    mov r8, 0xf8
-    stxb [r1], r0
-    stxb [r1+1], r2
-    stxb [r1+2], r3
-    stxb [r1+3], r4
-    stxb [r1+4], r5
-    stxb [r1+5], r6
-    stxb [r1+6], r7
-    stxb [r1+7], r8
-    ldxdw r0, [r1]
-    be64 r0
-    exit
-    ",
-    [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-    0xf0f2f3f4f5f6f7f8
-);
-
-test_cranelift!(
-    test_cranelift_stxb_all2,
-    "
-    mov r0, r1
-    mov r1, 0xf1
-    mov r9, 0xf9
-    stxb [r0], r1
-    stxb [r0+1], r9
-    ldxh r0, [r0]
-    be16 r0
-    exit
-    ",
-    [0xff, 0xff],
-    0xf1f9
-);
-
-test_cranelift!(
-    test_cranelift_stxb_chain,
-    "
-    mov r0, r1
-    ldxb r9, [r0+0]
-    stxb [r0+1], r9
-    ldxb r8, [r0+1]
-    stxb [r0+2], r8
-    ldxb r7, [r0+2]
-    stxb [r0+3], r7
-    ldxb r6, [r0+3]
-    stxb [r0+4], r6
-    ldxb r5, [r0+4]
-    stxb [r0+5], r5
-    ldxb r4, [r0+5]
-    stxb [r0+6], r4
-    ldxb r3, [r0+6]
-    stxb [r0+7], r3
-    ldxb r2, [r0+7]
-    stxb [r0+8], r2
-    ldxb r1, [r0+8]
-    stxb [r0+9], r1
-    ldxb r0, [r0+9]
-    exit
-    ",
-    [0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
-    0x2a
-);
-
-test_cranelift!(
-    test_cranelift_stxdw,
-    "
-    mov r2, -2005440939
-    lsh r2, 32
-    or r2, 0x44332211
-    stxdw [r1+2], r2
-    ldxdw r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
-    0x8877665544332211
-);
-
-test_cranelift!(
-    test_cranelift_stxh,
-    "
-    mov32 r2, 0x2211
-    stxh [r1+2], r2
-    ldxh r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd],
-    0x2211
-);
-
-test_cranelift!(
-    test_cranelift_stxw,
-    "
-    mov32 r2, 0x44332211
-    stxw [r1+2], r2
-    ldxw r0, [r1+2]
-    exit
-    ",
-    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
-    0x44332211
-);
-
-test_cranelift!(
-    test_cranelift_subnet,
-    "
-    mov r2, 0xe
-    ldxh r3, [r1+12]
-    jne r3, 0x81, +2
-    mov r2, 0x12
-    ldxh r3, [r1+16]
-    and r3, 0xffff
-    jne r3, 0x8, +5
-    add r1, r2
-    mov r0, 0x1
-    ldxw r1, [r1+16]
-    and r1, 0xffffff
-    jeq r1, 0x1a8c0, +1
-    mov r0, 0x0
-    exit
-    ",
-    [
-        0x00, 0x00, 0xc0, 0x9f, 0xa0, 0x97, 0x00, 0xa0, 0xcc, 0x3b, 0xbf, 0xfa, 0x08, 0x00, 0x45,
-        0x10, 0x00, 0x3c, 0x46, 0x3c, 0x40, 0x00, 0x40, 0x06, 0x73, 0x1c, 0xc0, 0xa8, 0x01, 0x02,
-        0xc0, 0xa8, 0x01, 0x01, 0x06, 0x0e, 0x00, 0x17, 0x99, 0xc5, 0xa0, 0xec, 0x00, 0x00, 0x00,
-        0x00, 0xa0, 0x02, 0x7d, 0x78, 0xe0, 0xa3, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02,
-        0x08, 0x0a, 0x00, 0x9c, 0x27, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00,
-    ],
-    0x1
-);
-
-const PROG_TCP_PORT_80: [u8; 152] = [
-    0x71, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x13, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x67, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x02, 0x0a, 0x00, 0x06, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-    0x57, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x0f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x15, 0x02, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x69, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x55, 0x01, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-];
-
-#[test]
-fn test_cranelift_tcp_port80_match() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x1);
-}
-
-#[test]
-fn test_cranelift_tcp_port80_nomatch() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x00, 0x16, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x51, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x0);
-}
-
-#[test]
-fn test_cranelift_tcp_port80_nomatch_ethertype() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x01, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x0);
-}
-
-#[test]
-fn test_cranelift_tcp_port80_nomatch_proto() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x0);
-}
-
-#[test]
-fn test_cranelift_tcp_sack_match() {
-    let mut mem = TCP_SACK_MATCH.to_vec();
-    let prog = assemble(TCP_SACK_ASM).unwrap();
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(
-        vm.execute_program_cranelift(mem.as_mut_slice()).unwrap(),
-        0x1
-    );
-}
-
-#[test]
-fn test_cranelift_tcp_sack_nomatch() {
-    let mut mem = TCP_SACK_NOMATCH.to_vec();
-    let prog = assemble(TCP_SACK_ASM).unwrap();
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.cranelift_compile().unwrap();
-    assert_eq!(
-        vm.execute_program_cranelift(mem.as_mut_slice()).unwrap(),
-        0x0
-    );
-}
-
-#[test]
-fn test_cranelift_ldabsb() {
-    let prog = &[
-        0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x33);
-}
-
-#[test]
-fn test_cranelift_ldabsh() {
-    let prog = &[
-        0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x4433);
-}
-
-#[test]
-fn test_cranelift_ldabsw() {
-    let prog = &[
-        0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x66554433);
-}
-
-#[test]
-fn test_cranelift_ldabsdw() {
-    let prog = &[
-        0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(
-        vm.execute_program_cranelift(mem).unwrap(),
-        0xaa99887766554433
-    );
-}
-
-#[test]
-fn test_cranelift_ldindb() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x88);
-}
-
-#[test]
-fn test_cranelift_ldindh() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x9988);
-}
-
-#[test]
-fn test_cranelift_ldindw() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x88776655);
-}
-
-#[test]
-fn test_cranelift_ldinddw() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
-
-    vm.cranelift_compile().unwrap();
-    assert_eq!(
-        vm.execute_program_cranelift(mem).unwrap(),
-        0xccbbaa9988776655
-    );
-}

+ 0 - 377
kernel/crates/rbpf/tests/disassembler.rs

@@ -1,377 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2017 Jan-Erik Rediger <badboy@archlinux.us>
-//
-// Adopted from tests in `tests/assembler.rs`
-
-extern crate rbpf;
-mod common;
-
-use rbpf::{assembler::assemble, disassembler::to_insn_vec};
-
-// Using a macro to keep actual line numbers in failure output
-macro_rules! disasm {
-    ($src:expr) => {{
-        let src = $src;
-        let asm = assemble(src).expect("Can't assemble from string");
-        let insn = to_insn_vec(&asm);
-        let reasm = insn
-            .into_iter()
-            .map(|ins| ins.desc)
-            .collect::<Vec<_>>()
-            .join("\n");
-
-        assert_eq!(src, reasm);
-    }};
-}
-
-#[test]
-fn test_empty() {
-    disasm!("");
-}
-
-// Example for InstructionType::NoOperand.
-#[test]
-fn test_exit() {
-    disasm!("exit");
-}
-
-// Example for InstructionType::AluBinary.
-#[test]
-fn test_add64() {
-    disasm!("add64 r1, r3");
-    disasm!("add64 r1, 0x5");
-}
-
-// Example for InstructionType::AluUnary.
-#[test]
-fn test_neg64() {
-    disasm!("neg64 r1");
-}
-
-// Example for InstructionType::LoadReg.
-#[test]
-fn test_ldxw() {
-    disasm!("ldxw r1, [r2+0x5]");
-}
-
-// Example for InstructionType::StoreImm.
-#[test]
-fn test_stw() {
-    disasm!("stw [r2+0x5], 0x7");
-}
-
-// Example for InstructionType::StoreReg.
-#[test]
-fn test_stxw() {
-    disasm!("stxw [r2+0x5], r8");
-}
-
-// Example for InstructionType::JumpUnconditional.
-#[test]
-fn test_ja() {
-    disasm!("ja +0x8");
-}
-
-// Example for InstructionType::JumpConditional.
-#[test]
-fn test_jeq() {
-    disasm!("jeq r1, 0x4, +0x8");
-    disasm!("jeq r1, r3, +0x8");
-}
-
-// Example for InstructionType::Call.
-#[test]
-fn test_call() {
-    disasm!("call 0x3");
-}
-
-// Example for InstructionType::Endian.
-#[test]
-fn test_be32() {
-    disasm!("be32 r1");
-}
-
-// Example for InstructionType::LoadImm.
-#[test]
-fn test_lddw() {
-    disasm!("lddw r1, 0x1234abcd5678eeff");
-    disasm!("lddw r1, 0xff11ee22dd33cc44");
-}
-
-// Example for InstructionType::LoadAbs.
-#[test]
-fn test_ldabsw() {
-    disasm!("ldabsw 0x1");
-}
-
-// Example for InstructionType::LoadInd.
-#[test]
-fn test_ldindw() {
-    disasm!("ldindw r1, 0x2");
-}
-
-// Example for InstructionType::LoadReg.
-#[test]
-fn test_ldxdw() {
-    disasm!("ldxdw r1, [r2+0x3]");
-}
-
-// Example for InstructionType::StoreImm.
-#[test]
-fn test_sth() {
-    disasm!("sth [r1+0x2], 0x3");
-}
-
-// Example for InstructionType::StoreReg.
-#[test]
-fn test_stxh() {
-    disasm!("stxh [r1+0x2], r3");
-}
-
-// Test all supported AluBinary mnemonics.
-#[test]
-fn test_alu_binary() {
-    disasm!(
-        "add64 r1, r2
-sub64 r1, r2
-mul64 r1, r2
-div64 r1, r2
-or64 r1, r2
-and64 r1, r2
-lsh64 r1, r2
-rsh64 r1, r2
-mod64 r1, r2
-xor64 r1, r2
-mov64 r1, r2
-arsh64 r1, r2"
-    );
-
-    disasm!(
-        "add64 r1, 0x2
-sub64 r1, 0x2
-mul64 r1, 0x2
-div64 r1, 0x2
-or64 r1, 0x2
-and64 r1, 0x2
-lsh64 r1, 0x2
-rsh64 r1, 0x2
-mod64 r1, 0x2
-xor64 r1, 0x2
-mov64 r1, 0x2
-arsh64 r1, 0x2"
-    );
-
-    disasm!(
-        "add32 r1, r2
-sub32 r1, r2
-mul32 r1, r2
-div32 r1, r2
-or32 r1, r2
-and32 r1, r2
-lsh32 r1, r2
-rsh32 r1, r2
-mod32 r1, r2
-xor32 r1, r2
-mov32 r1, r2
-arsh32 r1, r2"
-    );
-
-    disasm!(
-        "add32 r1, 0x2
-sub32 r1, 0x2
-mul32 r1, 0x2
-div32 r1, 0x2
-or32 r1, 0x2
-and32 r1, 0x2
-lsh32 r1, 0x2
-rsh32 r1, 0x2
-mod32 r1, 0x2
-xor32 r1, 0x2
-mov32 r1, 0x2
-arsh32 r1, 0x2"
-    );
-}
-
-// Test all supported AluUnary mnemonics.
-#[test]
-fn test_alu_unary() {
-    disasm!(
-        "neg64 r1
-neg32 r1"
-    );
-}
-
-// Test all supported LoadAbs mnemonics.
-#[test]
-fn test_load_abs() {
-    disasm!(
-        "ldabsw 0x1
-ldabsh 0x1
-ldabsb 0x1
-ldabsdw 0x1"
-    );
-}
-
-// Test all supported LoadInd mnemonics.
-#[test]
-fn test_load_ind() {
-    disasm!(
-        "ldindw r1, 0x2
-ldindh r1, 0x2
-ldindb r1, 0x2
-ldinddw r1, 0x2"
-    );
-}
-
-// Test all supported LoadReg mnemonics.
-#[test]
-fn test_load_reg() {
-    disasm!(
-        r"ldxw r1, [r2+0x3]
-ldxh r1, [r2+0x3]
-ldxb r1, [r2+0x3]
-ldxdw r1, [r2+0x3]"
-    );
-}
-
-// Test all supported StoreImm mnemonics.
-#[test]
-fn test_store_imm() {
-    disasm!(
-        "stw [r1+0x2], 0x3
-sth [r1+0x2], 0x3
-stb [r1+0x2], 0x3
-stdw [r1+0x2], 0x3"
-    );
-}
-
-// Test all supported StoreReg mnemonics.
-#[test]
-fn test_store_reg() {
-    disasm!(
-        "stxw [r1+0x2], r3
-stxh [r1+0x2], r3
-stxb [r1+0x2], r3
-stxdw [r1+0x2], r3"
-    );
-}
-
-// Test all supported JumpConditional mnemonics.
-#[test]
-fn test_jump_conditional() {
-    disasm!(
-        "jeq r1, r2, +0x3
-jgt r1, r2, +0x3
-jge r1, r2, +0x3
-jlt r1, r2, +0x3
-jle r1, r2, +0x3
-jset r1, r2, +0x3
-jne r1, r2, +0x3
-jsgt r1, r2, +0x3
-jsge r1, r2, -0x3
-jslt r1, r2, +0x3
-jsle r1, r2, -0x3"
-    );
-
-    disasm!(
-        "jeq r1, 0x2, +0x3
-jgt r1, 0x2, +0x3
-jge r1, 0x2, +0x3
-jlt r1, 0x2, +0x3
-jle r1, 0x2, +0x3
-jset r1, 0x2, +0x3
-jne r1, 0x2, +0x3
-jsgt r1, 0x2, +0x3
-jsge r1, 0x2, -0x3
-jslt r1, 0x2, +0x3
-jsle r1, 0x2, -0x3"
-    );
-
-    disasm!(
-        "jeq32 r1, r2, +0x3
-jgt32 r1, r2, +0x3
-jge32 r1, r2, +0x3
-jlt32 r1, r2, +0x3
-jle32 r1, r2, +0x3
-jset32 r1, r2, +0x3
-jne32 r1, r2, +0x3
-jsgt32 r1, r2, +0x3
-jsge32 r1, r2, -0x3
-jslt32 r1, r2, +0x3
-jsle32 r1, r2, -0x3"
-    );
-
-    disasm!(
-        "jeq32 r1, 0x2, +0x3
-jgt32 r1, 0x2, +0x3
-jge32 r1, 0x2, +0x3
-jlt32 r1, 0x2, +0x3
-jle32 r1, 0x2, +0x3
-jset32 r1, 0x2, +0x3
-jne32 r1, 0x2, +0x3
-jsgt32 r1, 0x2, +0x3
-jsge32 r1, 0x2, -0x3
-jslt32 r1, 0x2, +0x3
-jsle32 r1, 0x2, -0x3"
-    );
-}
-
-// Test all supported Endian mnemonics.
-#[test]
-fn test_endian() {
-    disasm!(
-        "be16 r1
-be32 r1
-be64 r1
-le16 r1
-le32 r1
-le64 r1"
-    );
-}
-
-#[test]
-fn test_large_immediate() {
-    disasm!("add64 r1, 0x7fffffff");
-    disasm!("add64 r1, 0x7fffffff");
-}
-
-// Non-regression tests for overflow when trying to negate offset 0x8000i16.
-#[test]
-fn test_offset_overflow() {
-    let insns = [
-        0x62, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stw
-        0x6a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // sth
-        0x72, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stb
-        0x7a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stdw
-        0x61, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxw
-        0x69, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxh
-        0x71, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxb
-        0x79, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxdw
-        0x15, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq (imm)
-        0x1d, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq (reg)
-        0x16, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq32 (imm)
-        0x1e, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq32 (reg)
-    ];
-
-    let expected_output = "stw [r1-0x8000], 0x1
-sth [r1-0x8000], 0x1
-stb [r1-0x8000], 0x1
-stdw [r1-0x8000], 0x1
-ldxw r1, [r0-0x8000]
-ldxh r1, [r0-0x8000]
-ldxb r1, [r0-0x8000]
-ldxdw r1, [r0-0x8000]
-jeq r1, 0x2, -0x8000
-jeq r1, r2, -0x8000
-jeq32 r1, 0x2, -0x8000
-jeq32 r1, r2, -0x8000";
-
-    let prog = to_insn_vec(&insns);
-    let asm = prog
-        .into_iter()
-        .map(|ins| ins.desc)
-        .collect::<Vec<_>>()
-        .join("\n");
-
-    assert_eq!(asm, expected_output);
-}

+ 0 - 571
kernel/crates/rbpf/tests/misc.rs

@@ -1,571 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-// There are unused mut warnings due to unsafe code.
-#![allow(unused_mut)]
-#![allow(clippy::unreadable_literal)]
-
-// This crate would be needed to load bytecode from a BPF-compiled object file. Since the crate
-// is not used anywhere else in the library, it is deactivated: we do not want to load and compile
-// it just for the tests. If you want to use it, do not forget to add the following
-// dependency to your Cargo.toml file:
-//
-// ---
-// elf = "0.0.10"
-// ---
-//
-// extern crate elf;
-// use std::path::PathBuf;
-
-extern crate rbpf;
-
-#[cfg(feature = "std")]
-use rbpf::helpers;
-use rbpf::{assembler::assemble, Error, ErrorKind};
-
-// The following two examples have been compiled from C with the following command:
-//
-// ```bash
-//  clang -O2 -emit-llvm -c <file.c> -o - | llc -march=bpf -filetype=obj -o <file.o>
-// ```
-//
-// The C source code was the following:
-//
-// ```c
-// #include <linux/ip.h>
-// #include <linux/in.h>
-// #include <linux/tcp.h>
-// #include <linux/bpf.h>
-//
-// #define ETH_ALEN 6
-// #define ETH_P_IP 0x0008 /* htons(0x0800) */
-// #define TCP_HDR_LEN 20
-//
-// #define BLOCKED_TCP_PORT 0x9999
-//
-// struct eth_hdr {
-//     unsigned char   h_dest[ETH_ALEN];
-//     unsigned char   h_source[ETH_ALEN];
-//     unsigned short  h_proto;
-// };
-//
-// #define SEC(NAME) __attribute__((section(NAME), used))
-// SEC(".classifier")
-// int handle_ingress(struct __sk_buff *skb)
-// {
-//     void *data = (void *)(long)skb->data;
-//     void *data_end = (void *)(long)skb->data_end;
-//     struct eth_hdr *eth = data;
-//     struct iphdr *iph = data + sizeof(*eth);
-//     struct tcphdr *tcp = data + sizeof(*eth) + sizeof(*iph);
-//
-//     /* single length check */
-//     if (data + sizeof(*eth) + sizeof(*iph) + sizeof(*tcp) > data_end)
-//         return 0;
-//     if (eth->h_proto != ETH_P_IP)
-//         return 0;
-//     if (iph->protocol != IPPROTO_TCP)
-//         return 0;
-//     if (tcp->source == BLOCKED_TCP_PORT || tcp->dest == BLOCKED_TCP_PORT)
-//         return -1;
-//     return 0;
-// }
-// char _license[] SEC(".license") = "GPL";
-// ```
-//
-// This program, once compiled, can be injected into Linux kernel, with tc for instance. Sadly, we
-// need to bring some modifications to the generated bytecode in order to run it: the three
-// instructions with opcode 0x61 load data from a packet area as 4-byte words, where we need to
-// load it as 8-bytes double words (0x79). The kernel does the same kind of translation before
-// running the program, but rbpf does not implement this.
-//
-// In addition, the offset at which the pointer to the packet data is stored must be changed: since
-// we use 8 bytes instead of 4 for the start and end addresses of the data packet, we cannot use
-// the offsets produced by clang (0x4c and 0x50), the addresses would overlap. Instead we can use,
-// for example, 0x40 and 0x50. See comments on the bytecode below to see the modifications.
-//
-// Once the bytecode has been (manually, in our case) edited, we can load the bytecode directly
-// from the ELF object file. This is easy to do, but requires the addition of two crates in the
-// Cargo.toml file (see comments above), so here we use just the hardcoded bytecode instructions
-// instead.
-
-#[test]
-#[cfg(feature = "std")]
-fn test_vm_block_port() {
-    // To load the bytecode from an object file instead of using the hardcoded instructions,
-    // use the additional crates commented at the beginning of this file (and also add them to your
-    // Cargo.toml). See comments above.
-    //
-    // ---
-    // let filename = "my_ebpf_object_file.o";
-    //
-    // let path = PathBuf::from(filename);
-    // let file = match elf::File::open_path(&path) {
-    //     Ok(f) => f,
-    //     Err(e) => panic!("Error: {:?}", e),
-    // };
-    //
-    // let text_scn = match file.get_section(".classifier") {
-    //     Some(s) => s,
-    //     None => panic!("Failed to look up .classifier section"),
-    // };
-    //
-    // let prog = &text_scn.data;
-    // ---
-
-    let prog = &[
-        0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x12, 0x50, 0x00, 0x00, 0x00, 0x00,
-        0x00, // 0x79 instead of 0x61
-        0x79, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00,
-        0x00, // 0x79 instead of 0x61, 0x40 i.o. 0x4c
-        0xbf, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x36, 0x00, 0x00,
-        0x00, 0x2d, 0x23, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x12, 0x0c, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x55, 0x02, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x71, 0x12, 0x17, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x55, 0x02, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-        0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x22,
-        0x00, 0x00, 0x00, 0x00, 0x00, // 0x79 instead of 0x61
-        0xbf, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00,
-        0x00, 0x15, 0x02, 0x08, 0x00, 0x99, 0x99, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00,
-        0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x21, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x18, 0x02, 0x00, 0x00,
-        0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x21, 0x01,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-
-    let packet = &mut [
-        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x08,
-        0x00, // ethertype
-        0x45, 0x00, 0x00, 0x3b, // start ip_hdr
-        0xa6, 0xab, 0x40, 0x00, 0x40, 0x06, 0x96, 0x0f, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00,
-        0x01,
-        // Program matches the next two bytes: 0x9999 returns 0xffffffff, else return 0.
-        0x99, 0x99, 0xc6, 0xcc, // start tcp_hdr
-        0xd1, 0xe5, 0xc4, 0x9d, 0xd4, 0x30, 0xb5, 0xd2, 0x80, 0x18, 0x01, 0x56, 0xfe, 0x2f, 0x00,
-        0x00, 0x01, 0x01, 0x08, 0x0a, // start data
-        0x00, 0x23, 0x75, 0x89, 0x00, 0x23, 0x63, 0x2d, 0x71, 0x64, 0x66, 0x73, 0x64, 0x66, 0x0au8,
-    ];
-
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf)
-        .unwrap();
-
-    let res = vm.execute_program(packet).unwrap();
-    println!("Program returned: {res:?} ({res:#x})");
-    assert_eq!(res, 0xffffffff);
-}
-
-#[test]
-#[cfg(all(not(windows), feature = "std"))]
-fn test_jit_block_port() {
-    // To load the bytecode from an object file instead of using the hardcoded instructions,
-    // use the additional crates commented at the beginning of this file (and also add them to your
-    // Cargo.toml). See comments above.
-    //
-    // ---
-    // let filename = "my_ebpf_object_file.o";
-    //
-    // let path = PathBuf::from(filename);
-    // let file = match elf::File::open_path(&path) {
-    //     Ok(f) => f,
-    //     Err(e) => panic!("Error: {:?}", e),
-    // };
-    //
-    // let text_scn = match file.get_section(".classifier") {
-    //     Some(s) => s,
-    //     None => panic!("Failed to look up .classifier section"),
-    // };
-    //
-    // let prog = &text_scn.data;
-    // ---
-
-    let prog = &[
-        0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x12, 0x50, 0x00, 0x00, 0x00, 0x00,
-        0x00, // 0x79 instead of 0x61
-        0x79, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00,
-        0x00, // 0x79 instead of 0x61, 0x40 i.o. 0x4c
-        0xbf, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x36, 0x00, 0x00,
-        0x00, 0x2d, 0x23, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x12, 0x0c, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x55, 0x02, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x71, 0x12, 0x17, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x55, 0x02, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-        0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x22,
-        0x00, 0x00, 0x00, 0x00, 0x00, // 0x79 instead of 0x61
-        0xbf, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00,
-        0x00, 0x15, 0x02, 0x08, 0x00, 0x99, 0x99, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00,
-        0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x21, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x18, 0x02, 0x00, 0x00,
-        0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x21, 0x01,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-
-    let packet = &mut [
-        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x08,
-        0x00, // ethertype
-        0x45, 0x00, 0x00, 0x3b, // start ip_hdr
-        0xa6, 0xab, 0x40, 0x00, 0x40, 0x06, 0x96, 0x0f, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00,
-        0x01,
-        // Program matches the next two bytes: 0x9999 returns 0xffffffff, else return 0.
-        0x99, 0x99, 0xc6, 0xcc, // start tcp_hdr
-        0xd1, 0xe5, 0xc4, 0x9d, 0xd4, 0x30, 0xb5, 0xd2, 0x80, 0x18, 0x01, 0x56, 0xfe, 0x2f, 0x00,
-        0x00, 0x01, 0x01, 0x08, 0x0a, // start data
-        0x00, 0x23, 0x75, 0x89, 0x00, 0x23, 0x63, 0x2d, 0x71, 0x64, 0x66, 0x73, 0x64, 0x66, 0x0au8,
-    ];
-
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf)
-        .unwrap();
-    vm.jit_compile().unwrap();
-
-    unsafe {
-        let res = vm.execute_program_jit(packet).unwrap();
-        println!("Program returned: {res:?} ({res:#x})");
-        assert_eq!(res, 0xffffffff);
-    }
-}
-
-// Program and memory come from uBPF test ldxh.
-#[test]
-fn test_vm_mbuff() {
-    let prog = &[
-        // Load mem from mbuff into R1
-        0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-        0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &[0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
-
-    let mbuff = [0u8; 32];
-    unsafe {
-        let mut data = mbuff.as_ptr().offset(8) as *mut u64;
-        let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-        data.write_unaligned(mem.as_ptr() as u64);
-        data_end.write_unaligned(mem.as_ptr() as u64 + mem.len() as u64);
-    }
-
-    let vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem, &mbuff).unwrap(), 0x2211);
-}
-
-// Program and memory come from uBPF test ldxh.
-#[test]
-fn test_vm_mbuff_with_rust_api() {
-    use rbpf::insn_builder::*;
-
-    let mut program = BpfCode::new();
-    program
-        .load_x(MemSize::DoubleWord)
-        .set_dst(0x01)
-        .set_src(0x01)
-        .set_off(0x00_08)
-        .push()
-        .load_x(MemSize::HalfWord)
-        .set_dst(0x00)
-        .set_src(0x01)
-        .set_off(0x00_02)
-        .push()
-        .exit()
-        .push();
-
-    let mem = &[0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
-
-    let mbuff = [0u8; 32];
-    unsafe {
-        let mut data = mbuff.as_ptr().offset(8) as *mut u64;
-        let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-        *data = mem.as_ptr() as u64;
-        *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-    }
-
-    let vm = rbpf::EbpfVmMbuff::new(Some(program.into_bytes())).unwrap();
-    assert_eq!(vm.execute_program(mem, &mbuff).unwrap(), 0x2211);
-}
-
-// Program and memory come from uBPF test ldxh.
-#[test]
-#[cfg(all(not(windows), feature = "std"))]
-fn test_jit_mbuff() {
-    let prog = &[
-        // Load mem from mbuff into R1
-        0x79, 0x11, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // ldhx r1[2], r0
-        0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
-
-    let mut mbuff = [0u8; 32];
-    unsafe {
-        let mut data = mbuff.as_ptr().offset(8) as *mut u64;
-        let mut data_end = mbuff.as_ptr().offset(24) as *mut u64;
-        *data = mem.as_ptr() as u64;
-        *data_end = mem.as_ptr() as u64 + mem.len() as u64;
-    }
-
-    unsafe {
-        let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-        vm.jit_compile().unwrap();
-        assert_eq!(vm.execute_program_jit(mem, &mut mbuff).unwrap(), 0x2211);
-    }
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldabsb() {
-    let prog = &[
-        0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x33);
-
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x33);
-    };
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldabsh() {
-    let prog = &[
-        0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x4433);
-
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x4433);
-    };
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldabsw() {
-    let prog = &[
-        0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x66554433);
-    vm.jit_compile().unwrap();
-
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x66554433);
-    };
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldabsdw() {
-    let prog = &[
-        0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0xaa99887766554433);
-    vm.jit_compile().unwrap();
-
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0xaa99887766554433);
-    };
-}
-
-#[test]
-#[should_panic(expected = "Error: out of bounds memory load (insn #1),")]
-fn test_vm_err_ldabsb_oob() {
-    let prog = &[
-        0x38, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.execute_program(mem).unwrap();
-
-    // Memory check not implemented for JIT yet.
-}
-
-#[test]
-#[should_panic(expected = "Error: out of bounds memory load (insn #1),")]
-fn test_vm_err_ldabsb_nomem() {
-    let prog = &[
-        0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.execute_program().unwrap();
-
-    // Memory check not implemented for JIT yet.
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldindb() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x88);
-
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x88);
-    };
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldindh() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x9988);
-
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x9988);
-    };
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldindw() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x88776655);
-    vm.jit_compile().unwrap();
-
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x88776655);
-    };
-}
-
-#[cfg(all(not(windows), feature = "std"))]
-#[test]
-fn test_vm_jit_ldinddw() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0xccbbaa9988776655);
-    vm.jit_compile().unwrap();
-
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0xccbbaa9988776655);
-    };
-}
-
-#[test]
-#[should_panic(expected = "Error: out of bounds memory load (insn #2),")]
-fn test_vm_err_ldindb_oob() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00, 0x33, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let mem = &mut [
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.execute_program(mem).unwrap();
-
-    // Memory check not implemented for JIT yet.
-}
-
-#[test]
-#[should_panic(expected = "Error: out of bounds memory load (insn #2),")]
-fn test_vm_err_ldindb_nomem() {
-    let prog = &[
-        0xb7, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.execute_program().unwrap();
-
-    // Memory check not implemented for JIT yet.
-}
-
-#[test]
-#[should_panic(expected = "Error: No program set, call prog_set() to load one")]
-fn test_vm_exec_no_program() {
-    let vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xBEE);
-}
-
-fn verifier_success(_prog: &[u8]) -> Result<(), Error> {
-    Ok(())
-}
-
-fn verifier_fail(_prog: &[u8]) -> Result<(), Error> {
-    Err(Error::new(ErrorKind::Other, "Gaggablaghblagh!"))
-}
-
-#[test]
-fn test_verifier_success() {
-    let prog = assemble(
-        "mov32 r0, 0xBEE
-         exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    vm.set_verifier(verifier_success).unwrap();
-    vm.set_program(&prog).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xBEE);
-}
-
-#[test]
-#[should_panic(expected = "Gaggablaghblagh!")]
-fn test_verifier_fail() {
-    let prog = assemble(
-        "mov32 r0, 0xBEE
-         exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    vm.set_verifier(verifier_fail).unwrap();
-    vm.set_program(&prog).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xBEE);
-}

+ 0 - 2891
kernel/crates/rbpf/tests/ubpf_jit_x86_64.rs

@@ -1,2891 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Converted from the tests for uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-// The tests contained in this file are extracted from the unit tests of uBPF software. Each test
-// in this file has a name in the form `test_jit_<name>`, and corresponds to the (human-readable)
-// code in `ubpf/tree/master/tests/<name>`, available at
-// <https://github.com/iovisor/ubpf/tree/master/tests> (hyphen had to be replaced with underscores
-// as Rust will not accept them in function names). It is strongly advised to refer to the uBPF
-// version to understand what these program do.
-//
-// Each program was assembled from the uBPF version with the assembler provided by uBPF itself, and
-// available at <https://github.com/iovisor/ubpf/tree/master/ubpf>.
-// The very few modifications that have been realized should be indicated.
-
-// These are unit tests for the eBPF JIT compiler.
-
-#![allow(clippy::unreadable_literal)]
-#![cfg(all(not(windows), feature = "std"))]
-
-extern crate rbpf;
-mod common;
-
-use common::{TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH};
-use rbpf::{assembler::assemble, helpers};
-
-#[test]
-fn test_jit_add() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 2
-        add32 r0, 1
-        add32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x3);
-    }
-}
-
-#[test]
-fn test_jit_alu64_arith() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        mov r6, 6
-        mov r7, 7
-        mov r8, 8
-        mov r9, 9
-        add r0, 23
-        add r0, r7
-        sub r0, 13
-        sub r0, r1
-        mul r0, 7
-        mul r0, r3
-        div r0, 2
-        div r0, r4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x2a);
-    }
-}
-
-#[test]
-fn test_jit_alu64_bit() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        mov r6, 6
-        mov r7, 7
-        mov r8, 8
-        or r0, r5
-        or r0, 0xa0
-        and r0, 0xa3
-        mov r9, 0x91
-        and r0, r9
-        lsh r0, 32
-        lsh r0, 22
-        lsh r0, r8
-        rsh r0, 32
-        rsh r0, 19
-        rsh r0, r7
-        xor r0, 0x03
-        xor r0, r2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x11);
-    }
-}
-
-#[test]
-fn test_jit_alu_arith() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 1
-        mov32 r2, 2
-        mov32 r3, 3
-        mov32 r4, 4
-        mov32 r5, 5
-        mov32 r6, 6
-        mov32 r7, 7
-        mov32 r8, 8
-        mov32 r9, 9
-        add32 r0, 23
-        add32 r0, r7
-        sub32 r0, 13
-        sub32 r0, r1
-        mul32 r0, 7
-        mul32 r0, r3
-        div32 r0, 2
-        div32 r0, r4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x2a);
-    }
-}
-
-#[test]
-fn test_jit_alu_bit() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 1
-        mov32 r2, 2
-        mov32 r3, 3
-        mov32 r4, 4
-        mov32 r5, 5
-        mov32 r6, 6
-        mov32 r7, 7
-        mov32 r8, 8
-        or32 r0, r5
-        or32 r0, 0xa0
-        and32 r0, 0xa3
-        mov32 r9, 0x91
-        and32 r0, r9
-        lsh32 r0, 22
-        lsh32 r0, r8
-        rsh32 r0, 19
-        rsh32 r0, r7
-        xor32 r0, 0x03
-        xor32 r0, r2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x11);
-    }
-}
-
-#[test]
-fn test_jit_arsh32_high_shift() {
-    let prog = assemble(
-        "
-        mov r0, 8
-        lddw r1, 0x100000001
-        arsh32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x4);
-    }
-}
-
-#[test]
-fn test_jit_arsh() {
-    let prog = assemble(
-        "
-        mov32 r0, 0xf8
-        lsh32 r0, 28
-        arsh32 r0, 16
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xffff8000);
-    }
-}
-
-#[test]
-fn test_jit_arsh64() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        lsh r0, 63
-        arsh r0, 55
-        mov32 r1, 5
-        arsh r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xfffffffffffffff8);
-    }
-}
-
-#[test]
-fn test_jit_arsh_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0xf8
-        mov32 r1, 16
-        lsh32 r0, 28
-        arsh32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xffff8000);
-    }
-}
-
-#[test]
-fn test_jit_be16() {
-    let prog = assemble(
-        "
-        ldxh r0, [r1]
-        be16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1122);
-    }
-}
-
-#[test]
-fn test_jit_be16_high() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        be16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1122);
-    }
-}
-
-#[test]
-fn test_jit_be32() {
-    let prog = assemble(
-        "
-        ldxw r0, [r1]
-        be32 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11223344);
-    }
-}
-
-#[test]
-fn test_jit_be32_high() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        be32 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11223344);
-    }
-}
-
-#[test]
-fn test_jit_be64() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1122334455667788);
-    }
-}
-
-#[test]
-fn test_jit_call() {
-    let prog = assemble(
-        "
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        call 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0102030405);
-    }
-}
-
-#[test]
-fn test_jit_call_memfrob() {
-    let prog = assemble(
-        "
-        mov r6, r1
-        add r1, 2
-        mov r2, 4
-        call 1
-        ldxdw r0, [r6]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.register_helper(1, helpers::memfrob).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x102292e2f2c0708);
-    }
-}
-
-// TODO: helpers::trash_registers needs asm!().
-// Try this again once asm!() is available in stable.
-//#[test]
-//fn test_jit_call_save() {
-//let prog = &[
-//0xb7, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-//0xb7, 0x07, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-//0xb7, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
-//0xb7, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
-//0x85, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-//0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-//];
-//let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-//vm.register_helper(2, helpers::trash_registers);
-//vm.jit_compile().unwrap();
-//unsafe { assert_eq!(vm.execute_program_jit().unwrap(), 0x4321); }
-//}
-
-#[test]
-fn test_jit_div32_high_divisor() {
-    let prog = assemble(
-        "
-        mov r0, 12
-        lddw r1, 0x100000004
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x3);
-    }
-}
-
-#[test]
-fn test_jit_div32_imm() {
-    let prog = assemble(
-        "
-        lddw r0, 0x10000000c
-        div32 r0, 4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x3);
-    }
-}
-
-#[test]
-fn test_jit_div32_reg() {
-    let prog = assemble(
-        "
-        lddw r0, 0x10000000c
-        mov r1, 4
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x3);
-    }
-}
-
-#[test]
-fn test_jit_div64_imm() {
-    let prog = assemble(
-        "
-        mov r0, 0xc
-        lsh r0, 32
-        div r0, 4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x300000000);
-    }
-}
-
-#[test]
-fn test_jit_div64_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0xc
-        lsh r0, 32
-        mov r1, 4
-        div r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x300000000);
-    }
-}
-
-// For some register numbers, we don't emit the same instructions for handling divisions by zero,
-// which means we don't use the same offset to skip these instructions when the divisor is not
-// zero. We've had a regression because of this before, make sure we test it.
-#[test]
-fn test_jit_div32_highreg() {
-    let prog = assemble(
-        "
-        mov r0, 2
-        mov r7, 4
-        div32 r7, r0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x2);
-    }
-}
-
-#[test]
-fn test_jit_div64_highreg() {
-    let prog = assemble(
-        "
-        mov r0, 2
-        mov r7, 4
-        div r7, r0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x2);
-    }
-}
-
-#[test]
-fn test_jit_early_exit() {
-    let prog = assemble(
-        "
-        mov r0, 3
-        exit
-        mov r0, 4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x3);
-    }
-}
-
-// uBPF limits the number of user functions at 64. We don't.
-//#[test]
-//fn test_jit_err_call_bad_imm() {
-//}
-
-#[test]
-#[should_panic(expected = "[JIT] Error: unknown helper function (id: 0x3f)")]
-fn test_jit_err_call_unreg() {
-    let prog = assemble(
-        "
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        call 63
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        vm.execute_program_jit().unwrap();
-    }
-}
-
-#[test]
-fn test_jit_div64_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        div r0, 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_div_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        div32 r0, 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_mod64_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mod r0, 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_mod_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mod32 r0, 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_div64_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        div r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_div_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_mod64_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        mod r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_mod_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        mod32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-// TODO SKIP: JIT disabled for this testcase (stack oob check not implemented)
-// #[test]
-// #[should_panic(expected = "Error: out of bounds memory store (insn #1)")]
-// fn test_jit_err_stack_out_of_bound() {
-//     let prog = &[
-//         0x72, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-//     ];
-//     let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-//     vm.jit_compile().unwrap();
-//     unsafe { vm.execute_program_jit().unwrap(); }
-// }
-
-#[test]
-fn test_jit_exit() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_ja() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        ja +1
-        mov r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jeq_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xa
-        jeq r1, 0xb, +4
-        mov32 r0, 1
-        mov32 r1, 0xb
-        jeq r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jeq_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xa
-        mov32 r2, 0xb
-        jeq r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0xb
-        jeq r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jge_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xa
-        jge r1, 0xb, +4
-        mov32 r0, 1
-        mov32 r1, 0xc
-        jge r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jle_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 5
-        jle r1, 4, +1
-        jle r1, 6, +1
-        exit
-        jle r1, 5, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jle_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        jle r1, r2, +2
-        jle r1, r1, +1
-        exit
-        jle r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jgt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 5
-        jgt r1, 6, +2
-        jgt r1, 5, +1
-        jgt r1, 4, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jgt_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 5
-        mov r2, 6
-        mov r3, 4
-        jgt r1, r2, +2
-        jgt r1, r1, +1
-        jgt r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jlt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 5
-        jlt r1, 4, +2
-        jlt r1, 5, +1
-        jlt r1, 6, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jlt_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        jlt r1, r2, +2
-        jlt r1, r1, +1
-        jlt r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jit_bounce() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        mov r6, r0
-        mov r7, r6
-        mov r8, r7
-        mov r9, r8
-        mov r0, r9
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jne_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xb
-        mov32 r2, 0xb
-        jne r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0xa
-        jne r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jset_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0x7
-        jset r1, 0x8, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset r1, 0x8, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jset_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0x7
-        mov32 r2, 0x8
-        jset r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsge_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jsge r1, -1, +5
-        jsge r1, 0, +4
-        mov32 r0, 1
-        mov r1, -1
-        jsge r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsge_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        mov r2, -1
-        mov32 r3, 0
-        jsge r1, r2, +5
-        jsge r1, r3, +4
-        mov32 r0, 1
-        mov r1, r2
-        jsge r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsle_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jsle r1, -3, +1
-        jsle r1, -1, +1
-        exit
-        mov32 r0, 1
-        jsle r1, -2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsle_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -1
-        mov r2, -2
-        mov32 r3, 0
-        jsle r1, r2, +1
-        jsle r1, r3, +1
-        exit
-        mov32 r0, 1
-        mov r1, r2
-        jsle r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsgt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jsgt r1, -1, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsgt_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        mov r2, -1
-        jsgt r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jslt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jslt r1, -3, +2
-        jslt r1, -2, +1
-        jslt r1, -1, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jslt_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        mov r2, -3
-        mov r3, -1
-        jslt r1, r1, +2
-        jslt r1, r2, +1
-        jslt r1, r3, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jeq32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0x0
-        mov32 r1, 0xa
-        jeq32 r1, 0xb, +5
-        mov32 r0, 1
-        mov r1, 0xb
-        or r1, r9
-        jeq32 r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jeq32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xa
-        mov32 r2, 0xb
-        jeq32 r1, r2, +5
-        mov32 r0, 1
-        mov32 r1, 0xb
-        or r1, r9
-        jeq32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jge32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xa
-        jge32 r1, 0xb, +5
-        mov32 r0, 1
-        or r1, r9
-        mov32 r1, 0xc
-        jge32 r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jge32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xa
-        mov32 r2, 0xb
-        jge32 r1, r2, +5
-        mov32 r0, 1
-        or r1, r9
-        mov32 r1, 0xc
-        jge32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jgt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 5
-        or r1, r9
-        jgt32 r1, 6, +4
-        jgt32 r1, 5, +3
-        jgt32 r1, 4, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jgt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov r0, 0
-        mov r1, 5
-        mov32 r1, 5
-        or r1, r9
-        mov r2, 6
-        mov r3, 4
-        jgt32 r1, r2, +4
-        jgt32 r1, r1, +3
-        jgt32 r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jle32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 5
-        or r1, r9
-        jle32 r1, 4, +5
-        jle32 r1, 6, +1
-        exit
-        jle32 r1, 5, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jle32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        or r1, r9
-        jle32 r1, r2, +5
-        jle32 r1, r1, +1
-        exit
-        jle32 r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jlt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 5
-        or r1, r9
-        jlt32 r1, 4, +4
-        jlt32 r1, 5, +3
-        jlt32 r1, 6, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jlt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        or r1, r9
-        jlt32 r1, r2, +4
-        jlt32 r1, r1, +3
-        jlt32 r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jne32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xb
-        or r1, r9
-        jne32 r1, 0xb, +4
-        mov32 r0, 1
-        mov32 r1, 0xa
-        or r1, r9
-        jne32 r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jne32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xb
-        or r1, r9
-        mov32 r2, 0xb
-        jne32 r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0xa
-        or r1, r9
-        jne32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jset32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0x7
-        or r1, r9
-        jset32 r1, 0x8, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset32 r1, 0x8, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jset32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0x7
-        or r1, r9
-        mov32 r2, 0x8
-        jset32 r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsge32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jsge32 r1, -1, +5
-        jsge32 r1, 0, +4
-        mov32 r0, 1
-        mov r1, -1
-        jsge32 r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsge32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -1
-        mov32 r3, 0
-        jsge32 r1, r2, +5
-        jsge32 r1, r3, +4
-        mov32 r0, 1
-        mov r1, r2
-        jsge32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsgt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jsgt32 r1, -1, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt32 r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsgt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -1
-        jsgt32 r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsle32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jsle32 r1, -3, +5
-        jsle32 r1, -1, +1
-        exit
-        mov32 r0, 1
-        jsle32 r1, -2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jsle32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -3
-        mov32 r3, 0
-        jsle32 r1, r2, +6
-        jsle32 r1, r3, +1
-        exit
-        mov32 r0, 1
-        mov r1, r2
-        jsle32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jslt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jslt32 r1, -3, +4
-        jslt32 r1, -2, +3
-        jslt32 r1, -1, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_jslt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -3
-        mov r3, -1
-        jslt32 r1, r1, +4
-        jslt32 r1, r2, +3
-        jslt32 r1, r3, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_lddw() {
-    let prog = assemble(
-        "
-        lddw r0, 0x1122334455667788
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1122334455667788);
-    }
-}
-
-#[test]
-fn test_jit_lddw2() {
-    let prog = assemble(
-        "
-        lddw r0, 0x0000000080000000
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x80000000);
-    }
-}
-
-#[test]
-fn test_jit_ldxb_all() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxb r9, [r0+0]
-        lsh r9, 0
-        ldxb r8, [r0+1]
-        lsh r8, 4
-        ldxb r7, [r0+2]
-        lsh r7, 8
-        ldxb r6, [r0+3]
-        lsh r6, 12
-        ldxb r5, [r0+4]
-        lsh r5, 16
-        ldxb r4, [r0+5]
-        lsh r4, 20
-        ldxb r3, [r0+6]
-        lsh r3, 24
-        ldxb r2, [r0+7]
-        lsh r2, 28
-        ldxb r1, [r0+8]
-        lsh r1, 32
-        ldxb r0, [r0+9]
-        lsh r0, 36
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x9876543210);
-    }
-}
-
-#[test]
-fn test_jit_ldxb() {
-    let prog = assemble(
-        "
-        ldxb r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0x11, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11);
-    }
-}
-
-#[test]
-fn test_jit_ldxdw() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xcc, 0xdd,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x8877665544332211);
-    }
-}
-
-#[test]
-fn test_jit_ldxh_all() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxh r9, [r0+0]
-        be16 r9
-        lsh r9, 0
-        ldxh r8, [r0+2]
-        be16 r8
-        lsh r8, 4
-        ldxh r7, [r0+4]
-        be16 r7
-        lsh r7, 8
-        ldxh r6, [r0+6]
-        be16 r6
-        lsh r6, 12
-        ldxh r5, [r0+8]
-        be16 r5
-        lsh r5, 16
-        ldxh r4, [r0+10]
-        be16 r4
-        lsh r4, 20
-        ldxh r3, [r0+12]
-        be16 r3
-        lsh r3, 24
-        ldxh r2, [r0+14]
-        be16 r2
-        lsh r2, 28
-        ldxh r1, [r0+16]
-        be16 r1
-        lsh r1, 32
-        ldxh r0, [r0+18]
-        be16 r0
-        lsh r0, 36
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00,
-        0x07, 0x00, 0x08, 0x00, 0x09,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x9876543210);
-    }
-}
-
-#[test]
-fn test_jit_ldxh_all2() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxh r9, [r0+0]
-        be16 r9
-        ldxh r8, [r0+2]
-        be16 r8
-        ldxh r7, [r0+4]
-        be16 r7
-        ldxh r6, [r0+6]
-        be16 r6
-        ldxh r5, [r0+8]
-        be16 r5
-        ldxh r4, [r0+10]
-        be16 r4
-        ldxh r3, [r0+12]
-        be16 r3
-        ldxh r2, [r0+14]
-        be16 r2
-        ldxh r1, [r0+16]
-        be16 r1
-        ldxh r0, [r0+18]
-        be16 r0
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00,
-        0x80, 0x01, 0x00, 0x02, 0x00,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x3ff);
-    }
-}
-
-#[test]
-fn test_jit_ldxh() {
-    let prog = assemble(
-        "
-        ldxh r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x2211);
-    }
-}
-
-#[test]
-fn test_jit_ldxh_same_reg() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        sth [r0], 0x1234
-        ldxh r0, [r0]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xff, 0xff];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1234);
-    }
-}
-
-#[test]
-fn test_jit_ldxw_all() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxw r9, [r0+0]
-        be32 r9
-        ldxw r8, [r0+4]
-        be32 r8
-        ldxw r7, [r0+8]
-        be32 r7
-        ldxw r6, [r0+12]
-        be32 r6
-        ldxw r5, [r0+16]
-        be32 r5
-        ldxw r4, [r0+20]
-        be32 r4
-        ldxw r3, [r0+24]
-        be32 r3
-        ldxw r2, [r0+28]
-        be32 r2
-        ldxw r1, [r0+32]
-        be32 r1
-        ldxw r0, [r0+36]
-        be32 r0
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x030f0f);
-    }
-}
-
-#[test]
-fn test_jit_ldxw() {
-    let prog = assemble(
-        "
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x44332211);
-    }
-}
-
-#[test]
-fn test_jit_le16() {
-    let prog = assemble(
-        "
-        ldxh r0, [r1]
-        le16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x22, 0x11];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1122);
-    }
-}
-
-#[test]
-fn test_jit_le32() {
-    let prog = assemble(
-        "
-        ldxw r0, [r1]
-        le32 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x44, 0x33, 0x22, 0x11];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11223344);
-    }
-}
-
-#[test]
-fn test_jit_le64() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        le64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1122334455667788);
-    }
-}
-
-#[test]
-fn test_jit_lsh_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0x1
-        mov r7, 4
-        lsh r0, r7
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x10);
-    }
-}
-
-#[test]
-fn test_jit_mod() {
-    let prog = assemble(
-        "
-        mov32 r0, 5748
-        mod32 r0, 92
-        mov32 r1, 13
-        mod32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x5);
-    }
-}
-
-#[test]
-fn test_jit_mod32() {
-    let prog = assemble(
-        "
-        lddw r0, 0x100000003
-        mod32 r0, 3
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_mod64() {
-    let prog = assemble(
-        "
-        mov32 r0, -1316649930
-        lsh r0, 32
-        or r0, 0x100dc5c8
-        mov32 r1, 0xdde263e
-        lsh r1, 32
-        or r1, 0x3cbef7f3
-        mod r0, r1
-        mod r0, 0x658f1778
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x30ba5a04);
-    }
-}
-
-#[test]
-fn test_jit_mov() {
-    let prog = assemble(
-        "
-        mov32 r1, 1
-        mov32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_mul32_imm() {
-    let prog = assemble(
-        "
-        mov r0, 3
-        mul32 r0, 4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xc);
-    }
-}
-
-#[test]
-fn test_jit_mul32_reg() {
-    let prog = assemble(
-        "
-        mov r0, 3
-        mov r1, 4
-        mul32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xc);
-    }
-}
-
-#[test]
-fn test_jit_mul32_reg_overflow() {
-    let prog = assemble(
-        "
-        mov r0, 0x40000001
-        mov r1, 4
-        mul32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x4);
-    }
-}
-
-#[test]
-fn test_jit_mul64_imm() {
-    let prog = assemble(
-        "
-        mov r0, 0x40000001
-        mul r0, 4
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x100000004);
-    }
-}
-
-#[test]
-fn test_jit_mul64_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0x40000001
-        mov r1, 4
-        mul r0, r1
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x100000004);
-    }
-}
-
-#[test]
-fn test_jit_mul_loop() {
-    let prog = assemble(
-        "
-        mov r0, 0x7
-        add r1, 0xa
-        lsh r1, 0x20
-        rsh r1, 0x20
-        jeq r1, 0x0, +4
-        mov r0, 0x7
-        mul r0, 0x7
-        add r1, -1
-        jne r1, 0x0, -3
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x75db9c97);
-    }
-}
-
-#[test]
-fn test_jit_neg64() {
-    let prog = assemble(
-        "
-        mov32 r0, 2
-        neg r0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xfffffffffffffffe);
-    }
-}
-
-#[test]
-fn test_jit_neg() {
-    let prog = assemble(
-        "
-        mov32 r0, 2
-        neg32 r0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xfffffffe);
-    }
-}
-
-#[test]
-fn test_jit_prime() {
-    let prog = assemble(
-        "
-        mov r1, 67
-        mov r0, 0x1
-        mov r2, 0x2
-        jgt r1, 0x2, +4
-        ja +10
-        add r2, 0x1
-        mov r0, 0x1
-        jge r2, r1, +7
-        mov r3, r1
-        div r3, r2
-        mul r3, r2
-        mov r4, r1
-        sub r4, r3
-        mov r0, 0x0
-        jne r4, 0x0, -10
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_rhs32() {
-    let prog = assemble(
-        "
-        xor r0, r0
-        sub r0, 1
-        rsh32 r0, 8
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x00ffffff);
-    }
-}
-
-#[test]
-fn test_jit_rsh_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0x10
-        mov r7, 4
-        rsh r0, r7
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_stack() {
-    let prog = assemble(
-        "
-        mov r1, 51
-        stdw [r10-16], 0xab
-        stdw [r10-8], 0xcd
-        and r1, 1
-        lsh r1, 3
-        mov r2, r10
-        add r2, r1
-        ldxdw r0, [r2-16]
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0xcd);
-    }
-}
-
-#[test]
-fn test_jit_stack2() {
-    let prog = assemble(
-        "
-        stb [r10-4], 0x01
-        stb [r10-3], 0x02
-        stb [r10-2], 0x03
-        stb [r10-1], 0x04
-        mov r1, r10
-        mov r2, 0x4
-        sub r1, r2
-        call 1
-        mov r1, 0
-        ldxb r2, [r10-4]
-        ldxb r3, [r10-3]
-        ldxb r4, [r10-2]
-        ldxb r5, [r10-1]
-        call 0
-        xor r0, 0x2a2a2a2a
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes).unwrap();
-    vm.register_helper(1, helpers::memfrob).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x01020304);
-    }
-}
-
-#[test]
-fn test_jit_stb() {
-    let prog = assemble(
-        "
-        stb [r1+2], 0x11
-        ldxb r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11);
-    }
-}
-
-#[test]
-fn test_jit_stdw() {
-    let prog = assemble(
-        "
-        stdw [r1+2], 0x44332211
-        ldxdw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x44332211);
-    }
-}
-
-#[test]
-fn test_jit_sth() {
-    let prog = assemble(
-        "
-        sth [r1+2], 0x2211
-        ldxh r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x2211);
-    }
-}
-
-#[test]
-fn test_jit_string_stack() {
-    let prog = assemble(
-        "
-        mov r1, 0x78636261
-        stxw [r10-8], r1
-        mov r6, 0x0
-        stxb [r10-4], r6
-        stxb [r10-12], r6
-        mov r1, 0x79636261
-        stxw [r10-16], r1
-        mov r1, r10
-        add r1, -8
-        mov r2, r1
-        call 0x4
-        mov r1, r0
-        mov r0, 0x1
-        lsh r1, 0x20
-        rsh r1, 0x20
-        jne r1, 0x0, +11
-        mov r1, r10
-        add r1, -8
-        mov r2, r10
-        add r2, -16
-        call 0x4
-        mov r1, r0
-        lsh r1, 0x20
-        rsh r1, 0x20
-        mov r0, 0x1
-        jeq r1, r6, +1
-        mov r0, 0x0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(4, helpers::strcmp).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit().unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_stw() {
-    let prog = assemble(
-        "
-        stw [r1+2], 0x44332211
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x44332211);
-    }
-}
-
-#[test]
-fn test_jit_stxb() {
-    let prog = assemble(
-        "
-        mov32 r2, 0x11
-        stxb [r1+2], r2
-        ldxb r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x11);
-    }
-}
-
-#[test]
-fn test_jit_stxb_all() {
-    let prog = assemble(
-        "
-        mov r0, 0xf0
-        mov r2, 0xf2
-        mov r3, 0xf3
-        mov r4, 0xf4
-        mov r5, 0xf5
-        mov r6, 0xf6
-        mov r7, 0xf7
-        mov r8, 0xf8
-        stxb [r1], r0
-        stxb [r1+1], r2
-        stxb [r1+2], r3
-        stxb [r1+3], r4
-        stxb [r1+4], r5
-        stxb [r1+5], r6
-        stxb [r1+6], r7
-        stxb [r1+7], r8
-        ldxdw r0, [r1]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0xf0f2f3f4f5f6f7f8);
-    }
-}
-
-#[test]
-fn test_jit_stxb_all2() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        mov r1, 0xf1
-        mov r9, 0xf9
-        stxb [r0], r1
-        stxb [r0+1], r9
-        ldxh r0, [r0]
-        be16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xff, 0xff];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0xf1f9);
-    }
-}
-
-#[test]
-fn test_jit_stxb_chain() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxb r9, [r0+0]
-        stxb [r0+1], r9
-        ldxb r8, [r0+1]
-        stxb [r0+2], r8
-        ldxb r7, [r0+2]
-        stxb [r0+3], r7
-        ldxb r6, [r0+3]
-        stxb [r0+4], r6
-        ldxb r5, [r0+4]
-        stxb [r0+5], r5
-        ldxb r4, [r0+5]
-        stxb [r0+6], r4
-        ldxb r3, [r0+6]
-        stxb [r0+7], r3
-        ldxb r2, [r0+7]
-        stxb [r0+8], r2
-        ldxb r1, [r0+8]
-        stxb [r0+9], r1
-        ldxb r0, [r0+9]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x2a);
-    }
-}
-
-#[test]
-fn test_jit_stxdw() {
-    let prog = assemble(
-        "
-        mov r2, -2005440939
-        lsh r2, 32
-        or r2, 0x44332211
-        stxdw [r1+2], r2
-        ldxdw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x8877665544332211);
-    }
-}
-
-#[test]
-fn test_jit_stxh() {
-    let prog = assemble(
-        "
-        mov32 r2, 0x2211
-        stxh [r1+2], r2
-        ldxh r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x2211);
-    }
-}
-
-#[test]
-fn test_jit_stxw() {
-    let prog = assemble(
-        "
-        mov32 r2, 0x44332211
-        stxw [r1+2], r2
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x44332211);
-    }
-}
-
-#[test]
-fn test_jit_subnet() {
-    let prog = assemble(
-        "
-        mov r2, 0xe
-        ldxh r3, [r1+12]
-        jne r3, 0x81, +2
-        mov r2, 0x12
-        ldxh r3, [r1+16]
-        and r3, 0xffff
-        jne r3, 0x8, +5
-        add r1, r2
-        mov r0, 0x1
-        ldxw r1, [r1+16]
-        and r1, 0xffffff
-        jeq r1, 0x1a8c0, +1
-        mov r0, 0x0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x00, 0xc0, 0x9f, 0xa0, 0x97, 0x00, 0xa0, 0xcc, 0x3b, 0xbf, 0xfa, 0x08, 0x00, 0x45,
-        0x10, 0x00, 0x3c, 0x46, 0x3c, 0x40, 0x00, 0x40, 0x06, 0x73, 0x1c, 0xc0, 0xa8, 0x01, 0x02,
-        0xc0, 0xa8, 0x01, 0x01, 0x06, 0x0e, 0x00, 0x17, 0x99, 0xc5, 0xa0, 0xec, 0x00, 0x00, 0x00,
-        0x00, 0xa0, 0x02, 0x7d, 0x78, 0xe0, 0xa3, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02,
-        0x08, 0x0a, 0x00, 0x9c, 0x27, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00,
-    ];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1);
-    }
-}
-
-const PROG_TCP_PORT_80: [u8; 152] = [
-    0x71, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x13, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x67, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x02, 0x0a, 0x00, 0x06, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-    0x57, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x0f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x15, 0x02, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x69, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x55, 0x01, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-];
-
-#[test]
-fn test_jit_tcp_port80_match() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_tcp_port80_nomatch() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x00, 0x16, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x51, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_tcp_port80_nomatch_ethertype() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x01, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_tcp_port80_nomatch_proto() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x0);
-    }
-}
-
-#[test]
-fn test_jit_tcp_sack_match() {
-    let mut mem = TCP_SACK_MATCH.to_vec();
-    let prog = assemble(TCP_SACK_ASM).unwrap();
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem.as_mut_slice()).unwrap(), 0x1);
-    }
-}
-
-#[test]
-fn test_jit_tcp_sack_nomatch() {
-    let mut mem = TCP_SACK_NOMATCH.to_vec();
-    let prog = assemble(TCP_SACK_ASM).unwrap();
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.jit_compile().unwrap();
-    unsafe {
-        assert_eq!(vm.execute_program_jit(mem.as_mut_slice()).unwrap(), 0x0);
-    }
-}

+ 0 - 177
kernel/crates/rbpf/tests/ubpf_verifier.rs

@@ -1,177 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Converted from the tests for uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-// The tests contained in this file are extracted from the unit tests of uBPF software. Each test
-// in this file has a name in the form `test_verifier_<name>`, and corresponds to the
-// (human-readable) code in `ubpf/tree/master/tests/<name>`, available at
-// <https://github.com/iovisor/ubpf/tree/master/tests> (hyphen had to be replaced with underscores
-// as Rust will not accept them in function names). It is strongly advised to refer to the uBPF
-// version to understand what these program do.
-//
-// Each program was assembled from the uBPF version with the assembler provided by uBPF itself, and
-// available at <https://github.com/iovisor/ubpf/tree/master/ubpf>.
-// The very few modifications that have been realized should be indicated.
-
-// These are unit tests for the eBPF “verifier”.
-
-extern crate rbpf;
-
-use rbpf::{assembler::assemble, ebpf};
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: unsupported argument for LE/BE (insn #0)")]
-fn test_verifier_err_endian_size() {
-    let prog = &[
-        0xdc, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    ];
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: incomplete LD_DW instruction (insn #0)")]
-fn test_verifier_err_incomplete_lddw() {
-    // Note: ubpf has test-err-incomplete-lddw2, which is the same
-    let prog = &[
-        0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: infinite loop")]
-fn test_verifier_err_infinite_loop() {
-    let prog = assemble(
-        "
-        ja -1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: invalid destination register (insn #0)")]
-fn test_verifier_err_invalid_reg_dst() {
-    let prog = assemble(
-        "
-        mov r11, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: invalid source register (insn #0)")]
-fn test_verifier_err_invalid_reg_src() {
-    let prog = assemble(
-        "
-        mov r0, r11
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: jump to middle of LD_DW at #2 (insn #0)")]
-fn test_verifier_err_jmp_lddw() {
-    let prog = assemble(
-        "
-        ja +1
-        lddw r0, 0x1122334455667788
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: jump out of code to #3 (insn #0)")]
-fn test_verifier_err_jmp_out() {
-    let prog = assemble(
-        "
-        ja +2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: program does not end with “EXIT” instruction")]
-fn test_verifier_err_no_exit() {
-    let prog = assemble(
-        "
-        mov32 r0, 0",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-fn test_verifier_err_no_exit_backward_jump() {
-    let prog = assemble(
-        "
-        ja +1
-        exit
-        ja -2",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: eBPF program length limited to 1000000, here 1000001")]
-fn test_verifier_err_too_many_instructions() {
-    // uBPF uses 65637 instructions, because it sets its limit at 65636.
-    // We use the classic 4096 limit from kernel, so no need to produce as many instructions.
-    let mut prog = (0..(1_000_000 * ebpf::INSN_SIZE))
-        .map(|x| match x % 8 {
-            0 => 0xb7,
-            1 => 0x01,
-            _ => 0,
-        })
-        .collect::<Vec<u8>>();
-    prog.append(&mut vec![0x95, 0, 0, 0, 0, 0, 0, 0]);
-
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: unknown eBPF opcode 0x6 (insn #0)")]
-fn test_verifier_err_unknown_opcode() {
-    let prog = &[
-        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00,
-    ];
-    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-#[should_panic(expected = "[Verifier] Error: cannot write into register r10 (insn #0)")]
-fn test_verifier_err_write_r10() {
-    let prog = assemble(
-        "
-        mov r10, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}

+ 0 - 2674
kernel/crates/rbpf/tests/ubpf_vm.rs

@@ -1,2674 +0,0 @@
-// SPDX-License-Identifier: (Apache-2.0 OR MIT)
-// Converted from the tests for uBPF <https://github.com/iovisor/ubpf>
-// Copyright 2015 Big Switch Networks, Inc
-// Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
-
-// The tests contained in this file are extracted from the unit tests of uBPF software. Each test
-// in this file has a name in the form `test_vm_<name>`, and corresponds to the (human-readable)
-// code in `ubpf/tree/master/tests/<name>`, available at
-// <https://github.com/iovisor/ubpf/tree/master/tests> (hyphen had to be replaced with underscores
-// as Rust will not accept them in function names). It is strongly advised to refer to the uBPF
-// version to understand what these program do.
-//
-// Each program was assembled from the uBPF version with the assembler provided by uBPF itself, and
-// available at <https://github.com/iovisor/ubpf/tree/master/ubpf>.
-// The very few modifications that have been realized should be indicated.
-
-// These are unit tests for the eBPF interpreter.
-
-#![allow(clippy::unreadable_literal)]
-
-extern crate rbpf;
-mod common;
-
-use common::{TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH};
-use rbpf::{assembler::assemble, helpers};
-
-#[test]
-fn test_vm_add() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 2
-        add32 r0, 1
-        add32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-}
-
-#[test]
-fn test_vm_alu64_arith() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        mov r6, 6
-        mov r7, 7
-        mov r8, 8
-        mov r9, 9
-        add r0, 23
-        add r0, r7
-        sub r0, 13
-        sub r0, r1
-        mul r0, 7
-        mul r0, r3
-        div r0, 2
-        div r0, r4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x2a);
-}
-
-#[test]
-fn test_vm_alu64_bit() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        mov r6, 6
-        mov r7, 7
-        mov r8, 8
-        or r0, r5
-        or r0, 0xa0
-        and r0, 0xa3
-        mov r9, 0x91
-        and r0, r9
-        lsh r0, 32
-        lsh r0, 22
-        lsh r0, r8
-        rsh r0, 32
-        rsh r0, 19
-        rsh r0, r7
-        xor r0, 0x03
-        xor r0, r2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x11);
-}
-
-#[test]
-fn test_vm_alu_arith() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 1
-        mov32 r2, 2
-        mov32 r3, 3
-        mov32 r4, 4
-        mov32 r5, 5
-        mov32 r6, 6
-        mov32 r7, 7
-        mov32 r8, 8
-        mov32 r9, 9
-        add32 r0, 23
-        add32 r0, r7
-        sub32 r0, 13
-        sub32 r0, r1
-        mul32 r0, 7
-        mul32 r0, r3
-        div32 r0, 2
-        div32 r0, r4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x2a);
-}
-
-#[test]
-fn test_vm_alu_bit() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 1
-        mov32 r2, 2
-        mov32 r3, 3
-        mov32 r4, 4
-        mov32 r5, 5
-        mov32 r6, 6
-        mov32 r7, 7
-        mov32 r8, 8
-        or32 r0, r5
-        or32 r0, 0xa0
-        and32 r0, 0xa3
-        mov32 r9, 0x91
-        and32 r0, r9
-        lsh32 r0, 22
-        lsh32 r0, r8
-        rsh32 r0, 19
-        rsh32 r0, r7
-        xor32 r0, 0x03
-        xor32 r0, r2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x11);
-}
-
-#[test]
-fn test_vm_arsh32_high_shift() {
-    let prog = assemble(
-        "
-        mov r0, 8
-        lddw r1, 0x100000001
-        arsh32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x4);
-}
-
-#[test]
-fn test_vm_arsh() {
-    let prog = assemble(
-        "
-        mov32 r0, 0xf8
-        lsh32 r0, 28
-        arsh32 r0, 16
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xffff8000);
-}
-
-#[test]
-fn test_vm_arsh64() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        lsh r0, 63
-        arsh r0, 55
-        mov32 r1, 5
-        arsh r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xfffffffffffffff8);
-}
-
-#[test]
-fn test_vm_arsh_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0xf8
-        mov32 r1, 16
-        lsh32 r0, 28
-        arsh32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xffff8000);
-}
-
-#[test]
-fn test_vm_arsh_imm_overflow() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        lsh r0, 63
-        arsh r0, 0xff20
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xffffffff80000000);
-}
-
-#[test]
-fn test_vm_arsh_reg_overflow() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        lsh r0, 63
-        mov r1, 0xff04
-        arsh r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xf800000000000000);
-}
-
-#[test]
-fn test_vm_arsh32_imm_overflow() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        lsh32 r0, 31
-        arsh32 r0, 0xff10
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xffff8000);
-}
-
-#[test]
-fn test_vm_arsh32_reg_overflow() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        lsh32 r0, 31
-        mov32 r1, 32
-        arsh32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x80000000);
-}
-
-#[test]
-fn test_vm_be16() {
-    let prog = assemble(
-        "
-        ldxh r0, [r1]
-        be16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1122);
-}
-
-#[test]
-fn test_vm_be16_high() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        be16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1122);
-}
-
-#[test]
-fn test_vm_be32() {
-    let prog = assemble(
-        "
-        ldxw r0, [r1]
-        be32 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x11223344);
-}
-
-#[test]
-fn test_vm_be32_high() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        be32 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x11223344);
-}
-
-#[test]
-fn test_vm_be64() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1122334455667788);
-}
-
-#[test]
-fn test_vm_call() {
-    let prog = assemble(
-        "
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        call 0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0102030405);
-}
-
-#[test]
-fn test_vm_call_memfrob() {
-    let prog = assemble(
-        "
-        mov r6, r1
-        add r1, 2
-        mov r2, 4
-        call 1
-        ldxdw r0, [r6]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
-    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.register_helper(1, helpers::memfrob).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x102292e2f2c0708);
-}
-
-// TODO: helpers::trash_registers needs asm!().
-// Try this again once asm!() is available in stable.
-//#[test]
-//fn test_vm_call_save() {
-//let prog = &[
-//0xb7, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-//0xb7, 0x07, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-//0xb7, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
-//0xb7, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
-//0x85, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-//0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x4f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-//0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-//];
-//let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-//vm.register_helper(2, helpers::trash_registers);
-//assert_eq!(vm.execute_program().unwrap(), 0x4321);
-//}
-
-#[test]
-fn test_vm_div32_high_divisor() {
-    let prog = assemble(
-        "
-        mov r0, 12
-        lddw r1, 0x100000004
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-}
-
-#[test]
-fn test_vm_div32_imm() {
-    let prog = assemble(
-        "
-        lddw r0, 0x10000000c
-        div32 r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-}
-
-#[test]
-fn test_vm_div32_reg() {
-    let prog = assemble(
-        "
-        lddw r0, 0x10000000c
-        mov r1, 4
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-}
-
-#[test]
-fn test_vm_div64_imm() {
-    let prog = assemble(
-        "
-        mov r0, 0xc
-        lsh r0, 32
-        div r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x300000000);
-}
-
-#[test]
-fn test_vm_div64_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0xc
-        lsh r0, 32
-        mov r1, 4
-        div r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x300000000);
-}
-
-#[test]
-fn test_vm_early_exit() {
-    let prog = assemble(
-        "
-        mov r0, 3
-        exit
-        mov r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x3);
-}
-
-// uBPF limits the number of user functions at 64. We don't.
-//#[test]
-//fn test_vm_err_call_bad_imm() {
-//}
-
-#[test]
-#[should_panic(expected = "Error: unknown helper function (id: 0x3f)")]
-fn test_vm_err_call_unreg() {
-    let prog = assemble(
-        "
-        mov r1, 1
-        mov r2, 2
-        mov r3, 3
-        mov r4, 4
-        mov r5, 5
-        call 63
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-fn test_vm_div64_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        div r0, 0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_div_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        div32 r0, 0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_mod64_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mod r0, 0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_mod_by_zero_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mod32 r0, 0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-// Make sure we only consider the last 32 bits of the divisor.
-#[test]
-fn test_vm_mod_by_zero_reg_long() {
-    let prog = assemble(
-        "
-        lddw r1, 0x100000000
-        mod32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_div64_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        div r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_div_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-// Make sure we only consider the last 32 bits of the divisor.
-#[test]
-fn test_vm_div_by_zero_reg_long() {
-    let prog = assemble(
-        "
-        lddw r1, 0x100000000
-        div32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_mod64_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        mod r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_mod_by_zero_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r1, 0
-        mod32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-#[should_panic(expected = "Error: out of bounds memory store (insn #1)")]
-fn test_vm_err_stack_out_of_bound() {
-    let prog = assemble(
-        "
-        stb [r10], 0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.execute_program().unwrap();
-}
-
-#[test]
-fn test_vm_exit() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_ja() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        ja +1
-        mov r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jeq_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xa
-        jeq r1, 0xb, +4
-        mov32 r0, 1
-        mov32 r1, 0xb
-        jeq r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jeq_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xa
-        mov32 r2, 0xb
-        jeq r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0xb
-        jeq r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jge_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xa
-        jge r1, 0xb, +4
-        mov32 r0, 1
-        mov32 r1, 0xc
-        jge r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jle_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 5
-        jle r1, 4, +1
-        jle r1, 6, +1
-        exit
-        jle r1, 5, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jle_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        jle r1, r2, +2
-        jle r1, r1, +1
-        exit
-        jle r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jgt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 5
-        jgt r1, 6, +2
-        jgt r1, 5, +1
-        jgt r1, 4, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jgt_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 5
-        mov r2, 6
-        mov r3, 4
-        jgt r1, r2, +2
-        jgt r1, r1, +1
-        jgt r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jlt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 5
-        jlt r1, 4, +2
-        jlt r1, 5, +1
-        jlt r1, 6, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jlt_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        jlt r1, r2, +2
-        jlt r1, r1, +1
-        jlt r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jit_bounce() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        mov r6, r0
-        mov r7, r6
-        mov r8, r7
-        mov r9, r8
-        mov r0, r9
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jne_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0xb
-        mov32 r2, 0xb
-        jne r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0xa
-        jne r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jset_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0x7
-        jset r1, 0x8, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset r1, 0x8, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jset_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov32 r1, 0x7
-        mov32 r2, 0x8
-        jset r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsge_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jsge r1, -1, +5
-        jsge r1, 0, +4
-        mov32 r0, 1
-        mov r1, -1
-        jsge r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsge_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        mov r2, -1
-        mov32 r3, 0
-        jsge r1, r2, +5
-        jsge r1, r3, +4
-        mov32 r0, 1
-        mov r1, r2
-        jsge r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsle_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jsle r1, -3, +1
-        jsle r1, -1, +1
-        exit
-        mov32 r0, 1
-        jsle r1, -2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsle_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -1
-        mov r2, -2
-        mov32 r3, 0
-        jsle r1, r2, +1
-        jsle r1, r3, +1
-        exit
-        mov32 r0, 1
-        mov r1, r2
-        jsle r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsgt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jsgt r1, -1, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsgt_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        mov r2, -1
-        jsgt r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jslt_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        jslt r1, -3, +2
-        jslt r1, -2, +1
-        jslt r1, -1, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jslt_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 0
-        mov r1, -2
-        mov r2, -3
-        mov r3, -1
-        jslt r1, r1, +2
-        jslt r1, r2, +1
-        jslt r1, r3, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jeq32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0x0
-        mov32 r1, 0xa
-        jeq32 r1, 0xb, +5
-        mov32 r0, 1
-        mov r1, 0xb
-        or r1, r9
-        jeq32 r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jeq32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xa
-        mov32 r2, 0xb
-        jeq32 r1, r2, +5
-        mov32 r0, 1
-        mov32 r1, 0xb
-        or r1, r9
-        jeq32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jge32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xa
-        jge32 r1, 0xb, +5
-        mov32 r0, 1
-        or r1, r9
-        mov32 r1, 0xc
-        jge32 r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jge32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xa
-        mov32 r2, 0xb
-        jge32 r1, r2, +5
-        mov32 r0, 1
-        or r1, r9
-        mov32 r1, 0xc
-        jge32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jgt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 5
-        or r1, r9
-        jgt32 r1, 6, +4
-        jgt32 r1, 5, +3
-        jgt32 r1, 4, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jgt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov r0, 0
-        mov r1, 5
-        mov32 r1, 5
-        or r1, r9
-        mov r2, 6
-        mov r3, 4
-        jgt32 r1, r2, +4
-        jgt32 r1, r1, +3
-        jgt32 r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jle32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 5
-        or r1, r9
-        jle32 r1, 4, +5
-        jle32 r1, 6, +1
-        exit
-        jle32 r1, 5, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jle32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        or r1, r9
-        jle32 r1, r2, +5
-        jle32 r1, r1, +1
-        exit
-        jle32 r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jlt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 5
-        or r1, r9
-        jlt32 r1, 4, +4
-        jlt32 r1, 5, +3
-        jlt32 r1, 6, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jlt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov r0, 0
-        mov r1, 5
-        mov r2, 4
-        mov r3, 6
-        or r1, r9
-        jlt32 r1, r2, +4
-        jlt32 r1, r1, +3
-        jlt32 r1, r3, +1
-        exit
-        mov r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jne32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xb
-        or r1, r9
-        jne32 r1, 0xb, +4
-        mov32 r0, 1
-        mov32 r1, 0xa
-        or r1, r9
-        jne32 r1, 0xb, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jne32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0xb
-        or r1, r9
-        mov32 r2, 0xb
-        jne32 r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0xa
-        or r1, r9
-        jne32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jset32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0x7
-        or r1, r9
-        jset32 r1, 0x8, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset32 r1, 0x8, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jset32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, 0x7
-        or r1, r9
-        mov32 r2, 0x8
-        jset32 r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0x9
-        jset32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsge32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jsge32 r1, -1, +5
-        jsge32 r1, 0, +4
-        mov32 r0, 1
-        mov r1, -1
-        jsge32 r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsge32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -1
-        mov32 r3, 0
-        jsge32 r1, r2, +5
-        jsge32 r1, r3, +4
-        mov32 r0, 1
-        mov r1, r2
-        jsge32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsgt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jsgt32 r1, -1, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt32 r1, -1, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsgt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -1
-        jsgt32 r1, r2, +4
-        mov32 r0, 1
-        mov32 r1, 0
-        jsgt32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsle32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jsle32 r1, -3, +5
-        jsle32 r1, -1, +1
-        exit
-        mov32 r0, 1
-        jsle32 r1, -2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jsle32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -3
-        mov32 r3, 0
-        jsle32 r1, r2, +6
-        jsle32 r1, r3, +1
-        exit
-        mov32 r0, 1
-        mov r1, r2
-        jsle32 r1, r2, +1
-        mov32 r0, 2
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jslt32_imm() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        jslt32 r1, -3, +4
-        jslt32 r1, -2, +3
-        jslt32 r1, -1, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_jslt32_reg() {
-    let prog = assemble(
-        "
-        mov r9, 1
-        lsh r9, 32
-        mov32 r0, 0
-        mov32 r1, -2
-        or r1, r9
-        mov r2, -3
-        mov r3, -1
-        jslt32 r1, r1, +4
-        jslt32 r1, r2, +3
-        jslt32 r1, r3, +1
-        exit
-        mov32 r0, 1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_lddw() {
-    let prog = assemble(
-        "lddw r0, 0x1122334455667788
-                         exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1122334455667788);
-}
-
-#[test]
-fn test_vm_lddw2() {
-    let prog = assemble(
-        "
-        lddw r0, 0x0000000080000000
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x80000000);
-}
-
-#[test]
-fn test_vm_ldxb_all() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxb r9, [r0+0]
-        lsh r9, 0
-        ldxb r8, [r0+1]
-        lsh r8, 4
-        ldxb r7, [r0+2]
-        lsh r7, 8
-        ldxb r6, [r0+3]
-        lsh r6, 12
-        ldxb r5, [r0+4]
-        lsh r5, 16
-        ldxb r4, [r0+5]
-        lsh r4, 20
-        ldxb r3, [r0+6]
-        lsh r3, 24
-        ldxb r2, [r0+7]
-        lsh r2, 28
-        ldxb r1, [r0+8]
-        lsh r1, 32
-        ldxb r0, [r0+9]
-        lsh r0, 36
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x9876543210);
-}
-
-#[test]
-fn test_vm_ldxb() {
-    let prog = assemble(
-        "
-        ldxb r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0x11, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x11);
-}
-
-#[test]
-fn test_vm_ldxdw() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xcc, 0xdd,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x8877665544332211);
-}
-
-#[test]
-fn test_vm_ldxh_all() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxh r9, [r0+0]
-        be16 r9
-        lsh r9, 0
-        ldxh r8, [r0+2]
-        be16 r8
-        lsh r8, 4
-        ldxh r7, [r0+4]
-        be16 r7
-        lsh r7, 8
-        ldxh r6, [r0+6]
-        be16 r6
-        lsh r6, 12
-        ldxh r5, [r0+8]
-        be16 r5
-        lsh r5, 16
-        ldxh r4, [r0+10]
-        be16 r4
-        lsh r4, 20
-        ldxh r3, [r0+12]
-        be16 r3
-        lsh r3, 24
-        ldxh r2, [r0+14]
-        be16 r2
-        lsh r2, 28
-        ldxh r1, [r0+16]
-        be16 r1
-        lsh r1, 32
-        ldxh r0, [r0+18]
-        be16 r0
-        lsh r0, 36
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00,
-        0x07, 0x00, 0x08, 0x00, 0x09,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x9876543210);
-}
-
-#[test]
-fn test_vm_ldxh_all2() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxh r9, [r0+0]
-        be16 r9
-        ldxh r8, [r0+2]
-        be16 r8
-        ldxh r7, [r0+4]
-        be16 r7
-        ldxh r6, [r0+6]
-        be16 r6
-        ldxh r5, [r0+8]
-        be16 r5
-        ldxh r4, [r0+10]
-        be16 r4
-        ldxh r3, [r0+12]
-        be16 r3
-        ldxh r2, [r0+14]
-        be16 r2
-        ldxh r1, [r0+16]
-        be16 r1
-        ldxh r0, [r0+18]
-        be16 r0
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00,
-        0x80, 0x01, 0x00, 0x02, 0x00,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x3ff);
-}
-
-#[test]
-fn test_vm_ldxh() {
-    let prog = assemble(
-        "
-        ldxh r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x2211);
-}
-
-#[test]
-fn test_vm_ldxh_same_reg() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        sth [r0], 0x1234
-        ldxh r0, [r0]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xff, 0xff];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1234);
-}
-
-#[test]
-fn test_vm_ldxw_all() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxw r9, [r0+0]
-        be32 r9
-        ldxw r8, [r0+4]
-        be32 r8
-        ldxw r7, [r0+8]
-        be32 r7
-        ldxw r6, [r0+12]
-        be32 r6
-        ldxw r5, [r0+16]
-        be32 r5
-        ldxw r4, [r0+20]
-        be32 r4
-        ldxw r3, [r0+24]
-        be32 r3
-        ldxw r2, [r0+28]
-        be32 r2
-        ldxw r1, [r0+32]
-        be32 r1
-        ldxw r0, [r0+36]
-        be32 r0
-        or r0, r1
-        or r0, r2
-        or r0, r3
-        or r0, r4
-        or r0, r5
-        or r0, r6
-        or r0, r7
-        or r0, r8
-        or r0, r9
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x030f0f);
-}
-
-#[test]
-fn test_vm_ldxw() {
-    let prog = assemble(
-        "
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211);
-}
-
-#[test]
-fn test_vm_le16() {
-    let prog = assemble(
-        "
-        ldxh r0, [r1]
-        le16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x22, 0x11];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1122);
-}
-
-#[test]
-fn test_vm_le32() {
-    let prog = assemble(
-        "
-        ldxw r0, [r1]
-        le32 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x44, 0x33, 0x22, 0x11];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x11223344);
-}
-
-#[test]
-fn test_vm_le64() {
-    let prog = assemble(
-        "
-        ldxdw r0, [r1]
-        le64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1122334455667788);
-}
-
-#[test]
-fn test_vm_lsh_imm() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        lsh r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x10);
-}
-
-#[test]
-fn test_vm_lsh_reg() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        mov r7, 4
-        lsh r0, r7
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x10);
-}
-
-#[test]
-fn test_vm_lsh32_imm() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        lsh32 r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x10);
-}
-
-#[test]
-fn test_vm_lsh32_reg() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r7, 4
-        lsh32 r0, r7
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x10);
-}
-
-#[test]
-fn test_vm_lsh_imm_overflow() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        lsh r0, 64
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_lsh_reg_overflow() {
-    let prog = assemble(
-        "
-        mov r0, 1
-        mov r7, 64
-        lsh r0, r7
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_lsh32_imm_overflow() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        lsh32 r0, 32
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_lsh32_reg_overflow() {
-    let prog = assemble(
-        "
-        mov32 r0, 1
-        mov32 r7, 32
-        lsh32 r0, r7
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_mod() {
-    let prog = assemble(
-        "
-        mov32 r0, 5748
-        mod32 r0, 92
-        mov32 r1, 13
-        mod32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x5);
-}
-
-#[test]
-fn test_vm_mod32() {
-    let prog = assemble(
-        "
-        lddw r0, 0x100000003
-        mod32 r0, 3
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_mod64() {
-    let prog = assemble(
-        "
-        mov32 r0, -1316649930
-        lsh r0, 32
-        or r0, 0x100dc5c8
-        mov32 r1, 0xdde263e
-        lsh r1, 32
-        or r1, 0x3cbef7f3
-        mod r0, r1
-        mod r0, 0x658f1778
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x30ba5a04);
-}
-
-#[test]
-fn test_vm_mov() {
-    let prog = assemble(
-        "
-        mov32 r1, 1
-        mov32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_mul32_imm() {
-    let prog = assemble(
-        "
-        mov r0, 3
-        mul32 r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xc);
-}
-
-#[test]
-fn test_vm_mul32_reg() {
-    let prog = assemble(
-        "
-        mov r0, 3
-        mov r1, 4
-        mul32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xc);
-}
-
-#[test]
-fn test_vm_mul32_reg_overflow() {
-    let prog = assemble(
-        "
-        mov r0, 0x40000001
-        mov r1, 4
-        mul32 r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x4);
-}
-
-#[test]
-fn test_vm_mul64_imm() {
-    let prog = assemble(
-        "
-        mov r0, 0x40000001
-        mul r0, 4
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x100000004);
-}
-
-#[test]
-fn test_vm_mul64_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0x40000001
-        mov r1, 4
-        mul r0, r1
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x100000004);
-}
-
-#[test]
-fn test_vm_mul_loop() {
-    let prog = assemble(
-        "
-        mov r0, 0x7
-        add r1, 0xa
-        lsh r1, 0x20
-        rsh r1, 0x20
-        jeq r1, 0x0, +4
-        mov r0, 0x7
-        mul r0, 0x7
-        add r1, -1
-        jne r1, 0x0, -3
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x75db9c97);
-}
-
-#[test]
-fn test_vm_neg64() {
-    let prog = assemble(
-        "
-        mov32 r0, 2
-        neg r0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xfffffffffffffffe);
-}
-
-#[test]
-fn test_vm_neg() {
-    let prog = assemble(
-        "
-        mov32 r0, 2
-        neg32 r0
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xfffffffe);
-}
-
-#[test]
-fn test_vm_prime() {
-    let prog = assemble(
-        "
-        mov r1, 67
-        mov r0, 0x1
-        mov r2, 0x2
-        jgt r1, 0x2, +4
-        ja +10
-        add r2, 0x1
-        mov r0, 0x1
-        jge r2, r1, +7
-        mov r3, r1
-        div r3, r2
-        mul r3, r2
-        mov r4, r1
-        sub r4, r3
-        mov r0, 0x0
-        jne r4, 0x0, -10
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_rhs32() {
-    let prog = assemble(
-        "
-        xor r0, r0
-        sub r0, 1
-        rsh32 r0, 8
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x00ffffff);
-}
-
-#[test]
-fn test_vm_rsh_reg() {
-    let prog = assemble(
-        "
-        mov r0, 0x10
-        mov r7, 4
-        rsh r0, r7
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_stack() {
-    let prog = assemble(
-        "
-        mov r1, 51
-        stdw [r10-16], 0xab
-        stdw [r10-8], 0xcd
-        and r1, 1
-        lsh r1, 3
-        mov r2, r10
-        add r2, r1
-        ldxdw r0, [r2-16]
-        exit",
-    )
-    .unwrap();
-    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0xcd);
-}
-
-#[test]
-fn test_vm_stack2() {
-    let prog = assemble(
-        "
-        stb [r10-4], 0x01
-        stb [r10-3], 0x02
-        stb [r10-2], 0x03
-        stb [r10-1], 0x04
-        mov r1, r10
-        mov r2, 0x4
-        sub r1, r2
-        call 1
-        mov r1, 0
-        ldxb r2, [r10-4]
-        ldxb r3, [r10-3]
-        ldxb r4, [r10-2]
-        ldxb r5, [r10-1]
-        call 0
-        xor r0, 0x2a2a2a2a
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes).unwrap();
-    vm.register_helper(1, helpers::memfrob).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x01020304);
-}
-
-#[test]
-fn test_vm_stb() {
-    let prog = assemble(
-        "
-        stb [r1+2], 0x11
-        ldxb r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x11);
-}
-
-#[test]
-fn test_vm_stdw() {
-    let prog = assemble(
-        "
-        stdw [r1+2], 0x44332211
-        ldxdw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211);
-}
-
-// If this case is not handled properly in check_mem(), then we may overflow when adding the
-// context address and the offset, and make the thread panic with "attempt to add with overflow".
-// Check that we panic with the expected out-of-bounds error.
-//
-// The new toolchain introduced `assert_unsafe_precondition` which panics with a different message and can't be
-// caught by `#[should_panic]`. This is why we use `#[ignore]` here.
-#[test]
-#[should_panic(expected = "Error: out of bounds memory store (insn #1)")]
-#[ignore]
-fn test_vm_stdw_add_overflow() {
-    let prog = assemble(
-        "
-        stdw [r2-0x1], 0x44332211
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd,
-    ];
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(&prog), 0x00, 0x10).unwrap();
-    _ = vm.execute_program(mem).unwrap();
-}
-
-#[test]
-fn test_vm_sth() {
-    let prog = assemble(
-        "
-        sth [r1+2], 0x2211
-        ldxh r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x2211);
-}
-
-#[test]
-fn test_vm_string_stack() {
-    let prog = assemble(
-        "
-        mov r1, 0x78636261
-        stxw [r10-8], r1
-        mov r6, 0x0
-        stxb [r10-4], r6
-        stxb [r10-12], r6
-        mov r1, 0x79636261
-        stxw [r10-16], r1
-        mov r1, r10
-        add r1, -8
-        mov r2, r1
-        call 0x4
-        mov r1, r0
-        mov r0, 0x1
-        lsh r1, 0x20
-        rsh r1, 0x20
-        jne r1, 0x0, +11
-        mov r1, r10
-        add r1, -8
-        mov r2, r10
-        add r2, -16
-        call 0x4
-        mov r1, r0
-        lsh r1, 0x20
-        rsh r1, 0x20
-        mov r0, 0x1
-        jeq r1, r6, +1
-        mov r0, 0x0
-        exit",
-    )
-    .unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(4, helpers::strcmp).unwrap();
-    assert_eq!(vm.execute_program().unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_stw() {
-    let prog = assemble(
-        "
-        stw [r1+2], 0x44332211
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211);
-}
-
-#[test]
-fn test_vm_stxb() {
-    let prog = assemble(
-        "
-        mov32 r2, 0x11
-        stxb [r1+2], r2
-        ldxb r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x11);
-}
-
-#[test]
-fn test_vm_stxb_all() {
-    let prog = assemble(
-        "
-        mov r0, 0xf0
-        mov r2, 0xf2
-        mov r3, 0xf3
-        mov r4, 0xf4
-        mov r5, 0xf5
-        mov r6, 0xf6
-        mov r7, 0xf7
-        mov r8, 0xf8
-        stxb [r1], r0
-        stxb [r1+1], r2
-        stxb [r1+2], r3
-        stxb [r1+3], r4
-        stxb [r1+4], r5
-        stxb [r1+5], r6
-        stxb [r1+6], r7
-        stxb [r1+7], r8
-        ldxdw r0, [r1]
-        be64 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0xf0f2f3f4f5f6f7f8);
-}
-
-#[test]
-fn test_vm_stxb_all2() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        mov r1, 0xf1
-        mov r9, 0xf9
-        stxb [r0], r1
-        stxb [r0+1], r9
-        ldxh r0, [r0]
-        be16 r0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xff, 0xff];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0xf1f9);
-}
-
-#[test]
-fn test_vm_stxb_chain() {
-    let prog = assemble(
-        "
-        mov r0, r1
-        ldxb r9, [r0+0]
-        stxb [r0+1], r9
-        ldxb r8, [r0+1]
-        stxb [r0+2], r8
-        ldxb r7, [r0+2]
-        stxb [r0+3], r7
-        ldxb r6, [r0+3]
-        stxb [r0+4], r6
-        ldxb r5, [r0+4]
-        stxb [r0+5], r5
-        ldxb r4, [r0+5]
-        stxb [r0+6], r4
-        ldxb r3, [r0+6]
-        stxb [r0+7], r3
-        ldxb r2, [r0+7]
-        stxb [r0+8], r2
-        ldxb r1, [r0+8]
-        stxb [r0+9], r1
-        ldxb r0, [r0+9]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x2a);
-}
-
-#[test]
-fn test_vm_stxdw() {
-    let prog = assemble(
-        "
-        mov r2, -2005440939
-        lsh r2, 32
-        or r2, 0x44332211
-        stxdw [r1+2], r2
-        ldxdw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x8877665544332211);
-}
-
-#[test]
-fn test_vm_stxh() {
-    let prog = assemble(
-        "
-        mov32 r2, 0x2211
-        stxh [r1+2], r2
-        ldxh r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x2211);
-}
-
-#[test]
-fn test_vm_stxw() {
-    let prog = assemble(
-        "
-        mov32 r2, 0x44332211
-        stxw [r1+2], r2
-        ldxw r0, [r1+2]
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211);
-}
-
-#[test]
-fn test_vm_subnet() {
-    let prog = assemble(
-        "
-        mov r2, 0xe
-        ldxh r3, [r1+12]
-        jne r3, 0x81, +2
-        mov r2, 0x12
-        ldxh r3, [r1+16]
-        and r3, 0xffff
-        jne r3, 0x8, +5
-        add r1, r2
-        mov r0, 0x1
-        ldxw r1, [r1+16]
-        and r1, 0xffffff
-        jeq r1, 0x1a8c0, +1
-        mov r0, 0x0
-        exit",
-    )
-    .unwrap();
-    let mem = &mut [
-        0x00, 0x00, 0xc0, 0x9f, 0xa0, 0x97, 0x00, 0xa0, 0xcc, 0x3b, 0xbf, 0xfa, 0x08, 0x00, 0x45,
-        0x10, 0x00, 0x3c, 0x46, 0x3c, 0x40, 0x00, 0x40, 0x06, 0x73, 0x1c, 0xc0, 0xa8, 0x01, 0x02,
-        0xc0, 0xa8, 0x01, 0x01, 0x06, 0x0e, 0x00, 0x17, 0x99, 0xc5, 0xa0, 0xec, 0x00, 0x00, 0x00,
-        0x00, 0xa0, 0x02, 0x7d, 0x78, 0xe0, 0xa3, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02,
-        0x08, 0x0a, 0x00, 0x9c, 0x27, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00,
-    ];
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1);
-}
-
-const PROG_TCP_PORT_80: [u8; 152] = [
-    0x71, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x13, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x67, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x02, 0x0a, 0x00, 0x06, 0x00, 0x00, 0x00,
-    0x71, 0x12, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-    0x57, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x0f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x15, 0x02, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x69, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x55, 0x01, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-];
-
-#[test]
-fn test_vm_tcp_port80_match() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_tcp_port80_nomatch() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x00, 0x16, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x51, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_tcp_port80_nomatch_ethertype() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x01, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_tcp_port80_nomatch_proto() {
-    let mem = &mut [
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x08, 0x00, 0x45,
-        0x00, 0x00, 0x56, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, 0xf9, 0x4d, 0xc0, 0xa8, 0x00, 0x01,
-        0xc0, 0xa8, 0x00, 0x02, 0x27, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x50, 0x02, 0x20, 0x00, 0xc5, 0x18, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-        0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-    ];
-    let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.execute_program(mem).unwrap(), 0x0);
-}
-
-#[test]
-fn test_vm_tcp_sack_match() {
-    let mut mem = TCP_SACK_MATCH.to_vec();
-    let prog = assemble(TCP_SACK_ASM).unwrap();
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem.as_mut_slice()).unwrap(), 0x1);
-}
-
-#[test]
-fn test_vm_tcp_sack_nomatch() {
-    let mut mem = TCP_SACK_NOMATCH.to_vec();
-    let prog = assemble(TCP_SACK_ASM).unwrap();
-    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.execute_program(mem.as_mut_slice()).unwrap(), 0x0);
-}

+ 36 - 23
kernel/src/perf/kprobe.rs

@@ -11,7 +11,7 @@ use crate::filesystem::vfs::{FilePrivateData, FileSystem, IndexNode};
 use crate::libs::casting::DowncastArc;
 use crate::libs::spinlock::SpinLockGuard;
 use crate::perf::util::PerfProbeArgs;
-use crate::perf::PerfEventOps;
+use crate::perf::{BasicPerfEbpfCallBack, PerfEventOps};
 use alloc::boxed::Box;
 use alloc::string::String;
 use alloc::sync::Arc;
@@ -19,7 +19,7 @@ use alloc::vec::Vec;
 use core::any::Any;
 use core::fmt::Debug;
 use kprobe::{CallBackFunc, ProbeArgs};
-use rbpf::EbpfVmRawOwned;
+use rbpf::EbpfVmRaw;
 use system_error::SystemError;
 #[derive(Debug)]
 pub struct KprobePerfEvent {
@@ -40,33 +40,49 @@ impl KprobePerfEvent {
             .downcast_arc::<BpfProg>()
             .ok_or(SystemError::EINVAL)?;
         let prog_slice = file.insns();
-        let mut vm = EbpfVmRawOwned::new(Some(prog_slice.to_vec())).map_err(|e| {
+
+        let prog_slice =
+            unsafe { core::slice::from_raw_parts(prog_slice.as_ptr(), prog_slice.len()) };
+        let mut vm = EbpfVmRaw::new(Some(prog_slice)).map_err(|e| {
             log::error!("create ebpf vm failed: {:?}", e);
             SystemError::EINVAL
         })?;
-        vm.register_helper_set(BPF_HELPER_FUN_SET.get())
-            .map_err(|_| SystemError::EINVAL)?;
+
+        for (id, f) in BPF_HELPER_FUN_SET.get() {
+            vm.register_helper(*id, *f)
+                .map_err(|_| SystemError::EINVAL)?;
+        }
+
         // create a callback to execute the ebpf prog
-        let callback = Box::new(KprobePerfCallBack::new(file, vm));
+        let callback;
+
+        #[cfg(target_arch = "x86_64")]
+        {
+            use crate::perf::JITMem;
+
+            log::info!("Using JIT compilation for BPF program on x86_64 architecture");
+            let jit_mem = Box::new(JITMem::new());
+            let jit_mem = Box::leak(jit_mem);
+            let jit_mem_addr = core::ptr::from_ref::<JITMem>(jit_mem) as usize;
+            vm.set_jit_exec_memory(jit_mem).unwrap();
+            vm.jit_compile().unwrap();
+            let basic_callback = BasicPerfEbpfCallBack::new(file, vm, jit_mem_addr);
+            callback = Box::new(KprobePerfCallBack(basic_callback));
+        }
+        #[cfg(not(target_arch = "x86_64"))]
+        {
+            vm.register_allowed_memory(0..u64::MAX);
+            let basic_callback = BasicPerfEbpfCallBack::new(file, vm);
+            callback = Box::new(KprobePerfCallBack(basic_callback));
+        }
+
         // update callback for kprobe
         self.kprobe.write().update_event_callback(callback);
         Ok(())
     }
 }
 
-pub struct KprobePerfCallBack {
-    _bpf_prog_file: Arc<BpfProg>,
-    vm: EbpfVmRawOwned,
-}
-
-impl KprobePerfCallBack {
-    fn new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRawOwned) -> Self {
-        Self {
-            _bpf_prog_file: bpf_prog_file,
-            vm,
-        }
-    }
-}
+pub struct KprobePerfCallBack(BasicPerfEbpfCallBack);
 
 impl CallBackFunc for KprobePerfCallBack {
     fn call(&self, trap_frame: &dyn ProbeArgs) {
@@ -78,10 +94,7 @@ impl CallBackFunc for KprobePerfCallBack {
                 size_of::<KProbeContext>(),
             )
         };
-        let res = self.vm.execute_program(probe_context);
-        if res.is_err() {
-            log::error!("kprobe callback error: {:?}", res);
-        }
+        self.0.call(probe_context);
     }
 }
 

+ 105 - 2
kernel/src/perf/mod.rs

@@ -3,6 +3,8 @@ mod kprobe;
 mod tracepoint;
 mod util;
 
+use crate::arch::MMArch;
+use crate::bpf::prog::BpfProg;
 use crate::filesystem::epoll::{event_poll::EventPoll, EPollEventType, EPollItem};
 use crate::filesystem::page_cache::PageCache;
 use crate::filesystem::vfs::file::{File, FileMode};
@@ -15,8 +17,11 @@ use crate::include::bindings::linux_bpf::{
 };
 use crate::libs::casting::DowncastArc;
 use crate::libs::spinlock::{SpinLock, SpinLockGuard};
+use crate::mm::allocator::page_frame::{
+    allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
+};
 use crate::mm::fault::{PageFaultHandler, PageFaultMessage};
-use crate::mm::VmFaultReason;
+use crate::mm::{MemoryManagementArch, VirtAddr, VmFaultReason};
 use crate::perf::bpf::BpfPerfEvent;
 use crate::perf::util::{PerfEventIoc, PerfEventOpenFlags, PerfProbeArgs, PerfProbeConfig};
 use crate::process::ProcessManager;
@@ -30,10 +35,11 @@ use alloc::vec::Vec;
 use core::any::Any;
 use core::ffi::c_void;
 use core::fmt::Debug;
-use core::ops::Deref;
+use core::ops::{Deref, DerefMut};
 use intertrait::{CastFrom, CastFromSync};
 use log::info;
 use num_traits::FromPrimitive;
+use rbpf::EbpfVmRaw;
 use system_error::SystemError;
 
 type Result<T> = core::result::Result<T, SystemError>;
@@ -55,6 +61,103 @@ pub trait PerfEventOps: Send + Sync + Debug + CastFromSync + CastFrom + IndexNod
     fn readable(&self) -> bool;
 }
 
+pub struct JITMem {
+    virt_addr: VirtAddr,
+}
+
+impl JITMem {
+    pub fn new() -> Self {
+        let vaddr = unsafe {
+            let (paddr, _count) =
+                allocate_page_frames(PageFrameCount::new(1)).expect("JITMem alloc failed");
+            MMArch::phys_2_virt(paddr).unwrap()
+        };
+        Self { virt_addr: vaddr }
+    }
+}
+
+impl Deref for JITMem {
+    type Target = [u8];
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let ptr = self.virt_addr.as_ptr();
+            core::slice::from_raw_parts(ptr, 4096)
+        }
+    }
+}
+
+impl DerefMut for JITMem {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            let ptr = self.virt_addr.as_ptr();
+            core::slice::from_raw_parts_mut(ptr, 4096)
+        }
+    }
+}
+
+impl Drop for JITMem {
+    fn drop(&mut self) {
+        unsafe {
+            let paddr = MMArch::virt_2_phys(self.virt_addr).expect("JITMem drop failed");
+            let count = PageFrameCount::new(1);
+            deallocate_page_frames(PhysPageFrame::new(paddr), count);
+        }
+    }
+}
+
+pub struct BasicPerfEbpfCallBack {
+    _bpf_prog_file: Arc<BpfProg>,
+    vm: EbpfVmRaw<'static>,
+    #[cfg(target_arch = "x86_64")]
+    jit_mem_ptr: usize,
+}
+
+unsafe impl Send for BasicPerfEbpfCallBack {}
+unsafe impl Sync for BasicPerfEbpfCallBack {}
+
+impl BasicPerfEbpfCallBack {
+    #[cfg(not(target_arch = "x86_64"))]
+    fn new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRaw<'static>) -> Self {
+        Self {
+            _bpf_prog_file: bpf_prog_file,
+            vm,
+        }
+    }
+    #[cfg(target_arch = "x86_64")]
+    fn new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRaw<'static>, jit_mem_ptr: usize) -> Self {
+        Self {
+            _bpf_prog_file: bpf_prog_file,
+            vm,
+            jit_mem_ptr,
+        }
+    }
+
+    pub fn call(&self, entry: &mut [u8]) {
+        let res = if cfg!(target_arch = "x86_64") {
+            unsafe { self.vm.execute_program_jit(entry) }
+        } else {
+            self.vm.execute_program(entry)
+        };
+        if res.is_err() {
+            log::error!("kprobe callback error: {:?}", res);
+        }
+    }
+}
+
+impl Drop for BasicPerfEbpfCallBack {
+    fn drop(&mut self) {
+        #[cfg(target_arch = "x86_64")]
+        {
+            unsafe {
+                let jit_mem = &mut *(self.jit_mem_ptr as *mut JITMem);
+                let jit_mem = Box::from_raw(jit_mem);
+                drop(jit_mem);
+            }
+        }
+    }
+}
+
 #[derive(Debug)]
 pub struct PerfEventInode {
     event: Box<dyn PerfEventOps>,

+ 32 - 22
kernel/src/perf/tracepoint.rs

@@ -5,6 +5,7 @@ use crate::filesystem::page_cache::PageCache;
 use crate::libs::casting::DowncastArc;
 use crate::libs::spinlock::SpinLock;
 use crate::perf::util::PerfProbeConfig;
+use crate::perf::{BasicPerfEbpfCallBack, JITMem};
 use crate::tracepoint::{TracePoint, TracePointCallBackFunc};
 use crate::{
     filesystem::vfs::{file::File, FilePrivateData, FileSystem, IndexNode},
@@ -16,7 +17,7 @@ use alloc::sync::Arc;
 use alloc::{string::String, vec::Vec};
 use core::any::Any;
 use core::sync::atomic::AtomicUsize;
-use rbpf::EbpfVmRawOwned;
+use rbpf::EbpfVmRaw;
 use system_error::SystemError;
 
 #[derive(Debug)]
@@ -74,29 +75,14 @@ impl IndexNode for TracepointPerfEvent {
     }
 }
 
-pub struct TracePointPerfCallBack {
-    _bpf_prog_file: Arc<BpfProg>,
-    vm: EbpfVmRawOwned,
-}
-
-impl TracePointPerfCallBack {
-    fn new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRawOwned) -> Self {
-        Self {
-            _bpf_prog_file: bpf_prog_file,
-            vm,
-        }
-    }
-}
+pub struct TracePointPerfCallBack(BasicPerfEbpfCallBack);
 
 impl TracePointCallBackFunc for TracePointPerfCallBack {
     fn call(&self, entry: &[u8]) {
         // ebpf needs a mutable slice
         let entry =
             unsafe { core::slice::from_raw_parts_mut(entry.as_ptr() as *mut u8, entry.len()) };
-        let res = self.vm.execute_program(entry);
-        if res.is_err() {
-            log::error!("tracepoint callback error: {:?}", res);
-        }
+        self.0.call(entry);
     }
 }
 
@@ -109,15 +95,39 @@ impl PerfEventOps for TracepointPerfEvent {
             .downcast_arc::<BpfProg>()
             .ok_or(SystemError::EINVAL)?;
         let prog_slice = file.insns();
-        let mut vm = EbpfVmRawOwned::new(Some(prog_slice.to_vec())).map_err(|e| {
+
+        let prog_slice =
+            unsafe { core::slice::from_raw_parts(prog_slice.as_ptr(), prog_slice.len()) };
+        let mut vm = EbpfVmRaw::new(Some(prog_slice)).map_err(|e| {
             log::error!("create ebpf vm failed: {:?}", e);
             SystemError::EINVAL
         })?;
-        vm.register_helper_set(BPF_HELPER_FUN_SET.get())
-            .map_err(|_| SystemError::EINVAL)?;
+        for (id, f) in BPF_HELPER_FUN_SET.get() {
+            vm.register_helper(*id, *f)
+                .map_err(|_| SystemError::EINVAL)?;
+        }
 
         // create a callback to execute the ebpf prog
-        let callback = Box::new(TracePointPerfCallBack::new(file, vm));
+        let callback;
+
+        #[cfg(target_arch = "x86_64")]
+        {
+            log::info!("Using JIT compilation for BPF program on x86_64 architecture");
+            let jit_mem = Box::new(JITMem::new());
+            let jit_mem = Box::leak(jit_mem);
+            let jit_mem_addr = core::ptr::from_ref::<JITMem>(jit_mem) as usize;
+            vm.set_jit_exec_memory(jit_mem).unwrap();
+            vm.jit_compile().unwrap();
+            let basic_callback = BasicPerfEbpfCallBack::new(file, vm, jit_mem_addr);
+            callback = Box::new(TracePointPerfCallBack(basic_callback));
+        }
+        #[cfg(not(target_arch = "x86_64"))]
+        {
+            vm.register_allowed_memory(0..u64::MAX);
+            let basic_callback = BasicPerfEbpfCallBack::new(file, vm);
+            callback = Box::new(TracePointPerfCallBack(basic_callback));
+        }
+
         let id = CALLBACK_ID.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
         self.tp.register_raw_callback(id, callback);
 

+ 0 - 2
triagebot.toml

@@ -84,7 +84,6 @@ trigger_files = ["kernel/src/virt", "kernel/src/arch/x86_64/kvm"]
 
 [autolabel."T-Obs and Test"]
 trigger_files = [
-    "/kernel/crates/rbpf",
     "/kernel/crates/kprobe",
     "/kernel/src/debug/kprobe",
     "/kernel/src/bpf",
@@ -167,7 +166,6 @@ infra = ["@dragonos/infra"]
 "/kernel/src/arch/x86_64/kvm" = ["virtulization"]
 "/kernel/src/arch/x86_64" = ["x86_64"]
 "/kernel/src/arch/riscv64" = ["riscv64"]
-"/kernel/crates/rbpf" = ["sig-obs"]
 "/kernel/crates/kprobe" = ["sig-obs"]
 "/kernel/src/debug/kprobe" = ["sig-obs"]
 "/kernel/src/bpf" = ["sig-obs"]