如何将rustc生成的x86汇编代码汇编为可执行文件并调试?
问题:汇编Rustc生成的x86汇编代码并生成带调试信息的可执行文件
我在汇编rustc编译器生成的x86汇编代码时遇到困难,尝试多种方法均无法生成可执行文件。代码本身很简单,但生成的汇编无法正常执行。
我尝试了三种方法:
- 通过rustc生成汇编代码后,再用rustc汇编该代码;
- 编译为LLVM字节码,再转为LLVM x86汇编,尝试用clang、rustc或gcc编译;
- 使用
as和ld工具,虽能生成目标文件,但无法链接为可执行文件。
所有步骤中,x86汇编代码均可正常生成,但无法将其汇编/链接为可执行文件。
关键需求:汇编过程需包含调试信息,因为我需要将其在GDB中调试,用于我的毕业论文。
测试代码
假设我有文件main.rs,代码如下:
pub fn main() { let mut j = 0; for i in 0..10 { j = j + 100; if i % 2 == 0 { j = j - 1; } else { j = j + 1; } } }
尝试的方法及错误
方法1:用rustc生成汇编后再用rustc汇编
执行命令:
$ rustc --target=x86_64-unknown-linux-gnu --emit=asm -o main.s main.rs $ rustc main.s
出现大量错误:
error: unknown character escape: `b` --> your_code.s:381:11 | 381 | .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" | ^ unknown character escape ... error: expected item, found `.` --> your_code.s:1:2 | 1 | .text | ^ expected item
方法2(及方法3):用as+ld或clang/gcc编译
执行命令:
$ as -o main.o main.s $ ld -o main main.o
链接时出现未定义引用错误:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000 ld: main.o: in function `std::rt::lang_start': main.aaccb3f0a8cfdec6-cgu.0:(.text._ZN3std2rt10lang_start17h10f5244e46882c73E+0x23): undefined reference to `std::rt::lang_start_internal' ld: main.o: in function `core::ops::function::FnOnce::call_once': main.aaccb3f0a8cfdec6-cgu.0:(.text._ZN4core3ops8function6FnOnce9call_once17h90749210ed415b5cE+0x1f): undefined reference to `_Unwind_Resume' ... ld: main.o:(.data.DW.ref.rust_eh_personality[DW.ref.rust_eh_personality]+0x0): undefined reference to `rust_eh_personality'
解决方案
一、正确生成带调试信息的汇编并编译为可执行文件
Rust生成的汇编包含大量Rust标准库依赖和特定汇编语法,直接用rustc汇编或裸as+ld会因缺少依赖、语法不兼容失败,正确步骤如下:
步骤1:生成带调试信息的汇编代码
要保留调试信息,生成汇编时需添加-g参数:
rustc --target=x86_64-unknown-linux-gnu -g --emit=asm -o main.s main.rs
该命令会生成包含DWARF调试信息的汇编文件main.s。
步骤2:用rustc链接汇编代码(解决方法1的错误)
不能直接用rustc main.s——rustc会把.s文件当成Rust源码处理,而非汇编。正确做法是让rustc调用汇编器并自动链接标准库:
rustc --target=x86_64-unknown-linux-gnu -g main.s -o main
此命令会调用系统as汇编器处理main.s,再链接Rust标准库和启动代码,最终生成带调试信息的可执行文件main。
替代方案:用clang/gcc汇编+rustc链接(解决方法2的错误)
若想用clang/gcc汇编,可先生成目标文件(保留调试信息):
clang -c -g main.s -o main.o
再用rustc完成链接(rustc知晓如何正确处理Rust依赖):
rustc --target=x86_64-unknown-linux-gnu main.o -o main
二、在GDB中调试汇编代码
生成带调试信息的可执行文件后,直接启动GDB:
gdb ./main
常用调试命令:
break main::main:在Rust的main函数处打断点(自动对应到汇编代码位置)disassemble:查看当前函数的汇编代码stepi:单步执行一条汇编指令info registers:查看寄存器状态list:查看对应Rust源码(因保留调试信息,GDB可关联源码与汇编)
若想直接调试汇编入口,可打断点到_start:
break _start run
内容的提问来源于stack exchange,提问作者kush
相关产品推荐
相关产品推荐

