- 一个基于 rustc_driver 的编译器 wrapper,命名为
rustc-pa。 - 通过宏占位 + MIR 重写,在不修改上游 rustc 的前提下访问结构体私有字段。
- 提供两种能力:
priv_access!:只读访问私有字段(字段需实现Copy)。priv_field_ptr!:获取字段的裸指针(可读写,保持可变性语义)。
- 调试、性能剖析、运行时观测、二进制插桩、ABI 研究等需要窥视内部状态的场景。
- 需要避免手算 offset、兼容字段重排,或需要在不改动上游源码的前提下观测 std / 第三方库内部。
- 宏展开为占位函数调用,携带父类型与字段名哈希(FNV-1a)。
- rustc-pa 覆写
mir_built,扫描占位调用并解析字段。 - 将调用重写为字段投影:
priv_access!→Copy读取字段。priv_field_ptr!→ 生成裸指针,保持 & / &mut 可变性。
- 未被 wrapper 处理时,占位函数会 panic,暴露配置错误。
- 零 rustc 源码改动:独立二进制,直接通过
RUSTC_WRAPPER注入。 - 布局自适应:基于真实布局生成字段投影,无硬编码 offset。
- 受控风险:只读访问要求字段
Copy;指针路径显式unsafe。 - 清晰报错:类型非 struct、字段缺失/冲突、字段非
Copy均在编译期报错。
# 构建 wrapper(当前依赖 nightly,因为 rustc_private 仅在 nightly 提供)
cargo build -p priv_access_driver
# 使用时设置 RUSTC_WRAPPER
env RUSTC_WRAPPER=target/debug/priv_access_driver \
RUSTUP_TOOLCHAIN=nightly \
cargo test -p example --manifest-path tests/fixtures/priv_access_example/Cargo.toml示例测试将读取/写入私有字段,验证 wrapper 生效。
- 不上 crates.io,直接在 GitHub 发布构建好的
rustc-pa二进制。 - 建议流程:
cargo build -p priv_access_driver --release,产物位于target/release/priv_access_driver。- 在 Git 标签对应的 Release 附带各平台构建产物(可重命名为
rustc-pa便于使用)。 - 文档示例统一使用
RUSTC_WRAPPER=/path/to/rustc-pa,避免用户额外配置。
// src/private_types.rs (被访问方,独立模块)
pub struct PrivateBox { value: i32 }
pub struct Pair { pub left: i32, right: i32 }
impl PrivateBox { pub fn new(v: i32) -> Self { Self { value: v } } }
impl Pair { pub fn new(l: i32, r: i32) -> Self { Self { left: l, right: r } } }
// src/lib.rs (访问方,非同一模块)
use priv_access::{priv_access, priv_field_ptr};
use crate::private_types::{Pair, PrivateBox};
fn demo_read(boxed: &PrivateBox) -> i32 {
// 越权读取私有字段 value(字段需 Copy)
unsafe { priv_access!(boxed, crate::private_types::PrivateBox, value) }
}
fn demo_write(pair: &mut Pair) {
// 获取私有字段 right 的裸指针并写入
let ptr: *mut i32 = unsafe { priv_field_ptr!(pair, crate::private_types::Pair, right) };
unsafe { *ptr = 42 };
}- 提供与 stable 版本对齐的预编译
rustc-pa二进制,减少 nightly 依赖。 - 丰富 UI/运行时测试,覆盖更多标准库内部场景。