ひょんな理由でM1 Macを使う必要が生じたのだが、MacOSにはlibelfが無いということが分かった。 いろいろ考えて、x86のLinuxを仮想マシンでシミュレートするか、それともそもそもMac環境で開発することを諦めるか考えたのだが、よく考えてみるとriscv-isa-sim(spike)はちゃんと動作している。どうしているんだろうと思ったら、libelfによるelfのローディングを使用せず、自前でelfを取り込む環境を用意していた。
elf.h
は自前で定義しており、必要最低限の実装を用意しているようだ。memif
にELFのデータを書いているようなので、これを現在使用しているELFローダの実装で置き換える。
このへんの実装だな。
#define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t, bswap) \ do { \ ehdr_t* eh = (ehdr_t*)buf; \ phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \ *entry = bswap(eh->e_entry); \ assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum) * sizeof(*ph)); \ for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \ if (bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \ if (bswap(ph[i].p_filesz)) { \ assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz)); \ memif->write(bswap(ph[i].p_paddr), bswap(ph[i].p_filesz), \ (uint8_t*)buf + bswap(ph[i].p_offset)); \ } \ if (size_t pad = bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)) { \ zeros.resize(pad); \ memif->write(bswap(ph[i].p_paddr) + bswap(ph[i].p_filesz), pad, \ zeros.data()); \ } \ } \ } \
無理やり書き換える。下記のg_memory
に挿入したデータが、そのまま外部RAMに書き込まれてフェッチ・データアクセスに使用される。
#define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t, bswap) do { \ ehdr_t* eh = (ehdr_t*)buf; \ phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \ /* *entry = bswap(eh->e_entry); */ \ assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum)*sizeof(*ph)); \ for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \ if(bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \ if (bswap(ph[i].p_filesz)) { \ assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz)); \ for (int b_idx = 0; b_idx < ph[i].p_filesz; b_idx++) { \ g_memory->StoreMemory<Byte_t> (ph[i].p_paddr + b_idx, (Byte_t *)(buf + bswap(ph[i].p_offset) + b_idx)); \ } \ } \ zeros.resize(bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)); \ } \ } \
一応ここまでで、シミュレーション環境を構築できるようになった。