『操作系统』操作系统实验LAB1——ELF文件,Printk
『操作系统』操作系统实验LAB1——ELF文件,Printk
一. 思考题
Question1: 请阅读附录中的编译链接详解,尝试分别使用实验环境中的原生x86工具链(gcc、ld、readelf、objdump 等)和MIPS交叉编译工具链(带有 mips-linux-gnu-前缀),重复其中的编译和解析过程,观察相应的结果,并解释其中向 objdump 传入的参数的含义。
原生环境是基于x86架构下的,而运用MIPS交叉编译工具则是虚拟了一个MIPS架构环境,编译链接反汇编等建立在MIPS架构下,二者有很大不同。
对于Helloworld文件,下图是用GCC编译后的结果:
下图是使用交叉编译器后的结果:
objdump
是反汇编命令,观察LAB1内Makefile的objdump
部分,有一些常用的参数如下:
1 | objdump [command] |
一般而言,我们使用 objdump -alds <目标文件或可执行文件名> -o <得到的反汇编文件>
即可满足需求。
Question2: 思考下述问题
• 尝试使用我们编写的 readelf 程序,解析之前在 target 目录下生成的内核 ELF 文件。
• 也许你会发现我们编写的 readelf 程序是不能解析 readelf 文件本身的,而我们刚才介绍的系统工具 readelf 则可以解析,这是为什么呢?
内核的节头地址如下图所示:
用真正的readelf -h
来查看我们编写的readelf头:
再来查看hello的头:
Hello的Makefile如图所示,注意参数-m32
:
节选自readelf.c
:
综上分析,Hello在编译的过程中定义了类别为ELF32,而readelf的类别为ELF64,而可以看到readelf解析的是ELF32类别的文件,因此readelf无法解析它自身。
Question3:在理论课上我们了解到,MIPS 体系结构上电时,启动入口地址为 0xBFC00000(其实启动入口地址是根据具体型号而定的,由硬件逻辑确定,也有可能不是这个地址,但一定是一个确定的地址),但实验操作系统的内核入口并没有放在上电启动地址,而是按照内存布局图放置。思考为什么这样放置内核还能保证内核入口被正确跳转到?
我们在kernel.lds中设置好了各个节被加载的位置,即最终的 segment地址,同时使用了 ENTRY(_start)指定了程序入口(即内核入口)。而在stage1和2阶段时由bootloader掌管执行,在完成必要的初始化后,会将内核引导装填进内存中的指定位置(即lds中设置好的各个节被加载的位置),最后将PC指向_start内核入口处,将控制权交给内核, 最终保证了内核入口能够被正确跳转。
二. 实验难点
本次实验难点有二,其一是有关ELF文件的理解,其二是填写printk函数。
ELF文件
引用教程中的一张图,重点在于理解ELF文件内部的结构,首先一个满足条件的程序(可执行,共享,目标)即对应了一个ELF文件,他的主要组成包括:
- ELF头:由一个结构体组成,包括程序的基本信息,比如体系结构和操作系统,同时也包含了节头表和段头表相对文件的偏移量(offset)。
- 节头表:是由数个节头结构体组成的一个结构体数组(笔者一开始便云里雾里了很久),每个节头称为一个节头表项,有固定的size。
- 段头表:是由数个段头结构体组成的一个结构体数组
- 以及各个节的代码数据内容。
我们可根据ELF头地址+节头表偏移量寻到节头表的首地址,然后再根据节头表的项数和节头的size找到每个节头的首地址,再指向其对应的节地址即可。需要注意对c语言中指针的理解,将一个int型指针加1实际则是在地址上加了4,它是以数据类型的大小为单位进行计算的。同时const void*是万能指针,由它可以转化为任何类型的指针(加上强转更好),也可由任何类型的指针转为它,因为指针本质都是一个四字节的地址。
Printk函数
有关printk函数的实现:与OO中Lexer词法分析器的实现类似,开始时字符串指针处于字符串头,用指针扫描每个字符,针对扫描到的指定字符进行分析,直至指针扫描到’\0’停止。
值得注意的是在八进制,十六进制,二进制中负数皆被看作补码形式,而十进制下有关负数的处理不同,它会保留负号输出,因此若从参数列表中提取出来的为负数,则应将其绝对值进行输出,再在前面加上负号。
三. 实验总结
本次LAB1实验带我们完成了内核的启动,readelf文件的编写,以及printk函数的实现,相比较LAB0,可以说这才是真正进入了操作系统世界的大门。而随着实验的深入,笔者明显察觉到的是指导书内容篇幅的增加以及读起来会有更多不理解的磕绊,同时C语言代码部分难度开始提高,令笔者不得不重新复习一年前学过的数据结构与指针等等基础知识(原来大一上了一年用处在这里);同时做一道题依赖的文件数也变得连分屏都难以看过来,这令我不得不去尝试VScode的使用,当然还有英文注释带来不便感。然而我们更愿意相信如今苦难的背后一定是光明,克服烦躁,去享受操作系统带给我们的快乐吧!