静态链接 -- 程序员的自我修养学习笔记

前言

参考第 2 章

笔记

静态链接
    测试程序如下:
        //a.c                                                      |  // b.c                                                      
        extern int shared;                                         |  int shared =1;                     
        int main()                                                 |  void swap( int* a, int* b )    
        {                                                          |  {                              
            int a = 100;                                           |          *a ^= *b ^= *a ^= *b;  
            swap( &a, &shared );                                   |  }                                                     
        }                                                          |  
    ======================================================================================================================================
    // 编译中目标文件: gcc -c a.c b.c
    ======================================================================================================================================
    $ readelf -s a.o                                               | $ readelf -s b.o
                                                                   | 
    Symbol table '.symtab' contains 10 entries:                    | Symbol table '.symtab' contains 9 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name        |    Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND             |      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 00000000     0 FILE    LOCAL  DEFAULT  ABS a.c         |      1: 00000000     0 FILE    LOCAL  DEFAULT  ABS b.c
         2: 00000000     0 SECTION LOCAL  DEFAULT    1             |      2: 00000000     0 SECTION LOCAL  DEFAULT    1 
         3: 00000000     0 SECTION LOCAL  DEFAULT    3             |      3: 00000000     0 SECTION LOCAL  DEFAULT    2 
         4: 00000000     0 SECTION LOCAL  DEFAULT    4             |      4: 00000000     0 SECTION LOCAL  DEFAULT    3 
         5: 00000000     0 SECTION LOCAL  DEFAULT    6             |      5: 00000000     0 SECTION LOCAL  DEFAULT    5 
         6: 00000000     0 SECTION LOCAL  DEFAULT    5             |      6: 00000000     0 SECTION LOCAL  DEFAULT    4 
         7: 00000000    39 FUNC    GLOBAL DEFAULT    1 main        |      7: 00000000     4 OBJECT  GLOBAL DEFAULT    2 shared
         8: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND shared      |      8: 00000000    58 FUNC    GLOBAL DEFAULT    1 swap  
         9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND swap        |

    链接这两个目标文件:
            $ ld a.o b.o -e main -o ab
        -e main: 表示将 main 函数作为程序入口,ld 链接器默认的程序入口为 _start 
        -o ab: 表示链接输出文件名为 ab,默认为 a.out   

    使用 objdump -h 查看链接前后地址的分配情况:
        注: 
                VMA 表示 Virtual Memory Address 即虚拟地址,LMA 表示 Load Memory Address,即加载地址,
            正常情况下这两个值应该是一样的,但是在有些嵌入式系统中,特别是在那些程序存放在 ROM 的系统
            中时,LMA 和 VMA 是不相同的。这里我们只要关注 VMA 即可。
        ////////////////////////////////////////////////////////////////////////////////////
            $ objdump -h a.o

            a.o:     file format elf32-i386

            Sections:
            Idx Name          Size      VMA       LMA       File off  Algn
              0 .text         00000027  00000000  00000000  00000034  2**2
                              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
              1 .data         00000000  00000000  00000000  0000005c  2**2
                              CONTENTS, ALLOC, LOAD, DATA
              2 .bss          00000000  00000000  00000000  0000005c  2**2
                              ALLOC
              3 .comment      00000024  00000000  00000000  0000005c  2**0
                              CONTENTS, READONLY
              4 .note.GNU-stack 00000000  00000000  00000000  00000080  2**0
                              CONTENTS, READONLY
            book@book-desktop:/work/link_test$ objdump -h b.o

        ////////////////////////////////////////////////////////////////////////////////////
            $ objdump -h b.o

            b.o:     file format elf32-i386

            Sections:
            Idx Name          Size      VMA       LMA       File off  Algn
              0 .text         0000003a  00000000  00000000  00000034  2**2
                              CONTENTS, ALLOC, LOAD, READONLY, CODE
              1 .data         00000004  00000000  00000000  00000070  2**2
                              CONTENTS, ALLOC, LOAD, DATA
              2 .bss          00000000  00000000  00000000  00000074  2**2
                              ALLOC
              3 .comment      00000024  00000000  00000000  00000074  2**0
                              CONTENTS, READONLY
              4 .note.GNU-stack 00000000  00000000  00000000  00000098  2**0
                              CONTENTS, READONLY    

        ////////////////////////////////////////////////////////////////////////////////////
            $ objdump -h ab

            ab:     file format elf32-i386

            Sections:
            Idx Name          Size      VMA       LMA       File off  Algn
              0 .text         00000062  08048094  08048094  00000094  2**2
                              CONTENTS, ALLOC, LOAD, READONLY, CODE
              1 .data         00000004  080490f8  080490f8  000000f8  2**2
                              CONTENTS, ALLOC, LOAD, DATA
              2 .comment      00000023  00000000  00000000  000000fc  2**0
                              CONTENTS, READONLY

            链接前后的程序中所使用的地址已经是程序在进程中的虚拟地址,即我们关心上面各个段中的 VMA 和 Size,
        而忽略文件偏移。可以看到,在链接之前,目标文件中的所有段的 VMA 都是 0,因为虚拟空间还没有被分配,所
        以它们默认都为 0.等到链接之后,可执行文件 ab 中的各个段都被分配了相应的虚拟地址。这里的输出程序 ab 
        中,.text 段被分配地址 0x0808 8094,大小为 0x72 字节,.data 段从地址 0x0804 9108 开始,大小为 4 字
        节。  

猜你喜欢

转载自blog.csdn.net/wangjun7121/article/details/88244053
今日推荐