美文网首页
四、静态链接

四、静态链接

作者: 小虾米不爱吃虾 | 来源:发表于2016-07-25 14:43 被阅读31次

    1.源代码(a.c b.c)

    extern int shared;
    
    int main()
    {
            int a = 100;
            swap( &a, &shared );
            return 0;
    }
    
    int shared = 1;
    
    void swap( int *a, int *b )
    {
            *a = *a ^ *b;
            *b = *a ^ *b;
            *a = *a ^ *b;
    }
    

    结合$ readelf -S$ readelf -s的输出,可以获取到两个目标文件的Section信息和symbol信息等

    2.空间和地址分配

    目标文件a.o和b.o链接输出可执行文件ab,它们的Section是如何合并到输出文件中的?输出文件和虚拟内存中的地址和空间又是如何分配的?

    • 相似段合并
      • 空间与地址分配
        扫描所有的目标文件,获取各个Section的长度、属性和位置,收集符号表中的所有符号定义和符号引用;合并,计算出输出文件中各个段合并后的位置和长度,并建立映射关系
      • $ ld a.o b.o -e main -o ab -melf_i386
    $ objdump -h a.o b.o ab
    
    a.o:     file format elf32-i386
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 .text         0000002c  00000000  00000000  00000034  2**2
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
      1 .data         00000000  00000000  00000000  00000060  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      2 .bss          00000000  00000000  00000000  00000060  2**2
                      ALLOC
      3 .comment      0000002b  00000000  00000000  00000060  2**0
                      CONTENTS, READONLY
      4 .note.GNU-stack 00000000  00000000  00000000  0000008b  2**0
                      CONTENTS, READONLY
      5 .eh_frame     00000038  00000000  00000000  0000008c  2**2
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
    
    b.o:     file format elf32-i386
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 .text         00000038  00000000  00000000  00000034  2**2
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      1 .data         00000004  00000000  00000000  0000006c  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      2 .bss          00000000  00000000  00000000  00000070  2**2
                      ALLOC
      3 .comment      0000002b  00000000  00000000  00000070  2**0
                      CONTENTS, READONLY
      4 .note.GNU-stack 00000000  00000000  00000000  0000009b  2**0
                      CONTENTS, READONLY
      5 .eh_frame     00000038  00000000  00000000  0000009c  2**2
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
    
    ab:     file format elf32-i386
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 .text         00000064  08048094  08048094  00000094  2**2
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      1 .eh_frame     00000058  080480f8  080480f8  000000f8  2**2
                      CONTENTS, ALLOC, LOAD, READONLY, DATA
      2 .data         00000004  08049150  08049150  00000150  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      3 .comment      0000002a  00000000  00000000  00000154  2**0
                      CONTENTS, READONLY
    

    从合并后的文件ab可以看出,合并的各个段已经在虚拟内存中分配了地址(VMA)

    • 符号地址的确定
      • 符号解析与重定位
        使用第一步收集到的所有信息,读取输入文件中的Section的数据、重定位信息,进行符号解析与重定位、调整代码中的地址
      • 经过相似段合并过程,各个段在虚拟地址空间中的地址已经确定了,各个符号定义 的地址也已经确定了(段的虚拟地址加上符号定义的偏移量)
      • 重定位过程是针对代码中的符号引用的地址的修改
    $ objdump -d a.o ab   部分结果,主要是main函数
    
    a.o:     file format elf32-i386
    
    Disassembly of section .text:
    
    00000000 <main>:
       0:   55                      push   %ebp
       1:   89 e5                   mov    %esp,%ebp
       3:   83 e4 f0                and    $0xfffffff0,%esp
       6:   83 ec 20                sub    $0x20,%esp
       9:   c7 44 24 1c 64 00 00    movl   $0x64,0x1c(%esp)
      10:   00 
      11:   c7 44 24 04 00 00 00    movl   $0x0,0x4(%esp)       对shared变量的引用
      18:   00 
      19:   8d 44 24 1c             lea    0x1c(%esp),%eax
      1d:   89 04 24                mov    %eax,(%esp)
      20:   e8 fc ff ff ff          call   21 <main+0x21>       对swap函数的调用
      25:   b8 00 00 00 00          mov    $0x0,%eax
      2a:   c9                      leave  
      2b:   c3                      ret    
    
    ab:     file format elf32-i386
    
    
    Disassembly of section .text:
    
    08048094 <main>:
     8048094:       55                      push   %ebp
     8048095:       89 e5                   mov    %esp,%ebp
     8048097:       83 e4 f0                and    $0xfffffff0,%esp
     804809a:       83 ec 20                sub    $0x20,%esp
     804809d:       c7 44 24 1c 64 00 00    movl   $0x64,0x1c(%esp)
     80480a4:       00 
     80480a5:       c7 44 24 04 50 91 04    movl   $0x8049150,0x4(%esp)    对shared变量的地址引用&shared
     80480ac:       08 
     80480ad:       8d 44 24 1c             lea    0x1c(%esp),%eax
     80480b1:       89 04 24                mov    %eax,(%esp)
     80480b4:       e8 07 00 00 00          call   80480c0 <swap>   对swap函数的调用
     80480b9:       b8 00 00 00 00          mov    $0x0,%eax
     80480be:       c9                      leave  
     80480bf:       c3                      ret 
    

    c7 44 24 是movl指令,后边的4个字节是地址,可以看到链接过程,对符号地址做了重定位修正

    重定位过程的完成需要重定位表的协助,.text的重定位表是.rel.text

    • 重定位表每一个表项的结构体
    typedef struct
    {
     Elf32_Addr    r_offset;       /* Address */
     Elf32_Word    r_info;         /* Relocation type and symbol index */
    } Elf32_Rel;
    

    offset 代表相对于要修正的段的偏移地址,r_info 包含了重定位符号的信息(符号表的下标)

    相关文章

      网友评论

          本文标题:四、静态链接

          本文链接:https://www.haomeiwen.com/subject/zrkbjttx.html