欢迎光临
我们一直在努力

动态链接程序的执行流程分析

文章目录

    • 示例代码
    • 执行流程详解
      • 1. 内核加载阶段
      • 2. 动态链接器执行阶段
      • 3. 控制权转移
      • 4. 主程序执行阶段
        • _start 函数:
        • __libc_start_main:
    • 关键技术点
      • 1. 入口点设置
      • 2. 符号解析与重定位
      • 3. 与静态链接的对比
    • 执行流程示意
    • 技术细节
      • 1. 内存布局示例
      • 2. _start 函数的实现
      • 3. 动态链接器的跳转机制
      • 4. 地址空间布局
    • 总结

示例代码

#include <stdio.h>
int main() {
printf("Hello Kernel\\n");
sleep(2); // 添加 2 秒延迟
return 0;
}

编译成动态链接程序(默认)

gcc o dlink link.c

执行流程详解

当动态链接程序加载完毕并完成内存地址更新后,程序确实从 _start 开始执行,但这个过程涉及多个步骤:

1. 内核加载阶段

execve 系统调用:内核解析 ELF 文件,发现 PT_INTERP 段 加载动态链接器:内核将动态链接器(如 /lib64/ld-linux-x86-64.so.2)加载到内存 设置入口点:内核将进程的入口点设置为动态链接器的入口地址,而非主程序的 _start

2. 动态链接器执行阶段

初始化:动态链接器自身初始化 加载依赖库:读取 PT_DYNAMIC 段,加载所有依赖的共享库 符号解析:解析所有外部符号引用 重定位:更新 GOT/PLT 表,修正内存地址 初始化全局构造函数:执行 init_array 中的初始化函数

3. 控制权转移

查找主程序入口点:动态链接器查找主程序的 _start 函数地址 跳转到 _start:动态链接器通过 dl_runtime_resolve 等机制,最终跳转到主程序的 _start 函数

4. 主程序执行阶段

_start 函数:

初始化栈帧 设置 argc、argv、envp 等参数 调用 __libc_start_main

__libc_start_main:

初始化 libc 调用全局构造函数 调用用户的 main 函数 处理 main 函数的返回值 调用全局析构函数 调用 exit 函数结束进程

关键技术点

1. 入口点设置

内核视角:内核只负责加载和设置初始入口点为动态链接器 动态链接器视角:动态链接器完成所有准备工作后,负责跳转到主程序的 _start

2. 符号解析与重定位

延迟绑定:默认情况下,动态链接器采用延迟绑定策略,只在函数首次调用时解析 GOT/PLT 机制:通过全局偏移表和过程链接表实现地址的动态解析

3. 与静态链接的对比

阶段静态链接程序动态链接程序
加载者内核直接加载内核加载动态链接器,动态链接器加载主程序
入口点设置内核直接设置为 _start内核设置为动态链接器入口,动态链接器后续跳转到 _start
符号解析编译时完成运行时由动态链接器完成
重定位编译时完成运行时由动态链接器完成

执行流程示意

┌─────────────────┐
│ 内核加载阶段 │
└────────┬────────┘

┌─────────────────┐ 完成依赖加载和
│ 动态链接器执行 │────→ 符号解析重定位
└────────┬────────┘

┌─────────────────┐
│ 跳转到 _start │
└────────┬────────┘

┌─────────────────┐
│ __libc_start_main │
└────────┬────────┘

┌─────────────────┐
│ 调用 main 函数 │
└─────────────────┘

技术细节

1. 内存布局示例

creek@:~/Cprogram$ ./dlink &
PID=$!
cat /proc/$PID/maps
kill $PID # 结束进程
[1] 218306
Hello Kernel
63ac752f1000-63ac752f2000 r–p 00000000 08:30 9424 /home/creek/Cprogram/dlink
63ac752f2000-63ac752f3000 r-xp 00001000 08:30 9424 /home/creek/Cprogram/dlink
63ac752f3000-63ac752f4000 r–p 00002000 08:30 9424 /home/creek/Cprogram/dlink
63ac752f4000-63ac752f5000 r–p 00002000 08:30 9424 /home/creek/Cprogram/dlink
63ac752f5000-63ac752f6000 rw-p 00003000 08:30 9424 /home/creek/Cprogram/dlink
63ac9f2d1000-63ac9f2f2000 rw-p 00000000 00:00 0 [heap]
7b5261200000-7b5261228000 r–p 00000000 08:30 17529 /usr/lib/x86_64-linux-gnu/libc.so.6
7b5261228000-7b52613b0000 r-xp 00028000 08:30 17529 /usr/lib/x86_64-linux-gnu/libc.so.6
7b52613b0000-7b52613ff000 r–p 001b0000 08:30 17529 /usr/lib/x86_64-linux-gnu/libc.so.6
7b52613ff000-7b5261403000 r–p 001fe000 08:30 17529 /usr/lib/x86_64-linux-gnu/libc.so.6
7b5261403000-7b5261405000 rw-p 00202000 08:30 17529 /usr/lib/x86_64-linux-gnu/libc.so.6
7b5261405000-7b5261412000 rw-p 00000000 00:00 0
7b526154b000-7b526154e000 rw-p 00000000 00:00 0
7b5261557000-7b5261559000 rw-p 00000000 00:00 0
7b5261559000-7b526155a000 r–p 00000000 08:30 17526 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7b526155a000-7b5261585000 r-xp 00001000 08:30 17526 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7b5261585000-7b526158f000 r–p 0002c000 08:30 17526 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7b526158f000-7b5261591000 r–p 00036000 08:30 17526 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7b5261591000-7b5261593000 rw-p 00038000 08:30 17526 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffe9efbe000-7ffe9efe0000 rw-p 00000000 00:00 0 [stack]
7ffe9effa000-7ffe9effe000 r–p 00000000 00:00 0 [vvar]
7ffe9effe000-7ffe9f000000 r-xp 00000000 00:00 0 [vdso]
[1]+ Terminated ./dlink

2. _start 函数的实现

_start 函数通常由编译器生成,位于 crt1.o 或类似的启动文件中:

void _start() {
// 初始化栈帧
// 设置 argc, argv, envp
// 调用 __libc_start_main
__libc_start_main(main, argc, argv, __libc_csu_init, __libc_csu_fini, environ);
}

3. 动态链接器的跳转机制

动态链接器通过以下步骤跳转到主程序的 _start:

从 ELF 头中获取主程序的入口地址(通常是 _start 的地址) 执行完所有初始化操作后,使用跳转指令(如 jmp)跳转到该地址 主程序从此开始执行,完全接管控制权

4. 地址空间布局

动态链接器:加载到内存的某个位置 主程序:加载到另一个位置(可能受 ASLR 影响) 共享库:加载到各自的位置(地址随机化)

总结

动态链接程序在加载完毕并更新内存地址后,确实从 _start 开始执行,但这个过程是由动态链接器在完成所有准备工作后主动跳转到 _start 的。整个流程体现了动态链接的灵活性和延迟绑定的优势,同时也展示了内核与用户态链接器的协作机制。

赞(0)
未经允许不得转载:171主机测评 » 动态链接程序的执行流程分析
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址