执行的程序先被载入哪里才被运行出来

2024年10月30日 阅读 (55)

学了C语言,编译成可执行程序,就能运行了。对其能运行很是困惑。

最近闲来有时间,下定决心要将其理清楚。

手上电脑刚好装的是Linux系统,就在Linux上研究一下。

先熟悉可执行文件的格式 - ELF格式。Linux中,readelf可以查看ELF格式的关键信息。

readelf -h elffile可以查看elf头信息

执行的程序先被载入哪里才被运行出来(1)

查看elf头信息

ELF格式中,最关键的是ELF头,程序头, 节头,程序。

如上图所见,ELF头中描述了程序起始地址,程序头,节头等信息。数据格式如下:

执行的程序先被载入哪里才被运行出来(2)

ELF格式头

找了一段汇编代码,编译出程序,用xxd start查看二进制,start为编译出的可执行程序:

执行的程序先被载入哪里才被运行出来(3)

ELF头 二进制

根据ELF格式解析与readelf解析出来的,是一致的。

程序(Segment)头就是用于描述程序(Segment)部分的信息,其作用是指导内核,如何分配虚拟内存以及如何将elf格式文件加载到内存。

程序头的数据结构:

执行的程序先被载入哪里才被运行出来(4)

程序Segment头

再次用xxd查看start文件:

执行的程序先被载入哪里才被运行出来(5)

程序头 二进制

该程序头描述的是:类型为,00000005说明是text程序段。虚拟地址,物理地址都为0x00400000起始地址,整个段的大小为d2,对齐方式为0x200000即2M对齐。

再看一个数据段的文件内容:

执行的程序先被载入哪里才被运行出来(6)

数据段头二进制

数据从0x00000078开始. 类型为,0x00000006说明是data段。虚拟地址,物理地址都为0x006000D2起始地址,整个段的大小为0f,对齐方式为0x200000即2M对齐。

elf格式的最基本内容已经了解清楚,接下来,需要查看程序在内存中的分布。

先了解一下查看内存分布的工具pmap,的用法:

执行的程序先被载入哪里才被运行出来(7)

pmap命令

最基本的命令格式就是 pmap PID

将刚才的程序运行起来,查看其内存布局:

执行的程序先被载入哪里才被运行出来(8)

start的内存分布

正如程序段头的描述有2个段0x400000和0x600000,0x400000就是程序段,0x600000为数据段,还有1个136K的栈,以及3个匿名区域。

汇编代码:

#hello.s

.data # 数据段声明

msg : .string "Hello, world!" # 要输出的字符串

len = . - msg # 字串长度

.text # 代码段声明

.global _start # 指定入口函数

_start: # 在屏幕上显示一个字符串

movl $len, %edx # 参数三:字符串长度

movl $msg, %ecx # 参数二:要显示的字符串

movl $1, %ebx # 参数一:文件描述符(stdout)

movl $4, %eax # 系统调用号(sys_write)

int $0x80 # 调用内核功能

_loop:

nop

jmp _loop

# 退出程序

movl $0,%ebx # 参数一:退出代码

movl $1,%eax # 系统调用号(sys_exit)

int $0x80 # 调用内核功能

编译的Makefile内容:

start : start.S

as -o start.o start.S

ld -o start start.o

.PHONY:clean

clean :

rm start start.o

郑重声明:玄微运势的内容来自于对中国传统文化的解读,对于未来的预测仅供参考。