C语言程序的入口真的是main方法吗?
从刚开始学C语言的时候就给我们大脑里灌输了一个知识点: main函数是程序的入口,并且有且仅有一个.
当时我学习这个部分的时候对此深信不疑,main嘛,主嘛,那肯定就这个是入口了
根据后来的学习,慢慢地发现…好像这句话…真的是这样吗?如果是,那为什么会这样呢?或者说,为什么大家都说C语言main函数是程序的入口呢?
一段简单的C语言demo
#include<stdio.h>int main(){printf("hello world\n");return 0;}
这段代码很简单,都会写
那么gcc编译成a.out可执行文件后运行一下看看?
没有问题,能成功编译并且成功打印
对这个编译出来的可执行文件好好认识一下
由于我们知道,在linux平台的可执行文件一般是ELF文件,那么我们可以通过阅读elf文件的工具来看一看这个咋回事
执行指令 readelf -a a.out
ELF 头:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64数据: 2 补码,小端序 (little endian)版本: 1 (current)OS/ABI: UNIX - System VABI 版本: 0类型: EXEC (可执行文件)系统架构: Advanced Micro Devices X86-64版本: 0x1入口点地址: 0x400440程序头起点: 64 (bytes into file)Start of section headers: 6480 (bytes into file)标志: 0x0本头的大小: 64 (字节)程序头大小: 56 (字节)Number of program headers: 9节头大小: 64 (字节)节头数量: 30字符串表索引节头: 29节头:[号] 名称 类型 地址 偏移量大小 全体大小 旗标 链接 信息 对齐[ 0] NULL 0000000000000000 000000000000000000000000 0000000000000000 0 0 0[ 1] .interp PROGBITS 0000000000400238 00000238000000000000001c 0000000000000000 A 0 0 1[ 2] .note.ABI-tag NOTE 0000000000400254 000002540000000000000020 0000000000000000 A 0 0 4[ 3] .note.gnu.build-i NOTE 0000000000400274 000002740000000000000024 0000000000000000 A 0 0 4[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298000000000000001c 0000000000000000 A 5 0 8[ 5] .dynsym DYNSYM 00000000004002b8 000002b80000000000000060 0000000000000018 A 6 1 8[ 6] .dynstr STRTAB 0000000000400318 00000318000000000000003d 0000000000000000 A 0 0 1[ 7] .gnu.version VERSYM 0000000000400356 000003560000000000000008 0000000000000002 A 5 0 2[ 8] .gnu.version_r VERNEED 0000000000400360 000003600000000000000020 0000000000000000 A 6 1 8[ 9] .rela.dyn RELA 0000000000400380 000003800000000000000018 0000000000000018 A 5 0 8[10] .rela.plt RELA 0000000000400398 000003980000000000000048 0000000000000018 AI 5 23 8[11] .init PROGBITS 00000000004003e0 000003e0000000000000001a 0000000000000000 AX 0 0 4[12] .plt PROGBITS 0000000000400400 000004000000000000000040 0000000000000010 AX 0 0 16[13] .text PROGBITS 0000000000400440 000004400000000000000182 0000000000000000 AX 0 0 16[14] .fini PROGBITS 00000000004005c4 000005c40000000000000009 0000000000000000 AX 0 0 4[15] .rodata PROGBITS 00000000004005d0 000005d0000000000000001c 0000000000000000 A 0 0 8[16] .eh_frame_hdr PROGBITS 00000000004005ec 000005ec0000000000000034 0000000000000000 A 0 0 4[17] .eh_frame PROGBITS 0000000000400620 0000062000000000000000f4 0000000000000000 A 0 0 8[18] .init_array INIT_ARRAY 0000000000600e10 00000e100000000000000008 0000000000000008 WA 0 0 8[19] .fini_array FINI_ARRAY 0000000000600e18 00000e180000000000000008 0000000000000008 WA 0 0 8[20] .jcr PROGBITS 0000000000600e20 00000e200000000000000008 0000000000000000 WA 0 0 8[21] .dynamic DYNAMIC 0000000000600e28 00000e2800000000000001d0 0000000000000010 WA 6 0 8[22] .got PROGBITS 0000000000600ff8 00000ff80000000000000008 0000000000000008 WA 0 0 8[23] .got.plt PROGBITS 0000000000601000 000010000000000000000030 0000000000000008 WA 0 0 8[24] .data PROGBITS 0000000000601030 000010300000000000000004 0000000000000000 WA 0 0 1[25] .bss NOBITS 0000000000601034 000010340000000000000004 0000000000000000 WA 0 0 1[26] .comment PROGBITS 0000000000000000 00001034000000000000005a 0000000000000001 MS 0 0 1[27] .symtab SYMTAB 0000000000000000 0000109000000000000005e8 0000000000000018 28 46 8[28] .strtab STRTAB 0000000000000000 0000167800000000000001c9 0000000000000000 0 0 1[29] .shstrtab STRTAB 0000000000000000 000018410000000000000108 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),l (large), p (processor specific)There are no section groups in this file.程序头:Type Offset VirtAddr PhysAddrFileSiz MemSiz Flags AlignPHDR 0x0000000000000040 0x0000000000400040 0x00000000004000400x00000000000001f8 0x00000000000001f8 R E 8INTERP 0x0000000000000238 0x0000000000400238 0x00000000004002380x000000000000001c 0x000000000000001c R 1[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]LOAD 0x0000000000000000 0x0000000000400000 0x00000000004000000x0000000000000714 0x0000000000000714 R E 200000LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e100x0000000000000224 0x0000000000000228 RW 200000DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e280x00000000000001d0 0x00000000000001d0 RW 8NOTE 0x0000000000000254 0x0000000000400254 0x00000000004002540x0000000000000044 0x0000000000000044 R 4GNU_EH_FRAME 0x00000000000005ec 0x00000000004005ec 0x00000000004005ec0x0000000000000034 0x0000000000000034 R 4GNU_STACK 0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 RW 10GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e100x00000000000001f0 0x00000000000001f0 R 1Section to Segment mapping:段节...00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got Dynamic section at offset 0xe28 contains 24 entries:标记 类型 名称/值0x0000000000000001 (NEEDED) 共享库:[libc.so.6]0x000000000000000c (INIT) 0x4003e00x000000000000000d (FINI) 0x4005c40x0000000000000019 (INIT_ARRAY) 0x600e100x000000000000001b (INIT_ARRAYSZ) 8 (bytes)0x000000000000001a (FINI_ARRAY) 0x600e180x000000000000001c (FINI_ARRAYSZ) 8 (bytes)0x000000006ffffef5 (GNU_HASH) 0x4002980x0000000000000005 (STRTAB) 0x4003180x0000000000000006 (SYMTAB) 0x4002b80x000000000000000a (STRSZ) 61 (bytes)0x000000000000000b (SYMENT) 24 (bytes)0x0000000000000015 (DEBUG) 0x00x0000000000000003 (PLTGOT) 0x6010000x0000000000000002 (PLTRELSZ) 72 (bytes)0x0000000000000014 (PLTREL) RELA0x0000000000000017 (JMPREL) 0x4003980x0000000000000007 (RELA) 0x4003800x0000000000000008 (RELASZ) 24 (bytes)0x0000000000000009 (RELAENT) 24 (bytes)0x000000006ffffffe (VERNEED) 0x4003600x000000006fffffff (VERNEEDNUM) 10x000000006ffffff0 (VERSYM) 0x4003560x0000000000000000 (NULL) 0x0重定位节 '.rela.dyn' 位于偏移量 0x380 含有 1 个条目:偏移量 信息 类型 符号值 符号名称 + 加数
000000600ff8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0重定位节 '.rela.plt' 位于偏移量 0x398 含有 3 个条目:偏移量 信息 类型 符号值 符号名称 + 加数
000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000601028 000300000007 R_X86_64_JUMP_SLO 0000000000000000 __gmon_start__ + 0The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.Symbol table '.dynsym' contains 4 entries:Num: Value Size Type Bind Vis Ndx Name0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__Symbol table '.symtab' contains 63 entries:Num: Value Size Type Bind Vis Ndx Name0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 5: 00000000004002b8 0 SECTION LOCAL DEFAULT 5 6: 0000000000400318 0 SECTION LOCAL DEFAULT 6 7: 0000000000400356 0 SECTION LOCAL DEFAULT 7 8: 0000000000400360 0 SECTION LOCAL DEFAULT 8 9: 0000000000400380 0 SECTION LOCAL DEFAULT 9 10: 0000000000400398 0 SECTION LOCAL DEFAULT 10 11: 00000000004003e0 0 SECTION LOCAL DEFAULT 11 12: 0000000000400400 0 SECTION LOCAL DEFAULT 12 13: 0000000000400440 0 SECTION LOCAL DEFAULT 13 14: 00000000004005c4 0 SECTION LOCAL DEFAULT 14 15: 00000000004005d0 0 SECTION LOCAL DEFAULT 15 16: 00000000004005ec 0 SECTION LOCAL DEFAULT 16 17: 0000000000400620 0 SECTION LOCAL DEFAULT 17 18: 0000000000600e10 0 SECTION LOCAL DEFAULT 18 19: 0000000000600e18 0 SECTION LOCAL DEFAULT 19 20: 0000000000600e20 0 SECTION LOCAL DEFAULT 20 21: 0000000000600e28 0 SECTION LOCAL DEFAULT 21 22: 0000000000600ff8 0 SECTION LOCAL DEFAULT 22 23: 0000000000601000 0 SECTION LOCAL DEFAULT 23 24: 0000000000601030 0 SECTION LOCAL DEFAULT 24 25: 0000000000601034 0 SECTION LOCAL DEFAULT 25 26: 0000000000000000 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c28: 0000000000600e20 0 OBJECT LOCAL DEFAULT 20 __JCR_LIST__29: 0000000000400470 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones30: 00000000004004a0 0 FUNC LOCAL DEFAULT 13 register_tm_clones31: 00000000004004e0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux32: 0000000000601034 1 OBJECT LOCAL DEFAULT 25 completed.635533: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fin34: 0000000000400500 0 FUNC LOCAL DEFAULT 13 frame_dummy35: 0000000000600e10 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_36: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c37: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c38: 0000000000400710 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__39: 0000000000600e20 0 OBJECT LOCAL DEFAULT 20 __JCR_END__40: 0000000000000000 0 FILE LOCAL DEFAULT ABS 41: 0000000000600e18 0 NOTYPE LOCAL DEFAULT 18 __init_array_end42: 0000000000600e28 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC43: 0000000000600e10 0 NOTYPE LOCAL DEFAULT 18 __init_array_start44: 00000000004005ec 0 NOTYPE LOCAL DEFAULT 16 __GNU_EH_FRAME_HDR45: 0000000000601000 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_46: 00000000004005c0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini47: 0000000000601030 0 NOTYPE WEAK DEFAULT 24 data_start48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.549: 0000000000601034 0 NOTYPE GLOBAL DEFAULT 24 _edata50: 00000000004005c4 0 FUNC GLOBAL DEFAULT 14 _fini51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_52: 0000000000601030 0 NOTYPE GLOBAL DEFAULT 24 __data_start53: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__54: 00000000004005d8 0 OBJECT GLOBAL HIDDEN 15 __dso_handle55: 00000000004005d0 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used56: 0000000000400550 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init57: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 _end58: 0000000000400440 0 FUNC GLOBAL DEFAULT 13 _start59: 0000000000601034 0 NOTYPE GLOBAL DEFAULT 25 __bss_start60: 000000000040052d 21 FUNC GLOBAL DEFAULT 13 main61: 0000000000601038 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__62: 00000000004003e0 0 FUNC GLOBAL DEFAULT 11 _initVersion symbols section '.gnu.version' contains 4 entries:地址:0000000000400356 Offset: 0x000356 Link: 5 (.dynsym)000: 0 (*本地*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*本地*) Version needs section '.gnu.version_r' contains 1 entries:地址:0x0000000000400360 Offset: 0x000360 Link: 6 (.dynstr)000000: 版本: 1 文件:libc.so.6 计数:10x0010:名称:GLIBC_2.2.5 标志:无 版本:2Displaying notes found at file offset 0x00000254 with length 0x00000020:所有者 Data size DescriptionGNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)OS: Linux, ABI: 2.6.32Displaying notes found at file offset 0x00000274 with length 0x00000024:所有者 Data size DescriptionGNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)Build ID: a22f3cbab085833d1404bce09e1fd1fb7138db77
重点关注,程序的入口点地址 0x400440
通过另外一个指令objdump -S a.out
查看已经编译完之后反汇编的结果
a.out: 文件格式 elf64-x86-64Disassembly of section .init:00000000004003e0 <_init>:4003e0: 48 83 ec 08 sub $0x8,%rsp4003e4: 48 8b 05 0d 0c 20 00 mov 0x200c0d(%rip),%rax # 600ff8 <__gmon_start__>4003eb: 48 85 c0 test %rax,%rax4003ee: 74 05 je 4003f5 <_init+0x15>4003f0: e8 3b 00 00 00 callq 400430 <__gmon_start__@plt>4003f5: 48 83 c4 08 add $0x8,%rsp4003f9: c3 retq Disassembly of section .plt:0000000000400400 <.plt>:400400: ff 35 02 0c 20 00 pushq 0x200c02(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>400406: ff 25 04 0c 20 00 jmpq *0x200c04(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>40040c: 0f 1f 40 00 nopl 0x0(%rax)0000000000400410 <puts@plt>:400410: ff 25 02 0c 20 00 jmpq *0x200c02(%rip) # 601018 <puts@GLIBC_2.2.5>400416: 68 00 00 00 00 pushq $0x040041b: e9 e0 ff ff ff jmpq 400400 <.plt>0000000000400420 <__libc_start_main@plt>:400420: ff 25 fa 0b 20 00 jmpq *0x200bfa(%rip) # 601020 <__libc_start_main@GLIBC_2.2.5>400426: 68 01 00 00 00 pushq $0x140042b: e9 d0 ff ff ff jmpq 400400 <.plt>0000000000400430 <__gmon_start__@plt>:400430: ff 25 f2 0b 20 00 jmpq *0x200bf2(%rip) # 601028 <__gmon_start__>400436: 68 02 00 00 00 pushq $0x240043b: e9 c0 ff ff ff jmpq 400400 <.plt>Disassembly of section .text:0000000000400440 <_start>:400440: 31 ed xor %ebp,%ebp400442: 49 89 d1 mov %rdx,%r9400445: 5e pop %rsi400446: 48 89 e2 mov %rsp,%rdx400449: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp40044d: 50 push %rax40044e: 54 push %rsp40044f: 49 c7 c0 c0 05 40 00 mov $0x4005c0,%r8400456: 48 c7 c1 50 05 40 00 mov $0x400550,%rcx40045d: 48 c7 c7 2d 05 40 00 mov $0x40052d,%rdi400464: e8 b7 ff ff ff callq 400420 <__libc_start_main@plt>400469: f4 hlt 40046a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)0000000000400470 <deregister_tm_clones>:400470: b8 3f 10 60 00 mov $0x60103f,%eax400475: 55 push %rbp400476: 48 2d 38 10 60 00 sub $0x601038,%rax40047c: 48 83 f8 0e cmp $0xe,%rax400480: 48 89 e5 mov %rsp,%rbp400483: 77 02 ja 400487 <deregister_tm_clones+0x17>400485: 5d pop %rbp400486: c3 retq 400487: b8 00 00 00 00 mov $0x0,%eax40048c: 48 85 c0 test %rax,%rax40048f: 74 f4 je 400485 <deregister_tm_clones+0x15>400491: 5d pop %rbp400492: bf 38 10 60 00 mov $0x601038,%edi400497: ff e0 jmpq *%rax400499: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)00000000004004a0 <register_tm_clones>:4004a0: b8 38 10 60 00 mov $0x601038,%eax4004a5: 55 push %rbp4004a6: 48 2d 38 10 60 00 sub $0x601038,%rax4004ac: 48 c1 f8 03 sar $0x3,%rax4004b0: 48 89 e5 mov %rsp,%rbp4004b3: 48 89 c2 mov %rax,%rdx4004b6: 48 c1 ea 3f shr $0x3f,%rdx4004ba: 48 01 d0 add %rdx,%rax4004bd: 48 d1 f8 sar %rax4004c0: 75 02 jne 4004c4 <register_tm_clones+0x24>4004c2: 5d pop %rbp4004c3: c3 retq 4004c4: ba 00 00 00 00 mov $0x0,%edx4004c9: 48 85 d2 test %rdx,%rdx4004cc: 74 f4 je 4004c2 <register_tm_clones+0x22>4004ce: 5d pop %rbp4004cf: 48 89 c6 mov %rax,%rsi4004d2: bf 38 10 60 00 mov $0x601038,%edi4004d7: ff e2 jmpq *%rdx4004d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)00000000004004e0 <__do_global_dtors_aux>:4004e0: 80 3d 4d 0b 20 00 00 cmpb $0x0,0x200b4d(%rip) # 601034 <_edata>4004e7: 75 11 jne 4004fa <__do_global_dtors_aux+0x1a>4004e9: 55 push %rbp4004ea: 48 89 e5 mov %rsp,%rbp4004ed: e8 7e ff ff ff callq 400470 <deregister_tm_clones>4004f2: 5d pop %rbp4004f3: c6 05 3a 0b 20 00 01 movb $0x1,0x200b3a(%rip) # 601034 <_edata>4004fa: f3 c3 repz retq 4004fc: 0f 1f 40 00 nopl 0x0(%rax)0000000000400500 <frame_dummy>:400500: 48 83 3d 18 09 20 00 cmpq $0x0,0x200918(%rip) # 600e20 <__JCR_END__>400507: 00 400508: 74 1e je 400528 <frame_dummy+0x28>40050a: b8 00 00 00 00 mov $0x0,%eax40050f: 48 85 c0 test %rax,%rax400512: 74 14 je 400528 <frame_dummy+0x28>400514: 55 push %rbp400515: bf 20 0e 60 00 mov $0x600e20,%edi40051a: 48 89 e5 mov %rsp,%rbp40051d: ff d0 callq *%rax40051f: 5d pop %rbp400520: e9 7b ff ff ff jmpq 4004a0 <register_tm_clones>400525: 0f 1f 00 nopl (%rax)400528: e9 73 ff ff ff jmpq 4004a0 <register_tm_clones>000000000040052d <main>:40052d: 55 push %rbp40052e: 48 89 e5 mov %rsp,%rbp400531: bf e0 05 40 00 mov $0x4005e0,%edi400536: e8 d5 fe ff ff callq 400410 <puts@plt>40053b: b8 00 00 00 00 mov $0x0,%eax400540: 5d pop %rbp400541: c3 retq 400542: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)400549: 00 00 00 40054c: 0f 1f 40 00 nopl 0x0(%rax)0000000000400550 <__libc_csu_init>:400550: 41 57 push %r15400552: 41 89 ff mov %edi,%r15d400555: 41 56 push %r14400557: 49 89 f6 mov %rsi,%r1440055a: 41 55 push %r1340055c: 49 89 d5 mov %rdx,%r1340055f: 41 54 push %r12400561: 4c 8d 25 a8 08 20 00 lea 0x2008a8(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>400568: 55 push %rbp400569: 48 8d 2d a8 08 20 00 lea 0x2008a8(%rip),%rbp # 600e18 <__init_array_end>400570: 53 push %rbx400571: 4c 29 e5 sub %r12,%rbp400574: 31 db xor %ebx,%ebx400576: 48 c1 fd 03 sar $0x3,%rbp40057a: 48 83 ec 08 sub $0x8,%rsp40057e: e8 5d fe ff ff callq 4003e0 <_init>400583: 48 85 ed test %rbp,%rbp400586: 74 1e je 4005a6 <__libc_csu_init+0x56>400588: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)40058f: 00 400590: 4c 89 ea mov %r13,%rdx400593: 4c 89 f6 mov %r14,%rsi400596: 44 89 ff mov %r15d,%edi400599: 41 ff 14 dc callq *(%r12,%rbx,8)40059d: 48 83 c3 01 add $0x1,%rbx4005a1: 48 39 eb cmp %rbp,%rbx4005a4: 75 ea jne 400590 <__libc_csu_init+0x40>4005a6: 48 83 c4 08 add $0x8,%rsp4005aa: 5b pop %rbx4005ab: 5d pop %rbp4005ac: 41 5c pop %r124005ae: 41 5d pop %r134005b0: 41 5e pop %r144005b2: 41 5f pop %r154005b4: c3 retq 4005b5: 90 nop4005b6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)4005bd: 00 00 00 00000000004005c0 <__libc_csu_fini>:4005c0: f3 c3 repz retq Disassembly of section .fini:00000000004005c4 <_fini>:4005c4: 48 83 ec 08 sub $0x8,%rsp4005c8: 48 83 c4 08 add $0x8,%rsp4005cc: c3 retq
可以看到我们当前的a.out程序的main函数对应的汇编指令的起始地址是000000000040052d,并不是一开始在elf文件中显示的那个0x400440,不过你会发现,有一个代码段是0x400440 <_start>
所以至此我们可以知道<_start> 便是C语言程序的入口,操作系统调用程序的第一行执行的代码,并不是main函数中的指令
那么,是怎么到main的呢??
下面来看看glibc中的一些内容
_start的节选:
很显然,调用了一个__libc_start_main@PLT
说明这个地方是用到了动态链接的,将__libc_start_main
链接到了当前的这个地方来
而__libc_start_main
干了件什么事呢?? 也就是进到了csu文件夹下的libc-start.c的LIBC_START_MAIN
方法中(因为这个libc-start.c头部有段宏定义# define LIBC_START_MAIN __libc_start_main
)
STATIC int
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),int argc, char **argv,
#ifdef LIBC_START_MAIN_AUXVEC_ARGElfW(auxv_t) *auxvec,
#endif__typeof (main) init,void (*fini) (void),void (*rtld_fini) (void), void *stack_end)
{/* Result of the 'main' function. */int result;__libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;#ifndef SHARED_dl_relocate_static_pie ();char **ev = &argv[argc + 1];__environ = ev;/* Store the lowest stack address. This is done in ld.so if this isthe code for the DSO. */__libc_stack_end = stack_end;# ifdef HAVE_AUX_VECTOR/* First process the auxiliary vector since we need to find theprogram header to locate an eventually present PT_TLS entry. */
# ifndef LIBC_START_MAIN_AUXVEC_ARGElfW(auxv_t) *auxvec;{char **evp = ev;while (*evp++ != NULL);auxvec = (ElfW(auxv_t) *) evp;}
# endif_dl_aux_init (auxvec);if (GL(dl_phdr) == NULL)
# endif{/* Starting from binutils-2.23, the linker will define themagic symbol __ehdr_start to point to our own ELF headerif it is visible in a segment that also includes the phdrs.So we can set up _dl_phdr and _dl_phnum even without anyinformation from auxv. */extern const ElfW(Ehdr) __ehdr_start__attribute__ ((weak, visibility ("hidden")));if (&__ehdr_start != NULL){assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;GL(dl_phnum) = __ehdr_start.e_phnum;}}/* Initialize very early so that tunables can use it. */__libc_init_secure ();__tunables_init (__environ);ARCH_INIT_CPU_FEATURES ();/* Perform IREL{,A} relocations. */ARCH_SETUP_IREL ();/* The stack guard goes into the TCB, so initialize it early. */ARCH_SETUP_TLS ();/* In some architectures, IREL{,A} relocations happen after TLS setup inorder to let IFUNC resolvers benefit from TCB information, e.g. powerpc'shwcap and platform fields available in the TCB. */ARCH_APPLY_IREL ();/* Set up the stack checker's canary. */uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
# ifdef THREAD_SET_STACK_GUARDTHREAD_SET_STACK_GUARD (stack_chk_guard);
# else__stack_chk_guard = stack_chk_guard;
# endif# ifdef DL_SYSDEP_OSCHECKif (!__libc_multiple_libcs){/* This needs to run to initiliaze _dl_osversion before TLSsetup might check it. */DL_SYSDEP_OSCHECK (__libc_fatal);}
# endif/* Initialize libpthread if linked in. */if (__pthread_initialize_minimal != NULL)__pthread_initialize_minimal ();/* Set up the pointer guard value. */uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,stack_chk_guard);
# ifdef THREAD_SET_POINTER_GUARDTHREAD_SET_POINTER_GUARD (pointer_chk_guard);
# else__pointer_chk_guard_local = pointer_chk_guard;
# endif#endif /* !SHARED *//* Register the destructor of the dynamic linker if there is any. */if (__glibc_likely (rtld_fini != NULL))__cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);#ifndef SHARED/* Call the initializer of the libc. This is only needed here if weare compiling for the static library in which case we haven'trun the constructors in `_dl_start_user'. */__libc_init_first (argc, argv, __environ);/* Register the destructor of the program, if any. */if (fini)__cxa_atexit ((void (*) (void *)) fini, NULL, NULL);/* Some security at this point. Prevent starting a SUID binary wherethe standard file descriptors are not opened. We have to do thisonly for statically linked applications since otherwise the dynamicloader did the work already. */if (__builtin_expect (__libc_enable_secure, 0))__libc_check_standard_fds ();
#endif/* Call the initializer of the program, if any. */
#ifdef SHAREDif (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
#endifif (init)(*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);#ifdef SHARED/* Auditing checkpoint: we have a new object. */if (__glibc_unlikely (GLRO(dl_naudit) > 0)){struct audit_ifaces *afct = GLRO(dl_audit);struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt){if (afct->preinit != NULL)afct->preinit (&head->l_audit[cnt].cookie);afct = afct->next;}}
#endif#ifdef SHAREDif (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
#endif#ifndef SHARED_dl_debug_initialize (0, LM_ID_BASE);
#endif
#ifdef HAVE_CLEANUP_JMP_BUF/* Memory for the cancellation buffer. */struct pthread_unwind_buf unwind_buf;int not_first_call;not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);if (__glibc_likely (! not_first_call)){struct pthread *self = THREAD_SELF;/* Store old info. */unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);/* Store the new cleanup handler info. */THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);/* Run the program. */result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);}else{/* Remove the thread-local data. */
# ifdef SHAREDPTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
# elseextern void __nptl_deallocate_tsd (void) __attribute ((weak));__nptl_deallocate_tsd ();
# endif/* One less thread. Decrement the counter. If it is zero weterminate the entire process. */result = 0;
# ifdef SHAREDunsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
# ifdef PTR_DEMANGLEPTR_DEMANGLE (ptr);
# endif
# elseextern unsigned int __nptl_nthreads __attribute ((weak));unsigned int *const ptr = &__nptl_nthreads;
# endifif (! atomic_decrement_and_test (ptr))/* Not much left to do but to exit the thread, not the process. */__exit_thread ();}
#else/* Nothing fancy, just call the function. */result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
#endifexit (result);
}
重点关注 先 if (init) (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
然后经过一系列动态链接的过程,最终调用 LIBC_START_MAIN
中的main方法,至此程序才正式进入到main方法
所以…C语言程序的入口是main函数么?你们怎么觉得的呢???
C语言程序的入口真的是main方法吗?相关推荐
- 《JAVA 语言程序设计基础篇》chapter 5 方法
<JAVA 语言程序设计基础篇>chapter 5 方法 依然是先回顾一下上一章的内容 主要是关于循环语句 这里做一个有关于蒙特卡罗模拟有关的练习 先是一段背景介绍 蒙特卡罗方法通过抓住事 ...
- c语言清除键盘缓冲区函数,C语言程序中清除键盘缓冲区的方法
第四期2006年12月益阳职业技术学院学报 JournalofYiyangVocationalandTechnicalCollegeNO.4Dec.2006 C语言程序中清除键盘缓冲区的方法 杨长虹 ...
- c语言程序的入口是哪部分,C语言入口函数和LD_PRELOAD环境变量
零.C语言入口函数 从第一天学习C语言开始,我们的脑子里就深深烙下这样一个概念:C语言程序总是从main()函数开始执行,main()函数结束,程序也就结束了.在平时的练习中貌似这没有问题,但事实真的 ...
- c语言程序 5ms 延时,计算机单片机延时方法电脑c语言.docx
计算机单片机延时方法电脑C 语言 您需要登录后才可以回帖登录| 注册发布 单片机是一种集成电路芯片,是采用超大规模集成电路技术把 具有数据处理能力的中央处理器CPU.随机存储器RAM.只读存储器 RO ...
- Linux系统中创建C语言程序文件并编译执行的方法
使用vim编辑器创建并编辑C语言源程序文件 执行命令"vim button_led.c"打开Button_Led目录下button_led.c源程序文件并进行编 ...
- linux下运行c语言程序报Segmentation Fault的定位方法
打开终端,然后输入以下命令开启ulimit ulimit -c unlimited # 打开ulimit ulimit -c # 如果打开成功会返回unlimited PS:以上开启ulimit的操作 ...
- 杨辉三角python语言程序思路_python杨辉三角方法的实例介绍
程序输出需要实现如下效果:[1] [1,1] [1,2,1] [1,3,3,1] ...... 方法:迭代,生成器def triangles() L = [1] while True: yiled L ...
- 激光测距仪系统设计 c语言程序),基于时差法的激光测距方法与应用
摘要: 激光测距技术被发现并研制出以后,因为它的测量精度非常高,与其他传统测距技术相比具有的优点非常多,并且激光测距基本能够应用在所有测量环境,激光测距的基本方法是用激光在目标物与发射器之间传播时间来 ...
- Java中的main方法
2019独角兽企业重金招聘Python工程师标准>>> 在一个Java应用程序中,通常程序的入口是一个main方法,它被声明为公有静态方法,参数是一个字符串数组,返回值为Void类型 ...
最新文章
- FPGA中的Logic Cells, Logic Slices, Configurable Logic Blocks and Gates 的定义
- 稀疏多项式的运算用链表_用漫画告诉你—什么是HashMap?
- 用CSS的 filter 来轻松实现图层半透明
- 20.毛玻璃效果blur
- 巧用拦截器:高效的扩展点设计
- Spark Metrics配置详解
- linux服务器做301跳转,nginx 实现当找不到文件时实现301跳转
- C++基础——类模板
- Android计分器课程设计,比赛计分器课程设计.doc
- linux能yum装mcafee吗,Ubuntu安装Mcafee步骤
- .kux转mp4文件
- 微信小程序tabBar闪烁问题
- 关于癌症的思考:癌症的本质是什么
- 类动态规划求解较小规模的最大团问题(Python实现)
- Python设置32位环境
- c语言中立方和乘法怎么表示什么区别,c语言中的乘方符号是什么?
- 设计模式之观察者模式详解(附应用举例实现)
- mac下统计代码行数方法
- Apache Velocity 模板语言 特殊字符${ $!{ 原样输出问题 转义符 # ! 无效
- windows 没有应用商店,直接安装所需应用的解决方案
热门文章
- Pyecharts绘制上下组合图、左右组合图、一轴多图,超经典!
- php文件如何上传到服务器,php文件怎么上传到云服务器
- 卡巴斯基网络安全解决方案-服务器虚拟化安全2.0安装方法,营销材料(内部)_卡巴斯基网络安全解决方案-虚拟化安全(KSV2.0)_V1.0.docx...
- High performance server architecture(高性能服务器架构)
- 迭代求解线性方程组的解
- ElasticSerach7.6.0拼音分词器安装和使用
- 最好的vsftpd配置教程
- 实时语音通讯的回音消除技术详解
- 每天学点英语语法-重头开始8
- c程序的基本组成单位是什么?