Rustc链接和目标文件

文摘   2024-09-07 08:19   湖北  

点击上方蓝字 江湖评谈设为关注/星标




前言

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过程。

参考如下:

Rust musl/.NET-Glibc简析

Rust编译器研究+.NET9 PreView7

Rust语法简析

Rust编译器深入

Rust编译器+语法探究

Rustc Compile过程+线程


江湖评谈
记录,分享,自由。
 最新文章