编译链接原理

gcc -E 进行预处理(cl -E 是vs下编译器的预处理)
gcc -S main.c -o main.s  编译(翻译成汇编)
as hello.s -o main.o 汇编(翻译成2进制) 下面进行链接
gcc -c main.c -o main.o 也是对程序只进行编译,并不链接


gcc main.c  -o main 对程序进行编译并链接 




1、符号:它用来表示一个地址,这个地址可以是一段子程序(后来发展成函数的起始地址),也是一个变量的的起始地址
函数访问厅知道目标函数的地址,变量访问也要知道目标变量的地址,所以这两种方式都可以归结为一种方式,那就是模块间符号的引用
2、链接:
从原理上廛,综的工作主是把一些指令对其他符号地址的引用加以修正,链接过程主要包括了地址和空间分配、答号决议、重定位

3、对于函数与变量的调用在经过汇编之后,编译成的二进制中,如果是全局量或静态变量都是将地址暂时置为0,而地址则是0xFFFFFFFc,这些地址的修正都是
在链接时间才进行完成的,因此,在编译时,编译器只认答号,只能没有语法错误,就可以编译通过




4、查看objdump Elf文件结构
 readelf -S 查看段表的结构
 obj 文件段表结构:
 [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000030 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 0003a0 000010 08     10   1  4
  [ 3] .data             PROGBITS        00000000 000064 000008 00  WA  0   0  4
  [ 4] .rel.data         REL             00000000 0003b0 000008 08     10   3  4
  [ 5] .bss              NOBITS          00000000 00006c 000000 00  WA  0   0  4
  [ 6] .rodata           PROGBITS        00000000 00006c 00000b 00   A  0   0  1
  [ 7] .comment          PROGBITS        00000000 000077 00002e 00      0   0  1
  [ 8] .note.GNU-stack   PROGBITS        00000000 0000a5 000000 00      0   0  1
  [ 9] .shstrtab         STRTAB          00000000 0000a5 000055 00      0   0  1
  [10] .symtab           SYMTAB          00000000 0002dc 0000b0 10     11   9  4
  [11] .strtab           STRTAB          00000000 00038c 000013 00      0   0  1
  
名字 类型 虚拟地址 文件中偏移 长度

可执行文件段表结构:(程序虚拟地址从08048000开始,用户栈从0xbFFFFFFF开始,共享对象从0x40000000开始)
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4
  [ 3] .gnu.hash         GNU_HASH        08048168 000168 000020 04   A  4   0  4
  [ 4] .dynsym           DYNSYM          08048188 000188 000040 10   A  5   1  4
  [ 5] .dynstr           STRTAB          080481c8 0001c8 000045 00   A  0   0  1
  [ 6] .gnu.version      VERSYM          0804820e 00020e 000008 02   A  4   0  2
  [ 7] .gnu.version_r    VERNEED         08048218 000218 000020 00   A  5   1  4
  [ 8] .rel.dyn          REL             08048238 000238 000008 08   A  4   0  4
  [ 9] .rel.plt          REL             08048240 000240 000010 08   A  4  11  4
  [10] .init             PROGBITS        08048250 000250 000017 00  AX  0   0  4
  [11] .plt              PROGBITS        08048268 000268 000030 04  AX  0   0  4
  [12] .text             PROGBITS        080482a0 0002a0 0001b8 00  AX  0   0 16
  [13] .fini             PROGBITS        08048458 000458 00001c 00  AX  0   0  4
  [14] .rodata           PROGBITS        08048474 000474 000017 00   A  0   0  4
  [15] .eh_frame_hdr     PROGBITS        0804848c 00048c 00001c 00   A  0   0  4
  [16] .eh_frame         PROGBITS        080484a8 0004a8 000058 00   A  0   0  4
  [17] .ctors            PROGBITS        08049500 000500 000008 00  WA  0   0  4
  [18] .dtors            PROGBITS        08049508 000508 000008 00  WA  0   0  4
  [19] .jcr              PROGBITS        08049510 000510 000004 00  WA  0   0  4
  [20] .dynamic          DYNAMIC         08049514 000514 0000c8 08  WA  5   0  4
  [21] .got              PROGBITS        080495dc 0005dc 000004 04  WA  0   0  4
  [22] .got.plt          PROGBITS        080495e0 0005e0 000014 04  WA  0   0  4
  [23] .data             PROGBITS        080495f4 0005f4 00000c 00  WA  0   0  4
  [24] .bss              NOBITS          08049600 000600 000008 00  WA  0   0  4
  [25] .comment          PROGBITS        00000000 000600 000114 00      0   0  1
  [26] .shstrtab         STRTAB          00000000 000714 0000e9 00      0   0  1
  [27] .symtab           SYMTAB          00000000 000c88 000460 10     28  50  4
  [28] .strtab           STRTAB          00000000 0010e8 00024e 00      0   0  1
 
 1、链接:
 符号是链接的粘合剂,整个链接过程正是基于符号才能正确完成
 ,链接过程中很关键的一部分就是对符号怕管理,每个目标文件都会有一个相应的
 符号表,这个表里面记录了目标文件中所用到的所有符号,每个定义的一个符号
 有一个对应的值,叫符号值,对于变量 和函数来说,符号
 值就是它们的地址,除了函数和变量之外,还存在其他几种不常用到的符号
分类:
1、定义在目标文件中的全局符号,可以被其他目标文件引用
2、在本目标文件中引用的全局符号,却没有定义在本目标文件,外部符号
3、段名:这种符号由编译器产生,它的值是段的起始地址
4、局部符号:这类符号只在编译单元内部可以,如果函数中的静态变量
nm main.o 可以直接查看符号表
或readelf -s main


Symbol table '.dynsym' contains 4 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     2: 00000000   415 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.0 (2)
     3: 08048478     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used


Symbol table '.symtab' contains 70 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 08048134     0 SECTION LOCAL  DEFAULT    1 
     2: 08048148     0 SECTION LOCAL  DEFAULT    2 
     3: 08048168     0 SECTION LOCAL  DEFAULT    3 
     4: 08048188     0 SECTION LOCAL  DEFAULT    4 
     5: 080481c8     0 SECTION LOCAL  DEFAULT    5 
     6: 0804820e     0 SECTION LOCAL  DEFAULT    6 
     7: 08048218     0 SECTION LOCAL  DEFAULT    7 
     8: 08048238     0 SECTION LOCAL  DEFAULT    8 
     9: 08048240     0 SECTION LOCAL  DEFAULT    9 
    10: 08048250     0 SECTION LOCAL  DEFAULT   10 
    11: 08048268     0 SECTION LOCAL  DEFAULT   11 
    12: 080482a0     0 SECTION LOCAL  DEFAULT   12 
    13: 08048458     0 SECTION LOCAL  DEFAULT   13 
    14: 08048474     0 SECTION LOCAL  DEFAULT   14 
    15: 0804848c     0 SECTION LOCAL  DEFAULT   15 
    16: 080484a8     0 SECTION LOCAL  DEFAULT   16 
    17: 08049500     0 SECTION LOCAL  DEFAULT   17 
    18: 08049508     0 SECTION LOCAL  DEFAULT   18 
    19: 08049510     0 SECTION LOCAL  DEFAULT   19 
    20: 08049514     0 SECTION LOCAL  DEFAULT   20 
    21: 080495dc     0 SECTION LOCAL  DEFAULT   21 
    22: 080495e0     0 SECTION LOCAL  DEFAULT   22 
    23: 080495f4     0 SECTION LOCAL  DEFAULT   23 
    24: 08049600     0 SECTION LOCAL  DEFAULT   24 
    25: 00000000     0 SECTION LOCAL  DEFAULT   25 
    26: 080482c4     0 FUNC    LOCAL  DEFAULT   12 call_gmon_start
    27: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    28: 08049500     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_LIST__
    29: 08049508     0 OBJECT  LOCAL  DEFAULT   18 __DTOR_LIST__
    30: 08049510     0 OBJECT  LOCAL  DEFAULT   19 __JCR_LIST__
    31: 08049600     4 OBJECT  LOCAL  DEFAULT   24 dtor_idx.5793
    32: 08049604     1 OBJECT  LOCAL  DEFAULT   24 completed.5791
    33: 080482f0     0 FUNC    LOCAL  DEFAULT   12 __do_global_dtors_aux
    34: 08048350     0 FUNC    LOCAL  DEFAULT   12 frame_dummy
    35: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    36: 08049504     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_END__
    37: 080484fc     0 OBJECT  LOCAL  DEFAULT   16 __FRAME_END__
    38: 08049510     0 OBJECT  LOCAL  DEFAULT   19 __JCR_END__
    39: 08048430     0 FUNC    LOCAL  DEFAULT   12 __do_global_ctors_aux
    40: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
    41: 080495f8     4 OBJECT  LOCAL  DEFAULT   23 var
    42: 08049500     0 NOTYPE  LOCAL  HIDDEN   17 __preinit_array_start
    43: 08049500     0 NOTYPE  LOCAL  HIDDEN   17 __fini_array_end
    44: 080495e0     0 OBJECT  LOCAL  HIDDEN   22 _GLOBAL_OFFSET_TABLE_
    45: 08049500     0 NOTYPE  LOCAL  HIDDEN   17 __preinit_array_end
    46: 08049500     0 NOTYPE  LOCAL  HIDDEN   17 __fini_array_start
    47: 08049500     0 NOTYPE  LOCAL  HIDDEN   17 __init_array_end
    48: 08049500     0 NOTYPE  LOCAL  HIDDEN   17 __init_array_start
    49: 08049514     0 OBJECT  LOCAL  HIDDEN   20 _DYNAMIC
    50: 080495f4     0 NOTYPE  WEAK   DEFAULT   23 data_start
    51: 080495fc     4 OBJECT  GLOBAL DEFAULT   23 s
    52: 080483b0     5 FUNC    GLOBAL DEFAULT   12 __libc_csu_fini
    53: 080482a0     0 FUNC    GLOBAL DEFAULT   12 _start
    54: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    55: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    56: 08048474     4 OBJECT  GLOBAL DEFAULT   14 _fp_hw
    57: 08048458     0 FUNC    GLOBAL DEFAULT   13 _fini
    58: 00000000   415 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
    59: 08048478     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used
    60: 080495f4     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
    61: 0804847c     0 OBJECT  GLOBAL HIDDEN   14 __dso_handle
    62: 0804950c     0 OBJECT  GLOBAL HIDDEN   18 __DTOR_END__
    63: 080483c0   105 FUNC    GLOBAL DEFAULT   12 __libc_csu_init
    64: 08049600     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    65: 08049608     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    66: 08049600     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    67: 08048429     0 FUNC    GLOBAL HIDDEN   12 __i686.get_pc_thunk.bx
    68: 08048374    48 FUNC    GLOBAL DEFAULT   12 main
    69: 08048250     0 FUNC    GLOBAL DEFAULT   10 _init



第二章 静态链接

1、定义两个文件a.b,b.c 
extern int shared;
int main(){
int a = 100;
swap(&a,&shared);
}


b.c
int shared = 12;
int swap(int *a,int *b){
int t = *a;
*a = *b;
*b =t;
}


#gcc -c a.c
#gcc -c b.c
#objdump -h a.o


Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000034  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  00000068  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000068  2**2
                  ALLOC
  3 .comment      0000002e  00000000  00000000  00000068  2**0
                  CONTENTS, READONLY
  4 .note.GNU-stack 00000000  00000000  00000000  00000096  2**0
                  CONTENTS, READONLY
 
#objdump -h b.o


Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000022  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000004  00000000  00000000  00000058  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
 
#ld a.o b.o -e main -o ab
#objdump -h ab
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000056  08048094  08048094  00000094  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000004  080490ec  080490ec  000000ec  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .comment      0000005c  00000000  00000000  000000f0  2**0
                  CONTENTS, READONLY
 
链接步骤:
1、扫描所有输入目标文件,将输入目标文件中的符号表中所有的符号定义和引用收集起来
统一放到一个全局符号表
2、符号解析与重定位
使用上一步中收到的所有信息,将符号进行解析与重定位
对于#inlcude 的代码在预处理阶段就复制过来了,但它要的只是一个声明
有了声明就能进行编译,但在链接时,要的就是一个定义了,你引用的一个函数或
变量,如果不在本文件内,在链接时,它会将它们都分配到自己文件内,为它们分配
空间,确定它们的地址,
在编译时,如果引用了其他文件的变量或方法(其实不光是其他文件内,自己文件也是如果),它们的地址都是不
确定的,对于变量是用一个0 暂时表示它的地址,而方法则用 0xbffffff来表示,而这个地址的确定要在链接
阶段最终确定,这也是叫重定位


3、查看重定位表
在编译a.c 到 a.o后,由于a.c 中调用了b.c 中的数据,所以a.c中要有一个重定位表,用以重定位
在b.c中定义的数据,
objdump -r a.o
RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
0000001c R_386_32          shared
00000027 R_386_PC32        swap
偏移表示要被重定位的地方
对于函数调用全局变量调用,即使是在自己文件中定义的,也会放在重定位表中
它们在链接过程中都会被重定位
还有一点就是如果引用了外部文件中或者本文件只是声明没有定义,在符号表中都有相应信息
readelf -s a.o
Symbol table '.symtab' contains 12 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     4 OBJECT  LOCAL  DEFAULT    3 var
     6: 00000000     0 SECTION LOCAL  DEFAULT    6 
     7: 00000000     0 SECTION LOCAL  DEFAULT    5 
     8: 00000000     5 FUNC    GLOBAL DEFAULT    1 change
     9: 00000005    71 FUNC    GLOBAL DEFAULT    1 main
    10: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND shared
    11: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND swap




第7章 动态链接
1、链接操作推迟到运行时再进行,动态链接要有操作系统的支持
2、programe1.c
#include "lib.h"
int main(){
foobar1);
return 0;
}
program2.c
#include "lib.h"
int main(){
foobar(2);
return 0;
}
lib.c 
#include <stdio.h>
void foobar(int i){
printf("Printing from lib.so%d\n",i);
}
lib.h
#ifndef LIB_B
#define LIB_H
void foobar(int i);
#endif

#gcc -fPIC -shared -o lib.so lib.c (将lib.c编译成共享对象)
#gcc -o program1 program1.c  ./lib.so
#gcc -o program2 program2.c ./lib.so
在查看program1 中符号表时,看到 foobar 符号的类型为UND(undefined )
这也就表明了在链接过程中并没有把此函数链接进来
 52: 00000000    45 FUNC    GLOBAL DEFAULT  UND foobar、
 解析:在静态链接时,要对没有定义的的符号进行链接进来,并重定位它们的地址,但如果要链接的符号
 定义在一个动态共享对象的函数中,那么链接器就会将这个符号的引用标记为一个动态链接的符号,不对
 它们进行地址重定位,把这个过程留在装载时再进行
 
 我们可以查看动态链接符号表,也就是在要动态链接的符号:objdump -T program1
 [root@localhost compile]# objdump -T program1


program1:     file format elf32-i386


DYNAMIC SYMBOL TABLE:
00000000      DF *UND* 0000002d              foobar
00000000  w   D  *UND* 00000000              __gmon_start__
00000000  w   D  *UND* 00000000              _Jv_RegisterClasses
00000000      DF *UND* 0000019f  GLIBC_2.0   __libc_start_main
080496e0 g    D  *ABS* 00000000  Base        _end
080496d8 g    D  *ABS* 00000000  Base        _edata
08048558 g    DO .rodata 00000004  Base        _IO_stdin_used
080496d8 g    D  *ABS* 00000000  Base        __bss_start
08048338 g    DF .init 00000000  Base        _init
08048538 g    DF .fini 00000000  Base        _fini


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值