### Setting Up and Running CKB VM Bare Metal Debugger Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-debug-utils/README.md Commands to display the example C program, clone the `ckb-vm-debug-utils` repository, build the debugger, compile the C program for RISC-V, and start the bare metal debugger server on a specified address and port. ```bash $ cat program.c int power(int, int); int main() { int i, result; for (i = 0; i < 10; i++) { result += power(2, i); } return result; } int power(int base, int n) { int i, p; p = 1; for (i = 1; i <= n; i++) p = p * base; return p; } $ git clone https://github.com/nervosnetwork/ckb-vm-debug-utils $ cd ckb-vm-debug-utils $ cargo build $ riscv64-unknown-elf-gcc -g ../program.c -o program $ ./target/debug/baremetal 0.0.0.0:2000 program ``` -------------------------------- ### Debugging CKB Script with GDB and ckb-debugger (Shell) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/exec.md These commands initiate a GDB debugging session for a CKB script. The first command starts `ckb-debugger` in GDB mode, listening on a specified address, while the second launches `riscv64-unknown-elf-gdb` and loads GDB commands from a file to connect to the debugger. ```sh ckb-debugger --tx-file exec.json --cell-index 0 --cell-type input --script-group-type lock --mode gdb --gdb-listen 127.0.0.1:9999 riscv64-unknown-elf-gdb --command=exec_gdb_cmd.txt ``` -------------------------------- ### Example C Program for CKB VM Debugging Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-debug-utils/README.md A simple C program defining `main` and `power` functions, used as an example target for CKB VM debugging. It calculates the sum of powers of 2, demonstrating basic control flow and function calls. ```C int power(int, int); int main() { int i, result; for (i = 0; i < 10; i++) { result += power(2, i); } return result; } int power(int base, int n) { int i, p; p = 1; for (i = 1; i <= n; i++) p = p * base; return p; } ``` -------------------------------- ### Installing Protobuf on macOS (Bash) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/README.md This command installs the `protobuf` package using Homebrew on macOS. It is a prerequisite for compiling `ckb-vm-pprof-converter`, ensuring the `protoc` binary is available for compilation. ```bash $ brew install protobuf ``` -------------------------------- ### Installing Inferno for Flamegraph Visualization Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-pprof/README.md This shell command uses `cargo` to install the `inferno` tool, which is required to convert textual flamegraph data into a visual SVG format. `inferno` provides the `inferno-flamegraph` utility. ```Shell $ cargo install inferno ``` -------------------------------- ### Cloning CKB C Standard Library (sh) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/print_log.md This command clones the `ckb-c-stdlib` repository from GitHub, which provides the necessary standard library functions for C programs running on the CKB VM. ```sh $ git clone https://github.com/nervosnetwork/ckb-c-stdlib ``` -------------------------------- ### Invoking file_write Syscall - C Example Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/file_write.md This C example demonstrates invoking the `file_write` syscall (number 9013) to write 'Hello World!' to 'file_write_foo.txt'. It initializes a `char` pointer `data` and its `size`, then passes these along with the filename to the `syscall` function. The trailing zeros are unused arguments for this specific syscall invocation. ```c char *data = "Hello World!\n"; size_t size = 13; syscall(9013, "file_write_foo.txt", data, size, 0, 0, 0); ``` -------------------------------- ### Installing Inferno for Flamegraph Generation Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/fib.md This command installs the `inferno` tool, a Rust-based utility, which is required to convert the textual pprof output generated by `ckb-debugger` into a visual flamegraph (SVG format). ```Shell $ cargo install inferno ``` -------------------------------- ### Installing CKB Debugger CLI Tool (Shell) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/README.md This command installs the `ckb-debugger` command-line tool directly from the Git repository. It allows users to develop CKB scripts offline and is a core component of the CKB standalone debugger suite. ```sh cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger ``` -------------------------------- ### Invoking file_write Syscall - Rust Example Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/file_write.md This Rust example shows how to call the `file_write` syscall (number 9013) to write 'Hello World!' to 'file_write_foo.txt'. It converts the filename and data string into `u64` pointers using `CString` and `as_bytes().as_ptr()`, then passes them with the data size to the `syscall` function. The remaining arguments are placeholders. ```rs syscall( CString::from_str("file_write_foo.txt").unwrap().as_ptr() as u64, "Hello World!\n".as_bytes().as_ptr() as u64, 13, 0, 0, 0, 0, 9013, ); ``` -------------------------------- ### Debugging Callee Entry Point - Debugger Commands Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/exec_gdb_cmd.txt These commands are designed to load the 'exec_callee' executable, set a breakpoint at its `_start` entry point, continue execution until that breakpoint is hit, and then list the source code around the current execution point. This is useful for inspecting the initial execution flow and setup of the callee program. ```Debugger Commands file exec_callee b _start c l ``` -------------------------------- ### Downloading CKB Transaction with ckb-cli Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/mock_tx.md This command uses `ckb-cli` to download a specific transaction from the CKB mainnet by its hash and saves it to a local JSON file named `mock_tx.json`. This prepares the transaction for subsequent local debugging. ```sh ckb-cli --url https://mainnet.ckbapp.dev/rpc mock-tx dump --tx-hash 0x5f0a4162622daa0e50b2cf8f49bc6ece22d1458d96fc12a094d6f074d6adbb55 --output-file mock_tx.json ``` -------------------------------- ### DSL for Simplifying CKB Transaction JSON (Text) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/spawn.md This snippet describes a Domain Specific Language (DSL) used to simplify the creation of `tx.json` files for CKB. It includes syntax for embedding file content as hexadecimal data, calculating and embedding file Blake2b hashes, and defining or referencing `type_id` values within the transaction structure. ```text {{ data path/to/file }} => replact it by hexdata of path/to/file {{ hash path/to/file }} => replace it by blake2b of path/to/file {{ def_type any_type_id_name }} => create a new type_id named any_type_id_name {{ ref_type any_type_id_name }} => refer to the type_id above ``` -------------------------------- ### Installing CKB Debugger WASM Package in Node.js Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/wasm.md After building the WebAssembly package with `wasm-pack`, this command demonstrates how to install the generated `pkg` directory into a Node.js project using `npm install`. This makes the WASM module available for import. ```Shell $ npm install path/to/pkg ``` -------------------------------- ### Compiling C Program for CKB VM (sh) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/print_log.md This command compiles the `print_log.c` source file using `riscv64-unknown-elf-gcc`, linking it statically with the CKB C standard library. It disables built-in printf and standard includes to ensure compatibility with the CKB environment, producing an executable named `print_log`. ```sh $ riscv64-unknown-elf-gcc -fno-builtin-printf -nostdinc -nostdlib -nostartfiles -I ./ckb-c-stdlib/libc -I ./ckb-c-stdlib -g -Wl,-static -o print_log print_log.c ``` -------------------------------- ### Debugging CKB Program with ckb-debugger (sh) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/print_log.md This command executes the compiled `print_log` program using the `ckb-debugger`. The `RUST_LOG=debug` environment variable enables detailed debug logging, showing the execution flow and values of `n` as printed by the C program. ```sh $ RUST_LOG=debug ckb-debugger --bin print_log DEBUG:: SCRIPT>n = 5 DEBUG:: SCRIPT>n = 4 DEBUG:: SCRIPT>n = 3 DEBUG:: SCRIPT>n = 2 DEBUG:: SCRIPT>n = 1 DEBUG:: SCRIPT>n = 0 DEBUG:: SCRIPT>n = 1 DEBUG:: SCRIPT>n = 2 DEBUG:: SCRIPT>n = 1 DEBUG:: SCRIPT>n = 0 DEBUG:: SCRIPT>n = 3 DEBUG:: SCRIPT>n = 2 DEBUG:: SCRIPT>n = 1 DEBUG:: SCRIPT>n = 0 DEBUG:: SCRIPT>n = 1 ``` -------------------------------- ### Debugging CKB Spawn Syscall with ckb-debugger (Shell) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/spawn.md This shell command executes the `ckb-debugger` in 'fast' mode to debug a transaction defined in `spawn.json`. It targets the input cell at index 0 and specifies that the debugging should focus on the lock script group, demonstrating the usage of the `spawn` syscall. ```sh $ ckb-debugger --mode fast --tx-file spawn.json --cell-index 0 --cell-type input --script-group-type lock ``` -------------------------------- ### Launching LLDB with Debug Symbols - Shell Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This shell command starts the LLDB debugger, loading the compiled contract binary that includes debug symbols. This prepares LLDB to connect to a remote GDB server for debugging. ```shell lldb build/ckb-debugger/c1.debug ``` -------------------------------- ### Example C Program for CKB-VM Function Tracing Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This C program defines `test_func` which allocates memory and stores two integer parameters, returning a pointer to the allocated memory. The `main` function calls `test_func` and frees the returned memory. This program serves as a target for demonstrating advanced function call and return tracing techniques using tools like bcc. ```C int* test_func(int parameter1, int parameter2) { int *mem = (int *)malloc(sizeof(parameter1) + sizeof(parameter2)); mem[0] = parameter1; mem[1] = parameter2; return mem; } int main(int argc, char **argv) { free((void *) test_func(42, 43)); return 0; } ``` -------------------------------- ### Executing CKB Script with ckb-debugger (Shell) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/exec.md This command executes a CKB script using the `ckb-debugger` tool. It specifies the transaction file (`exec.json`), the cell index, cell type, and script group type for the execution, demonstrating a standard script run. ```sh ckb-debugger --tx-file exec.json --cell-index 0 --cell-type input --script-group-type lock ``` -------------------------------- ### Debugging Out-of-Memory with ckb-debugger (Shell) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/out_of_memory.md This snippet demonstrates how to compile and run an example CKB contract that triggers an out-of-memory error using `make` and `ckb-debugger`. It shows the debugger's output, which includes the function call stack leading to the OOM, the state of the registers at the point of failure, and the 'MemOutOfBound' error message. This output is crucial for diagnosing memory-related issues in CKB contract development. ```sh $ make out_of_memory $ ckb-debugger --bin out_of_memory ??:??:?? /home/ubuntu/src/ckb-standalone-debugger/ckb-debugger/examples/ckb-c-stdlib/libc/entry.h:9:_start /home/ubuntu/src/ckb-standalone-debugger/ckb-debugger/examples/out_of_memory.c:25:main /home/ubuntu/src/ckb-standalone-debugger/ckb-debugger/examples/out_of_memory.c:21:c /home/ubuntu/src/ckb-standalone-debugger/ckb-debugger/examples/out_of_memory.c:17:b /home/ubuntu/src/ckb-standalone-debugger/ckb-debugger/examples/out_of_memory.c:7:a pc : 0x 12D28 zero: 0x 0 ra : 0x 12D3E sp : 0x 3FFFA0 gp : 0x 146E8 tp : 0x 0 t0 : 0x 0 t1 : 0x 0 t2 : 0x 0 s0 : 0x 3FFFB0 s1 : 0x 0 a0 : 0x 0 a1 : 0x 400000 a2 : 0x 0 a3 : 0x 0 a4 : 0x 0 a5 : 0x 0 a6 : 0x 0 a7 : 0x 0 s2 : 0x 0 s3 : 0x 0 s4 : 0x 0 s5 : 0x 0 s6 : 0x 0 s7 : 0x 0 s8 : 0x 0 s9 : 0x 0 s10 : 0x 0 s11 : 0x 0 t3 : 0x 0 t4 : 0x 0 t5 : 0x 0 t6 : 0x 0 Error: MemOutOfBound ``` -------------------------------- ### Configuring VSCode Launch for GDB Debugging - JSON Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This VSCode `launch.json` configuration sets up a GDB attach debugger. It specifies the executable with debug symbols, the remote target address, and defines `preLaunchTask` and `postDebugTask` to automatically start and stop `ckb-debugger` during the debugging session. ```json { "name": "GDB", "type": "gdb", "request": "attach", "executable": "build/ckb-debug/c1.debug", "debugger_args": [], "cwd": "${workspaceRoot}", "remote": true, "target": "127.0.0.1:8000", "preLaunchTask": "Debug c1", "postDebugTask": "stop-ckb-debugger" } ``` -------------------------------- ### Launching GDB with Debug Symbols - Shell Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This shell command starts the GDB debugger, loading the compiled contract binary that includes debug symbols. This prepares GDB to connect to a remote GDB server for debugging. ```shell gdb build/ckb-debug/c1.debug ``` -------------------------------- ### Building CKB Debugger for Node.js with wasm-pack Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/wasm.md This snippet provides the shell commands to install `wasm-pack` and build the `ckb-debugger` project for a Node.js target. `wasm-pack` is a tool for building Rust-generated WebAssembly and publishing it to npm. ```Shell $ cargo install wasm-pack $ wasm-pack build --target nodejs ``` -------------------------------- ### Executing Lock Script with ckb-debugger Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/mock_tx.md This command executes the lock script of the input cell at index 0 from the `mock_tx.json` file using `ckb-debugger`. It demonstrates how to run a specific script group within a downloaded transaction locally to observe its behavior and cycle consumption. ```sh ckb-debugger --tx-file mock_tx.json --cell-index 0 --cell-type input --script-group-type lock ``` -------------------------------- ### Executing BCC Python Script for Function Tracing Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This command executes the `trace.py` BCC Python script with superuser privileges. This script is designed to trace function calls and returns, including parameters and return values, for CKB-VM programs, as demonstrated with the provided C example. It leverages BCC for sophisticated tracing capabilities. ```bash sudo ./trace.py ``` -------------------------------- ### Defining Fibonacci Function in C Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-pprof/README.md This C code defines a recursive `fib` function to calculate Fibonacci numbers and a `main` function that calls `fib(10)` and asserts the result is 55. It serves as an example program for profiling. ```C int fib(int n) { if (n == 0 || n == 1) { return n; } else { return fib(n-1) + fib(n-2); } } int main() { if (fib(10) != 55) { return 1; } return 0; } ``` -------------------------------- ### GDB Commands for Debugging CKB Exec Scripts (GDB Commands) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/exec.md This sequence of GDB commands is used to debug CKB 'exec' scripts. It imports symbols from both caller and callee executables, sets breakpoints at internal syscalls and the `_start` function, and continues execution to hit these breakpoints for inspection. ```gdb-commands file exec_caller # Import symbols from exec_caller target remote 127.0.0.1:9999 # Link to ckb-debugger b __internal_syscall # Set a breakpoint at __internal_syscall c # Fetch the 1st breakpoint: ckb_debug c # Fetch the 2nd breakpoint: ckb_exec file exec_callee # Import symbols from exec_callee b _start # Set a breakpoint at exec_callee's _start c # Continue l # List raw codes ``` -------------------------------- ### Starting CKB Debugger in GDB Server Mode - Shell Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This shell command launches `ckb-debugger` in `gdb_gdbstub` mode, specifying the contract binary, listening port (8000), and the path to the transaction data file. The `-s` and `-i` flags specify the script and input index for debugging. ```shell ckb-debugger \ --bin=build/ckb-debug/c1 \ --mode=gdb_gdbstub \ --gdb-listen=0.0.0.0:8000 \ --tx-file=tests/tx.json \ -s=lock \ -i=0 ``` -------------------------------- ### Replacing and Executing Script with ckb-debugger Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/mock_tx.md This command uses `ckb-debugger` to execute the lock script of the input cell at index 0 from `mock_tx.json`, but replaces the original script with the compiled `always_failure` binary. This demonstrates how to debug a transaction with a modified or new script version, allowing for rapid iteration and testing. ```sh ckb-debugger --tx-file mock_tx.json --cell-index 0 --cell-type input --script-group-type lock --bin always_failure ``` -------------------------------- ### Dumping Uncommitted Transaction with ckb-cli Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/mock_tx.md This `ckb-cli` command dumps an uncommitted transaction, provided as a raw JSON file (`mock_raw_tx.json`), into a debug-ready `mock_tx.json` file. This allows for local debugging of transactions that have not yet been sent or have failed to commit to the chain, enabling pre-submission validation. ```sh ckb-cli --url https://mainnet.ckbapp.dev/rpc mock-tx dump --tx-file mock_raw_tx.json --output-file mock_tx.json ``` -------------------------------- ### Running CKB Debugger WASM for Transaction Verification in Node.js Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/wasm.md This JavaScript snippet demonstrates how to use the `ckb-debugger` WASM module to perform basic transaction verification. It reads a `tx.json` file, calls `run_json` with the transaction data, a script type ('lock'), a script hash, and a capacity, then logs the result. It requires the `ckb-debugger` WASM package to be installed. ```JavaScript import * as wasm from 'ckb-debugger'; const tx_file = fs.readFileSync('tx.json', 'utf8'); const result = wasm.run_json(tx_file, 'lock', '0x494e57d09aa7d17ad9559046fdab6a455811f6f86c5f6594b76de934d47e2553', '1000000000') console.log(result) ``` -------------------------------- ### Executing CKB Debugger WASM with WASI in Node.js Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/wasm.md This JavaScript snippet demonstrates how to load and execute a `ckb-debugger` WASM module compiled for WASI within a Node.js environment. It configures a WASI host, sets up arguments and preopened directories, compiles the WASM binary, instantiates it with the WASI import object, and starts the WASI instance. It requires `node:fs` and `node:wasi` modules. ```JavaScript import * as fs from 'node:fs' import * as wasi from 'node:wasi' const wasihost = new wasi.WASI({ version: 'preview1', args: ['ckb-debugger', '--bin', '/path/to/binary'], preopens: { '/path/to/binary': '/path/to/binary', }, }); async function main() { const wasm = await WebAssembly.compile( fs.readFileSync('/path/to/ckb-debugger.wasm'), ); const instance = await WebAssembly.instantiate(wasm, wasihost.getImportObject()); wasihost.start(instance); } main() ``` -------------------------------- ### C Program for Always Failing Script Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/mock_tx.md This C code defines a simple program named `always_failure.c` that always returns an exit code of `1`. It is intended to be compiled and used with `ckb-debugger` to replace an existing script, demonstrating how to test script failures or specific error conditions. ```c // always_failure.c int main() { return 1; } ``` -------------------------------- ### Configuring VSCode Task to Launch CKB Debugger - JSON Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This VSCode `tasks.json` configuration defines a background process task to automatically start `ckb-debugger` with specified arguments, including the binary path, GDB listen address, and transaction file. The `isBackground` setting ensures the debugger remains active during the VSCode debugging session. ```json { "label": "Debug c1", "isBackground": true, "type": "process", "command": "ckb-debugger", "args": [ "--bin=build/ckb-debug/c1", "--mode=gdb_gdbstub", "--gdb-listen=0.0.0.0:8000", "--tx-file=tests/tx.json", "-s=lock", "-i=0" ], "options": { "cwd": "${workspaceRoot}" } } ``` -------------------------------- ### Converting ckb-vm-pprof data to pprof format using Rust Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-pprof-converter/README.md This command executes the `ckb-vm-pprof-converter` tool, which takes raw profiling data from `ckb-vm-pprof` (simulated here with `res/fib`) via a pipe and converts it into the `profile.proto` format. This is the first step in generating a `pprof` compatible output file. ```Shell cargo run -- --bin res/fib | ckb-vm-pprof-converter ``` -------------------------------- ### Interactive GDB Debugging Session with CKB VM Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-debug-utils/README.md An interactive GDB session demonstrating how to connect to the CKB VM debugger, set a breakpoint at `main`, continue execution, step through the code, and print the value of a variable `i`. ```bash $ cd ckb-vm-debug-utils $ gdb program (gdb) target remote localhost:2000 Remote debugging using localhost:2000 0x00000000000100c8 in _start () (gdb) b main Breakpoint 1 at 0x101ba: file program.c, line 6. (gdb) c Continuing. Breakpoint 1, main () at program.c:6 6 for (i = 0; i < 10; i++) { (gdb) s 7 result += power(2, i); (gdb) print i $1 = 0 (gdb) ``` -------------------------------- ### Loading generated profile data into pprof Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-pprof-converter/README.md This command loads the `output.pprof` file, which was generated by `ckb-vm-pprof-converter`, into the `pprof` tool. The `res/fib` argument likely provides the binary context for symbol resolution within the profile, enabling detailed analysis of the profiling data. ```Shell pprof res/fib output.pprof ``` -------------------------------- ### Configuring VSCode Task for Debug Build - JSON Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This VSCode `tasks.json` configuration defines a shell task named 'Build Debug' that compiles the contract, copies it to a `.debug` version, and then strips the original binary using `llvm-objcopy` for release, ensuring a debug-ready binary is available. ```json { "label": "Build Debug", "type": "shell", "command": "make build && cp build/ckb-debug/c1 build/ckb-debug/c1.debug && llvm-objcopy --strip-debug --strip-all build/ckb-debug/c1" } ``` -------------------------------- ### Tracing `do_sys_open` Function with bpftrace Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This `bpftrace` script demonstrates how to trace the `do_sys_open` function in the Linux kernel. It uses a `uprobe` to attach to the function and prints a message to the console every time the function is called. This illustrates a basic use case for `bpftrace` in user-level function tracing. ```bpftrace uprobe:/usr/src/linux/fs/open.c:do_sys_open { printf("do_sys_open called\n"); } ``` -------------------------------- ### Displaying CKB Debugger Command Line Help (Text) Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/README.md This snippet illustrates the command-line interface (CLI) usage for the `ckb-debugger` tool. It outlines the various flags, options, and arguments available, providing comprehensive details on how to configure and control the debugger's execution, including modes, cycle limits, and GDB remote debugging. This information is crucial for users to effectively invoke and customize the debugger from the terminal. ```text ckb-debugger 0.119.0 USAGE: ckb-debugger [FLAGS] [OPTIONS] --mode [args]... FLAGS: --enable-overlapping-detection Set to true to enable overlapping detection between stack and heap --enable-steplog Set to true to enable step mode, where we print PC address for each instruction -h, --help Prints help information --prompt Set to true to prompt for stdin input before executing -V, --version Prints version information OPTIONS: --bin File used to replace the binary denoted in the script -i, --cell-index Index of cell to run -t, --cell-type Type of cell to run [possible values: input, output] --dump-file Dump file name --gdb-listen Address to listen for GDB remote debugging server [default: 127.0.0.1:9999] --max-cycles Max cycles [default: 3500000000] --mode Execution mode of debugger [default: full] [possible values: decode-instruction, fast, full, gdb, probe] --pid Process ID [default: 0] --pprof Performance profiling, specify output file for further use --read-file Read content from local file or stdin. Then feed the content to syscall in scripts -s, --script-group-type Script group type [possible values: lock, type] --script-hash Script hash --script-version Script version [default: 2] -f, --tx-file Filename containing JSON formatted transaction dump ARGS: ... ``` -------------------------------- ### Tracing CKB-VM Syscall Instructions with bpftrace Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This `bpftrace` command traces the execution of `ecall` (syscall) instructions within the `ckb-debugger` by monitoring the `ckb_vm:execute_inst` USDT probe. It filters for instructions with the encoding `0x2000023` and prints the program counter, consumed cycles, instruction, and register/memory addresses. This helps in debugging and understanding syscall behavior. ```bpftrace sudo bpftrace -e 'usdt:./target/release/ckb-debugger:ckb_vm:execute_inst /arg2 == 0x2000023/ { printf("%p, %d, %p, %p, %p\n", arg0, arg1, arg2, arg3, arg4); }' ``` -------------------------------- ### Compiling C Code with Debugging Information using GCC Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-pprof/README.md This shell command compiles the `res/fib.c` source file into an executable `res/fib` using `riscv64-unknown-elf-gcc`. The `-g` option is crucial for including debugging information, which is necessary for profiling tools like `ckb-vm-pprof`. ```Shell $ riscv64-unknown-elf-gcc -g -o res/fib res/fib.c ``` -------------------------------- ### Building CKB Debugger for WASI with Rust Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/wasm.md This snippet provides the shell commands to add the `wasm32-wasip1` target to Rust and build the `ckb-debugger` project for WASI. It also includes a dependency for `gcc-multilib` which might be needed for some WASI builds on Linux. ```Shell $ rustup target add wasm32-wasip1 $ sudo apt install gcc-multilib $ cargo build --target wasm32-wasip1 ``` -------------------------------- ### Generating Performance Profile with CKB Debugger Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/fib.md This command uses `ckb-debugger` to execute the `fib` binary and save its execution trace data into a pprof-compatible file (`fib.pprof`), which can then be used for performance analysis and flamegraph visualization. ```Shell $ ckb-debugger --bin fib --pprof fib.pprof ``` -------------------------------- ### Generating SVG Flamegraph from CKB VM Profile Data Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-vm-pprof/README.md This shell command executes the `ckb-vm-pprof` tool (via `cargo run`) with the compiled binary `res/fib`. The output, which is raw profiling data, is then piped to `inferno-flamegraph` to generate an SVG visualization, saved as `res/fib.svg`. ```Shell $ cargo run -- --bin res/fib | inferno-flamegraph > res/fib.svg ``` -------------------------------- ### Defining file_write Syscall Signature - C Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/file_write.md This C snippet presents the function signature for `file_write`, a cross-platform syscall. It accepts a `path` for the file, a `ptr` to the data buffer, and the `size` of the data. The syscall writes content to the local file system on Windows, *nix, and wasm-wasi, and to localstorage in hexadecimal format within wasm browser environments. ```c int file_write(const char* path, void *ptr, size_t size) ``` -------------------------------- ### Converting Pprof Data to Flamegraph SVG Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/fib.md This command pipes the performance profile data from `fib.pprof` (generated by `ckb-debugger`) into `inferno-flamegraph`, which then generates an SVG visualization of the flamegraph, saved as `fib.svg`. ```Shell $ cat fib.pprof | inferno-flamegraph > fib.svg ``` -------------------------------- ### Extracting Function Parameters/Return Values in C Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This C snippet demonstrates how to extract function parameters or return values using BPF helper functions. It first reads a memory address using bpf_usdt_readarg, then reads a return value from a register (A0) using bpf_probe_read_user. Finally, it reads the content from the calculated memory address (mem_addr + ret) and updates a BPF table named memory_contents with the extracted data. ```C uint64_t mem_addr = 0; bpf_usdt_readarg(5, ctx, &mem_addr); uint64_t ret = 0; bpf_probe_read_user(&ret, sizeof(uint64_t), (void *)(regs_addr + 8 * A0)); uint64_t content = 0; bpf_probe_read_user(&content, sizeof(uint64_t), (void *)(mem_addr + ret)); memory_contents.update(&ret, &content); ``` -------------------------------- ### Determining Function Call/Return Status in C Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This C snippet determines if a jump is a function call or a return. It checks if the next_pc matches a predefined @@LOW_PC@@ to identify a call, incrementing a reference count for the link address. For returns, it checks if the link address is within a valid range (@@LOW_PC@@ to @@HIGH_PC@@) and decrements a reference count associated with next_pc in a hash table (jump_from_addresses). ```C int is_calling = 0; int is_returning = 0; if (next_pc == @@LOW_PC@@) { // Initialize reference of the link, increment refcount if neccesary. jump_from_addresses.increment(link); is_calling = 1; } if (link > @@LOW_PC@@ && link <= @@HIGH_PC@@) { uint64_t *refcount = jump_from_addresses.lookup(&next_pc); (*refcount)--; if (*refcount == 0) { jump_from_addresses.delete(&next_pc); } is_returning = 1; } ``` -------------------------------- ### Debugging RISC-V Programs with GDB and CKB Debugger Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/fib.md This snippet demonstrates how to set up GDB for remote debugging a RISC-V program (`fib`) using `ckb-debugger`. It shows connecting GDB to the debugger, setting a breakpoint at the `fib` function, and continuing execution to inspect parameters at the breakpoint. ```Shell $ ckb-debugger --mode gdb --gdb-listen 127.0.0.1:9999 --bin fib $ riscv64-unknown-elf-gdb fib $ (gdb) target remote 127.0.0.1:9999 $ (gdb) b fib $ (gdb) c ``` -------------------------------- ### Decoding RISC-V Jump Instructions in C Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This C snippet decodes various RISC-V jump instructions (JAL, JALR, OP_FAR_JUMP_ABS, OP_FAR_JUMP_REL) to determine the link address (return address) and the next program counter. It uses BPF helper functions like bpf_probe_read_user to access register values for JALR. The snippet is crucial for identifying potential function calls or returns by calculating the target addresses. ```C InstructionOpcode opcode = EXTRACT_OPCODE(instruction); uint8_t instruction_length = INSTRUCTION_LENGTH(instruction); // The return address that we will jump to when this jump instruction finishes, // normally current_pc + instruction_length. uint64_t link; // The address that this jump instruction will jump to. uint64_t next_pc; SImmediate imm; RegisterIndex ind; // Decode the instuction to get function calls/returns information. switch (opcode) { case OP_JAL: link = pc + instruction_length; imm = UTYPE_IMMEDIATE_S(instruction); next_pc = pc + imm; break; case OP_JALR_VERSION0: case OP_JALR_VERSION1: link = pc + instruction_length; imm = ITYPE_IMMEDIATE_S(instruction); ind = ITYPE_RS1(instruction); uint64_t reg_value = 0; bpf_probe_read_user(®_value, sizeof(uint64_t), (void *)(regs_addr + sizeof(uint64_t) * ind)); next_pc = (reg_value + imm) & ~1; break; case OP_FAR_JUMP_ABS: link = pc + instruction_length; imm = UTYPE_IMMEDIATE_S(instruction); next_pc = imm & ~1; break; case OP_FAR_JUMP_REL: link = pc + instruction_length; imm = UTYPE_IMMEDIATE_S(instruction); next_pc = (pc + imm) & ~1; break; default: return 0; } ``` -------------------------------- ### Extracting Transaction Data for Debugger - Rust Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This Rust code snippet, intended for unit tests, uses `context.dump_tx` to extract transaction information and then writes it to a `tx.json` file. This file is crucial for `ckb-debugger` when the contract requires transaction context. ```rust let tx_data = context.dump_tx(&tx).expect("dump tx info"); std::fs::write( "tx.json", serde_json::to_string_pretty(&tx_data).expect("json"), ).expect("write tx"); ``` -------------------------------- ### Processing Compiled Contracts for Debugging - Shell Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This shell command copies the compiled contract to a `.debug` version and then strips debug symbols and all symbols from the original binary using `llvm-objcopy` to reduce its size, while keeping the debug version for debugging. ```shell cp build/ckb-debug/ build/ckb-debug/.debug llvm-objcopy --strip-debug --strip-all build/ckb-debug/ ``` -------------------------------- ### Compiling RISC-V Program with Debugging Information Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/fib.md This command compiles the `fib.c` source file into an executable `fib` for a RISC-V target, including debugging information (`-g` option) necessary for tools like GDB and flamegraph generation. ```Shell $ riscv64-unknown-elf-gcc -g -o fib fib.c ``` -------------------------------- ### Debugging Caller with Remote Target - Debugger Commands Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/examples/exec_gdb_cmd.txt This sequence of debugger commands is used to load the 'exec_caller' executable, connect to a remote debugger instance at 127.0.0.1:9999, set a breakpoint at the `__internal_syscall` function, and then continue execution twice. This is typical for debugging the caller's side of an interaction or a specific system call. ```Debugger Commands file exec_caller target remote 127.0.0.1:9999 b __internal_syscall c c ``` -------------------------------- ### Printing Traced Memory Contents in Python Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/probes.md This Python snippet iterates over the memory_contents BPF table, which was populated by the C BPF program. It sorts the items by memory address (k.value) and then prints each memory address and its corresponding content in a formatted hexadecimal string. This allows userspace programs to view the extracted function parameters or return values. ```Python for k, v in sorted(b.get_table("memory_contents").items(), key=lambda kv: kv[0].value): print(f"memory addr: {k.value:016x}, content: {v.value:016x}") ``` -------------------------------- ### Connecting LLDB to Remote CKB Debugger - LLDB Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This LLDB command connects the local LLDB instance to the `ckb-debugger`'s GDB server, which is listening on port 8000. Once connected, standard LLDB commands can be used for debugging the contract. ```lldb gdb-remote 8000 ``` -------------------------------- ### Connecting GDB to Remote CKB Debugger - GDB Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This GDB command connects the local GDB instance to the `ckb-debugger`'s GDB server, which is listening on `127.0.0.1:8000`. Once connected, standard GDB commands can be used for debugging the contract. ```gdb target remote 127.0.0.1:8000 ``` -------------------------------- ### Configuring VSCode Task to Stop CKB Debugger - JSON Source: https://github.com/nervosnetwork/ckb-standalone-debugger/blob/develop/ckb-debugger/docs/debugging_contract_with_vscode.md This VSCode `tasks.json` configuration defines a shell task to stop the `ckb-debugger` process. Since `ckb-debugger` doesn't exit automatically, this task uses `killall ckb-debugger` to terminate it, ensuring a clean shutdown after debugging. ```json { "label": "stop-ckb-debugger", "type": "shell", "command": "killall ckb-debugger || true" } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.