ELF有执行视图,那么ELF是怎么执行的起来的呢?
这里,分为2个进行说明:
一、CPU在EDA上,仿真执行ELF
在验证环境中,会有一块memory,专门用来放置CPU要执行的指令,以及访问的数据。而verilog提供了$memreadh系统函数,可以将hex文件,直接载入到memory中。
因此只要将ELF文件,转化成hex文件即可。
比如对于如下的链接脚本:
3个代码段,起始地址从0x5000_0000开始,2个数据段,从0x8000_0000开始。
最终转换出来的hex文件如图下所示:
因为VMA和LMA一样,所以hex文件中的地址,也就是VMA。
对于如下的链接脚本,使用AT,修改了加载地址,也就是LMA。
此时转换得到hex文件如下图所示:
二、对于操作系统
对于操作系统而言,如何执行ELF程序。
demo代码如下图所示:
gcc –static a.c -o out.elf 进行编译, 得到out.elf
readelf –a out.elf,查看elf信息
有42个段,但是对于执行,我们关心的执行视图,也就是segment。如下图所示。
elf有2个segment, section中属于 可读可执行的section,合并成 1个segment
section中属于 可读可写的section,合并成1个segment
将可执行程序, out.elf 通过后台,执行2次, 查看程序运行的memory映射关系
可以看出,segment1和segment2的va地址,两个程序的地址映射都是一样的。但是看不到PA地址。
那么操作系统有时如何执行ELF程序的呢?
-
读取ELF程序前128字节。判断是ELF,调用ELF解析程序进行下一步
-
调用fork,创建进程,并且创建页表,此时还没有将elf程序,装载到内存
-
将执行入口,设置为elf的entry point address
-
返回到用户态,从入口地址开始执行
-
产生mmu abort,切换到内核态,内核分配memory物理空间,建立页表映射,并将elf中数据,搬移到memory物理空间中去
-
返回到用户态,继续执行
三、自定义加载地址
可以在链接脚本中,使用AT关键字,自定义加载地址。
例如如下代码,3个代码段,2个数据段。
链接脚本如下:
makefile如下:
查看elf的section信息,有8个段。
有2个segment。VMA和LMA一致。
将链接脚本,修改如下,使用AT,为section,指定LMA。
重新,编译,查看ELF的segment,变成3个segment
-
segment0:LMA是0x1000,boot section的集合
-
segment1:LMA是0x2000,text1和text2 section的集合
-
segment2:LMA是0x5000,data和data1 section的集合