赞
踩
代码的编译过程
ELF文件的头是用于描述整个文件的,这个文件格式在内核中有定义 struct elf64_hlr。
1. 可重定位文件 *.o
2. 可执行文件 *
3. 共享对象文件(shared object) *.so
- gcc -c a.c (输出是 a.o) 可重定位(ELF第一种格式)
- gcc a.c (输出是 a.out) 可执行 (ELF第二种格式)
.text 代码
.data 初始化的全局变量
.rodata 只读数据,字符串常量,const变量
.bss 未初始化的全局变量(运行时置0)
.symtab 符号表(函数和变量)
.strtab 字符串表,字符串常量和变量名
NOTE: 局部变量是运行时在stack里。这个文件是编译时。
我们刚才说了可重定位,为啥叫可重定位呢?我们可以想象一下,这
个编译好的代码和变量,将来加载到内存里面的时候,都是要加载到
一定位置的。比如说,调用一个函数,其实就是跳到这个函数所在的
代码位置执行;再比如修改一个全局变量,也是要到变量的位置那里
去修改。但是现在这个时候,还是.o文件,不是一个可以直接运行的
程序,这里面只是部分代码片段。
假设我的场景是 func.c main.c
那么在main.c里面调用了func这个函数,但这个函数在另一个.o里面,main.o根本不知道这个被调用函数的位置,只好在 rel.text里标注,这个func是需要重定位的。
- gcc -c func.c
- gcc -c main.c
- ar r func.a func.o
- gcc -o chun main.o -L. -lfunc
-L表示在当前目录下找.a文件,-lfunc会自动补全文件名,比如加前缀lib,后缀.a,变成libfunc.a,找到这个.a文件后,将里面的func.o取出来,和main.o做一个链接,形成二进制执行文件chun。
在ELF的头里面,有一项e_entry,也就是虚拟地址,是这个程序运行的入口,可以用readelf -h 查看头
动态链接
- gcc -c main.c
- gcc -c func.c -fpic # -fpic (position independent code)
- gcc func.o -shared -o libfunc.so
- gcc -o main main.o -L. -lfunc
-
- ./main # error loading shared libraries: libfunc.so no such file or directory
- cp xxx.so /usr/lib
- export LD_LIBRARY_PATH=:/home/chun/lib
- ./main
- ldd main # find related dynamic so
linux默认使用的是动态链接,使用 gcc main.c -o out -static 使用-static 可能会因为没有安装静态库而报错
- apt-get install glibc-static
-
- libc.so
-
- -lc
-
- cd /usr/lib & ls | grep libc.so
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。