目录

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_c

Rust 语言

使用 rustc 编译器:

# 基础编译
rustc hello.rs -o hello_r
# 运行
./hello_r

2. 二进制文件分析

编译完成后,我们可以使用系统工具查看生成的二进制文件。

查看依赖库 (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_r

3. 进阶教程: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_r

3. 系统级配置 (/etc/ld.so.conf)

对于长期使用的库,可以将其路径加入系统配置:

  1. /etc/ld.so.conf.d/ 创建新文件 rust.conf
  2. 写入库路径。
  3. 执行 sudo ldconfig 刷新缓存。

4. 调试库加载过程

如果程序依然报错,可以使用 LD_DEBUG 环境变量查看加载详情:

LD_DEBUG=libs ./hello_r

这会输出系统尝试查找库文件的所有路径 and 过程。