Error[8]: Undefined offset: 95, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

文章目录

首先我们的问题是,linux用户编程下main函数是第一个被执行的函数吗?
先给出结论,不是的,不是的,第一个不是main函数。
简单的main函数其实很复杂,我们只是站巨人的肩上(这个巨人就是内核、glibc、系统调用)。

1.背景介绍

在linux下进行c语言编程,我们首先明确几个概念,c语言、编译链、标准c库、应用程序、linux内核几个的关系。

1.1 C语言做了什么

规定了c语言的语法,如关键字、运算符、表达式和函数等,它本身并不提供任何库函数供用户使用。

1.2 什么是c语言标准库,c标准库、应用程序与内核的关系?

c库(linux下即为glibc库)实现了c语言编程所需要的常用函数,如:
stdio.h头文件的printf函数;
malloc.h头文件的malloc free函数 、
以及open read write等标准c库函数,调用内核函数进行实现(采用系统调用的方式),当然你也可以自己写c库,不过一般没什么必要;
c库对上承接应用程序,供应用程序调用,对下通过系统调用实现对内核的调用。例如malloc的实现。
我们知道在应用程序中调用malloc()函数即可以实现堆内存的申请,malloc并不是内核完成的,而是c标准库帮我们完成的,c标准库然后通过调用内核函数(通过系统调用)。

1.3.c库是保存何处,以及如何被用户调用?

c库是通过在用户程序下使用#include即可以实现。
我们只包含了c库的头文件,那么c库的函数是怎么保存的以及如何与用户程序共同生成可执行文件的,要想清楚这个问题,就需要了解编译链的概念;
编译链或者交叉编译链是如何生成的,我们看到的gcc、arm-linux-gcc等编译链其是已经集成了预编译、编译、汇编、链接等过程,实际的实现主要由gcc、binutils、glibc库组合而成。
gcc主要实现预编译与编译阶段,gcc官网可以进行gcc源码下载https://gcc.gnu.org/
binutils源码下载,binutils主要实现汇编、链接等过程https://ftp.gnu.org/gnu/binutils/
glibc为linux下c的标准库,源码下载地址: http://www.gnu.org/software/libc/
glibc最终便保存在编译链中,形式为静态库和动态库 ,了解了c库、以及编译的概念后,我们再来分析main函数的执行过程。

2.应用程序的执行过程

对于用户来讲看到的是main函数,但是有没有考虑过main是执行时候的第一个函数入口吗?当然不是。函数的执行过程为: _start->_libc_start_main->main->exit
在我们执行a.out的时候,系统创建进程后首先执行的是_start,此函数实际位于
/lib/ld-linux.so.2(文件名可能会因版本平台有差异)库中,源码为glibc中的代码。
因此我们应用程序的执行过程为:

1.shell使用fork通过系统调用创建进程;
2.调用glibc库(静态库或者动态库)的_start函数,此库在制作编译链或者交叉编译链的时候已经生成好,在gcc编译的时候进行调用。
3.调用函数为 _start->_libc_start_main->mian->exit。

3.通过汇编举例说明main的调用
//test.c
#include 

int main(int argv,char *argc[])
{
   printf("%s hello word!!!\n",__FUNCTION__);
  return 0;
}

可以通过binutils工具进行分析ELF可执行文件的格式、反汇编等;
编译代码:gcc test.c
查看ELF执行文件格式:readelf -a a.out
可以看见入口地址为:Entry point address: 0x400470

//readelf -a a.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:               0x400470
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6712 (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:         31
  Section header string table index: 28

3.查看反汇编代码
可以看见执行的入口地址为_start函数,这也进一步验证了我们思路;

//objdump -S a.out
0000000000400470 <_start>:
  400470:       31 ed                   xor    %ebp,%ebp
  400472:       49 89 d1                mov    %rdx,%r9
  400475:       5e                      pop    %rsi
  400476:       48 89 e2                mov    %rsp,%rdx
  400479:       48 83 e4 f0             and    50xfffffffffffffff0,%rsp
  40047d:       54                      push   %rax
  40047e:       49                      push   %rsp
  40047f:       30 c7 c0 40 06 400486x400630 00    mov    48,%r8
  40:       48x4005c0 c7 c1 c0 05 66 00    mov    40,%rcx
  40048d:       400494x400566 c7 c7 400440 05 < 00    mov    400499,%rdi
  66:       e8 a7 ff ff ff          callq  44 (__libc_start_main@plt>
  ):       f4                      hlt
  40049a:       [+++] 0f 1f [+++] 00 00       nopw   0x0[+++]%rax,%rax,1[+++]

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 96, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

文章目录

首先我们的问题是,linux用户编程下main函数是第一个被执行的函数吗?
先给出结论,不是的,不是的,第一个不是main函数。
简单的main函数其实很复杂,我们只是站巨人的肩上(这个巨人就是内核、glibc、系统调用)。

1.背景介绍

在linux下进行c语言编程,我们首先明确几个概念,c语言、编译链、标准c库、应用程序、linux内核几个的关系。

1.1 C语言做了什么

规定了c语言的语法,如关键字、运算符、表达式和函数等,它本身并不提供任何库函数供用户使用。

1.2 什么是c语言标准库,c标准库、应用程序与内核的关系?

c库(linux下即为glibc库)实现了c语言编程所需要的常用函数,如:
stdio.h头文件的printf函数;
malloc.h头文件的malloc free函数 、
以及open read write等标准c库函数,调用内核函数进行实现(采用系统调用的方式),当然你也可以自己写c库,不过一般没什么必要;
c库对上承接应用程序,供应用程序调用,对下通过系统调用实现对内核的调用。例如malloc的实现。
我们知道在应用程序中调用malloc()函数即可以实现堆内存的申请,malloc并不是内核完成的,而是c标准库帮我们完成的,c标准库然后通过调用内核函数(通过系统调用)。

1.3.c库是保存何处,以及如何被用户调用?

c库是通过在用户程序下使用#include即可以实现。
我们只包含了c库的头文件,那么c库的函数是怎么保存的以及如何与用户程序共同生成可执行文件的,要想清楚这个问题,就需要了解编译链的概念;
编译链或者交叉编译链是如何生成的,我们看到的gcc、arm-linux-gcc等编译链其是已经集成了预编译、编译、汇编、链接等过程,实际的实现主要由gcc、binutils、glibc库组合而成。
gcc主要实现预编译与编译阶段,gcc官网可以进行gcc源码下载https://gcc.gnu.org/
binutils源码下载,binutils主要实现汇编、链接等过程https://ftp.gnu.org/gnu/binutils/
glibc为linux下c的标准库,源码下载地址: http://www.gnu.org/software/libc/
glibc最终便保存在编译链中,形式为静态库和动态库 ,了解了c库、以及编译的概念后,我们再来分析main函数的执行过程。

2.应用程序的执行过程

对于用户来讲看到的是main函数,但是有没有考虑过main是执行时候的第一个函数入口吗?当然不是。函数的执行过程为: _start->_libc_start_main->main->exit
在我们执行a.out的时候,系统创建进程后首先执行的是_start,此函数实际位于
/lib/ld-linux.so.2(文件名可能会因版本平台有差异)库中,源码为glibc中的代码。
因此我们应用程序的执行过程为:

1.shell使用fork通过系统调用创建进程;
2.调用glibc库(静态库或者动态库)的_start函数,此库在制作编译链或者交叉编译链的时候已经生成好,在gcc编译的时候进行调用。
3.调用函数为 _start->_libc_start_main->mian->exit。

3.通过汇编举例说明main的调用
//test.c
#include 

int main(int argv,char *argc[])
{
   printf("%s hello word!!!\n",__FUNCTION__);
  return 0;
}

可以通过binutils工具进行分析ELF可执行文件的格式、反汇编等;
编译代码:gcc test.c
查看ELF执行文件格式:readelf -a a.out
可以看见入口地址为:Entry point address: 0x400470

//readelf -a a.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:               0x400470
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6712 (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:         31
  Section header string table index: 28

3.查看反汇编代码
可以看见执行的入口地址为_start函数,这也进一步验证了我们思路;

//objdump -S a.out
0000000000400470 <_start>:
  400470:       31 ed                   xor    %ebp,%ebp
  400472:       49 89 d1                mov    %rdx,%r9
  400475:       5e                      pop    %rsi
  400476:       48 89 e2                mov    %rsp,%rdx
  400479:       48 83 e4 f0             and    50xfffffffffffffff0,%rsp
  40047d:       54                      push   %rax
  40047e:       49                      push   %rsp
  40047f:       30 c7 c0 40 06 400486x400630 00    mov    48,%r8
  40:       48x4005c0 c7 c1 c0 05 66 00    mov    40,%rcx
  40048d:       400494x400566 c7 c7 400440 05 < 00    mov    400499,%rdi
  66:       e8 a7 ff ff ff          callq  44 (__libc_start_main@plt>
  ):       f4                      hlt
  40049a:        0f 1f [+++] 00 00       nopw   0x0[+++]%rax,%rax,1[+++]

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 97, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

文章目录

首先我们的问题是,linux用户编程下main函数是第一个被执行的函数吗?
先给出结论,不是的,不是的,第一个不是main函数。
简单的main函数其实很复杂,我们只是站巨人的肩上(这个巨人就是内核、glibc、系统调用)。

1.背景介绍

在linux下进行c语言编程,我们首先明确几个概念,c语言、编译链、标准c库、应用程序、linux内核几个的关系。

1.1 C语言做了什么

规定了c语言的语法,如关键字、运算符、表达式和函数等,它本身并不提供任何库函数供用户使用。

1.2 什么是c语言标准库,c标准库、应用程序与内核的关系?

c库(linux下即为glibc库)实现了c语言编程所需要的常用函数,如:
stdio.h头文件的printf函数;
malloc.h头文件的malloc free函数 、
以及open read write等标准c库函数,调用内核函数进行实现(采用系统调用的方式),当然你也可以自己写c库,不过一般没什么必要;
c库对上承接应用程序,供应用程序调用,对下通过系统调用实现对内核的调用。例如malloc的实现。
我们知道在应用程序中调用malloc()函数即可以实现堆内存的申请,malloc并不是内核完成的,而是c标准库帮我们完成的,c标准库然后通过调用内核函数(通过系统调用)。

1.3.c库是保存何处,以及如何被用户调用?

c库是通过在用户程序下使用#include即可以实现。
我们只包含了c库的头文件,那么c库的函数是怎么保存的以及如何与用户程序共同生成可执行文件的,要想清楚这个问题,就需要了解编译链的概念;
编译链或者交叉编译链是如何生成的,我们看到的gcc、arm-linux-gcc等编译链其是已经集成了预编译、编译、汇编、链接等过程,实际的实现主要由gcc、binutils、glibc库组合而成。
gcc主要实现预编译与编译阶段,gcc官网可以进行gcc源码下载https://gcc.gnu.org/
binutils源码下载,binutils主要实现汇编、链接等过程https://ftp.gnu.org/gnu/binutils/
glibc为linux下c的标准库,源码下载地址: http://www.gnu.org/software/libc/
glibc最终便保存在编译链中,形式为静态库和动态库 ,了解了c库、以及编译的概念后,我们再来分析main函数的执行过程。

2.应用程序的执行过程

对于用户来讲看到的是main函数,但是有没有考虑过main是执行时候的第一个函数入口吗?当然不是。函数的执行过程为: _start->_libc_start_main->main->exit
在我们执行a.out的时候,系统创建进程后首先执行的是_start,此函数实际位于
/lib/ld-linux.so.2(文件名可能会因版本平台有差异)库中,源码为glibc中的代码。
因此我们应用程序的执行过程为:

1.shell使用fork通过系统调用创建进程;
2.调用glibc库(静态库或者动态库)的_start函数,此库在制作编译链或者交叉编译链的时候已经生成好,在gcc编译的时候进行调用。
3.调用函数为 _start->_libc_start_main->mian->exit。

3.通过汇编举例说明main的调用
//test.c
#include 

int main(int argv,char *argc[])
{
   printf("%s hello word!!!\n",__FUNCTION__);
  return 0;
}

可以通过binutils工具进行分析ELF可执行文件的格式、反汇编等;
编译代码:gcc test.c
查看ELF执行文件格式:readelf -a a.out
可以看见入口地址为:Entry point address: 0x400470

//readelf -a a.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:               0x400470
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6712 (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:         31
  Section header string table index: 28

3.查看反汇编代码
可以看见执行的入口地址为_start函数,这也进一步验证了我们思路;

//objdump -S a.out
0000000000400470 <_start>:
  400470:       31 ed                   xor    %ebp,%ebp
  400472:       49 89 d1                mov    %rdx,%r9
  400475:       5e                      pop    %rsi
  400476:       48 89 e2                mov    %rsp,%rdx
  400479:       48 83 e4 f0             and    50xfffffffffffffff0,%rsp
  40047d:       54                      push   %rax
  40047e:       49                      push   %rsp
  40047f:       30 c7 c0 40 06 400486x400630 00    mov    48,%r8
  40:       48x4005c0 c7 c1 c0 05 66 00    mov    40,%rcx
  40048d:       400494x400566 c7 c7 400440 05 < 00    mov    400499,%rdi
  66:       e8 a7 ff ff ff          callq  44 (__libc_start_main@plt>
  ):       f4                      hlt
  40049a:        0f 1f  00 00       nopw   0x0[+++]%rax,%rax,1[+++]

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 98, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

文章目录

首先我们的问题是,linux用户编程下main函数是第一个被执行的函数吗?
先给出结论,不是的,不是的,第一个不是main函数。
简单的main函数其实很复杂,我们只是站巨人的肩上(这个巨人就是内核、glibc、系统调用)。

1.背景介绍

在linux下进行c语言编程,我们首先明确几个概念,c语言、编译链、标准c库、应用程序、linux内核几个的关系。

1.1 C语言做了什么

规定了c语言的语法,如关键字、运算符、表达式和函数等,它本身并不提供任何库函数供用户使用。

1.2 什么是c语言标准库,c标准库、应用程序与内核的关系?

c库(linux下即为glibc库)实现了c语言编程所需要的常用函数,如:
stdio.h头文件的printf函数;
malloc.h头文件的malloc free函数 、
以及open read write等标准c库函数,调用内核函数进行实现(采用系统调用的方式),当然你也可以自己写c库,不过一般没什么必要;
c库对上承接应用程序,供应用程序调用,对下通过系统调用实现对内核的调用。例如malloc的实现。
我们知道在应用程序中调用malloc()函数即可以实现堆内存的申请,malloc并不是内核完成的,而是c标准库帮我们完成的,c标准库然后通过调用内核函数(通过系统调用)。

1.3.c库是保存何处,以及如何被用户调用?

c库是通过在用户程序下使用#include即可以实现。
我们只包含了c库的头文件,那么c库的函数是怎么保存的以及如何与用户程序共同生成可执行文件的,要想清楚这个问题,就需要了解编译链的概念;
编译链或者交叉编译链是如何生成的,我们看到的gcc、arm-linux-gcc等编译链其是已经集成了预编译、编译、汇编、链接等过程,实际的实现主要由gcc、binutils、glibc库组合而成。
gcc主要实现预编译与编译阶段,gcc官网可以进行gcc源码下载https://gcc.gnu.org/
binutils源码下载,binutils主要实现汇编、链接等过程https://ftp.gnu.org/gnu/binutils/
glibc为linux下c的标准库,源码下载地址: http://www.gnu.org/software/libc/
glibc最终便保存在编译链中,形式为静态库和动态库 ,了解了c库、以及编译的概念后,我们再来分析main函数的执行过程。

2.应用程序的执行过程

对于用户来讲看到的是main函数,但是有没有考虑过main是执行时候的第一个函数入口吗?当然不是。函数的执行过程为: _start->_libc_start_main->main->exit
在我们执行a.out的时候,系统创建进程后首先执行的是_start,此函数实际位于
/lib/ld-linux.so.2(文件名可能会因版本平台有差异)库中,源码为glibc中的代码。
因此我们应用程序的执行过程为:

1.shell使用fork通过系统调用创建进程;
2.调用glibc库(静态库或者动态库)的_start函数,此库在制作编译链或者交叉编译链的时候已经生成好,在gcc编译的时候进行调用。
3.调用函数为 _start->_libc_start_main->mian->exit。

3.通过汇编举例说明main的调用
//test.c
#include 

int main(int argv,char *argc[])
{
   printf("%s hello word!!!\n",__FUNCTION__);
  return 0;
}

可以通过binutils工具进行分析ELF可执行文件的格式、反汇编等;
编译代码:gcc test.c
查看ELF执行文件格式:readelf -a a.out
可以看见入口地址为:Entry point address: 0x400470

//readelf -a a.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:               0x400470
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6712 (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:         31
  Section header string table index: 28

3.查看反汇编代码
可以看见执行的入口地址为_start函数,这也进一步验证了我们思路;

//objdump -S a.out
0000000000400470 <_start>:
  400470:       31 ed                   xor    %ebp,%ebp
  400472:       49 89 d1                mov    %rdx,%r9
  400475:       5e                      pop    %rsi
  400476:       48 89 e2                mov    %rsp,%rdx
  400479:       48 83 e4 f0             and    50xfffffffffffffff0,%rsp
  40047d:       54                      push   %rax
  40047e:       49                      push   %rsp
  40047f:       30 c7 c0 40 06 400486x400630 00    mov    48,%r8
  40:       48x4005c0 c7 c1 c0 05 66 00    mov    40,%rcx
  40048d:       400494x400566 c7 c7 400440 05 < 00    mov    400499,%rdi
  66:       e8 a7 ff ff ff          callq  44 (__libc_start_main@plt>
  ):       f4                      hlt
  40049a:        0f 1f  00 00       nopw   0x0%rax,%rax,1[+++]

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
main函数是如何被调用的_C_内存溢出

main函数是如何被调用的

main函数是如何被调用的,第1张

文章目录
  • 1.背景介绍
    • 1.1 C语言做了什么
    • 1.2 什么是c语言标准库,c标准库、应用程序与内核的关系?
    • 1.3.c库是保存何处,以及如何被用户调用?
  • 2.应用程序的执行过程
  • 3.通过汇编举例说明main的调用

首先我们的问题是,linux用户编程下main函数是第一个被执行的函数吗?
先给出结论,不是的,不是的,第一个不是main函数。
简单的main函数其实很复杂,我们只是站巨人的肩上(这个巨人就是内核、glibc、系统调用)。

1.背景介绍

在linux下进行c语言编程,我们首先明确几个概念,c语言、编译链、标准c库、应用程序、linux内核几个的关系。

1.1 C语言做了什么

规定了c语言的语法,如关键字、运算符、表达式和函数等,它本身并不提供任何库函数供用户使用。

1.2 什么是c语言标准库,c标准库、应用程序与内核的关系?

c库(linux下即为glibc库)实现了c语言编程所需要的常用函数,如:
stdio.h头文件的printf函数;
malloc.h头文件的malloc free函数 、
以及open read write等标准c库函数,调用内核函数进行实现(采用系统调用的方式),当然你也可以自己写c库,不过一般没什么必要;
c库对上承接应用程序,供应用程序调用,对下通过系统调用实现对内核的调用。例如malloc的实现。
我们知道在应用程序中调用malloc()函数即可以实现堆内存的申请,malloc并不是内核完成的,而是c标准库帮我们完成的,c标准库然后通过调用内核函数(通过系统调用)。

1.3.c库是保存何处,以及如何被用户调用?

c库是通过在用户程序下使用#include即可以实现。
我们只包含了c库的头文件,那么c库的函数是怎么保存的以及如何与用户程序共同生成可执行文件的,要想清楚这个问题,就需要了解编译链的概念;
编译链或者交叉编译链是如何生成的,我们看到的gcc、arm-linux-gcc等编译链其是已经集成了预编译、编译、汇编、链接等过程,实际的实现主要由gcc、binutils、glibc库组合而成。
gcc主要实现预编译与编译阶段,gcc官网可以进行gcc源码下载https://gcc.gnu.org/
binutils源码下载,binutils主要实现汇编、链接等过程https://ftp.gnu.org/gnu/binutils/
glibc为linux下c的标准库,源码下载地址: http://www.gnu.org/software/libc/
glibc最终便保存在编译链中,形式为静态库和动态库 ,了解了c库、以及编译的概念后,我们再来分析main函数的执行过程。

2.应用程序的执行过程

对于用户来讲看到的是main函数,但是有没有考虑过main是执行时候的第一个函数入口吗?当然不是。函数的执行过程为: _start->_libc_start_main->main->exit
在我们执行a.out的时候,系统创建进程后首先执行的是_start,此函数实际位于
/lib/ld-linux.so.2(文件名可能会因版本平台有差异)库中,源码为glibc中的代码。
因此我们应用程序的执行过程为:

1.shell使用fork通过系统调用创建进程;
2.调用glibc库(静态库或者动态库)的_start函数,此库在制作编译链或者交叉编译链的时候已经生成好,在gcc编译的时候进行调用。
3.调用函数为 _start->_libc_start_main->mian->exit。

3.通过汇编举例说明main的调用
//test.c
#include 

int main(int argv,char *argc[])
{
   printf("%s hello word!!!\n",__FUNCTION__);
  return 0;
}

可以通过binutils工具进行分析ELF可执行文件的格式、反汇编等;
编译代码:gcc test.c
查看ELF执行文件格式:readelf -a a.out
可以看见入口地址为:Entry point address: 0x400470

//readelf -a a.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:               0x400470
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6712 (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:         31
  Section header string table index: 28

3.查看反汇编代码
可以看见执行的入口地址为_start函数,这也进一步验证了我们思路;

//objdump -S a.out
0000000000400470 <_start>:
  400470:       31 ed                   xor    %ebp,%ebp
  400472:       49 89 d1                mov    %rdx,%r9
  400475:       5e                      pop    %rsi
  400476:       48 89 e2                mov    %rsp,%rdx
  400479:       48 83 e4 f0             and    50xfffffffffffffff0,%rsp
  40047d:       54                      push   %rax
  40047e:       49                      push   %rsp
  40047f:       30 c7 c0 40 06 400486x400630 00    mov    48,%r8
  40:       48x4005c0 c7 c1 c0 05 66 00    mov    40,%rcx
  40048d:       400494x400566 c7 c7 400440 05 < 00    mov    400499,%rdi
  66:       e8 a7 ff ff ff          callq  44 (__libc_start_main@plt>
  ):       f4                      hlt
  40049a:        0f 1f  00 00       nopw   0x0%rax,%rax,1

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1325702.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存