Linux程序编译过程详解

计算机程序设计语言通常分为机器语言、汇编语言和高级语言三类。高级语言需要通过翻译成机器语言才能执行,而翻译的方式分为两种,一种是编译型,另一种是解释型。


(资料图片)

因此我们基本上将高级语言分为两大类,一种是编译型语言,例如C,C++,Java,另一种是解释型语言,例如Python、Ruby、MATLAB 、JavaScript。

本文将介绍如何将高层的C/C++语言编写的程序转换成为处理器能够执行的二进制代码的过程,包括四个步骤:

GCC 工具链介绍

通常所说的GCC是GUN Compiler Collection的简称,是Linux系统上常用的编译工具。GCC工具链软件包括GCC、Binutils、C运行库等。

GCC

GCC(GNU C Compiler)是编译工具。本文所要介绍的将C/C++语言编写的程序转换成为处理器能够执行的二进制代码的过程即由编译器完成。

Binutils

一组二进制程序处理工具,包括:addr2line、ar、objcopy、objdump、as、ld、ldd、readelf、size等。这一组工具是开发和调试不可缺少的工具,分别简介如下:

C运行库

C语言标准主要由两部分组成:一部分描述C的语法,另一部分描述C标准库。C标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏定义,譬如常见的printf函数便是一个C标准库函数,其原型定义在stdio头文件中。

C语言标准仅仅定义了C标准库函数原型,并没有提供实现。因此,C语言编译器通常需要一个C运行时库(C Run Time Libray,CRT)的支持。C运行时库又常简称为C运行库。与C语言类似,C++也定义了自己的标准,同时提供相关支持库,称为C++运行时库。

准备工作

由于GCC工具链主要是在Linux环境中进行使用,因此本文也将以Linux系统作为工作环境。为了能够演示编译的整个过程,本节先准备一个C语言编写的简单Hello程序作为示例,其源代码如下所示:

编译过程

1.预处理

预处理的过程主要包括以下过程:

使用gcc进行预处理的命令如下:

hello.i文件可以作为普通文本文件打开进行查看,其代码片段如下所示:

2.编译

编译过程就是对预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。

使用gcc进行编译的命令如下:

$gcc-Shello.i-ohello.s//将预处理生成的hello.i文件编译生成汇编程序hello.s//GCC的选项-S使GCC在执行完编译后停止,生成汇编程序

上述命令生成的汇编程序hello.s的代码片段如下所示,其全部为汇编代码。

3.汇编

汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o的目标文件中。由于每一个汇编语句几乎都对应一条处理器指令,因此,汇编相对于编译过程比较简单,通过调用Binutils中的汇编器as根据汇编指令和处理器指令的对照表一一翻译即可。

当程序由多个源代码文件构成时,每个文件都要先完成汇编工作,生成.o目标文件后,才能进入下一步的链接工作。注意:目标文件已经是最终程序的某一部分了,但是在链接之前还不能执行。

使用gcc进行汇编的命令如下:

$gcc-chello.s-ohello.o//将编译生成的hello.s文件汇编生成目标文件hello.o//GCC的选项-c使GCC在执行完汇编后停止,生成目标文件//或者直接调用as进行汇编$as-chello.s-ohello.o//使用Binutils中的as将hello.s文件汇编生成目标文件

注意:hello.o目标文件为ELF(Executable and Linkable Format)格式的可重定向文件。

4.链接

链接也分为静态链接和动态链接,其要点如下:

由于链接动态库和静态库的路径可能有重合,所以如果在路径中有同名的静态库文件和动态库文件,比如libtest.a和libtest.so,gcc链接时默认优先选择动态库,会链接libtest.so,如果要让gcc选择链接libtest.a则可以指定gcc选项-static,该选项会强制使用静态库进行链接。以Hello World为例:

如果使用命令“gcc -static hello.c -o hello”则会使用静态库进行链接,生成的ELF可执行文件的大小(使用Binutils的size命令查看)和链接的动态库(使用Binutils的ldd命令查看)如下所示:

链接器链接后生成的最终文件为ELF格式可执行文件,一个ELF可执行文件通常被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss等段。

分析ELF文件

1.ELF文件的段

ELF文件格式如下图所示,位于ELF Header和Section Header Table之间的都是段(Section)。一个典型的ELF文件包含下面几个段:

可以使用readelf -S查看其各个section的信息如下:

2.反汇编ELF

由于ELF文件无法被当做普通文本文件打开,如果希望直接查看一个ELF文件包含的指令和数据,需要使用反汇编的方法。

使用objdump -D对其进行反汇编如下:

使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:

------------END------------

关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

关键词:

为您推荐

Linux程序编译过程详解

关注+星标公众号,不错过精彩内容作者| strongerHuang微信公众号| strongerHuang计算机程序设计语言通常分为机器语言、汇编语言和高级语言三

来源:面包芯语2023-04-14

全球观速讯丨IMF:预计亚洲地区今年对全球经济增长贡献率将超过70% 中国约为1/3

当地时间4月13日,国际货币基金组织(IMF)发布报告称,预计亚洲地区2023年对全球经济增长的贡献率将超过70%,中国经济将为地区经济增长提供新

来源:央视新闻客户端 -->2023-04-14

澳门“全民国家安全教育展”将于4月15日揭幕

中新社澳门4月12日电澳门特区政府新闻局12日发布消息称,2023年“全民国家安全教育展”定于4月15日“全民国家安全教育日”在澳门举行揭幕仪式

来源:中国新闻网2023-04-14

贵州省贵阳市2023-04-13 23:45发布冰雹橙色预警

一、贵州省贵阳市天气预报1、清镇市气象台2023年04月13日23时45分继续发布冰雹橙色预警信号。2、预计未来3小时,

来源:互联网2023-04-14

【环球快播报】至少36个未被描述新种,我国蛇类物种多样性被低估

中新网昆明4月13日电(记者胡远航)13日,中国科学院昆明动物研究所发布中国蛇类DNA条形码参考数据集。研究表明:中国蛇类物种多样性被低估,保

来源:中国新闻网 发布时间:2023/4/13 22:00:31
2023-04-13

长沙申请公积金贷款后多久可以办理提前部分还款?官方答疑

4月13日,长沙住房公积金管理中心发布3月热点问题月报,其中,“职工之前在异地缴存公积金,转移至长沙公积金中心继续缴存,

来源:华声在线2023-04-13

我国载人航天环控生保技术跻身世界先进水平 中国空间站氧气资源100%再生

新华社哈尔滨4月13日电记者从13日在哈尔滨召开的第三届全国载人航天环境控制与生命保障技术大会上了解到,我国载人航天环控生保系统已实现由“

来源:新华网2023-04-13

世界今亮点!新华保险:前3月原保险保费收入647.72亿元

新华保险4月13日公告,2023年1月1日至2023年3月31日期间累计原保险保费收入为6472亿元。

来源:互联网2023-04-13