目标文件是什么鬼?

     目标文件就是源代码编译后但未进行链接的那些中间文件。


COFF、ELF、PE又是什么?

COFF(Common file format)又称通用目标文件格式,是一种用于可执行文件、目标代码、共享库(shared library)的文件格式,使用于类UNIX系统上。它最早使用于UNIX System V上,用来取代先前的a.out格式,后来又发展出XCOFF与ECOFF。COFF最主要的贡献是引入了“段”的机制,不通的目标文件可以拥有不同数量及不同类型的“段”


ELF (Executable and Linkable Format)可执行与可链接格式 常被称为ELF格式,在计算机科学中,是一种用于可执行文件、目标文件、共享库和核心转储的标准文件格式。COFF变种  LINUX使用ELF


PE (Portable Execuable)可移植性可执行文件是一种用于可执行文件、目标文件和动态链接库的文件格式,主要使用在32位和64位的Windows操作系统上。COFF变种   WINDOWS使用


目标文件格式


ELF文件类型说明实例
可重定位文件(Relocatable File)

这类文件包含了代码和数据,可以被用来
链接成可执行文件或共享目标文件,静态
链接库也可以归为这一类

Linux的.o

windows的.obj

可执行文件(Executable File)

这类文件包含了可以直接执行的程序,它
的代表就是ELF可执行文件,它们一般都
没有扩展名

如:Liunx /bin/bash

windows .exe 

共享目标文件(Shared Object File)

1、首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理, 生成另外一个目标文件。

2、其次动态链接器(Dynamic Linker)可能将它与某 个可执行文件以及其它共享目标一起组合,创建进程映像。

如:Linuxx下的.so

widnows的DLL

核心转存文件(Code Dump File)

当进程意外终止时,系统可以将该进程的
地址空间的内容及终止时的一些其他信息
转储到核心转储文件

Linux下的core dump


Linux下查看文件格式

重定位文件

[root@localhost ~]# file /usr/lib64/crt1.o
/usr/lib64/crt1.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), for GNU/Linux 2.6.32, not stripped


可执行文件

[root@localhost ~]# file /bin/bash
/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared lib       s), for GNU/Linux 2.6.32, BuildID[sha1]=9223530b1aa05d3dbea7e72738b28b1e9d82fbad, stripped



目标共享文件

[root@localhost ~]# file /lib/ld-2.17.so
/lib/ld-2.17.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=33446bb2067122aef759b21f15245840c26afa0a, not stripped



目标文件样子

image

     上面少的.bss Section,未初始化的全局变量和局部变量一般放在.bss中,未初始化的变量默认值为0,实际上可以放在data段中,但是没啥意义还需要占用些内存。BSS中只是给变量预留位置并不占用内存

      总体来说,程序源代码编译以后主要分成两个段,程序指令和程序数据。代码段属于程序指令,而数据段和.BSS都属于程序数据


实战分析

  实验代码:

  1 int printf( const char* format, ... );
  2 
  3 int global_init_var = 84;
  4 int global_uninit_var;
  5 
  6 void func1( int i ) {
  7     printf( "%d\n", i );
  8 }
  9 
 10 int main( void ) {
 11     static int static_var = 85;
 12     static int static_var2;
 13     int a = 1;
 14     int b;
 15     func1( static_var + static_var2 + a + b );
 16     return a;
 17 }
View Code

生成目标文件

[root@localhost ~]# gcc -c test1.c


查看目标文件结构和内容(-x选项输出更多内容)

[root@localhost ~]# objdump -h test1.o

image

补充其它段信息:

.rodata 只读数据段

.comment 注释信息段

.note.GNU-stack 堆栈提示段


段格式

Size  段的长度

File off 段所在位置

CONTENTS  表示该段在文件中存在

ALLOC  表示段的各种属性


查看ELF代码段、数据段、BSS段(dec表示三个段长度和的十进制,hex表示三个段长度和的十六进制)

[root@localhost ~]# size test1.o
    text    data     bss     dec     hex filename
     176       8       4     188      bc test1.o

  


[root@localhost ~]# objdump -s -d test1.o

执行结果
  1 test1.o:     file format elf64-x86-64
  2 
  3 Contents of section .text:
  4  0000 554889e5 4883ec10 897dfc8b 45fc89c6  UH..H....}..E...
  5  0010 bf000000 00b80000 0000e800 000000c9  ................
  6  0020 c3554889 e54883ec 10c745fc 01000000  .UH..H....E.....
  7  0030 8b150000 00008b05 00000000 01c28b45  ...............E
  8  0040 fc01c28b 45f801d0 89c7e800 0000008b  ....E...........
  9  0050 45fcc9c3                             E...
 10 Contents of section .data:
 11  0000 54000000 55000000                    T...U...
 12 Contents of section .rodata:
 13  0000 25640a00                             %d..
 14 Contents of section .comment:
 15  0000 00474343 3a202847 4e552920 342e382e  .GCC: (GNU) 4.8.
 16  0010 35203230 31353036 32332028 52656420  5 20150623 (Red
 17  0020 48617420 342e382e 352d3336 2900      Hat 4.8.5-36).
 18 Contents of section .eh_frame:
 19  0000 14000000 00000000 017a5200 01781001  .........zR..x..
 20  0010 1b0c0708 90010000 1c000000 1c000000  ................
 21  0020 00000000 21000000 00410e10 8602430d  ....!....A....C.
 22  0030 065c0c07 08000000 1c000000 3c000000  .\..........<...
 23  0040 00000000 33000000 00410e10 8602430d  ....3....A....C.
 24  0050 066e0c07 08000000                    .n......
 25 
 26 Disassembly of section .text:
 27 
 28 0000000000000000 <func1>:
 29    0:   55                      push   %rbp
 30    1:   48 89 e5                mov    %rsp,%rbp
 31    4:   48 83 ec 10             sub    $0x10,%rsp
 32    8:   89 7d fc                mov    %edi,-0x4(%rbp)
 33    b:   8b 45 fc                mov    -0x4(%rbp),%eax
 34    e:   89 c6                   mov    %eax,%esi
 35   10:   bf 00 00 00 00          mov    $0x0,%edi
 36   15:   b8 00 00 00 00          mov    $0x0,%eax
 37   1a:   e8 00 00 00 00          callq  1f <func1+0x1f>
 38   1f:   c9                      leaveq
 39   20:   c3                      retq
 40 
 41 0000000000000021 <main>:
 42   21:   55                      push   %rbp
 43   22:   48 89 e5                mov    %rsp,%rbp
 44   25:   48 83 ec 10             sub    $0x10,%rsp
 45   29:   c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)
 46   30:   8b 15 00 00 00 00       mov    0x0(%rip),%edx        # 36 <main+0x15>
 47   36:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 3c <main+0x1b>
 48   3c:   01 c2                   add    %eax,%edx
 49   3e:   8b 45 fc                mov    -0x4(%rbp),%eax
 50   41:   01 c2                   add    %eax,%edx
 51   43:   8b 45 f8                mov    -0x8(%rbp),%eax
 52   46:   01 d0                   add    %edx,%eax
 53   48:   89 c7                   mov    %eax,%edi
 54   4a:   e8 00 00 00 00          callq  4f <main+0x2e>
 55   4f:   8b 45 fc                mov    -0x4(%rbp),%eax
 56   52:   c9                      leaveq
 57   53:   c3                      retq

-s 以十六进制显示

-d 反汇编包含所有指令的段

大致说下结果:

最左面一侧是偏移量,中间4列是十六进制内容,最后右面一列是text段的ASCII码,


data段(初始化全局和局部变量)

Contents of section .data:
  0000 54000000 55000000                    T...U...

54000000对应是84,55000000 对应的是85

int global_init_var = 84;

static int static_var = 85;


bss段(未初始化全局变量和局部变量)

.bss          00000004  0000000000000000  0000000000000000  0000009c  2**2

00000004=4字节  代码global_uninit_var; static int static_var2; 前面4个字节但是这里有2个变量,显然有问题。实际在.bss段中只有static_var2。查看 SYMBOL TABLE  发现global_uninit_var没有存在任何地方 只是一个*COM*符号,这其实跟不同的语言与不同编译器有关系,有些编译器会将未初始化全局变量放在.bss中


详细查看ELF文件头

[root@localhost ~]# readelf -h test1.o
ELF Header:
   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
   Class:                             ELF64
   Data:                              2's complement, little endian
   Version:                           1 (current)
   OS/ABI:                            UNIX - System V
   ABI Version:                       0
   Type:                              REL (Relocatable file)
   Machine:                           Advanced Micro Devices X86-64
   Version:                           0x1
   Entry point address:               0x0
   Start of program headers:          0 (bytes into file)
   Start of section headers:          1048 (bytes into file)
   Flags:                             0x0
   Size of this header:               64 (bytes)
   Size of program headers:           0 (bytes)
   Number of program headers:         0
   Size of section headers:           64 (bytes)
   Number of section headers:         13
   Section header string table index: 12





posted @ 2019-09-11 20:15  MKY-门可意  阅读(2191)  评论(0编辑  收藏  举报