Rustを使ってELFファイルをダンプするプログラムが動くようになったので、今度はこれをRISC-VシミュレータにインポートしてELFファイルを読み込むことができるようにする。
まずはELF Loaderをインポートして、ELFファイルを読み込んだら、すべてのセクションについてデータをダンプして適切なメモリ領域に値を書き込む。
let loader = match ElfLoader::new(filename) { Ok(loader) => loader, Err(error) => { panic!("There was a problem opening the file: {:?}", error) }, }; ... // Dump All Section Headers for sh_header in sh_headers { sh_header.dump(); let mut sh_addr = sh_header.sh_addr; for byte_addr in (sh_header.sh_offset..(sh_header.sh_offset + sh_header.sh_size)) { let byte_data = loader.get_byte(byte_addr as usize); riscv_core.write_memory_byte(sh_addr as Addr64T, byte_data as Xlen64T); sh_addr += 1; }
しかしこれではメモリにロードすべきセクション以外のものまでロードしてしまうので、必要なセクションのみロードしたい。このために、セクションヘッダのtype
フィールドを使って、フィールドがPROGBITSのセクションのみロードするようにしよう。
/* Legal values for sh_type (section type). */ #define SHT_NULL 0 /* Section header table entry unused */ #define SHT_PROGBITS 1 /* Program data */ #define SHT_SYMTAB 2 /* Symbol table */ #define SHT_STRTAB 3 /* String table */ #define SHT_RELA 4 /* Relocation entries with addends */ #define SHT_HASH 5 /* Symbol hash table */ #define SHT_DYNAMIC 6 /* Dynamic linking information */ ...
PROGBITSの値は1なので、とりあえず以下のように条件判定を付ける。
// Dump All Section Headers for sh_header in sh_headers { sh_header.dump(); let mut sh_addr = sh_header.sh_addr; if sh_header.sh_type == 0x1 { // PROGBITS for byte_addr in (sh_header.sh_offset..(sh_header.sh_offset + sh_header.sh_size)) { let byte_data = loader.get_byte(byte_addr as usize); riscv_core.write_memory_byte(sh_addr as Addr64T, byte_data as Xlen64T); sh_addr += 1; } } }
これで、必要なセクションのみを選択してメモリにロードできるようになった。これでテストプログラムを動かしてみよう。
$ cargo run ${HOME}/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add
459:M:Bare:0000800005d8:01e00113:addi x02,x00,0x01e :x00=>0000000000000000 x02<=000000000000001e 460:M:Bare:0000800005dc:00208033:add x00,x01,x02 :x01=>0000000000000010 x02=>000000000000001e 461:M:Bare:0000800005e0:00000e93:addi x29,x00,0x000 :x00=>0000000000000000 x29<=0000000000000000 462:M:Bare:0000800005e4:02600193:addi x03,x00,0x026 :x00=>0000000000000000 x03<=0000000000000026 463:M:Bare:0000800005e8:01d01463:bne x00,x29,0x8 :x00=>0000000000000000 x29=>0000000000000000 464:M:Bare:0000800005ec:00301c63:bne x00,x03,0x18 :x00=>0000000000000000 x03=>0000000000000026 465:M:Bare:000080000604:0ff0000f:fence : 466:M:Bare:000080000608:00100193:addi x03,x00,0x001 :x00=>0000000000000000 x03<=0000000000000001 <Info: Generate Exception Code=11, TVAL=0000000000000000 PC=000000008000060c> <Info: Exception. ChangeMode from 3 to 3> <Info: Set Program Counter = 0x 80000004> 467:M:Bare:00008000060c:00000073:ecall : 468:M:Bare:000080000004:34202f73:csrrs x30,0x342,x00 :x00=>0000000000000000 x30<=000000000000000b 469:M:Bare:000080000008:00800f93:addi x31,x00,0x008 :x00=>0000000000000000 x31<=0000000000000008 470:M:Bare:00008000000c:03ff0a63:beq x30,x31,0x34 :x30=>000000000000000b x31=>0000000000000008 471:M:Bare:000080000010:00900f93:addi x31,x00,0x009 :x00=>0000000000000000 x31<=0000000000000009 472:M:Bare:000080000014:03ff0663:beq x30,x31,0x2c :x30=>000000000000000b x31=>0000000000000009 473:M:Bare:000080000018:00b00f93:addi x31,x00,0x00b :x00=>0000000000000000 x31<=000000000000000b 474:M:Bare:00008000001c:03ff0263:beq x30,x31,0x24 :x30=>000000000000000b x31=>000000000000000b 475:M:Bare:000080000040:00001f17:auipc x30,0x00001 :x30<=0000000080001040 476:M:Bare:000080000044:fc3f2023:sw x03,0x0000fc0(x30) :x03=>0000000000000001 x30=>0000000080001040 (000080001000)<=0000000000000001 PASS : /home/msyksphinz/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add
動作したようだ。基本的な確認はこれで問題ない。