编辑中间装配文件后重新链接

问题描述 投票:0回答:1

我们可以将一个标志传递给 Cargo,该标志又传递给

rustc
以发出板条箱的全部内容的中间汇编文件:

$ RUSTFLAGS="--emit=asm" cargo rustc --release

运行后,确实可以在

.s
下看到一大堆
target/$TARGET/release
文件:

$ ls target/avr-atmega32u4/release/deps/*.{s,elf}
target/avr-atmega32u4/release/deps/avr_config-e311e93c086c3db0.s
target/avr-atmega32u4/release/deps/avr_delay-157ca9fb1a916f1a.s
target/avr-atmega32u4/release/deps/avr_progmem-9dc1e040eb728712.s
target/avr-atmega32u4/release/deps/avr_std_stub-c3510b4296c6559e.s
target/avr-atmega32u4/release/deps/cfg_if-21f3790d6886cc57.s
target/avr-atmega32u4/release/deps/compiler_builtins-d2b51c47ad38c941.s
target/avr-atmega32u4/release/deps/core-195cf775332e0617.s
target/avr-atmega32u4/release/deps/ruduino-15843435a02e3c3a.s
target/avr-atmega32u4/release/deps/rustc_std_workspace_core-7426025ff9d9438f.s
target/avr-atmega32u4/release/deps/ufmt-b3d2cb48639acfb8.s
target/avr-atmega32u4/release/deps/ufmt_write-4e35e82da143e2d5.s
target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.elf*
target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.s
target/avr-atmega32u4/release/deps/worduino_engine-1dc7446bd9d04ccf.s

我如何更改其中一些,然后继续相同的汇编和链接过程?所以假设我编辑文件

target/avr-atmega32u4/release/deps/worduino_engine-1dc7446bd9d04ccf.s
,然后我如何要求 Cargo 创建新版本的
worduino_avr-b35d7970ef451ba9.elf
,其链接时间设置与
cargo rustc
的原始调用相同?

assembly rust reverse-engineering rust-cargo roundtrip
1个回答
0
投票

令我惊讶的是,事实证明,至少对于 AVR 来说,与顶层 crate 相对应的汇编代码包含了所需的一切,不需要链接。所以对于例如LLVM 中间文件,我们可以使用

llc
进行静态编译,然后使用 GCC 进行简单链接:

$ RUSTFLAGS="--emit=llvm-bc" cargo rustc --release
$ llc-15 -march=avr -mcpu=atmega32u4 -filetype=obj --function-sections target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.bc -o foo.o
$ avr-gcc -mmcu=atmega32u4 -Os foo.o -o foo.elf

这会在

foo.elf
中生成一个有效的ELF文件,但是,它与Rust生成的完全相同,这涉及到:

$ md5sum foo.elf target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.elf
5ba0a483b6adbc81faaba180e8e5ad1c  foo.elf
198eff7c052172bcff6a9a81306a7bf7  target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.elf

这似乎是因为

foo.o
本身与Rust创建的中间目标文件
worduino_avr-b35d7970ef451ba9.worduino_avr.124c28c8-cgu.0.rcgu.o
并不完全匹配;我不确定这里到底发生了什么。

从功能上来说,将生成的

.elf
文件加载到 AVR 模拟器中,结果似乎与真实 Rust 输出的行为相匹配,所以这很好。不过,如果我们能够准确复制
.elf
文件那就更好了。

无论如何,继续下一个问题是如何做同样的事情,但是从汇编

.s
文件而不是
.bc
。我们应该能够将上述管道中的
llc
替换为
llvm-mc

$ RUSTFLAGS="--emit=asm" cargo rustc --release
$ llvm-mc-15 --arch=avr --mcpu=atmega32u4 -filetype=obj target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.s -filetype=obj -o bar.o
$ avr-gcc -mmcu=atmega32u4 -Os bar.o -o bar.elf

但是,这里我们遇到了另一个问题,即

llvm-mc
错误地组装了文件

© www.soinside.com 2019 - 2024. All rights reserved.