C 与 Rust 编译与二进制分析实战教程
目录
本教程通过简单的 “Hello World” 程序,带你了解 C 和 Rust 的编译过程、二进制文件分析以及如何处理 Rust 的动态链接问题。
0. 代码准备
C 语言 (hello.c)
#include <stdio.h>
void main() {
printf("Hello, World!\n");
}Rust 语言 (hello.rs)
fn main() {
println!("Hello, World!");
}1. 基础编译与运行
C 语言
使用 gcc 编译器:
# 编译并命名为 hello_c
gcc hello.c -o hello_c
# 运行
./hello_cRust 语言
使用 rustc 编译器:
# 基础编译
rustc hello.rs -o hello_r
# 运行
./hello_r2. 二进制文件分析
编译完成后,我们可以使用系统工具查看生成的二进制文件。
查看依赖库 (ldd)
通过 ldd 可以查看程序运行所需的共享库。
C 语言的输出:
ldd hello_c
# 输出示例:
# linux-vdso.so.1 (0x00007f1fc4940000)
# libc.so.6 => /lib64/libc.so.6 (0x00007f1fc4745000)
# /lib64/ld-linux-x86-64.so.2 (0x00007f1fc4942000)Rust 语言的输出(默认静态链接标准库):
ldd hello_r
# 输出示例:
# linux-vdso.so.1 (0x00007fdc0c45c000)
# libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fdc0c3cf000)
# libc.so.6 => /lib64/libc.so.6 (0x00007fdc0c1dc000)
# /lib64/ld-linux-x86-64.so.2 (0x00007fdc0c45e000)查看符号表 (objdump)
查看二进制文件内部的符号(函数名、变量名等):
objdump -t hello_c
objdump -t hello_r优化体积 (Strip)
Rust 编译器默认包含大量调试信息。使用 strip 可以减小二进制体积:
rustc -C strip=debuginfo hello.rs -o hello_r3. 进阶教程:Rust 动态链接处理
在某些环境下,为了减小多个程序共享的总体积,我们可能希望 Rust 使用动态链接(prefer-dynamic)。
开启动态编译
rustc -C prefer-dynamic=yes hello.rs -o hello_r解决 “libstd” 找不到的问题
当你运行动态编译的程序时,可能会报错:error while loading shared libraries: libstd-xxxx.so。
方法 A:临时设置环境变量 (推荐)
你需要告诉系统 Rust 标准库的具体位置:
# 路径通常在 rustup 的 toolchain 目录下
LD_LIBRARY_PATH=~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib ./hello_r方法 B:将库文件复制到当前目录
如果你希望在当前目录下直接运行:
# 查找到对应的 .so 文件并复制(注意替换你的具体文件名)
cp ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-*.so .
./hello_r相关使用教程:Linux 共享库管理指南
本部分作为补充,讲解 Linux 系统下管理和调试共享库的通用技巧。
1. 环境变量 LD_LIBRARY_PATH
这是最快捷的临时加载非标准路径库文件的方法。
- 格式:
export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH - 注意:仅对当前终端会话有效。
2. 使用 rpath 嵌入路径
如果你希望生成的程序在任何地方都能自动找到库,可以在编译时使用 rpath:
# Rust 示例
rustc -C prefer-dynamic=yes -C link-args="-Wl,-rpath,/your/lib/path" hello.rs -o hello_r3. 系统级配置 (/etc/ld.so.conf)
对于长期使用的库,可以将其路径加入系统配置:
- 在
/etc/ld.so.conf.d/创建新文件rust.conf。 - 写入库路径。
- 执行
sudo ldconfig刷新缓存。
4. 调试库加载过程
如果程序依然报错,可以使用 LD_DEBUG 环境变量查看加载详情:
LD_DEBUG=libs ./hello_r这会输出系统尝试查找库文件的所有路径 and 过程。