# C 与 Rust 编译与二进制分析实战教程


本教程通过简单的 "Hello World" 程序，带你了解 C 和 Rust 的编译过程、二进制文件分析以及如何处理 Rust 的动态链接问题。

<!--more-->

## 0. 代码准备

### C 语言 (`hello.c`)
```c
#include <stdio.h>

void main() {
  printf("Hello, World!\n");
}
```

### Rust 语言 (`hello.rs`)
```rust
fn main() {
    println!("Hello, World!");
}
```

---

## 1. 基础编译与运行

### C 语言
使用 `gcc` 编译器：
```bash
# 编译并命名为 hello_c
gcc hello.c -o hello_c
# 运行
./hello_c
```

### Rust 语言
使用 `rustc` 编译器：
```bash
# 基础编译
rustc hello.rs -o hello_r
# 运行
./hello_r
```

## 2. 二进制文件分析

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

### 查看依赖库 (ldd)
通过 `ldd` 可以查看程序运行所需的共享库。

**C 语言的输出：**
```bash
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 语言的输出（默认静态链接标准库）：**
```bash
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)
查看二进制文件内部的符号（函数名、变量名等）：
```bash
objdump -t hello_c
objdump -t hello_r
```

### 优化体积 (Strip)
Rust 编译器默认包含大量调试信息。使用 `strip` 可以减小二进制体积：
```bash
rustc -C strip=debuginfo hello.rs -o hello_r
```

---

## 3. 进阶教程：Rust 动态链接处理

在某些环境下，为了减小多个程序共享的总体积，我们可能希望 Rust 使用动态链接（`prefer-dynamic`）。

### 开启动态编译
```bash
rustc -C prefer-dynamic=yes hello.rs -o hello_r
```

### 解决 "libstd" 找不到的问题
当你运行动态编译的程序时，可能会报错：`error while loading shared libraries: libstd-xxxx.so`。

#### 方法 A：临时设置环境变量 (推荐)
你需要告诉系统 Rust 标准库的具体位置：
```bash
# 路径通常在 rustup 的 toolchain 目录下
LD_LIBRARY_PATH=~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib ./hello_r
```

#### 方法 B：将库文件复制到当前目录
如果你希望在当前目录下直接运行：
```bash
# 查找到对应的 .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`：
```bash
# 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` 环境变量查看加载详情：
```bash
LD_DEBUG=libs ./hello_r
```
这会输出系统尝试查找库文件的所有路径 and 过程。

