GCC编译链接过程

编译链接过程

代码

#cat main.c
#include <stdio.h>

int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);

int main(void)
{
    printf("add:%d\n", add(1,2));
    printf("sub:%d\n", sub(10,100));
    printf("mul:%d\n", mul(5,10));
    printf("div:%d\n", div(200,100));

    return 0;
}

===


#cat math.c
#include <stdio.h>

int add(int x, int y)
{
    return (x + y);
}

int sub(int x, int y)
{
    return (x - y);
}

int mul(int x, int y)
{
    return (x * y);
}

int div(int x, int y)
{
    return (x/y);
}
预处理:
#gcc -E main.c -o main.i

编译: 生成.s 文件 
#gcc -c main.c math.c
#ls main.s math.s
main.s  math.s

汇编:生成.o 文件(可重定位目标文件)
#gcc -c main.c math.c
#ls main.o math.o
main.o  math.o


链接:生成 (可执行目标文件)
#gcc -o main.out main.o math.o

目标文件

分三种:

  1. 可重定位目标文件 (Relocatable file) (.o 文件,没有被链接的)
  2. 可执行目标文件 (Executable file)(.out文件 最终二进制文件)
  3. 可被共享目标文件 (Shared object file) (.so 结尾的)

看ELF的常见命令:

ELF文件格式需要知道;

#readelf -h main.out  看ELF文件的header部分
#readelf -S main.out  看ELF文件的Section header
#readelf -h main.out
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:                              EXEC (Executable file)  // 可执行文件
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400430   // 函数入口地址
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6720 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 27

  
  
#readelf -h main.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 // 所以,这里看函数入口地址为0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          1152 (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: 10

静态库:

静态库: (.a 结尾的) 从 .o 文件而来

//生成静态库 : 使用ar命令,将.o 生成.a 文件。这里名字有讲究的, lib + math + .a  中间的才是库名字。
#ar rcs libmath.a math.o

// 使用静态库: -L 表示路径, -l 表示库的名字
#gcc main.o -L. -l math -o main.out
#./main.out
add:3
sub:-90
mul:50
div:2

其实和.o 文件差距不大,都是 重定向文件,只不过做了归档。

#readelf -h  libmath.a
File: libmath.a(math.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:          840 (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:         11
  Section header string table index: 8

共享库:

共享库: (.so 结尾的)

#gcc --shared -fPIC -o libmath.so math.c
#ll libmath.so
-rwxr-xr-x 1 root root 7864 Feb  1 16:21 libmath.so

类型: Shared object file

#readelf -h libmath.so
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:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x5b0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6216 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         27
  Section header string table index: 24

GCC

gcc 不是一个简单的命令,里面有很多库

[root@r10n04359.sqa.zmf /usr/lib/gcc/x86_64-redhat-linux/6.4.0]
#ls
32           crtendS.o      finclude           libcaf_single.a  libgcc_s.so       libgomp.so    libmpx.spec        libstdc++.so
crtbegin.o   crtfastmath.o  include            libcilkrts.so    libgcov.a         libgomp.spec  libmpxwrappers.so  libtsan.so
crtbeginS.o  crtprec32.o    libasan_preinit.o  libcilkrts.spec  libgfortran.so    libitm.spec   libquadmath.so     libubsan.so
crtbeginT.o  crtprec64.o    libasan.so         libgcc.a         libgfortran.spec  liblsan.so    libsanitizer.spec  rpmver
crtend.o     crtprec80.o    libatomic.so       libgcc_eh.a      libgomp.a         libmpx.so     libstdc++fs.a

链接阶段

符号表

几个简单命令,不要混淆:

#readelf -S math.o  // 查看Section header
#readelf -s math.o  //  查看symble table
#readelf -h math.o // 查看ELF 的header(主要存放一些,ELF文件的类型,架构之类的)

查看Section header

一个ELF 的section 有哪些?

大家都知道的.text, .data, .bss 等section

#readelf -S math.o
There are 11 section headers, starting at offset 0x348:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000004c  0000000000000000  AX       0     0     1
  [ 2] .data             PROGBITS         0000000000000000  0000008c
       0000000000000000  0000000000000000  WA       0     0     1
  [ 3] .bss              NOBITS           0000000000000000  0000008c
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .comment          PROGBITS         0000000000000000  0000008c
       000000000000002d  0000000000000001  MS       0     0     1
  [ 5] .note.GNU-stack   PROGBITS         0000000000000000  000000b9
       0000000000000000  0000000000000000           0     0     1
  [ 6] .eh_frame         PROGBITS         0000000000000000  000000c0
       0000000000000098  0000000000000000   A       0     0     8
  [ 7] .rela.eh_frame    RELA             0000000000000000  00000290
       0000000000000060  0000000000000018   I       9     6     8
  [ 8] .shstrtab         STRTAB           0000000000000000  000002f0
       0000000000000054  0000000000000000           0     0     1
  [ 9] .symtab           SYMTAB           0000000000000000  00000158
       0000000000000120  0000000000000018          10     8     8
  [10] .strtab           STRTAB           0000000000000000  00000278
       0000000000000018  0000000000000000           0     0     1

查看Symbol table

虽然,你可以看到 math.c 中的add, sub, mul, div 这些符号表的名字,但是,这个符号表不存在这里,是通过索引获取的。 实际上是存在.strtab 这个section中的。

#readelf -s math.o

Symbol table '.symtab' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS math.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     8: 0000000000000000    20 FUNC    GLOBAL DEFAULT    1 add
     9: 0000000000000014    18 FUNC    GLOBAL DEFAULT    1 sub
    10: 0000000000000026    19 FUNC    GLOBAL DEFAULT    1 mul
    11: 0000000000000039    19 FUNC    GLOBAL DEFAULT    1 div
上一篇:2020最新学习笔记


下一篇:基于Spring+Struts+Hibernate实现的健康管理平台