Fork me on GitHub

[程序员的自我修养--链接、装载与库]笔记(三)

第三章 细探目标文件

目标文件的格式是什么

流行的可执行文件格式主要是win下的PE(Portable Executable) 和 Linux下的ELF(Executable Linkable Format),它们皆为COFF(Common file format)格式的变种
linux下的目标文件后缀为.o,终端中查看.o文件类型信息如下:
[root@slave02 temp]# file hello.o
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

均按照可执行文件格式存储 win下 linux下
可执行文件 .exe ELF
动态链接库 .dll .so
静态链接库 .lib .a



目标文件包含哪些内容

目标文件中的内容包括 编译后的机器指令代码、数据和供后续链接时所需要的一些信息,如符号表、调试信息、字符串等
目标文件内部分成不同的, 简单例子如下:


指令和数据分开存放的好处

  • 指令段设置为只读,数据段设置为可读写,提高安全性
  • 有利于提高cache缓存命中率
  • 当系统中运行多个该程序的副本时,只需保留一份指令段,当然,每个进程的数据段是私有的。有利于节省大量内存空间。

细探SimpleSection.o

在centos中编辑如下文件:

 //SimpleSection.c文件内容
#include <stdio.h>

int global_init_var = 84;
int global_unint_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

使用objdump命令或者readelf命令查看.o文件
objdump -h SimpleSection.o

SimpleSection.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000054  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  00000094  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000004  0000000000000000  0000000000000000  0000009c  2**2
                  ALLOC
  3 .rodata       00000004  0000000000000000  0000000000000000  0000009c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      0000002e  0000000000000000  0000000000000000  000000a0  2**0
                  CONTENTS, READONLY
  5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000ce  2**0
                  CONTENTS, READONLY
  6 .eh_frame     00000058  0000000000000000  0000000000000000  000000d0  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA


代码段

Contents of section .text:
 0000 554889e5 4883ec10 897dfc8b 45fc89c6  UH..H....}..E...
 0010 bf000000 00b80000 0000e800 000000c9  ................
 0020 c3554889 e54883ec 10c745fc 01000000  .UH..H....E.....
 0030 8b150000 00008b05 00000000 01c28b45  ...............E
 0040 fc01c28b 45f801d0 89c7e800 0000008b  ....E...........
 0050 45fcc9c3                             E...            

略去无关内容。。。

0000000000000000 :
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   89 7d fc                mov    %edi,-0x4(%rbp)
   b:   8b 45 fc                mov    -0x4(%rbp),%eax
   e:   89 c6                   mov    %eax,%esi
  10:   bf 00 00 00 00          mov    $0x0,%edi
  15:   b8 00 00 00 00          mov    $0x0,%eax
  1a:   e8 00 00 00 00          callq  1f 
  1f:   c9                      leaveq 
  20:   c3                      retq   

0000000000000021 
: 21: 55 push %rbp 22: 48 89 e5 mov %rsp,%rbp 25: 48 83 ec 10 sub $0x10,%rsp 29: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp) 30: 8b 15 00 00 00 00 mov 0x0(%rip),%edx # 36 36: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 3c 3c: 01 c2 add %eax,%edx 3e: 8b 45 fc mov -0x4(%rbp),%eax 41: 01 c2 add %eax,%edx 43: 8b 45 f8 mov -0x8(%rbp),%eax 46: 01 d0 add %edx,%eax 48: 89 c7 mov %eax,%edi 4a: e8 00 00 00 00 callq 4f 4f: 8b 45 fc mov -0x4(%rbp),%eax 52: c9 leaveq 53: c3 retq

数据段和只读数据段



.bbs段

其他段

自定义段

ELF文件结构描述

ELF文件头



[cmd] readelf -h SimpleSection.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:          1056 (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: 10

段表(Section Header Table)

它是除了文件头外最重要的结构,用于描述各个段的信息,比如:段名,段长,在文件中的位置偏移,读写权限和其它属性
[cmd] readelf -S SimpleSection.o

There are 13 section headers, starting at offset 0x420:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000054  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  00000378
       0000000000000078  0000000000000018   I      11     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000094
       0000000000000008  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  0000009c
       0000000000000004  0000000000000000  WA       0     0     4
  [ 5] .rodata           PROGBITS         0000000000000000  0000009c
       0000000000000004  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  000000a0
       000000000000002e  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000ce
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  000000d0
       0000000000000058  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  000003f0
       0000000000000030  0000000000000018   I      11     8     8
  [10] .shstrtab         STRTAB           0000000000000000  00000128
       0000000000000061  0000000000000000           0     0     1
  [11] .symtab           SYMTAB           0000000000000000  00000190
       0000000000000180  0000000000000018          12    11     8
  [12] .strtab           STRTAB           0000000000000000  00000310
       0000000000000065  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)



重定位表

字符串表


链接的Interface–符号

链接本质上就是将不同的目标文件”粘”到一起,

C++名称修饰机制实现函数重载

int func(int);
float func(float);

class C{
    int func(int);
    class C2{
       int func(int);
    };
};

namespace N{
    int func(int);
    class C{
       int func(int);
    };

}




值得注意的是,visual studio的名称修饰规则和上述规则不同,但目的都相同。

extern “C”


模板

模板
------ Happy Ending Meet The Better You ------