link もっと前
   2019年 10月 6日 -
      2019年 10月 6日  
link もっと後

link 未来から過去へ表示(*)
link 過去から未来へ表示

日々

link permalink

RISC-V のバイナリダンプを逆アセンブルする

相変わらず空き時間に RISC-V のエミュレータを書いています。RV64IMAC くらいが必要なのですが、意外と命令の種類が多くていっぺんにやるのは面倒なので、HiFive Unleashed のファームウェアを動かしてみて、足りない命令から実装していくスタイルで開発しています。

HiFive Unleashed の電源を入れたときに真っ先に起動してくるファームウェアというかブートローダは ZSBL(Zeroth Stage Boot Loader), FSBL(First Stage Boot Loader)という名前です。

なんと親切なことにソースコードが公開されていますGitHub - Freedom U540-C000 Bootloader Code のリンク)。素晴らしいですね……。

なぜか Unleashed から引っこ抜いてきたバイナリと、手元でコンパイルした ZSBL, FSBL のバイナリが一致しません。何か間違っているのかも?ちょっと気になります。しかしながら、ソースコードが公開されている意義は非常に大きいです。

メモリマップも公開されています。SiFive Freedom U540 SoC のサイトからダウンロードできます。

Unleashed リセット〜ZSBL を例に解説

U540 のマニュアルによると、リセット直後の PC は 0x1004 で、その後は MSEL の値を見て、適切な場所に飛ぶとあります。MSEL というのは、Unleashed ボード上の DIP スイッチのことです。購入後、変えていなければ状態だと全部 ON、つまり 0xf になっていると思います。

リセット直後に実行される領域の周辺バイナリをダンプしてみましょう。ダンプには拙作の memaccess(GitHub へのリンク)を使っています。

Unleashed 0x1000〜0x1040 領域のダンプ
# ma db 0x1000 0x40
00001000  0f 00 00 00 97 02 00 00  03 a3 c2 ff 13 13 33 00
00001010  b3 82 62 00 83 a2 c2 0f  67 80 02 00 00 00 00 00
00001020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00001030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00001040

何かが書いてあるようですが、RISC-V のバイナリがスラスラ読めるほど達人ではないので、ファイルにダンプして逆アセンブルします。

Unleashed 0x1000〜0x1040 領域の逆アセンブル
$ riscv64-unknown-elf-objdump -EL -D -b binary -m riscv:rv64 --adjust-vma=0x1000 reset.bin
reset.bin:     file format binary

Disassembly of section .data:

0000000000001000 <.data>:
    1000:       0000000f                fence   unknown,unknown
    1004:       00000297                auipc   t0,0x0
    1008:       ffc2a303                lw      t1,-4(t0) # 0x1000
    100c:       00331313                slli    t1,t1,0x3
    1010:       006282b3                add     t0,t0,t1
    1014:       0fc2a283                lw      t0,252(t0)
    1018:       00028067                jr      t0
        ...

先頭が変な命令に見えますが、これは命令ではなく MSEL です。値は先程も言ったとおり 0xf です。実行されるのは 0x1004 からです。大した量でもないし、1行毎に見ていきます。

0x1004: auipc t0, 0x0
PC + 0 を t0 にロードします。t0: 0x1004 です。
0x1008: lw t1,-4(t0) # 0x1000
レジスタ t1 にアドレス t0 - 4 = 0x1004 - 4 = 0x1000 つまり MSEL をロードします。t1: 0xf です。
0x100c: slli t1,t1,0x3
レジスタ t1 を 3ビット左シフト(= 8倍)します。t1: 0xf << 3 = 0x78 です。
0x1010: add t0,t0,t1
レジスタ t0 と t1 を足します。t0: です。t0: 0x1004 + 0x78 = 0x107c です。
0x1014: lw t0,252(t0)
レジスタ t0 に t0 + 252 のアドレスからロードします。アドレスは 0x107c + 252 = 0x1178 です。後述のとおり t0: 0x10000 です。
1018: jr t0
レジスタ t0 のアドレスにジャンプします。すなわち 0x10000 にジャンプします。

参考として、アドレス 0x1178 に何が書いてあるか示しておきます。付近の領域 0x1100〜0x1180 には MSEL の値に応じたジャンプ先のアドレスが書いてあります。MSEL が他の値になったらどこにジャンプするか、眺めてみると面白いかと思います。

Unleashed 0x1000〜0x1040 領域のダンプ
# ma dd 0x1100 0x80
00001100  00001004 00000000  20000000 00000000
00001110  30000000 00000000  40000000 00000000
00001120  60000000 00000000  00010000 00000000
00001130  00010000 00000000  00010000 00000000
00001140  00010000 00000000  00010000 00000000
00001150  00010000 00000000  00010000 00000000
00001160  00010000 00000000  00010000 00000000
00001170  00010000 00000000  00010000 00000000    ★0x1178 には 0x10000 が書いてある
00001180

マニュアルの言うとおり、MSEL が 0xf の場合、リセット後 ZSBL にジャンプ、アドレスで言うと 0x10000 にジャンプすることが確認できました。

以降も同様に 0x10000 付近をダンプし、逆アセンブルしたり、エミュレータに実行させてみたりして、開発を進めています。今は ZSBL は通過して、FSBL の先頭の方まで実行できるようになりました。いうなれば、砂山にトンネルを掘っているような気分でしょうか、なかなか面白いです。

通常は逆アセンブルだけだと処理の意図を掴むことが難しいですけども、その点 U540 はソースコードが読めるため、当たりを付けることが比較的容易です。しばらくは素敵なおもちゃになりそうなボードです。

[編集者: すずき]
[更新: 2019年 10月 13日 23:20]
link 編集する

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
   2019年 10月 6日 -
      2019年 10月 6日  
link もっと後

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 11/11 11:44

カレンダー

<2019>
<<<10>>>
--12345
6789101112
13141516171819
20212223242526
2728293031--

最近のコメント 5件

  • link 19年09月01日
    すずき 「私も正直びっくりです。間違って違う製品を...」
    (更新:09/04 23:39)
  • link 19年09月01日
    hdk 「車向けの製品の中でも、車載コンピューター...」
    (更新:09/02 23:20)
  • link 19年07月18日
    hdk 「あっ、AAMはマニュアルのオペレーション...」
    (更新:07/25 00:02)
  • link 19年07月18日
    すずき 「AAM(ASCII Adjust AX ...」
    (更新:07/24 22:22)
  • link 19年07月18日
    hdk 「加算減算は符号のありなしどちらも命令が同...」
    (更新:07/24 07:25)

最近の記事 3件

link もっとみる
  • link 19年11月07日
    すずき 「[独自の apt サーバー - その 6 - ソースコードパッ] ...」
    (更新:11/11 11:44)
  • link 19年08月29日
    すずき 「[独自の apt サーバー - その 5 - 複数のセクション] ...」
    (更新:11/08 00:41)
  • link 19年08月13日
    すずき 「[独自の apt サーバー - その 4 - まとめ] 独自の a...」
    (更新:11/08 00:41)

こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報