网站首页 > 博客文章 正文
程序的入口点是程序在内存中开始执行的首地址。当操作系统加载一个可执行文件时,它会将程序的代码和数据加载到内存中,并跳转到程序的入口点的地址开始执行程序。
在Linux平台上,我们以如下经典的hello world程序为例:
[root:~/work/v1/hello]# cat hello.c
//File Name: hello.c
//The hello world program
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
[root:~/work/v1/hello]#
假设这个hello.c源程序经过GCC编译后的可执行程序为hello。那么这个简单程序在编译后,其运行的入口点到底是什么呢?很多同学可能认为是main函数,也有同学说是hello ELF文件的_start的地址。
其实hello程序的入口点与对hello.c进行动态链接还是静态链接有关系。
- 对于静态链接的程序,程序开始执行的入口点是hello程序的_start符号的地址。
- 对于动态链接的程序,其在执行前需要加载器动态链接库文件,并进行动态重定位,这些工作都是由动态链接器ld.so来完成。对于动态链接的可执行程序,需要首先执行ld.so,所以其入口点为动态链接器ld.so的入口点(_start)。
对于静态链接的程序,其执行过程如下图所示:
对于动态链接的程序,其执行过程如下图所示:
如何查看程序运行的入口点呢?
GDB有一个starti指令,starti指令用于启动程序并停止在程序的第一条指令上。
(gdb) help starti
Start the debugged program stopping at the first instruction.
通过gdb启动hello程序,然后通过starti指令让程序运行并停止在程序的第一条指令上。
检查静态链接的hello程序的入口
编译:
[root:~/work/v1/hello]# gcc -static -g -o hello hello.c
[root:~/work/v1/hello]# file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=7abb97dc49af6aeaac3d0c5c5a532d6f17c77eca, for GNU/Linux 3.2.0, with debug_info, not stripped
[root:~/work/v1/hello]#
检查入口点:
[root:~/work/v1/hello]# gdb ./hello
Reading symbols from ./hello...
(gdb) starti
Starting program: /root/work/v1/hello/hello
Program stopped.
0x0000000000401be0 in _start ()
(gdb)
检查hello文件中的_start符号:
[root:~/work/v1/hello]# readelf -s hello | grep -w _start
1295: 0000000000401be0 47 FUNC GLOBAL DEFAULT 7 _start
[root:~/work/v1/hello]#
通过反汇编查看hello程序中的_start:
objdump -d hello > hello_static.dump
然后可以在hello_static.dump中找到_start符号:
0000000000401be0 <_start>:
401be0: f3 0f 1e fa endbr64
401be4: 31 ed xor %ebp,%ebp
401be6: 49 89 d1 mov %rdx,%r9
401be9: 5e pop %rsi
401bea: 48 89 e2 mov %rsp,%rdx
401bed: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
401bf1: 50 push %rax
401bf2: 54 push %rsp
401bf3: 49 c7 c0 a0 2d 40 00 mov $0x402da0,%r8
401bfa: 48 c7 c1 00 2d 40 00 mov $0x402d00,%rcx
401c01: 48 c7 c7 05 1d 40 00 mov $0x401d05,%rdi
401c08: 67 e8 92 04 00 00 addr32 callq 4020a0 <__libc_start_main>
401c0e: f4 hlt
401c0f: 90
可以看到,GDB调试hello程序时停止的第一条指令的地址为: 0x0000000000401be0, 这正是hello程序中_start符号的地址。所以对于静态链接的hello程序,其运行时的入口点为_start的地址。
检查动态链接的hello程序的入口
对于动态链接的可执行程序,其在执行前都需要加载动态链接库,并进行动态重定位,这些工作都是由ld.so来完成。对于动态链接的可执行程序,由于首先要加载并运行ld.so,所以对于动态链接的程序,其入口点为ld.so的入口点(_start)。我们可以通过gdb的starti指令来进行检查:
[root:~/work/v1/hello]# gcc -g hello.c -o hello
通过file命令可以看到hello为动态链接的可执行文件,如下:
[root:~/work/v1/hello]# file hello
hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=500380986e87b017e06ae8854782234dec8b43eb, for GNU/Linux 3.2.0, with debug_info, not stripped
通过GDB来检查动态链接的hello程序的入口:
[root:~/work/v1/hello]# gdb ./hello
Reading symbols from ./hello...
(gdb) starti
Starting program: /root/work/v1/hello/hello
Program stopped.
0x00007ffff7fd0100 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb)
可以看到,通过gdb的starti指令,可以看到程序停在了ld-linux-x86-64.so.2的_start符号的入口上。所以对于动态链接的可执行程序,其入口点为动态链接器ld.so的_start。
猜你喜欢
- 2024-10-20 JSA宏教程WPS表格常用内置对象——单元格区域(Range)对象(一)
- 2024-10-20 CAD快捷键命令大全汇总,建议收藏保存
- 2024-10-20 是时候拯救我的 HTML 技术了(是时候拯救我的+html+技术了什么)
- 2024-10-20 Linux内核:Crash学习ARM64虚拟地址空间布局
- 2024-10-20 雾非花:清清爽爽的夏季女士宽松短袖(有编织图解)
- 2024-10-20 几毛钱一片的谷维素,可以用来治哪些病?这4大功效认可度很高
- 2024-10-20 Java 8 之后,还有哪些进化的功能?
- 2024-10-20 扒一扒西欧喷气式战斗机家族谱(3)
- 2024-10-20 「小狮子诊所」内存时序到底有什么作用?
- 2024-10-20 与你相见恨晚的100个CAD快捷键+20个CAD制图技巧,轻松玩转CAD
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)