李成笔记网

专注域名、站长SEO知识分享与实战技巧

01. 可执行程序加载运行 可执行程序扩展名是

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

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

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

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

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


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

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


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


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


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

程序头的数据结构:



再次用xxd查看start文件:

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

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


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


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

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

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

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


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


汇编代码:

#hello.s

.data # 数据段声明

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

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

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言