はじめに
riscv-testsの個人的ハマりポイントの備忘録です。riscv-testsを初めて触った時の自分や将来完全に仕様を忘れてるであろう自分向けの記事です。参考になれば幸いです。もっといい方法や誤りがあれば教えてください。
テスト終了の判定
riscv-testsではテストが終了すると.tohostセクションに1が書き込まれます。readelf -Sで確認しましょう。以下が.tohostセクションのアドレスを表示させたものになります。このアドレスは物理アドレスです。0x80001000番地に.tohostセクションが多いですね。
1
2
3
4
5
6
|
> ls tests/isa/elves/* | grep -v -e \.dump$ -e Makefile | xargs -IFILE readelf -S FILE | grep tohost | awk '{print "0x" $5}' | sort | uniq -c
350 0x0000000080001000
3 0x0000000080002000
1 0x0000000080003000
268 0x80001000
1 0x80002000
|
フラットバイナリ
riscv-testsをビルドするとelfファイルとして出力されるのですがelfローダを実装するのが面倒(怠惰)でとりあえず以下のようにelfファイルをフラットバイナリに変換し、テストを実行していました。
1
|
riscv64-unknown-elf-objcopy -O binary file file.bin
|
ですが仮想メモリシステムを実装する際にテストが通らなかったのファイルの中身をみたところLOADセクションの配置すべき物理アドレスがちゃんとずれていました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
> readelf -l tests/isa/elves/rv64ui-v-add
Elf ファイルタイプは EXEC (実行可能ファイル) です
Entry point 0x80000000
There are 4 program headers, starting at offset 64
プログラムヘッダ:
タイプ オフセット 仮想Addr 物理Addr
ファイルサイズ メモリサイズ フラグ 整列
RISCV_ATTRIBUT 0x00000000000041c4 0x0000000000000000 0x0000000000000000
0x0000000000000065 0x0000000000000000 R 0x1
LOAD 0x0000000000001000 0x0000000080000000 0x0000000080000000
0x0000000000000200 0x0000000000000200 R E 0x1000
LOAD 0x0000000000002000 0x0000000080001000 0x0000000080001000
0x00000000000021c4 0x0000000000008010 RWE 0x1000
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
セグメントマッピングへのセクション:
セグメントセクション...
00 .riscv.attributes
01 .text.init
02 .tohost .text .rodata.str1.8 .bss .sbss
03
|
LOADセクションを正しい位置に配置するだけの簡易的なELFローダを作成しテストを実行したところテストを通すことができました。やはり怠惰はいけないです。そもそもフラットバイナリに変換するシェルスクリプト書くよりELFローダ書いた方が早かったのでは
0x80000000
フラットバイナリを0x0番地に配置し、pcを0にセットして実行していく形式にしていましたがこれも仮想メモリシステムを実装する際にテストが通らなくなりました。0x80000000番地に配置する想定にしましょう。リンカスクリプトを変更すれば別のところに配置することはできるようになると思います。(未検証)