第2部分 静态链接---(4)静态链接

来源:互联网 发布:程序员论坛排行榜 编辑:程序博客网 时间:2024/06/05 04:05
#################
# 4、静态链接

#################

// a.cextern int shared;int main(){    int a = 100;    swap(&a, &shared);}
// b.cint shared = 1;void swap(int *a, int *b){    *a ^= *b ^= *a ^= *b;}
// a.c中定义了一个全局符号main// b.c中定义了两个全局符号,变量shared和swap// 模块a.c里面引用到了b.c里面的swap和shared,所以需要把a.o和b.o链接在一起形成最后的可执行文件ab$ gcc -c a.c b.c                // 编译成目标文件a.o 和 b.o$ ld a.o b.o -e main -o ab      // -e main 表示将main函数作为程序入口,ld链接器默认的程序入口为_start,-o指定输出的文件名,默认为a.out

空间与地址分配
    相似段合并:将所有输入文件的.text合并到输出文件的.text段,接着是.data段、.bss段等。
整个链接过程分两步:
(1)空间与地址分配:扫描所有的输入目标文件,获取它们的各个段的长度、属性和位置,并且将输入目标文件中的符号表中所有的符号定义和符号引用收集起来,统一放到一个全局符号表。
(2)符号解析与重定位:使用上面第一步中收集到的所有信息,读取输入文件中段的数据、重定位信息,并且进行符号解析与重定位、调整代码中的地址等。
[xiaoloaw@AONT03 partTwo]$ objdump -h a.oa.o:     file format elf32-i386Sections: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      0000002e  00000000  00000000  0000005c  2**0                  CONTENTS, READONLY  4 .note.GNU-stack 00000000  00000000  00000000  0000008a  2**0                  CONTENTS, READONLY[xiaoloaw@AONT03 partTwo]$[xiaoloaw@AONT03 partTwo]$ objdump -h b.ob.o:     file format elf32-i386Sections: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      0000002e  00000000  00000000  00000074  2**0                  CONTENTS, READONLY  4 .note.GNU-stack 00000000  00000000  00000000  000000a2  2**0                  CONTENTS, READONLY[xiaoloaw@AONT03 partTwo]$[xiaoloaw@AONT03 partTwo]$ objdump -h abab:     file format elf32-i386Sections: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      0000002d  00000000  00000000  000000fc  2**0                  CONTENTS, READONLY[xiaoloaw@AONT03 partTwo]$[xiaoloaw@AONT03 partTwo]$[xiaoloaw@AONT03 partTwo]$ ld a.o b.o -e main -o ab[xiaoloaw@AONT03 partTwo]$ objdump -h a.oa.o:     file format elf32-i386Sections: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      0000002e  00000000  00000000  0000005c  2**0                  CONTENTS, READONLY  4 .note.GNU-stack 00000000  00000000  00000000  0000008a  2**0                  CONTENTS, READONLY[xiaoloaw@AONT03 partTwo]$ objdump -h b.ob.o:     file format elf32-i386Sections: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      0000002e  00000000  00000000  00000074  2**0                  CONTENTS, READONLY  4 .note.GNU-stack 00000000  00000000  00000000  000000a2  2**0                  CONTENTS, READONLY[xiaoloaw@AONT03 partTwo]$[xiaoloaw@AONT03 partTwo]$[xiaoloaw@AONT03 partTwo]$ objdump -h abab:     file format elf32-i386Sections: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      0000002d  00000000  00000000  000000fc  2**0                  CONTENTS, READONLY
[xiaoloaw@AONT03 partTwo]$ objdump -d a.o    // -d 查看a.o 的代码段反汇编结果a.o:     file format elf32-i386Disassembly 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)  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>  25:   c9                      leave   26:   c3                      ret   [xiaoloaw@AONT03 partTwo]$
[xiaoloaw@AONT03 partTwo]$ objdump -d abab:     file format elf32-i386Disassembly 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 f8 90 04    movl   $0x80490f8,0x4(%esp) 80480ac:       08 80480ad:       8d 44 24 1c             lea    0x1c(%esp),%eax 80480b1:       89 04 24                mov    %eax,(%esp) 80480b4:       e8 03 00 00 00          call   80480bc <swap> 80480b9:       c9                      leave  80480ba:       c3                      ret    80480bb:       90                      nop080480bc <swap>: 80480bc:       55                      push   %ebp 80480bd:       89 e5                   mov    %esp,%ebp 80480bf:       53                      push   %ebx 80480c0:       8b 45 08                mov    0x8(%ebp),%eax 80480c3:       8b 10                   mov    (%eax),%edx 80480c5:       8b 45 0c                mov    0xc(%ebp),%eax 80480c8:       8b 08                   mov    (%eax),%ecx 80480ca:       8b 45 08                mov    0x8(%ebp),%eax 80480cd:       8b 18                   mov    (%eax),%ebx 80480cf:       8b 45 0c                mov    0xc(%ebp),%eax 80480d2:       8b 00                   mov    (%eax),%eax 80480d4:       31 c3                   xor    %eax,%ebx 80480d6:       8b 45 08                mov    0x8(%ebp),%eax 80480d9:       89 18                   mov    %ebx,(%eax) 80480db:       8b 45 08                mov    0x8(%ebp),%eax 80480de:       8b 00                   mov    (%eax),%eax 80480e0:       31 c1                   xor    %eax,%ecx 80480e2:       8b 45 0c                mov    0xc(%ebp),%eax 80480e5:       89 08                   mov    %ecx,(%eax) 80480e7:       8b 45 0c                mov    0xc(%ebp),%eax 80480ea:       8b 00                   mov    (%eax),%eax 80480ec:       31 c2                   xor    %eax,%edx 80480ee:       8b 45 08                mov    0x8(%ebp),%eax 80480f1:       89 10                   mov    %edx,(%eax) 80480f3:       5b                      pop    %ebx 80480f4:       5d                      pop    %ebp 80480f5:       c3                      ret   
查看重定位表
[xiaoloaw@AONT03 partTwo]$ objdump -r a.oa.o:     file format elf32-i386RELOCATION RECORDS FOR [.text]:OFFSET   TYPE              VALUE00000015 R_386_32          shared00000021 R_386_PC32        swap
符号解析

[xiaoloaw@AONT03 partTwo]$ ld a.old: warning: cannot find entry symbol _start; defaulting to 0000000008048074a.o: In function `main':a.c:(.text+0x15): undefined reference to `shared'a.c:(.text+0x21): undefined reference to `swap'
查看a.o的符号表

[xiaoloaw@AONT03 partTwo]$ readelf -s a.oSymbol table '.symtab' contains 10 entries:   Num:    Value  Size Type    Bind   Vis      Ndx Name     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS a.c     2: 00000000     0 SECTION LOCAL  DEFAULT    1     3: 00000000     0 SECTION LOCAL  DEFAULT    3     4: 00000000     0 SECTION LOCAL  DEFAULT    4     5: 00000000     0 SECTION LOCAL  DEFAULT    6     6: 00000000     0 SECTION LOCAL  DEFAULT    5     7: 00000000    39 FUNC    GLOBAL DEFAULT    1 main     8: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND shared     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND swap
ar工具查看文件中包含哪些目标文件

[xiaoloaw@AONT03 lib]$ pwd/usr/lib/i686-redhat-linux5E/lib[xiaoloaw@AONT03 lib]$ ar -t libc.ainit-first.olibc-start.osysdep.oversion.ocheck_fds.olibc-tls.oelf-init.odso_handle.oerrno.oerrno-loc.ohp-timing.oiconv_open.oiconv.oiconv_close.ogconv_open.ogconv.ogconv_close.ogconv_db.o...
objdump查看libc.a的符号
[xiaoloaw@AONT03 lib]$ objdump -t libc.a  | grep "printf"
最"小"的程序

// TinyHelloWorld.cchar *str = "Hello world!\n";void print(){  asm( "movl $13, %%edx \n\t"       "movl %0, %%ecx \n\t"       "movl $0, %%ebx \n\t"       "movl $4, %%eax \n\t"       "int $0x80      \n\t"       ::"r"(str):"edx", "ecx", "ebx" );}void exit(){  asm( "movl $42,%ebx \n\t"       "movl $1,%eax  \n\t"       "int $0x80     \n\t" );}void nomain(){    print();    exit();
[xiaoloaw@AONT03 partTwo]$ gcc -c -fno-builtin TinyHelloWorld.c    // GCC编译器提供了很多内置函数,它会把一些常用的C库函数替换成编译器的内置函数,达到优化的功能。-fno-builtin参数关闭GCC内置函数功能。[xiaoloaw@AONT03 partTwo]$ ld -static -e nomain -o TinyHelloWorld TinyHelloWorld.o    // 使用静态链接方式来链接程序,而不是使用默认的动态链接方式。[xiaoloaw@AONT03 partTwo]$ ./TinyHelloWorldHello world![xiaoloaw@AONT03 partTwo]$ echo $?42