GUN/Linux的源头Elf文件是如何操控Glibc的

文章通过一个简单的C程序示例,详细阐述了从ELF文件到程序执行的流程,包括如何通过GCC编译生成ELF文件,如何使用readelf工具查看段信息,以及在LLDB中调试查看程序运行状态。重点讨论了Linux加载器如何调用elf的_start函数,进而控制Glibc并最终执行到托管的main函数,指出_main函数并非程序执行起点。
摘要由CSDN通过智能技术生成

楔子

今天是南方小年,祝南方的朋友节日快乐。
上一篇讲了Glibc是如何操控CLR的:点击这里
本篇看下更底层的elf是如何调用_start函数操控Glibc(它则操控的是CLR)。

例子

为了观察以上步骤,需要搞个简单例子试下。这点非大名鼎鼎GCC莫属。
一:建立source code
用命令:vim test.c建一个test.c源文件,里面写入如下:

#include<stdio.h>
void main()
{
   printf("hello tang!\r\n");
}

二:编译源文件
通过命令:gcc test.c -o test编译一个目标文件:test.o
三:链接成elf文件
通过命令:gcc test.o -o test

这样的话,就得到了一个elf格式的test文件,运行如下:
bfb89f2b4323feac00426d86bdc3e598.png

查看

运行命令readelf -s test查看elf文件段
cced88c5d50e6f8f84f79617e03953d4.png
可以看到_start函数的段起始地址data_start:0000000000004000
_start函数的偏移:0000000000001060
main入口函数(也就是上面例子的main)的偏移:0000000000001149

调看

在lldb里面看下test这个elf文件的运行状况
首先在main入口下个断点
8465d0859e0af64dc68ab9f8f72ffad5.png
看它这个断点的address就是上面elf文件main入口的地址。

r命令让它运行到main函数入口处
661c58846d5919f68b566725a9485729.png
可以看到它的第一条指令的地址末尾两字节是5419,那么说明这个elf文件在被linux加载器(也就是系统函数)加载的时候它的基地址应该是:0x555555554000。

有个有趣的现象就是断点下在哪里,这个基地址的偏移就和谁有关。比如断点下在_start这个函数上。那么基地址一定是末尾两个字节一定是_start的偏移1060加上data_start的基址4000等于5060这点下面验证下。
在_start处下断点
624d3230be2d027f58eee98b1aa9655e.png
然后run
0ca296db3dd1e085cfd553cd01b86aa6.png
可以看到基址是:0x555555555060,它的末尾两字节也确实是:5060.

总结

总体来说Ubuntu22.0上面,CLR被调用的顺序是:
linux elf加载器(这里有系统级调用比如fork)
-》_start
-》Glibc
-》CLR
-》托管main函数

所以这里来说,任何号称main函数为起始函数的都是不正确的描述。因为它们前面有N多的运行步骤。

结尾

作者:江湖评谈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值