操作系统:CentOS Linux release 7.7.1908

内核版本:3.10.0-1062.1.1.el7.x86_64

运行平台:x86_64

为了在64位的操作系统中编译32位的应用程序,可能须要安装以下动态库:

$ sudo yum install glibc.i686
$ sudo yum install glibc-devel.i686
$ sudo yum install libgcc.i686

C/C++程序的编译过程大致分为编译、汇编和链接等三个过程。执行gcc命令编译源文件tanglinux.c如下所示:

$ gcc --verbose -m32 tanglinux.c -o tanglinux

其中,-m32表示编译32位的应用程序,--verbose(也就是-v)表示显示编译时的详细过程。

源文件tanglinux.c的代码如下所示:

int main()
{return 0;
}

编译的详细过程如下所示:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
COLLECT_GCC_OPTIONS='-v' '-m32' '-o' 'tanglinux' '-mtune=generic' '-march=x86-64'/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/cc1 -quiet -v -imultilib 32 tanglinux.c -quiet -dumpbase tanglinux.c -m32 -mtune=generic -march=x86-64 -auxbase tanglinux -version -o /tmp/cc04RaVm.s
GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-39) (x86_64-redhat-linux)compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-39), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/usr/local/include/usr/include
End of search list.
GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-39) (x86_64-redhat-linux)compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-39), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: edd9a53947039836c859e437e8c9af72
COLLECT_GCC_OPTIONS='-v' '-m32' '-o' 'tanglinux' '-mtune=generic' '-march=x86-64'as -v --32 -o /tmp/ccACvBBI.o /tmp/cc04RaVm.s
GNU assembler version 2.27 (x86_64-redhat-linux) using BFD version version 2.27-41.base.el7
COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/32/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-m32' '-o' 'tanglinux' '-mtune=generic' '-march=x86-64'/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o tanglinux /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/32/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/32 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. /tmp/ccACvBBI.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/32/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib/crtn.o

其中,程序lto-wrapper只是lto1程序的封装,用于实现Link-Time Optimization(LTO)功能,即链接时优化。详情可参考网址https://gcc.gnu.org/wiki/LinkTimeOptimization。

从以“Configured with:”开头的行可查看所使用的gcc自身编译时所使用的选项。

编译C语言程序的cc1和编译C++语言程序的cc1plus都需要GMP(The GNU Multiple Precision Arithmetic Library)、MPFR和MPC等三个库的支持。MPC基于MPFR,而MPFR又基于GMP。GMP是针对有符号整数、有理数和浮点数的高精度的运算库。而MPFR只针对浮点数并且能正确舍入,MPC针对复数。

GGC (the GCC Garbage Collector),即垃圾收集器插件,用于管理gcc自身的内存分配。ggc-min-expand选项为ggc所使用的堆内存的最小扩展百分比,ggc-min-heapsize选项为ggc所使用的堆内存的最小字节数(单位为KiB)。

从编译的过程信息中,也能看出头文件和依赖库所查询的目录。

去除不必要的过程信息后,程序编译的三个过程其实是如下所示:

cc1 -quiet -v -imultilib 32 tanglinux.c -quiet -dumpbase tanglinux.c -m32 -mtune=generic -march=x86-64 -auxbase tanglinux -version -o cc04RaVm.s
as -v --32 -o ccACvBBI.o cc04RaVm.s
collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_i386 -dynamic-linker ld-linux.so.2 -o tanglinux crt1.o crti.o crtbegin.o ccACvBBI.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed crtend.o crtn.o

其中,C语言程序实质的编译程序为cc1;链接程序为collect2,它会调用实质的链接程序ld。cc1和collect2属于GCC项目,而as和ld属于GNU的Binutils项目。

编译选项-quiet表示不显示编译过程;选项-imultilib将所指定的值作为搜索的子目录;选项-dumpbase表示设置用于转储的文件基名,选项-auxbase也是将后面所列的值作为某种用途的文件的基本名;选项-m32表示生成32位的i386平台的代码;选项-march和-mtune用于指定硬件平台。

汇编选项--32表示使用i386体系结构。

链接选项--build-id表示为ELF文件创建名称为“.note.gnu.build-id”的note section,其主要内容为使用SHA1散列算法计算所得的20个字节的ID号;选项--no-add-needed被--no-copy-dt-needed-entries替代,表示不拷贝命令行中所列动态库中的DT_NEEDED表项;选项--as-needed使最终所生成的可执行文件中的动态链接表.dynamic的DT_NEEDED表项只记录真正用到的动态库(选择范围为命令行中位于该选项之后的动态库),选项--no-as-needed则恢复默认行为;选项--eh-frame-hdr表示创建名为.eh_frame_hdr的section以及名为PT_GNU_EH_FRAME的segment header;选项--hash-style的值为gnu时表示创建名为.gnu.hash的section;选项-m表示生成elf_i386格式的可执行文件;选项--dynamic-linker表示可执行文件将要使用的动态链接器,记录在可执行文件的.interp section中;最后还链接了crt1.o、crti.o、crtbegin.o、crtend.o和crtn.o等五个目标文件。

执行以下命令可以查看collect2的版本及其实质所使用的链接程序ld的版本:

$ /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --version
collect2 version 4.8.5 20150623 (Red Hat 4.8.5-39)
/usr/bin/ld --version
GNU ld version 2.27-41.base.el7
Copyright (C) 2016 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

然而,实际上/usr/bin/ld还不是最终的链接程序,它只是一个符号链接文件,链接到/etc/alternatives/ld文件,而后/etc/alternatives/ld又链接到/usr/bin/ld.bfd文件,这个ld.bfd文件才是真正的链接程序。

$ file /usr/bin/ld
/usr/bin/ld: symbolic link to `/etc/alternatives/ld'$ file /etc/alternatives/ld
/etc/alternatives/ld: symbolic link to `/usr/bin/ld.bfd'

程序的本质之一程序编译的详细过程相关推荐

  1. 语音识别:安装编译Kaldi详细过程及遇到的一些问题汇总

    语音识别-Kaldi的安装编译实录(Ubuntu环境) 本篇博客用于记录一次用开源语音识别(ASR)工具Kaldi来实现中文语音识别功能的经历,记录一路遇到的一些问题.希望本篇文章可以给广大有需要的人 ...

  2. Centos下lnmp编译安装详细过程

    整理下lnmp安装步骤: 相关软件用的lnmp一键安装的全包,懒得去到处找软件源 完整版:http://soft.vpser.net/lnmp/lnmp0.7-full.tar.gz(66.64MB) ...

  3. 程序的本质之二ELF文件的文件头、section header和program header

    操作系统:CentOS Linux release 7.7.1908 内核版本:3.10.0-1062.1.1.el7.x86_64 运行平台:x86_64 参考文献:http://refspecs. ...

  4. 全连接层的输入和输出_理解Web应用程序的本质,网络数据流处理与基础网络连接...

    前言 前面一篇文章,我从整个应用程序的整体以及跟运行环境的关系简单聊了一下我们现在常用的Spring框架的设计基础和原则,其中主要是控制反转和依赖注入,以及容器化编程等概念. 这里我不想去复述这些概念 ...

  5. 使用天乐软件加密狗(JDProtect)保护您的软件,防止程序被跟踪/逆向/反编译/破解

    作者:庄晓立(liigo) 日期:2011-4-8 原创链接:http://blog.csdn.net/liigo/archive/2011/04/08/6310677.aspx 转换请注明出处:ht ...

  6. 使用天乐软件加密狗(JDProtect)保护您的软件,防止程序被跟踪/逆向/反编译/破解...

    作者:庄晓立(liigo) 日期:2011-4-8 原创链接:http://blog.csdn.net/liigo/archive/2011/04/08/6310677.aspx 转换请注明出处:ht ...

  7. c51单片机秒表程序c语言,利用51单片机制作秒表的详细过程

    前面的话: 和很多朋友一样,在学51单片机的过程中我们肯定会涉及到制作一个秒表,牵涉到把单片机的多个部分组合起来使用,这对于我们初学者来说可能显得有些困难,我同大家一样,百思不得其解,最后头都弄大了才 ...

  8. 微信小程序是如何实现快速编译的?

    过往中小企业或技术团队开发一个 App 的时间成本和人力成本居高难下,但是随着微信上线小程序,更像是为这部分群体打开了一扇天窗,此后小程序呈现出井喷式发展的状态,不仅微信,支付宝.百度.抖音等超级 A ...

  9. 搬砖:程序中的局部变量是编译时候分配地址的还是运行时分配的呢

    太无耻了吧,都没给别人分,,,, 程序中的局部变量是编译时候分配地址的还是运行时分配的呢? [问题点数:40分] https://bbs.csdn.net/topics/350012472 boref ...

  10. 程序的编译和链接过程

    一.虚拟机.linux简介 简单介绍一下虚拟机还有就是各种操作系统,比如centos,Ubuntu 操作系统:linux(centos.Ubuntu.redhat),Android,Windows(x ...

最新文章

  1. tcpip测试工具软件,TCP Test Tool(TCP测试工具) V2.3 官方版
  2. 子对象是什么java_面向对象编程(什么是对象)——java
  3. 北邮国院c语言期末考试题,北邮C语言复习题2014.ppt
  4. 采用opencv_cascadetrain进行训练的步骤及注意事项
  5. springboot aop使用_Spring Boot 的自动配置,是如何实现的?
  6. mysql error 1231_解决ERROR 1231 (42000): Variable 'time_zone' can't
  7. 算法---字符串顺序平移
  8. axis2 json_带有Java和Axis2的JSON Web服务
  9. base64、File、Blob、ArrayBuffer互转
  10. 有哪些好用的word文件对比工具
  11. 用计算机绘制滴定曲线,利用Excel系统绘制酸碱滴定曲线
  12. vue - vue项目使用BOS (百度云对象存储)上传文件
  13. 最后1天,购票渠道即将关闭!Unite 2018开发者大会全日程公布
  14. 人工智能之我见(1)
  15. 你们知道官网购买服务器可以返佣吗
  16. matlab去除红眼代码及详细介绍
  17. macbook自带python保存文件夹_在mac下查找python包存放路径site-packages的实现方法 在Mac系统下python如何安装第三方函数库?...
  18. 压力测试-Jmeter脚本录制方案
  19. 修改Element-ui表格样式
  20. CVPR 2022 | 涨点显著!AMD提出:动态Sparse R-CNN

热门文章

  1. 自动化运维工具——Ansible
  2. Smart210学习记录-------内存初始化
  3. CNN-VGG16图片性别年龄识别(说白了就是图片分类)
  4. 傅里叶变换复数形式的实部代表什么_复数形式傅里叶变换的物理意义中,相位究竟指的是什么?...
  5. java 运行不出来的原因_小议Java程序不能运行的几种原因
  6. 每周一喂丨图说WiFi安全
  7. 利用Jupyter Notebook进行科学计算和数据分析
  8. Python画四张子图-导入数据
  9. python压缩文件夹为zip_python压缩文件夹内所有文件为zip文件的方法
  10. 脚本小子_python正则表达式