c,c++编译过程

举报
codeboy 发表于 2020/12/11 14:28:42 2020/12/11
【摘要】 c,c++编译过程

#预处理,编译,汇编,链接

  1. 预处理gcc -E hello.cpp -o hello.i
    • 处理#include ,宏定义
  2. 编译gcc -S hello.i -o hello.s
    • 实际调用ccl
    • 生成汇编代码
  3. 汇编gcc -c hello.s -o hello.o
    • 生成机器指令
  4. 链接ld
    • 静态链接
      • 地址和空间分配,符号决议,重定位
    • 动态链接

#目标文件格式

  1. 目标文件分类
    • 可重定位文件 .o文件
    • 可执行文件
    • 共享目标文件 .so文件
    • 核心转储文件 coredump文件
  2. 目标文件分段
    • text段(程序指令)
    • .data段(已经初始化值的全局变量和局部静态变量)
    • .bss段(未初始化的全局变量和局部静态变量),没有内容,不占空间,因为这些值默认都是0
  3. 文件格式查看
    • gcc -c hello.cpp生成hello.o
    • objdump -h hello.o 查看各个段的大小,起始位置
    • objdump -d -s hello.o 查看汇编代码
    • readelf -h hello.o查看文件的基本信息
    • readelf -S hello.o查看文件的具体段的分布
    • readelf -s hello.o查看文件的变量函数
  4. 强符号和弱符号
    • 初始化了的全局变量是强符号
    • 弱符号的使,通过 __attribute__((weak))指定此引用为弱引用,如果外部没有定义,可以链接出错,但是引用为空,如果外部有定义,正常运行,引用不为空,自己代码可以声明一个外部库的弱引用,如果为空,说明运行时没有外部库,可以执行自己另外的逻辑,达到一定的动态化

#静态链接过程

  1. 将每个.o文件的相同的段放在一起并合并,并根据每个文件的符号定义和引用,建立一个全局符号表
  2. 对每个.o文件,
    • 根据自己在合并之后的位置,更新自己的地址为原地址加现在在合并文件中的起始地址
    • 读取文件的重定位表中的每一项objdump -r a.o,在全局符号表中查找,并进行重定位

#动态链接过程

  1. 对于可共享的so文件,按照不同的段区分,数据段是每个个进程各自拥有一份,程序指令段需要编译此so的时候就编译为地址无关代码,
  2. so编译的具体过程是:凡是调用了本so外部的变量函数,都通过一个GOT表指针间接访问,而GOT表是此时未初始化的,而且GOT是放在数据段的
  3. Program装载这个so的时候,每个进程拥有自己的数据段和GOT,然后根据此时so的内存位置,填写GOT,此时Program调用的so的指令部分是多个进程共享的.但是指令访问数据函数的时候,会拿各自进程自己的GOT表,所以对数据的操作是各个进程独立的。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。