RISC-V on Rust 从零开始(10) - 实作ELF loader

在实际的硬体上,开机後执行的第一道指令已经烧录在ROM上面,对於CPU来说程序在开机时就已经位於位址空间的某处,但对於我们的模拟器来说,开机後的记忆体是一片空白,因此是必须要有人先把程序码放到记忆体中,CPU才能开始执行,这就是这次要实作的loader的主要功能。

由於目前开发的平台以Linux为主,因此选用的执行档格是为Linux系统上常见的ELF档。完整的loader程序码如下:

use goblin::elf;
use std::fs;

fn load_elf(mem: &mut memory_model::MemoryModel, path: &str) -> AddressType {
    let bytes = fs::read(path).unwrap();
    let elf = elf::Elf::parse(&bytes).unwrap(); //呼叫goblin函式库提供的parse function
    for ph in elf.program_headers {
        if ph.p_type == goblin::elf::program_header::PT_LOAD {
            for offset in 0..ph.p_filesz {
                mem.write_byte(
                    (ph.p_paddr + offset) as AddressType,
                    bytes[(ph.p_offset + offset) as usize],
                );
            }
        }
    }

    elf.entry as AddressType
}

这边使用了goblin函式库来处理elf档,elf档格式在此不细谈,只要知道所有的code以及data会分成多个section存放,而相同属性的section又会被合并成为一个个segment,这些segment资讯就存放在program header中。

需要特别注意的是目前只需要将type为PT_LOAD的segment载入,可能的type如下:

#define PT_NULL         0               /* Program header table entry unused */
#define PT_LOAD         1               /* Loadable program segment */
#define PT_DYNAMIC      2               /* Dynamic linking information */
#define PT_INTERP       3               /* Program interpreter */
#define PT_NOTE         4               /* Auxiliary information */
#define PT_SHLIB        5               /* Reserved */
#define PT_PHDR         6               /* Entry for header table itself */
#define PT_TLS          7               /* Thread-local storage segment */
#define PT_NUM          8               /* Number of defined types */
#define PT_LOOS         0x60000000      /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550      /* GCC .eh_frame_hdr segment */
#define PT_LOSUNW       0x6ffffffa
#define PT_SUNWBSS      0x6ffffffa      /* Sun Specific segment */
#define PT_SUNWSTACK    0x6ffffffb      /* Stack segment */
#define PT_HISUNW       0x6fffffff
#define PT_HIOS         0x6fffffff      /* End of OS-specific */
#define PT_LOPROC       0x70000000      /* Start of processor-specific */
#define PT_HIPROC       0x7fffffff      /* End of processor-specific */

一般程序的code与data都会属於PT_LOAD type的segment,故目前仅需载入此类segment。


<<:  在 Windows 10 上安装 Visual Studio Code EP1

>>:  Day58 (React)

Day11 CSS基本说明

讲完了那麽多的Html,接下来要进入到CSS环节的部分了,身为网页装潢师的它,我们先从怎麽使用它开始...

Day 09 - 云端监控帮手CloudWatch与Cloud Trail

云端资源是否正常运作以及谁去操作了云上的资源?今天我们来看看AWS上的云端资源监控服务 1. 为何使...

CMoney软件工程师战斗营_心得感想_Week 20

这篇会是在参加cmoney战斗营中的最後一篇 但这不是句点,而会是我展开资讯人的开端。 就在前天, ...

Day-18 任意举出三个你在开发 Rails 专案时常用到的 gem,并说明一下

又是专案题来了!基本上有做专案就会有很多对於专案的题型,大家要对专案熟一点比较好喔! 我们小组是作...

Day15 资料库-model的创建(1)

我们在Day08有介绍过model的功用,在你的views里使用到资料库里的变数时,这些变数都是需要...