iT邦幫忙

0

RISC-V on Rust 從零開始(10) - 實作ELF loader

  • 分享至 

  • xImage
  •  

在實際的硬體上,開機後執行的第一道指令已經燒錄在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。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言