コグノスケ


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

link もっと前
2019年9月13日 >>> 2019年10月13日
link もっと後

2019年9月17日

今まで知らなかったmakeの挙動

シェルからmakeに渡す環境変数とmake変数の関係を知らなくて、かなりハマったのでメモしておきます。

まず、どういう関係か説明します。下記のようなMakefileを2つ用意します。

ディレクトリ構成
$ tree
.
|-- Makefile
`-- sub
    `-- Makefile
親: Makefile

VAR_A = aaa
VAR_B = bbb

all:
	@echo "In parent"
	@echo "VAR_A: '$(VAR_A)'"
	@echo "VAR_B: '$(VAR_B)'"
	@echo "VAR_C: '$(VAR_C)'"
	make -C sub
子: sub/Makefile

all:
	@echo "In sub"
	@echo "VAR_A: '$(VAR_A)'"
	@echo "VAR_B: '$(VAR_B)'"
	@echo "VAR_C: '$(VAR_C)'"

親Makefileは変数VAR_A, VAR_Bを書き換え、子sub/Makefileを再帰的に呼び出します。各Makefileでは変数の値を表示しています。

では、トップディレクトリにてmakeを実行してみましょう。

通常の実行結果
$ make
In parent
VAR_A: 'aaa'    ★VAR_Aは設定した値になっている★
VAR_B: 'bbb'    ★VAR_Bは設定した値になっている★
VAR_C: ''       ★VAR_Cは特に書き換えていないので空★
make -C sub
make[1]: Entering directory '/home/katsuhiro/share/falcon/projects/c/makefile_env_var/sub'
In sub
VAR_A: ''    ★VAR_Aは渡されない★
VAR_B: ''    ★VAR_Bは渡されない★
VAR_C: ''    ★VAR_Cは渡されない★
make[1]: Leaving directory '/home/katsuhiro/share/falcon/projects/c/makefile_env_var/sub'

ご覧の通り、親のMakefileで値を設定したVAR_AやVAR_Bといった変数は、子のsub/Makefileに「引き継がれません」

make変数の渡し方

外部からmakeに変数を渡すには、下記の2つの方法があります。

  • 環境変数として渡す方法。例: VAR_A=A make
  • makeに渡す方法。例: make VAR_A=A

私は今まで、この2つの渡し方に何も差はないと思っていたのですが、実は全く動きが違いました。

環境変数の場合

下記のようにVAR_A, VAR_Cを環境変数として与えると、子Makefile側の結果がかなり変わります。

VAR_A, VAR_Cを環境変数として渡したときの実行結果
$ VAR_A=A VAR_C=C make
In parent
VAR_A: 'aaa'    ★VAR_Aは親が設定した値になる★
VAR_B: 'bbb'
VAR_C: 'C'      ★VAR_Cは特に書き換えていないので、渡された値のまま★
make -C sub
make[1]: Entering directory '/home/katsuhiro/share/falcon/projects/c/makefile_env_var/sub'
In sub
VAR_A: 'aaa'    ★VAR_Aが渡される、Aではなく親が設定した値aaaになっている★
VAR_B: ''
VAR_C: 'C'      ★VAR_Cが渡される、値は変わらず★
make[1]: Leaving directory '/home/katsuhiro/share/falcon/projects/c/makefile_env_var/sub'

何も渡さなかった場合の実行結果と異なり、子のsub/MakefileにもVAR_A, VAR_Cが渡されます。もし、親Makefileが変数の値を書き換えた場合は、書き換えた値が子Makefileに渡されます。

この動作は知りませんでした。特に子プロセスへの変数の渡し方が変わる点が衝撃的です。

makeに渡す場合

下記のようにVAR_A, VAR_Cをmakeに渡すと、環境変数として渡す場合とは違う結果になります。

VAR_A, VAR_Cをmakeの変数として渡したときの実行結果
$ make VAR_A=A VAR_C=C
In parent
VAR_A: 'A'      ★VAR_Aは親が設定した値にならない★
VAR_B: 'bbb'
VAR_C: 'C'
make -C sub
make[1]: Entering directory '/home/katsuhiro/share/falcon/projects/c/makefile_env_var/sub'
In sub
VAR_A: 'A'      ★VAR_Aが渡される、VAR_Aは親が設定した値にならない★
VAR_B: ''
VAR_C: 'C'      ★VAR_Cが渡される、値は変わらず★
make[1]: Leaving directory '/home/katsuhiro/share/falcon/projects/c/makefile_env_var/sub'

環境変数で渡した場合と同様に、子Makefileに変数の内容が渡されます。その点は同じです。しかし、親Makefileで行っているaaaという値の代入が無効化され、渡される値が全く違います。

この動作も知りませんでした……。私はMakefileやmakeとは長い付き合いですし、動きも何となくわかっていた気分になっていましたが、勘違いだったようです。makeは難しすぎます。

ハマったポイント

この動きによって、何が困ったかを紹介しておきます。同じ状況に陥る人は、まずもっていないと思いますけど、ご参考まで。

現象としては「makeでビルドすると成功するが、debuild(Debianのパッケージング作成スクリプト)経由でビルドすると失敗する」です。この現象から原因が予想できた人、あなたは凄い(少なくとも私より凄い)です!この先は読む必要はございません。

下記のような感じの、ちょっと変わったMakefileを使っているソフトウェアをビルドしていました。

  • 親Makefileから、子の ./configureを呼ぶ
  • 親MakefileはCFLAGSやLDFLAGSを固定値に設定している(固有のライブラリをリンクするため)

もう一つ大事な点は、親Makefileが使っているLDFLAGSを、子 ./configureに渡すと「そんなライブラリはないというエラー」になってしまう欠点があることです。

じゃあビルドエラーが起きるのか?というとそうではなく、先ほどご紹介した通り、何も指定せずにmakeを起動すれば、親Makefileの変数は、子 ./configureに渡りませんから、makeだけ実行すればエラーを起こさずビルドできるのです。

debuildと環境変数の罠

一見、正常にビルドできて問題ないように見えますが、このソフトウェアを *.debにパッケージングしようとするとハマります。Debianのパッケージ作成スクリプトdebuildは下記のような動作をするからです。

  • debuildはエラーチェック、セキュリティ強化のためCFLAGS, LDFLAGSにいくつかオプションを指定する
  • CFLAGS, LDFLAGSは「環境変数」でmakeに渡される

そろそろ何が起きるか予想が付くでしょう。そう、こうなるんです。

  • debuildが、親Makefileに環境変数でCFLAGS, LDFLAGSを渡す
  • 親MakefileがCFLAGS, LDFLAGSを書き換える
  • 親Makefileが、子 ./configureに書き換わった後のCFLAGS, LDFLAGSを渡す

この華麗なコンボが決まって、makeとするとビルドが成功し、debuild経由だとビルドが失敗する、謎のビルド環境ができあがります。

感想

こんなバグ、初見で分かる、はずもなし。

Makefileは大抵の人には難しすぎます。Makefileを手で書いているといつか地獄に落ちますよ、CMakeとかautomakeを使いましょう。便利だよ!

編集者:すずき(2019/09/19 02:27)

コメント一覧

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



2019年9月18日

linux-nextが久しぶりに更新された

ここしばらく更新されていなかったlinux-nextが約10日ぶりに更新(9/4の次が9/15)されたので、喜んでgit fetchしてTinker Boardのカーネルを書き換えたところ、ウンともスンとも言わなくなってしまいました。

質の悪いことにエラーメッセージも何も出さずにハングアップするため、起動しなくなった原因がさっぱりわかりません。

仕方ないので頑張ってgit bisectし、起動しなくなった原因のコミットを見つけましたが、実は9/17にLKMLにて既に指摘済みで、直し方まで検討されていました(LKMLへのリンク)。今までの苦労は何だったのか。

結果だけ見ると、最初にLKMLのメールスレッドに気づいていればbisectなんて不要でした。しかし、一切エラーメッセージを出さずにハングするので、検索のヒントがありません。ノーヒントでLKMLの当該メールスレッドを探せたか?と考えてみると、ちょっと難しい気がします。

いわゆる鶏と卵の問題ですね……。

編集者:すずき(2019/09/20 00:01)

コメント一覧

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



2019年10月6日

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

目次: 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はソースコードが読めるため、当たりを付けることが比較的容易です。しばらくは素敵なおもちゃになりそうなボードです。

編集者:すずき(2021/06/28 15:26)

コメント一覧

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



2019年10月12日

台風19号

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

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


多摩川の水位

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

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

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

家財

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

編集者:すずき(2019/10/24 01:35)

コメント一覧

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



2019年10月13日

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)

コメント一覧

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



link もっと前
2019年9月13日 >>> 2019年10月13日
link もっと後

管理用メニュー

link 記事を新規作成

<2019>
<<<09>>>
1234567
891011121314
15161718192021
22232425262728
2930-----

最近のコメント5件

  • link 24年6月17日
    すずきさん (06/23 00:12)
    「ありがとうございます。バルコニーではない...」
  • link 24年6月17日
    hdkさん (06/22 22:08)
    「GPSの最初の同期を取る時は見晴らしのい...」
  • link 24年5月16日
    すずきさん (05/21 11:41)
    「あー、確かにdpkg-reconfigu...」
  • link 24年5月16日
    hdkさん (05/21 08:55)
    「システム全体のlocale設定はDebi...」
  • link 24年5月17日
    すずきさん (05/20 13:16)
    「そうですねえ、普通はStandardなの...」

最近の記事3件

  • link 24年6月27日
    すずき (06/30 15:39)
    「[何もない組み込み環境でDOOMを動かす - その4 - 自作OSの組み込み環境へ移植] 目次: RISC-V目次: 独自OS...」
  • link 22年12月13日
    すずき (06/30 15:38)
    「[独自OS - まとめリンク] 目次: 独自OS一覧が欲しくなったので作りました。自作OSの紹介その1 - 概要自作OSの紹介...」
  • link 21年6月18日
    すずき (06/29 22:28)
    「[RISC-V - まとめリンク] 目次: RISC-VSiFive社ボードの話、CoreMarkの話のまとめ。RISC-V ...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
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 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

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

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 06/30 15:39