Priroda - MIR Debugger
运行示例
Priroda 的 Rust 工具链是四年前的 nightly-2021-03-13,虽然可以正常使用,但无法编译新的项目。
一个基本的 docker 运行 priroda 流程可以描述为:
FROM ubuntu:latest
RUN apt update \
&& apt install -y git curl build-essential pkg-config libgraphviz-dev
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain none -y && \
echo "export CARGO_TERM_COLOR=always" >> ~/.bashrc
# COPY . /priroda
RUN git clone https://github.com/oli-obk/priroda /priroda
WORKDIR /priroda
RUN bash -lc "\
rustup show \
&& rustup component add miri \
&& cargo install xargo --locked \
&& cargo miri setup \
"
ENV MIRI_SYSROOT=/root/.cache/miri/HOST
podman build -t priroda .
podman run -d --name priroda --replace --rm priroda sleep infinity
podman exec -it priroda bash
在 x86-64 上运行如下命令可得到
#![allow(unused)] fn main() { $ cargo run example.rs Running `target/debug/priroda example.rs` 🔧 Configured for development. => address: localhost => port: 54321 => log: normal => workers: 64 => secret key: generated => limits: forms = 32KiB => keep-alive: 5s => read timeout: 5s => write timeout: 5s => tls: disabled 🛰 Mounting /: => GET /please_panic (please_panic) => GET /resources/<path..> (resources) => GET /step_count (step_count) 🛰 Mounting /: => GET / (index) => GET /frame/<frame> (frame) => GET /frame/<frame> [42] (frame_invalid) => GET /ptr/<alloc_id>/<offset> (ptr) => GET /reverse_ptr/<ptr> (reverse_ptr) 🛰 Mounting /breakpoints: => GET /breakpoints/add_here (add_here) => GET /breakpoints/add/<path..> (add) => GET /breakpoints/remove/<path..> (remove) => GET /breakpoints/remove_all (remove_all) 🛰 Mounting /step: => GET /step/restart (restart) => GET /step/single (single) => GET /step/single_back (single_back) => GET /step/next (next) => GET /step/return (return_) => GET /step/continue (continue_) 🛰 Mounting /watch: => GET /watch/show (show) => GET /watch/continue_and_show (continue_and_show) => GET /watch/add/<id> (add) 📡 Fairings: => 1 launch: Priroda, because code has no privacy rights 🚀 Rocket has launched from http://localhost:54321 warning: unused variable: `u` --> example.rs:48:9 | 48 | let u = SomeUnion { a: true }; | ^ help: if this is intentional, prefix it with an underscore: `_u` | = note: `#[warn(unused_variables)]` on by default error: internal compiler error: compiler/rustc_metadata/src/rmeta/decoder.rs:1157:17: get_optimized_mir: missing MIR for `DefId(1:6671 ~ std[e 5ee]::rt::lang_start_internal)` thread 'rustc' panicked at 'Box<Any>', /rustc/b3e19a221e63dcffdef87e12eadf1f36a8b90295/library/std/src/panic.rs:59:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: aborting due to previous error; 1 warning emitted ============== Miri crashed - restart try 1 ============== warning: unused variable: `u` --> example.rs:48:9 | 48 | let u = SomeUnion { a: true }; | ^ help: if this is intentional, prefix it with an underscore: `_u` | = note: `#[warn(unused_variables)]` on by default GET /step_count: => Matched: GET /step_count (step_count) => Outcome: Success => Response succeeded. GET /step_count: => Matched: GET /step_count (step_count) => Outcome: Success => Response succeeded. }
在 aarch64 机器上运行示例将得到如下错误:
#![allow(unused)] fn main() { $ cargo run example.rs error[E0308]: mismatched types --> /root/.cargo/git/checkouts/cgraph-7a547510dd5167be/5e6a6d4/src/lib.rs:90:67 | 90 | let res = gvRenderFilename(gvc, self.0, svg.as_ptr(), file_path.as_ptr() as *const i8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `i8` | = note: expected raw pointer `*const u8` found raw pointer `*const i8` }
在指出的源码中修改指针类型,继续编译,就可以得到类似的终端输出结果。
然后打开 localhost:54321,浏览器中将看到 MIR 调试界面:
但点击 Step、Next 之类的按钮,并不能工作,可能因为后端 Miri 找不到 DefId 而 panic (见上面的输出)。