当前位置:   article > 正文

程序编译过程 & ELF格式 静态库 动态库_elf格式 动态库 函数

elf格式 动态库 函数

代码的编译过程

ELF文件的头是用于描述整个文件的,这个文件格式在内核中有定义 struct elf64_hlr。

1. 可重定位文件 *.o

2. 可执行文件 *

3. 共享对象文件(shared object) *.so

  1. gcc -c a.c (输出是 a.o) 可重定位(ELF第一种格式)
  2. 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是需要重定位的。

  1. gcc -c func.c
  2. gcc -c main.c
  3. ar r func.a func.o
  4. 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 查看头

 动态链接

  1. gcc -c main.c
  2. gcc -c func.c -fpic # -fpic (position independent code)
  3. gcc func.o -shared -o libfunc.so
  4. gcc -o main main.o -L. -lfunc
  5. ./main # error loading shared libraries: libfunc.so no such file or directory
  6. cp xxx.so /usr/lib
  7. export LD_LIBRARY_PATH=:/home/chun/lib
  8. ./main
  9. ldd main # find related dynamic so


 

linux默认使用的是动态链接,使用 gcc main.c -o out -static 使用-static 可能会因为没有安装静态库而报错

  1. apt-get install glibc-static
  2. libc.so
  3. -lc
  4. cd  /usr/lib & ls | grep libc.so

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/849267
推荐阅读
相关标签
  

闽ICP备14008679号