您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

时间:2020-11-16 13:33:54  来源:  作者:

如何使用 gcc 构建 c/c++ 项目,大家都很熟悉了,甚至对链接器、静态库、共享库等概念,大家也略知一二。然而,对于 ld 链接器、linux 操作系统(OS)及应用程序(exec)之间的详细交互流程,估计就有点懵了。接下来,我将从单个源文件编译、编译期链接、程序运行期这三个阶段入手,揭开应用程序运行背后的奥秘。

单个源文件编译

单个 c/cpp 文件可以被 gcc 编译成目标文件(.o 文件),这部分就不过多赘述,大家应该都很熟悉了。二进制目标文件中的 section 有很多,详细内容可以打开汇编代码详细研究下,下图列出了其中比较常见的段。

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

这里的目标文件包括 .o 文件及后面提到的库文件

符号表的作用是什么?

  1. 记录该目标文件中定义的全局变量及函数;
  2. 记录该目标文件中引用的全局变量及函数;
详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

Func 是源文件中引用的外部符号,a 是源文件中定义的全局变量

.rela.* 的作用是什么?

全称 relocation(重定位),记录编译器在编译时不确定的符号地址——针对引用的外部符号。

dynamic 段中保存了可执行文件依赖哪些动态库。

GOT 段记录了需要引用的外部符号的地址。

编译期链接

多个 .o 文件可以通过链接器(ld)被打包在一起,组合成库文件。

库文件又分为静态库(.a 文件)和共享库(.so 文件)。

什么是 ld 呢?它本身也是可执行文件,属于 GNU 的一部分,将一堆目标文件通过符号表链接成最终的目标文件、库文件和可执行文件。

.a 文件如何生成?

ld 直接将涉及的所有目标文件打包进静态库文件。

.so 文件如何生成?

在链接生成共享库文件的过程中,并不拷贝目标文件中涉及的代码段,只记录它需要引用的外部符号位置(在哪些目标文件中)。

所有的目标文件、库文件和可执行文件都有统一的格式,即 ELF,Executable and Linking Format(可执行链接格式)。

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

libstdc++.so 是标准库文件

上图中,多个 .o 文件链接在一起形成 .a 文件,多个 .o 和 .so 文件也可以链接形成 .so 文件,可执行文件也可以由 .a 文件、.so、.o 文件链接而成。

程序运行期

如果可执行文件没有使用共享库,那么该程序就可以独立运行,因为它内部所有的符号都有对应的二进制机器码。这种情况比较简单,我们这里主要讨论下面这种程序运行方式。

如果可执行文件要使用共享库,那么该程序就不能独立运行,它在运行时需要使用共享库的代码,且对应的两种使用方式,分别是运行时动态链接运行时动态加载

可执行文件的组成

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

 

ld-linux.so:不是一个可执行程序,只是一个 shell 脚本。作为解释器,写在 elf 文件(可执行文件)中,ld-linux.so 先于 main 函数工作,用于查找主程序所依赖的共享库,实际上可以直接执行 ld-linux.so. 还有另外一种比较常见的是 ld.so,它是个符号链接,指向 ld-linux.so.(通过命令 ln -s ld.so ld-linux.so 创建)。

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

 


详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

 

为什么这里使用解释器呢?

解释器的特点是动态特性和可移植性,比如在解释器执行时可以动态改变变量的类型、对程序进行修改以及在程序中插入良好的调试诊断信息等。而将解释器移植到不同的系统上,则程序不用改动就可以在移植了解释器的系统上运行。

同时解释器也有很大的缺点,比如执行效率低,占用空间大,因为不仅要给用户程序分配空间,解释器本身也占用了宝贵的系统资源。

动态链接和动态加载的区别

动态加载和动态链接都是在程序运行时发生,并将所需代码拷贝到内存这点很重要!

关键区别是:动态链接的流程是 OS 直接把共享库的代码拷贝到内存,而动态加载由人工指定(代码中的 dlopen() 接口)。

动态链接需要 OS 的特殊支持,通过动态链接方式拷贝到内存的库代码可以在各个进程之间共享。而对动态加载而言,可以在各自进程中打开共享库代码。

其他概念

ldconfig:这是个可执行程序,隶属于 GNU,作用是在默认搜寻目录(/lib和/usr/lib)以及共享库配置文件 /etc/ld.so.conf 内所列的目录下,搜索出共享库文件(lib*.so*),进而创建出 ld-linux.so 所需要的链接和缓存文件。缓存文件默认为 /etc/ld.so.cache,此文件保存已排好序的共享库名字列表。更新缓存使新添加的库生效,当然系统启动时会自动运行 ldconfig。

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

 

ldd:这是 Linux 内核中自带的脚本,可以用来查看可执行文件链接了哪些共享库

详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘

 

strip <可执行文件名> 去除符号表,可以给可执行文件瘦身

使用 objdump、readelf、nm 等命令可以查询目标文件的详细内容。

gcc -print-search-dirs 可以查看 gcc 在编译、链接过程中的共享库搜索路径。



Tags:gcc 编译   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
如何使用 gcc 构建 c/c++ 项目,大家都很熟悉了,甚至对链接器、静态库、共享库等概念,大家也略知一二。然而,对于 ld 链接器、Linux 操作系统(OS)及应用程序(exec)之间的详细交互流程...【详细内容】
2020-11-16  Tags: gcc 编译  点击:(123)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条