点击上方蓝字 江湖评谈设为关注/星标
前言
native语言一般的都是先把源码compile成目标文件,然后通过链接器链接目标文件生成当前平台可执行的二进制文件。
比如C++,先把源码编译成目标文件,然后进行目标文件链接。rust也不例外,看下它的rustc的这个链接和目标文件过程。
链接和目标文件
以linux发行版ubuntu为例,rustc在compile rust源码的时候,会在/tmp文件夹下面生成一个临时symbols.o目标文件。
rust开头的文件应是随机生成的,进入此文件就会包含symbols.o文件。
symbols.o文件里面包含了需要链接的符号。
在需要被compile的rust源文件同目录下,通过llvm::LLVMRustWriteOutputFile也会生成两个临时的目标文件。如下图:
这些临时的目标文件在链接器链接成功之后,就会被删除。基本上如果不对rustc进行debug就很难看到这些目标文件。
示例:
fn main() {
let number = 5;
let result = add_one(number);
println!("The result is: {}", result);
}
fn add_one(x: i32) -> i32 {
x + 1
}
rustfirstproj.22ye3ohdqcxv9h8a6gvq58fmt.rcgu.o的ASM如下:
#: objdump -d rustfirstproj.22ye3ohdqcxv9h8a6gvq58fmt.rcgu.o
rustfirstproj.22ye3ohdqcxv9h8a6gvq58fmt.rcgu.o: file format elf64-x86-64
Disassembly of section .text.__rust_alloc:
0000000000000000 <__rust_alloc>:
0: e9 00 00 00 00 jmp 5 <__rust_alloc+0x5>
Disassembly of section .text.__rust_dealloc:
0000000000000000 <__rust_dealloc>:
0: e9 00 00 00 00 jmp 5 <__rust_dealloc+0x5>
Disassembly of section .text.__rust_realloc:
0000000000000000 <__rust_realloc>:
0: e9 00 00 00 00 jmp 5 <__rust_realloc+0x5>
Disassembly of section .text.__rust_alloc_zeroed:
0000000000000000 <__rust_alloc_zeroed>:
0: e9 00 00 00 00 jmp 5 <__rust_alloc_zeroed+0x5>
Disassembly of section .text.__rust_alloc_error_handler:
0000000000000000 <__rust_alloc_error_handler>:
0: e9 00 00 00 00 jmp 5 <__rust_alloc_error_handler+0x5>
rustfirstproj.rustfirstproj.630d847d76b72b66-cgu.0.rcgu.o包含了main入口等其它
// 以上省略,便于观看
Disassembly of section .text.main:
0000000000000000 <main>:
0: 50 push %rax
1: 48 89 f2 mov %rsi,%rdx
4: 48 63 f7 movslq %edi,%rsi
7: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # e <main+0xe>
e: 31 c9 xor %ecx,%ecx
10: e8 00 00 00 00 call 15 <main+0x15>
15: 59 pop %rcx
16: c3 ret
可以通过如下断点跟踪:
(lldb)b codegen
(lldb)b exec_linker
(lldb)b /home/tang/opt/rust/compiler/rustbak/compiler/rustc_codegen_llvm/src/back/write.rs:701
(lldb)b /home/tang/opt/rust/compiler/rust/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp:594
(lldb)b /home/tang/opt/rust/compiler/rustbak/compiler/rustc_codegen_ssa/src/back/link.rs:138(lldb)b
(lldb)b thread.rs:105
(lldb)b /home/tang/opt/rust/compiler/rust/library/std/src/thread/mod.rs:522
(lldb)b b /home/tang/opt/rust/compiler/rust/library/std/src/thread/mod.rs:519
技巧,如果下一个断点多个地方可以断下,则可以观察断点的序号,通过其序号根据帧栈(bt)找其地址进行下断。减少不必要的步骤,另外一个方法也可以条件breakpoint。
结尾
rustc到目前为止,已经梳理完成了整个compile过程。
参考如下: