程序员自我修养-目标文件的结构

图片引用《程序员自我修养》一书中


下图是整个ELF的结构:

起始是ELF的头文件:

具体头文件内容见图2

                              

图1. ELF文件的结构

 

图2. ELF头文件内容<这个结构定义在Elf32_Ehdr或者是64的版本中>

在Elf头文件的一些属性解释:

e_entery :入口地址,如果是可重定向文件的话该值为0

e_shoff (start of section header):这个属性很重要,是段表的偏移

  e_shstrndx (section header string table index):段表字符串表的段在段表中的偏移位置


段表结构:


图3 每个段的信息

图4 段的属性



图5 段描述符
属性说明:
sh_name:  段名称,段名实际上是在字符串表中的 (.shstrtab)
sh_type:段属性 见书(p77)
sh_flag:段标志位,表示该段在进程虚拟空间中的属性,有SHF_WRITE(可写),SHF_ALLOC(在进程空间需要分配空间,有些指示或者控制的段不会有这个属性,但是代码段,数据段,.bss等都会有这个属性)
 SHF_EXECINSTR(可执行,一般指代码段)
sh_link,sh_info:段的链接信息具体见下图
6 链接信息
重定位表:
如果某个段的sh_type属性是SHT_REL,说明这个是一个重定位表,比如.rel.text 说明是针对.text段的重定位,.text段中至少有一个地方需要重定位,
如果.data中也有需要重定位的, 就会有.rel.data ,同时如果sh_type属性是SHT_REL的时候,sh_link表示符号表的下标,sh_info表示对那个段作用

字符串表和段表字符串表:
字符串表方的是普通的字符串, 所有符号表中的符号都是放在这里的,函数名变量名等等,在 符号表结构中有一个是st_name其实用到的是在字符串表中的下标
段表字符串表放的是段名字,最常见的是sh_name每个段的名称,它本身也是一个段,所以e_shstrndx说明的是段表字符串表这个段在段表中的下标


符号表:

每个函数和变量都有自己特有的名字,在连接中这些名字就是符号
每个符号对应一个符号值,如果是函数和变量的话,符号值就是它们的地址


图7 符号表的属性
属性介绍:
st_name:符号在字符串中的具体下标,所以函数名和全局标量,静态变量名的字符串都是在字符串表中
st_value:
1.在目标文件中,如果不是COMMON块,也即是sh_shndx符号所在段不为SHN_COMMON),st_value表示该符号在段中的偏移,最常见的是初始化好的全局变量符号和函数
2.在目标文件中,如果是COMMON块,表示对齐属性
3.如果是可执行文件,表示符号的虚拟地址,对于动态连接器很有用
     st_size:符号的大小,如果是int为4个字节,如果是double是8个字节,注意在变量名称修饰中没有把变量的类型属性放进去
其他属性见图8
8 符号表中字段属性

除了函数和标量外其他的符号:
1.定义在本目标文件中的全局符号,可以被其他目标文件应用,比如程序中的func,main和global变量
2.在本目标中引用的全局符号,但是这个符号没有定义在本目标文件中,比如print符号

3.段名也是一种符号(.text, .data不过这些符号是编译器产生的)
4.局部变量:比如static_var, static_var2这些符号对于链接的时候是没有用的
5.行号信息

这里最重要的时候第一和第二,因为链接过程只关心全局符号之间的协调。

下面是自己打印出来的符号表:
   readelf -s simplesection.c
   Symbol table '.symtab' contains 69 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
    26: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    27: 08049f14     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_LIST__
    28: 08049f1c     0 OBJECT  LOCAL  DEFAULT   18 __DTOR_LIST__
    29: 08049f24     0 OBJECT  LOCAL  DEFAULT   19 __JCR_LIST__
    30: 08048340     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux
    31: 0804a01c     1 OBJECT  LOCAL  DEFAULT   24 completed.7065
    32: 0804a020     4 OBJECT  LOCAL  DEFAULT   24 dtor_idx.7067
    33: 080483a0     0 FUNC    LOCAL  DEFAULT   13 frame_dummy
    34: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    35: 08049f18     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_END__
    36: 080484ec     0 OBJECT  LOCAL  DEFAULT   16 __FRAME_END__
    37: 08049f24     0 OBJECT  LOCAL  DEFAULT   19 __JCR_END__
    38: 08048490     0 FUNC    LOCAL  DEFAULT   13 __do_global_ctors_aux
    39: 00000000     0 FILE    LOCAL  DEFAULT  ABS simplesection.c
    40: 0804a018     4 OBJECT  LOCAL  DEFAULT   23 static_var.1254 //注意这个名字已经被修饰过了
    41: 0804a024     4 OBJECT  LOCAL  DEFAULT   24 static_var2.1255
    42: 08049ff4     0 OBJECT  LOCAL  DEFAULT   22 _GLOBAL_OFFSET_TABLE_
    43: 08049f14     0 NOTYPE  LOCAL  DEFAULT   17 __init_array_end
    44: 08049f14     0 NOTYPE  LOCAL  DEFAULT   17 __init_array_start
    45: 08049f28     0 OBJECT  LOCAL  DEFAULT   20 _DYNAMIC
    46: 0804a00c     0 NOTYPE  WEAK   DEFAULT   23 data_start
    47: 0804a014     4 OBJECT  GLOBAL DEFAULT   23 global_init_var   //因为这个应用的是本地目标文件中的全局函数,已经初始化23表示该符号所在段在段表中的偏移,应该在.data段中,而.data段的下标是23
    48: 08048420     5 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
    49: 08048310     0 FUNC    GLOBAL DEFAULT   13 _start 
    50: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    51: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    52: 080484d8     4 OBJECT  GLOBAL DEFAULT   15 _fp_hw
    53: 080484bc     0 FUNC    GLOBAL DEFAULT   14 _fini
    54: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
    55: 0804a028     4 OBJECT  GLOBAL DEFAULT   24 global_uninti_var  //因为这个应用的是本地目标文件中的全局函数,未初始化,24表示该符号所在段在段表中的偏移,应该在.bss段中,而.bss段的下标是24
    56: 080484dc     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used    57: 0804a00c     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
    58: 080483c4    27 FUNC    GLOBAL DEFAULT   13 func
    59: 0804a010     0 OBJECT  GLOBAL HIDDEN    23 __dso_handle
    60: 08049f20     0 OBJECT  GLOBAL HIDDEN    18 __DTOR_END__
    61: 08048430    90 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
    62: 00000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.0  //为定义的print函数
    63: 0804a01c     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    64: 0804a02c     0 NOTYPE  GLOBAL DEFAULT  ABS _end 
    65: 0804a01c     0 NOTYPE  GLOBAL DEFAULT  ABS _edata //数据段的结束
    66: 0804848a     0 FUNC    GLOBAL HIDDEN    13 __i686.get_pc_thunk.bx
    67: 080483df    54 FUNC    GLOBAL DEFAULT   13 main
    68: 08048294     0 FUNC    GLOBAL DEFAULT   11 _init




一些特殊的符号:
_start :程序的开始地址,不是入口函数,是最开始的地方
__bss_start:bss段开始的地方
data_start:数据段开始的地方
_edata :数据段结束的地方
这些符号可以再程序中直接使用 ,比如
   #include "stdio.h"
   extern char _start[];
   extern char data_start[];
   int main()
   {
       printf("start %X\n",_start);
       printf("data_start %X\n",data_start);
       return 0;
   }      

	





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值