diff --git a/doc/1.5.1_c_basic.md b/doc/1.5.1_c_basic.md index e08018e..25da7a0 100644 --- a/doc/1.5.1_c_basic.md +++ b/doc/1.5.1_c_basic.md @@ -1,6 +1,8 @@ # C 语言基础 -## 从源代码到可执行文件 +- [从源代码到可执行文件](#compile) + +## 从源代码到可执行文件 我们以经典著作《The C Programming Language》中的第一个程序 “Hello World” 为例,讲解 Linux 下 GCC 的编译过程。 ```c diff --git a/doc/1.5.3_elf.md b/doc/1.5.3_elf.md index 3ecb13e..5224387 100644 --- a/doc/1.5.3_elf.md +++ b/doc/1.5.3_elf.md @@ -1 +1,61 @@ # Linux ELF + +- [一个实例](#elfdemo) +- [目标文件](#object) + + +## 一个实例 +在 *1.5.1节 C语言基础* 中我们看到了从源代码到可执行文件的全过程,现在我们来看一个更复杂的例子。 +```text +#include + +int global_init_var = 10; +int global_uninit_var; + +void func(int sum) { + printf("%d\n", sum); +} + +void main(void) { + static int local_static_init_var = 20; + static int local_static_uninit_var; + + int local_init_val = 30; + int local_uninit_var; + + func(global_init_var + local_init_val + + local_static_init_var ); +} +``` + +然后分别执行下列命令生成两个文件: +```text +gcc -c elfDemo.c -o elfDemo.o + +gcc elfDemo.c -o elfDemo +``` +使用 ldd 命令打印所依赖的共享库: +```text +$ ldd elfDemo + linux-gate.so.1 (0xf76e3000) + libc.so.6 => /usr/lib32/libc.so.6 (0xf74e5000) + /lib/ld-linux.so.2 (0xf76e5000) +``` + +此时他们的结构如图: +![](../pic/1.5.3_elfdemo.png) + +可以看到,ELF 文件的开头是一个“文件头”,之后分别是代码段、数据段和.bss段。程序源代码编译后,执行语句变成机器指令,保存在.text段;已初始化的全局变量和局部静态变量都保存在.data段;未初始化的全局变量和局部静态变量则放在.bss段。 + + +## 目标文件 +ELF(Executable Linkable Format)是 Linux 的可执行文件格式,是 COFF (Common file format)格式的变种。目标文件主要分为三种类型: +- 可重定位文件(Relocatable file) + - 包含了代码和数据,可以和其他目标文件链接生成一个可执行文件或共享目标文件。 + - elfDemo.o +- 可执行文件(Executable File) + - 包含了可以直接执行的文件。 + - elfDemo +- 共享目标文件(Shared Object File) + - 包含了用于链接的代码和数据,分两种情况。一种是链接器将其与其他的可重定位文件和共享目标文件链接起来,生产新的目标文件。另一种是动态链接器将多个共享目标文件与可执行文件结合,作为进程映像的一部分。 + - libc.so.6 diff --git a/pic/1.5.3_elfdemo.png b/pic/1.5.3_elfdemo.png new file mode 100644 index 0000000..31cf4ba Binary files /dev/null and b/pic/1.5.3_elfdemo.png differ