link もっと前
   2019年 10月 6日 -
      2019年 10月 15日  
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 permalink

台風 19号

あの台風 15号(Faxai)(2019年 9月 8日の日記参照)を超える、かつてない規模の台風 19号(Hagibis)が来るということで、窓にガラス飛散防止でダンボールを貼ってみたり、食料、水を買い込んで備えていました。

都内だと多摩川沿いの一部堤防のない地域が水浸し、東日本だと長野、宮城が洪水で大変なことになっているそうで、東京の治水事業には感謝しかありません。


多摩川の水位

我が家からはやや遠いですが、最寄りの大きな川といえば多摩川です。水位が大変なことになっていて、思わずスクリーンショットを撮ってしまいました……。

我が家は北と東に窓がありまして、台風15号のときは北からガンガン風と雨が吹き付けていたため、あまりの風圧に、雨が窓サッシの隙間から侵入していました。壁に飛来物が当たり、ものすごい音もしていました(窓の真横に当たり、窓にはギリギリ当たらず本当に幸運だった)。今回はどうやら西、ないし、南から吹き付けていたようで、15号のときほど被害はありませんでした。

今回は全体的に幸運でしたが、災害への備えは日頃からやっておいて損はないですね。

家財

家の外にある家財は車くらいしかないので、台風が過ぎた後に見に行ってみましたが、特に飛来物が当たった形跡もなく、何ともなかったです。良かった良かった。

[編集者: すずき]
[更新: 2019年 10月 24日 01:35]
link 編集する

コメント一覧

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



link permalink

Git の小技、コミット ID 取得

最近、会社で CI/CD で自動化のマネごとを始めました。といっても大したことはなくて、ビルドして Debian や RPM パッケージを作って、Web サーバーにぶっこむだけです。

Nightly ビルドのパッケージを作成する際に、パッケージ名の最後に Git のコミット ID を付加しようと思ったのですが、方法が分かりません。調べてみると rev-parse というコマンドを使うそうです。知らなかった。

Git のコミット ID(全体、短縮)を取得する
$ git rev-parse HEAD

5ab7d0ae0c170fc0409d564fe945aac5ce54f86c

$ git rev-parse --short HEAD

5ab7d0ae0c1

ID 全部だと長すぎるため --short オプションを使うとより良いです。

[編集者: すずき]
[更新: 2019年 10月 21日 02:02]
link 編集する

コメント一覧

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



link permalink

linux-next の不思議なバージョン情報

Linux というか linux-next ですが、リポジトリ内のファイルをオリジナルから変更してビルドした場合、バージョン情報の最後に -dirty が付きます。あれはどうやっているのだろう??と気になりました。

Makefile を眺めていると、scripts/setlocalversion というスクリプトでローカルバージョンを付与しているように見えます。

試しに clean なリポジトリで scripts/setlocalversion を実行すると、-next-20191009 のような localversion のみ(※)が表示され、ファイルを適当に書き換えてから実行すると、-next-20191009-dirty になりました。このスクリプトで当たりっぽいです。

もし Linux Upstream カーネルで試す場合は、CONFIG_LOCALVERSION_AUTO を y にして、make prepare を実行する必要があります。そうしないと scripts/setlocalversion を実行しても "+" しか表示されません。

(※)この文字列はトップディレクトリの localversion-next というファイルに書いてあります。

Git の小技、リポジトリ変更を検知

スクリプト setlocalversion を追いかけてみると git --no-optional-locks status -uno --porcelain で変更を検知して、-dirty を出力するかどうか決めていました。オプション --porcelain のヘルプを見ると「スクリプトなどで処理しやすい形式で status を出力する」とのことです。へえー、こんなのあるんだ。初めて知りました。

オプション --no-optional-locks はロックを取らずに実行するという意味です。ヘルプ曰く、バックグラウンドで status を実行する際に、他の git status プロセスと衝突するので、指定した方が良いとのこと。手動で使うことはなさそうだし、気にしなくて良いでしょう。

オプション -uno は --untracked-files=no の省略形です。効果は実際に見た方が早いです。以下をご覧ください。

Git リポジトリに変更を加える
#### scripts/setlocalversion を書き換え

$ vim scripts/setlocalversion

#### 未追跡ファイル aaa を作成

$ touch aaa

上記の変更を加えたうえで、オプション -uno なし、オプション -uno ありで、それぞれ実行してみます。

Git リポジトリに変更が生じているか取得する(-uno なし、あり)
$ git status --porcelain

 M scripts/setlocalversion
?? aaa


$ git status -uno --porcelain

下記と同じ

$ git status --untracked-files=no --porcelain

 M scripts/setlocalversion

見た目で明らかだとは思いますが、オプション -uno が指定されていない場合は、未追跡のファイル aaa も表示されますが、-uno を指定すると未追跡のファイルは無視します。

スクリプト内で Git リポジトリが変更されたか?されていないか?を判定する必要は、普通の人はほぼ無いと思うんですけど……、もし必要が生じたら、sed とか grep とかでゴチャゴチャやらずに、オプション --porcelain を使いましょう。

[編集者: すずき]
[更新: 2019年 10月 21日 02:35]
link 編集する

コメント一覧

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



link もっと前
   2019年 10月 6日 -
      2019年 10月 15日  
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 サイトの情報