程序员自我修养3:目标文件

一、相同的文件格式:ELF

  • 目标文件:代码编译后未链接的文件(Linux的.o)
  • 可执行文件
  • 静态链接库(Linux的.a)
  • 动态链接库(Linux的.so)

二、ELF文件的结构

示例代码:simple.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;
}

为什么要将程序的指令和数据进行分段呢?

  • 当程序被装载后,数据和指令被映射到两个不同的虚存区域。数据区域对进程是可写可读的,而指令区只是可读的,这样就避免了进程修改指令带来的问题。
  • 当系统中运行着多个该程序的副本时,它们的指令是相同的,数据可能不同。因此在内存中只需保存一份该程序的指令,这样就节省了大量的存储空间。
  • 为了提高缓存的命中率。将数据和指令分离有助于提高程序的局部性;
1. 文件头

ELF文件头描述了整个文件的文件属性,包括文件是否可以执行、是静态链接还是动态链接、入口地址、目标硬件、目标操作系统等信息。

zhoumeng.2019@n224-024-082:~/hello$ readelf -h simple.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:          1104 (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

Entry point address:程序的入口虚拟地址,加载完程序后从这地址开始执行程序的指令。可重定位文件一般没有,为0;
Start of section headers:段表在文件中的偏移;
Start of program headers:segment,装载时的段;

2. 段表

描述了文件中各个段的段名、段大小、偏移位置、读写权限以及段的其他属性等。

zhoumeng.2019@n224-024-082:~/hello$ objdump -h simple.o

simple.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000057  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  00000098  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000004  0000000000000000  0000000000000000  000000a0  2**2
                  ALLOC
  3 .rodata       00000004  0000000000000000  0000000000000000  000000a0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      0000002e  0000000000000000  0000000000000000  000000a4  2**0
                  CONTENTS, READONLY
  5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000d2  2**0
                  CONTENTS, READONLY
  6 .eh_frame     00000058  0000000000000000  0000000000000000  000000d8  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  • VMA和LMA和虚拟地址有关,装载时才会确定;
  • CONTENTS 该段在文件中存在,.bss就不存在内容;
  • ALLOC 该段在进程空间总要分配空间;
3. 代码段.text
zhoumeng.2019@n224-024-082:~/hello$ objdump -d  simple.o

simple.o:     file format elf64-x86-64

Disassembly of section .text:
0000000000000000 <func1>:
   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:        48 8d 3d 00 00 00 00         lea    0x0(%rip),%rdi        # 17 <func1+0x17>
  17:        b8 00 00 00 00               mov    $0x0,%eax
  1c:        e8 00 00 00 00               callq  21 <func1+0x21>
  21:        90                           nop
  22:        c9                           leaveq
  23:        c3                           retq

0000000000000024 <main>:
  24:        55                           push   %rbp
  25:        48 89 e5                     mov    %rsp,%rbp
  28:        48 83 ec 10                  sub    $0x10,%rsp
  2c:        c7 45 fc 01 00 00 00         movl   $0x1,-0x4(%rbp)
  33:        8b 15 00 00 00 00            mov    0x0(%rip),%edx        # 39 <main+0x15>
  39:        8b 05 00 00 00 00            mov    0x0(%rip),%eax        # 3f <main+0x1b>
  3f:        01 c2                        add    %eax,%edx
  41:        8b 45 fc                     mov    -0x4(%rbp),%eax
  44:        01 c2                        add    %eax,%edx
  46:        8b 45 f8                     mov    -0x8(%rbp),%eax
  49:        01 d0                        add    %edx,%eax
  4b:        89 c7                        mov    %eax,%edi
  4d:        e8 00 00 00 00               callq  52 <main+0x2e>
  52:        8b 45 fc                     mov    -0x4(%rbp),%eax
  55:        c9                           leaveq
  56:        c3                           retq
4. 数据段

已经初始化的全局变量和局部静态变量保存在.data段;
未初始化的全局变量和局部静态变量保存在.bss段(默认都是0,预留位置不占据空间);

$ objdump -x -s -d  simple.o
......
Contents of section .data:
 0000 54000000 55000000                    T...U... //global_init_var和static_var
......
5. 只读数据段.rodata

存放只读数据,一般是程序中的只读变量(如const修饰的变量)和字符串常量;

$ objdump -x -s -d  simple.o
......
Contents of section .rodata:
 0000 25640a00                             %d.. (prinf中的%d)
......
6. 注释信息段.comment
7. 符号表.symtab

记录了目标文件中所用到的所有符号,例如定义的全局和局部符号,引用的全局符号,段名;
每个符号都有个对应的值,对于变量和函数来说,符号值就是他们的地址;

zhoumeng.2019@n224-024-082:~/hello$ readelf -s simple.o

Symbol table '.symtab' contains 17 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS simple.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    3 static_var.1765
     7: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 static_var2.1766
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
    10: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
    11: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_init_var
    12: 0000000000000004     4 OBJECT  GLOBAL DEFAULT  COM global_uninit_var
    13: 0000000000000000    36 FUNC    GLOBAL DEFAULT    1 func1
    14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
    16: 0000000000000024    51 FUNC    GLOBAL DEFAULT    1 main
8. 字符串表 .strtab

存储ELF文件中用到的各种字符串,比如段名、变量名等;
如此,引用字符串时只需用表中的偏移即可,而不用考虑字符串长度不定的问题;

9. 重定位段 .rel.text .rel.data

链接器处理目标文件时,需要对目标文件中的某些代码和数据进行重定位,这些信息都会记录在重定位表中;

zhoumeng.2019@n224-024-082:~/hello$ objdump -r simple.o
simple.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000013 R_X86_64_PC32     .rodata-0x0000000000000004
000000000000001d R_X86_64_PLT32    printf-0x0000000000000004
0000000000000035 R_X86_64_PC32     .data
000000000000003b R_X86_64_PC32     .bss-0x0000000000000004
000000000000004e R_X86_64_PC32     func1-0x0000000000000004
10. 动态链接信息.dynamic

ELF文件头存储的是静态链接时的相关内容,而.dynamic段可以被视为动态链接下的elf文件头。
保存了依赖于哪些共享对象、动态链接符号表的位置、动态链接重定位表、共享对象初始化代码的地址等;

zhoumeng.2019@n224-024-082:~/dynamix$ readelf -d P1

Dynamic section at offset 0xde0 contains 27 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [./Lib.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x5f8
 0x000000000000000d (FINI)               0x804
 0x0000000000000019 (INIT_ARRAY)         0x200dc8
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x200dd0
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x298
 0x0000000000000005 (STRTAB)             0x408
 0x0000000000000006 (SYMTAB)             0x2d0
 0x000000000000000a (STRSZ)              197 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x201000
 0x0000000000000002 (PLTRELSZ)           24 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x5e0
 0x0000000000000007 (RELA)               0x508
 0x0000000000000008 (RELASZ)             216 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffb (FLAGS_1)            Flags: PIE
 0x000000006ffffffe (VERNEED)            0x4e8
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x4ce
 0x000000006ffffff9 (RELACOUNT)          3
 0x0000000000000000 (NULL)               0x0
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358