2个不稳定版本

0.2.0 2023年6月16日
0.1.0 2023年4月13日

过程宏 中排名第824

MIT许可

21KB
380

mutself

创建自修改的可执行文件。

目的

// TODO

用法

mutself::mutself! {
    DATA = "alice"
}

fn main() {
    if let Some(arg) = std::env::args().nth(1) {
        println!("Hello {}", &arg);
        mutself("new.exe", Some(&arg)).unwrap();
    } else {
        println!("Hello {}", &*DATA);
    }
}

运行我们的可执行文件会得到

$ cargo run
Hello alice

现在带有参数

$ cargo run -- bob
Hello bob
# This creates another executable named 'new.exe'
$ new
Hello bob

是的,数据大小可以改变。

$ cargo run -- someverylongstringthatwouldntfitinsidethespace

如何?

库解析正在运行的可执行文件并更改值,然后输出一个新的可执行文件。

深入了解

简单来说:对 #[link_section = ".custom"] 属性的滥用。没有汇编修复或任何其他操作。在 mutself! 宏中的数据条目存储在可执行文件的自定义部分。运行的代码只有一个指向该部分顶端的指针(该指针始终有效,因为自定义部分在虚拟内存中始终位于同一位置)。该部分中的所有条目都相对于这个指针进行引用。

内存布局如下(考虑对齐)

#ENTRY0 size (usize) <-- hardcoded pointer
#ENTRY0
#ENTRY1 size (usize)
#ENTRY1
// And so on

由于每个条目都是相对于基址定义的,因此它们可以自由地增长或缩小,而不必担心运行时代码无法访问它们。

限制

初始化表达式必须是可以内联存储的类型(例如,不是切片)。切片只会在自定义可执行文件部分存储一个ptr和一个大小,引用 .data,这意味着我们无法修改它。

依赖项

~4MB
~74K SLoC