栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

神秘又熟悉的main函数

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

神秘又熟悉的main函数

目录

1 概述

2 程序编译

3 揭开最后的面纱

1 概述

学习C语言的同学都知道main函数,并且这是我们接触的第一个函数,但是很少有人去深究C语言为什么都是从main函数执行的。今天我们就来深入了解下。

2 程序编译

C语言生成可执行文件分为3个阶段:编译、链接、运行。每个编辑单元(例如多个.c源文件)是各自独立编译成目标文件(例如.o),最后由链接器把这些目标文件链接成可执行程序。

3 揭开最后的面纱

实际上使用gcc进行链接时要调用下面的命令:

ld /usr/lib/crt1.o /usr/lib/crti.o main.o -o main -lc -dynamic-linker /lib/ld-linux.so.2

main.o 需要和 crt1.o,crti.o 这两个目标文件链接在一起,从而生成可执行文件 main。你可以使用 readelf 命令来查看 crt1.o 文件的符号表,就会发现里面有一个 main 符号是未定义的,因此需要别的目标文件提供一个定义并且和 crt1.o 链接在一起(在 crt1.o 中要用到 main 这个符号所代表的地址,而 crt1.o 中的未定义符号 main 在 main.o 中定义了)。

下面看下crt1.o中的符号表:

parallels@ubuntu-linux-20-04-desktop:/usr/lib/aarch64-linux-gnu$ readelf -a crt1.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:                           AArch64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          1064 (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: 10

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.ABI-tag     NOTE             0000000000000000  00000040
       0000000000000020  0000000000000000   A       0     0     4
  [ 2] .text             PROGBITS         0000000000000000  00000060
       000000000000003c  0000000000000000  AX       0     0     4
  [ 3] .rela.text        RELA             0000000000000000  000002f0
       00000000000000d8  0000000000000018   I       8     2     8
  [ 4] .rodata.cst4      PROGBITS         0000000000000000  0000009c
       0000000000000004  0000000000000004  AM       0     0     4
  [ 5] .data             PROGBITS         0000000000000000  000000a0
       0000000000000004  0000000000000000  WA       0     0     1
  [ 6] .bss              NOBITS           0000000000000000  000000a4
       0000000000000000  0000000000000000  WA       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000a4
       0000000000000000  0000000000000000           0     0     1
  [ 8] .symtab           SYMTAB           0000000000000000  000000a8
       00000000000001e0  0000000000000018           9    11     8
  [ 9] .strtab           STRTAB           0000000000000000  00000288
       0000000000000067  0000000000000000           0     0     1
  [10] .shstrtab         STRTAB           0000000000000000  000003c8
       000000000000005c  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

There is no dynamic section in this file.

Relocation section '.rela.text' at offset 0x2f0 contains 9 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000018  000100000113 R_AARCH64_ADR_PRE 0000000000000000 .text + 38
00000000001c  000100000115 R_AARCH64_ADD_ABS 0000000000000000 .text + 38
000000000020  000e00000113 R_AARCH64_ADR_PRE 0000000000000000 __libc_csu_init + 0
000000000024  000e00000115 R_AARCH64_ADD_ABS 0000000000000000 __libc_csu_init + 0
000000000028  000b00000113 R_AARCH64_ADR_PRE 0000000000000000 __libc_csu_fini + 0
00000000002c  000b00000115 R_AARCH64_ADD_ABS 0000000000000000 __libc_csu_fini + 0
000000000030  00120000011b R_AARCH64_CALL26  0000000000000000 __libc_start_main + 0
000000000034  000c0000011b R_AARCH64_CALL26  0000000000000000 abort + 0
000000000038  000f0000011a R_AARCH64_JUMP26  0000000000000000 main + 0

The decoding of unwind sections for machine type AArch64 is not currently supported.

Symbol table '.symtab' contains 20 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     2: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    1 $d
     3: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    2 $x
     4: 0000000000000038     0 NOTYPE  LOCAL  DEFAULT    2 __wrap_main
     5: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    4 $d
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
    10: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
    11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_csu_fini
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND abort
    13: 0000000000000000     0 FUNC    GLOBAL DEFAULT    2 _start
    14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_csu_init
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND main
    16: 0000000000000000     0 NOTYPE  WEAK   DEFAULT    5 data_start
    17: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 _IO_stdin_used
    18: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_start_main
    19: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    5 __data_start

事实上,整个可执行程序真正的入口点是 crt1.o 中的 _start,而 main 函数是被 _start 调用的。

×

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/870942.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号