文章目录

  • SimpleSection.o 的结构
    • 代码段 .text
    • 数据段 .data和只读数据段 .rodata
    • .bss段
    • 其他段

今天来了解一下在编译过程中所产生的的目标文件的具体结构。(Ubuntu-20.04 64位虚拟机)

采用的源文件 SimpleSection.c 为:

int printf(const char* format,...);int global_init_var = 84;
int global_uninit_var;void func1(int i)
{printf("%d\n",i);
}int main(void)
{static int static_var = 85;static int static_var2;int a=1;int b;func1(static_var + static_var2 + a + b);return a;
}

采用命令: gcc -c SimpleSection.c 编译之后得到目标文件 SimpleSection.o 。下面就在这个目标文件上来分析。

SimpleSection.o 的结构

使用 binutils 的工具 objdump 来查看目标文件的结构,运行命令:objdump -h SimpleSection.o 将目标文件各个段的基本信息打印出来:


       关于段的几个重要属性:Size 表示段的长度,File off 表示段的位置,每个段的第2行中的 “CONTENTS” 表示该段在文件中存在。在 bss 段中没有 “CONTENTS” ,表示该段在目标文件中不存在。.note.GNU-stack 堆栈段的长度为0,在这里忽略掉它,认为它也不存在。

用 size 命令可以查看 ELF 文件的代码段、数据段和 bss 段的长度(dec 表示3个段长度的和的十进制,hex表示长度和的十六进制) 如下图。

为什么 size 和 objdump 查看目标文件的 .text 段的大小不一样呢?
      因为size默认是运行在"Berkeley compatibility mode"下。在这种模式下,会将不可执行的拥有"ALLOC"属性的只读段归到.text段下,很典型的就是.rodata段。而在我们这个例子中,使用 size 命令得到的 text 段长度 = .text + .rodata + .note.gnu.property + .eh_frame 。如果你使用"size -A obj.o",那么size会运行在"System V compatibility mode",此时,用objdump -h和size显示的.text段大小就差不多了,如下图。

代码段 .text

程序源代码编译之后的机器指令经常被放在代码段中。通过使用 -s -d 参数的 objdump 命令将所有段以十六进制的形式打印出来(-s),并将所有包含指令的段反汇编(-d)。如下:


      以及反汇编之后的代码段内容:


      Contents of section .text 就是将 .text 的数据以十六进制方式打印出来,总共 0x5f 字节,与前面我们得到的 .text 段长度相符合,最左边一列表示偏移量,中间四列为十六进制内容,最右边一列是 .text 的ASDII 码形式。对照下面的反汇编结果,可以得到,.text 段中包含的正是SimpleSection.c 中两个函数 func1() 和 main() 的指令。其中 func1() 函数在前,main() 在后。

数据段 .data和只读数据段 .rodata

.data 段保存的是那些已经初始化了的全局静态变量和局部静态变量。在我们这个例子 SimpleSection.c 中,global_init_var 和 static_var 是已经初始化过的,每个变量 4 个字节,一共 8 个字节被存储到 .data 段中。在这里采用小端法来存储,.data 段中前四个字节为 5400 0000 ,转换为十进制为 84;后四个字节为 5500 0000 ,转换为十进制为 85。分别与这两个变量的值一一对应。

.rodata 段中存放的是只读数据,一般是程序中的只读变量(如 const 修饰的变量)和字符串常量。在 SimpleSection.c 中调用 printf 时,用到了一个字符串常量 “%d\n”,它是一种只读数据,被存储到 .rodata 段中。.rodata 段中的四个字节 2564 0a00 分别对应的是字符 ‘%’、‘d’、’\n’ 和 ‘\0’ 。

有时候编译器也会将字符串常量放在 .data 段中。

.bss段

.bss 段中存放的是未初始化的全局变量和局部静态变量,在上述代码中,global_uninit_var 和 static_var2 是未被初始化过的,它们被存放在 .bss 段中,更准确的来讲,是在 .bss 段为它们预留空间。可以认为未初始化过的变量值为0,而存储 0 是没有必要的。.bss 段没有实际内容,所以它在可执行文件中也不占据空间。

上面得到的 .bss 段大小为 4 个字节,与变量 global_uninit_var 和 static_var2 的大小之和 8 个字节不符。实际上通过符号表(Symbol Table)能够看到,只有 static_var2 被放在了 .bss 段中,而 global_uninit_var 未被放在任何段,只是一个未定义的 “COMMON 符号”。这和不同的语言不同的编译器有关,有的编译器会将 全局未初始化变量 存放在目标文件 .bss 段中,有些则不存放,只是预留一个 未定义的全局变量符号,等到最终链接为可执行文件时再在 .bss 段中分配空间。原则上来讲,可以简单的认为全局未初始化变量被存放在 .bss 段中。但是未初始化的静态变量(编译单元内部可见)的确是存放在 .bss 段中的。

其他段

.comment 段中存放的是编译器版本信息。.其余两个段 .note.gnu.property 和 .eh_frame 在此不做说明。

目标文件(.o)结构的简单了解相关推荐

  1. 程序员的自我修养--链接、装载与库笔记:目标文件里有什么

    编译器编译源代码后生成的文件叫做目标文件.目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有被调整.其实它本身就是按照可执行文件格式存储的, ...

  2. 教程:12、文件存储结构

    大部分的Linux文件系统(如ext2.ext3)规定,一个文件由目录项.inode和数据块组成: 目录项:包括文件名和inode节点号. Inode:又称文件索引节点,包含文件的基础信息以及数据块的 ...

  3. Linux文件存储结构,包括目录项、inode、数据块

    2019独角兽企业重金招聘Python工程师标准>>> 先说inode 理解inode,要从文件储存说起.文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sec ...

  4. 目标文件里面到底有什么(1)?

    目标文件是指:编译器编译源代码后生成的文件,那么目标文件里面到底存放的是什么呢?或者说我们的源代码在经过编译以后是怎么样存储的呢? 目标文件从结构上将,它是已经编译后的可执行文件格式,只是好没有经过链 ...

  5. 使用 ld 命令链接目标文件生成可执行文件

    1.目标文件生链接成可执行文件依赖的库和目标文件 使用 ld 链接目标文件生成可执行文件,用于取代命令 g++,仅仅用于学习 ld 命令的使用,不用于实际的项目编译. 首先看一个简单的 C++ 源文件 ...

  6. 《程序员的自我修养-链接-装载与库》第三章 目标文件里有什么(1)

    目录 0.引言 1.目标文件的格式 1.1 目标文件的格式及ELF文件格式的文件的分类 1.2 目标文件与可执行文件格式的小历史 2.目标文件是什么样的 2.1 程序与目标文件简介 2.2 BSS历史 ...

  7. 《程序员的自我修养》第3章---目标文件里有什么

    第3章 目标文件里有什么 3.1 目标文件的格式: 编译器编译源代码后生成的文件叫做 "目标文件". 目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程, ...

  8. 关于可重定位目标文件的格式与其符号表的概述

            我们知道一个可执行的C程序要经过语言预处理.编译器.汇编器生成扩展名为.o的可重定位目标文件,再通过链接器链接生成可执行的目标文件. 1.什么是可重定位目标文件        一个扩展 ...

  9. 程序员的自我修养三目标文件里有什么

    编译器编译源代码后生成的文件叫做目标文件. 目标文件从结构上讲,它是已经编译后的可执行文件格式,只是没有经过链接的过程. 3.1目标文件的格式 现在PC平台流行的是可执行文件格式,主要是win下的PE ...

最新文章

  1. 15 年腾讯老兵谈技术人成长之路
  2. 腾讯云服务器搭建WampServer环境
  3. Python学习笔记系列——函数
  4. 读书笔记 - 《重新定义公司:谷歌是如何运营的》
  5. 计算机c语言二级题型,计算机二级C语言题型和评分标准
  6. 分类树/装袋法/随机森林算法的R语言实现
  7. linux怎么看文件状态,linux查看文件类型-file、状态-stat
  8. [计算机网络][总结][常见问题][TCP][三次握手][四次挥手]
  9. 安装Was liberty之步骤
  10. 为 Office 2007/2010 安装程序整合 Service Pack 及更新程序
  11. WebService的应用之winform身份验证
  12. 计算机中键盘可以共享吗,步骤详解什么是双模键盘(两台电脑共用一套鼠标键盘)...
  13. 看英语数据手册很难?5步帮你搞定!
  14. 如何把PDF转成护眼模式/反色/黑底白字
  15. 本地连接测试mysql失败,提示 flush hosts;
  16. 杭电18年计算机考研人数,2018杭州电子科技大学考研报考统计
  17. 学生家乡网页设计作品静态HTML网页模板源码 广西旅游景点网页设计 大学生家乡主题网站制作 简单家乡介绍网页设计成品
  18. STM32F429 13. SPI 通讯(code)
  19. linux服务器filesystem,linux mount报错:you must specify the filesystem type的解决方法
  20. linux分区格式化命令

热门文章

  1. 编译原理实验(算符优先文法)
  2. dwr消息推送和tomcat集群
  3. css js 兼容问题
  4. 关于错误 openssl/ssl.h:没有那个文件或目录的解决办法
  5. jee websocket搭建总结
  6. 数据挖掘(10):卷积神经网络算法的一个实现
  7. java类Timer和TimerTask的使用
  8. pgsql 两个时间字段相减_如何在Excel做专业的时间序列分析
  9. UVA11427玩纸牌(全概率+递推)
  10. hdu4771 水搜索(状态压缩+bfs)