• 程序编译过程 & 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

  • 相关阅读:
    享元模式【Java设计模式】
    【强化学习论文】离线元强化学习中基于对比学习的稳定表示
    Backtracking algorithm梳理
    文心一言 VS 讯飞星火 VS chatgpt (94)-- 算法导论9.2 3题
    安全性归约(构造 2)
    编写一个程序,实现以下功能:(1)计算n个学生的平均成绩aver;(C语言)
    连接mysql报错 :Host ‘xxx.xx.x.x‘ is not allowed to connect to this MySQL server
    这种动态规划你见过吗——状态机动态规划之股票问题(上)
    前端中间件Midway的使用
    多关键词高亮显示
  • 原文地址:https://blog.csdn.net/Chunying27/article/details/127567474