[OS] 目标文件的结构

1. 文件格式:

现在PC平台流行的可执行文件格式,主要是Windows下的PE(Portable Executable)和Linux的ELF(Executable Linkable Format),它们都是COFF(Common file format)格式的变种。

目标文件就是源代码编译后但未进行链接的那些中间文件(Windows的.obj和Linux的.o),它跟可执行文件的内容与结构很相似,所以一般跟可执行文件格式采用一种格式存储。

动态链接库(Windows的.dll和Linux的.so)及静态链接库(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。

2. 文件内容:

目标文件中的内容包含编译后的机器指令代码,数据。还包括了链接时所需要的一些信息,比如符号表,调试信息,字符串等。
目标文件将这些信息按不同的属性,以“节(Section)”的形式存储,有时候也叫做“段(Segment)”,它们表示一个一定长度的区域。

(1)代码段(.text)
程序源代码编译后的机器指令

(2)数据段(.data)
已初始化了的全局变量和局部静态变量数据

(3).bss段(.bss)
未初始化的全局变量和局部静态变量

注:
未初始化的全局变量和局部静态变量默认值都为0,本来也可以被放在.data段,但是在目标文件中为它们分配空间是没有必要的。因此,统一放到.bss段,.bss段大小为0,不出现在目标文件中。而变量名以及变量的大小,与其他变量一样,放在了符号表(.symtab段)中。

(4)其他段
除了.text,.data,.bss这3个最常用的段之外,目标文件也有可能包含其他的段,用来保存与程序相关的其他信息。

例如:.symtab符号表,.debug调试信息,.dynamic动态链接信息,等等。

3. 详细分析:

(1)用GCC编译SimpleScriont.c得到了目标文件SimpleSection.o

$ gcc -c SimpleSection.c

(2)使用binutils的工具objdump来查看目标文件内部结构,-h显示各个段的基本信息

$ objdump -h SimpleSection.o

其中,Size表示段的长度,File off(File Offset)表示段所在的位置,
每个段第二行表示段的属性,例如,CONTENTS表示该段在文件中存在。
根据偏移地址我们就可以画出文件结构了。


我们看到,.bss段和.note.GNU-stack段在文件中都不存在。

(3)查看代码段

$ objdump -s -d SimpleSection.o

其中,
-s用于将所有段的内容以16进制的方式打印出来,
-d用于将所有包含指令的段反汇编。

段数据:


最左边一列是偏移量,中间4列是16进制内容,最右边一列是.text段的ASCII码形式。

反汇编结果:


对照反汇编结果,可以看到.text段里包含的正是SimpleSection.c里两个函数func1()和main()的机器指令。

(4)查看数据段


我们看到54000000(0x00000054)正好是全局变量global_init_var的值84,
55000000(0x00000055)正好是局部静态变量static_var的值85。

注:
.rodata段存放的是只读数据,一般是程序里面的只读变量和字符串常量。

(5).bss段
虽然在段的基本信息里,.bss段的大小为4字节,但是.bss段的数据为空,因此不占用目标文件的空间。

.bss段基本信息:


注:
程序中,未初始化的全局变量global_uninit_var和局部静态变量static_var2共占8字节空间,可是.bss段的大小只有4字节大小。原因是,有些编译器会将全局未初始化的变量放到.bss段,有些则不然,只是预留一个未定义的全局变量符号。因此,这里的4字节,指的是static_var2。

4. 符号表

链接的本质,就是把不同的多个目标文件粘合到一起。
每个函数或变量都必须有自己独特的名字,才能避免在链接过程中产生混乱。
在链接中,函数和符号统称为符号(Symbol),函数名或变量名称为符号名(Symbol Name)

每个目标文件都有一个相应的符号表(Symbol Table),记录了目标文件中用到的所有符号。每个符号都有一个对应的值,叫做符号值(Symbol Value),符号值可以是符号所对应的数据在段中的偏移量,也可以是该符号的对齐属性。

符号表保存在.symtab段中,信息如下:


第1列Num表示符号表数组的下标,第2列Value就是符号值,第3列Size为符号大小,第4列第5列分别为符号类型和绑定信息,第6列暂时忽略它,第7列Ndx表示该符号所属的段,最后一列,符号名称。

我们看到func和main的Ndx为1,表示代码段,因为.text在段表中的下标为1。

其中,段表信息如下:


printf这个符号,Ndx为UND(SHN_UNDEF),没有在SimpleSection.c中定义,是被引用的。

global_init_var是已初始化的全局变量,Ndx是3,定义在.data段,偏移量为0
static_var.1553是已初始化的局部静态变量,Ndx是3,定义在.data段,偏移量为4

global_uninit_var是未初始化的全局变量,Ndx是COM(SHN_COMMON)本身并没有在.bss段中。
static_var2.1534是未初始化的局部静态变量,Ndx是4,定义在.bss段,偏移量为0

对于类型为STT_SECTION的符号,名称并没有显示,它们是Ndx所示段的段名

SimpleSection.c这个符号表示编译单元的源文件名。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容