目次: Zephyr
Zephyr SDKのhosttoolsを移動したらハマったので、メモしておきます。
Zephyr SDKは自前のhosttools(dtcやopenocd、qemuなど)のバイナリを持っていてシステム側のバイナリのバージョンによる不具合などを避けて必要なツールを使うことができます。が、インストールしたパスに強く依存していてディレクトリを移動させると動かなくなります。
今回は動かないバイナリを観察してなぜ動かないのか調べます。
ダイナミックリンカーのパスは実行バイナリに含まれています。
$ readelf -S ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc There are 29 section headers, starting at offset 0x1e7b8: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 00000000000002a8 000002a8 ★これ★ 0000000000001000 0000000000000000 A 0 0 1 [ 2] .note.gnu.bu[...] NOTE 00000000000012a8 000012a8 0000000000000024 0000000000000000 A 0 0 4 $ hexdump -C ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc ...略... 00000290 10 09 00 00 00 00 00 00 10 09 00 00 00 00 00 00 |................| 000002a0 01 00 00 00 00 00 00 00 2f 68 6f 6d 65 2f 6b 61 |......../home/ka| ★.interpセクションヘッダ★ 000002b0 74 73 75 68 69 72 6f 2f 74 65 73 74 2f 7a 65 70 |tsuhiro/test/zep| ★環境依存のパスがある★ 000002c0 68 79 72 2d 73 64 6b 2d 30 2e 31 36 2e 35 2d 31 |hyr-sdk-0.16.5-1| 000002d0 2f 73 79 73 72 6f 6f 74 73 2f 78 38 36 5f 36 34 |/sysroots/x86_64| 000002e0 2d 70 6f 6b 79 73 64 6b 2d 6c 69 6e 75 78 2f 6c |-pokysdk-linux/l| 000002f0 69 62 2f 6c 64 2d 6c 69 6e 75 78 2d 78 38 36 2d |ib/ld-linux-x86-| 00000300 36 34 2e 73 6f 2e 32 00 00 00 00 00 00 00 00 00 |64.so.2.........| 00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Zephyrの公式サイトで配布しているバイナリに、私のホームディレクトリを含むパスが入っている訳がありません。おそらくインストール時に書き換えているのでしょう。
解析のためhosttoolsのインストーラを改造し、バイナリを書き換える前(292行目辺り)に入力待ちで止まるコマンド(catとか)を入れて実行を止めます。インストーラ改造の際の注意点として、インストーラ末尾にあるバイナリを壊さないように編集してください(例えばVimのバイナリモードvim -bなどを使う)。
## zephyr-sdk-x86_64-hosttools-standalone-0.9.sh: 290行目付近
...
executable_files=$($SUDO_EXEC find $native_sysroot -type f \
\( -perm -0100 -o -perm -0010 -o -perm -0001 \) -printf "'%h/%f' ")
if [ "x$executable_files" = "x" ]; then
echo "SDK relocate failed, could not get executalbe files"
exit 1
fi
cat ★この後で書き換えているようなので、ここで止める★
tdir=`mktemp -d`
if [ x$tdir = x ] ; then
echo "SDK relocate failed, could not create a temporary directory"
exit 1
fi
...
$ ./zephyr-sdk-x86_64-hosttools-standalone-0.9.sh -y -d ~/test/aaa Zephyr Yocto Toolchain SDK installer version 0.9 ================================================ You are about to install the SDK to "/home/katsuhiro/test/aaa". Proceed [Y/n]? Y Extracting SDK..................done Setting it up...^Z [1]+ 停止 ./zephyr-sdk-x86_64-hosttools-standalone-0.9.sh -y -d ~/test/aaa
バイナリの書き換えが起こる前に止めました。この状態でダイナミックリンカーのパスを見ます。
$ ldd ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc linux-vdso.so.1 (0x00007ffd5d74f000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa4d5e8e000) /opt/zephyr-sdk/0.9/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fa4d60b5000)
書き換える前のパスは/opt/zephyr-sdk/0.9で、インストーラのデフォルトインストール先と同じパスです。
ダイナミックリンカーのパスを書き換えるのは誰か?ディレクトリにあるrelocate_sdk.pyスクリプトです。このスクリプトはhosttoolsインストール終了後に消されるので、インストーラを改造して途中で止めないと中身を拝むことができません。
$ ls environment-setup-x86_64-pokysdk-linux relocate_sdk.py ★このスクリプト★ sysroots version-x86_64-pokysdk-linux zephyr-sdk-x86_64-hosttools-standalone-0.9.sh
詳しく追っていませんが、change_interpreter()関数が書き換える本体のようです。
def change_interpreter(elf_file_name):
if arch == 32:
ph_fmt = "<IIIIIIII"
else:
ph_fmt = "<IIQQQQQQ"
""" look for PT_INTERP section """
for i in range(0,e_phnum):
f.seek(e_phoff + i * e_phentsize)
ph_hdr = f.read(e_phentsize)
if arch == 32:
# 32bit
p_type, p_offset, p_vaddr, p_paddr, p_filesz,\
p_memsz, p_flags, p_align = struct.unpack(ph_fmt, ph_hdr)
else:
# 64bit
p_type, p_flags, p_offset, p_vaddr, p_paddr, \
p_filesz, p_memsz, p_align = struct.unpack(ph_fmt, ph_hdr)
""" change interpreter """
if p_type == 3:
# PT_INTERP section
f.seek(p_offset)
# External SDKs with mixed pre-compiled binaries should not get
# relocated so look for some variant of /lib
fname = f.read(11)
if fname.startswith(b("/lib/")) or fname.startswith(b("/lib64/")) or \
fname.startswith(b("/lib32/")) or fname.startswith(b("/usr/lib32/")) or \
fname.startswith(b("/usr/lib32/")) or fname.startswith(b("/usr/lib64/")):
break
if p_filesz == 0:
break
if (len(new_dl_path) >= p_filesz):
print("ERROR: could not relocate %s, interp size = %i and %i is needed." \
% (elf_file_name, p_memsz, len(new_dl_path) + 1))
break
dl_path = new_dl_path + b("\0") * (p_filesz - len(new_dl_path))
f.seek(p_offset)
f.write(dl_path) #★新たなパスに書き換え★
break
プログラムヘッダのPT_INTERPセクションを探して、/libや/usr/libから始まるパス以外であれば書き換える仕組みです。バイナリにデフォルトで含まれているパスは/optから始まっていましたから、書き換え対象になるわけです。
Zephyr SDKのhosttoolsインストール時にこんなことしてたんですね……知らんかった。
目次: Zephyr
Zephyr SDKのhosttoolsを移動したらハマったので、メモしておきます。
Zephyr SDKは自前のhosttools(dtcやopenocd、qemuなど)のバイナリを持っていてシステム側のバイナリのバージョンによる不具合などを避けて必要なツールを使うことができます。直接呼び出すことはなくても、westを使っている人は間接的に使っているはずです。
そんな便利なhosttoolsなんですけど、インストールしたパスに強く依存していてディレクトリを移動させると動かなくなります。何が起きるか順に見ましょう。初めにhosttoolsのみをインストールし、dtcを実行します。
$ mkdir test $ cd ~/test $ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.5-1/zephyr-sdk-0.16.5-1_linux-x86_64_minimal.tar.xz $ tar xf zephyr-sdk-0.16.5-1_linux-x86_64_minimal.tar.xz $ cd ~/test/zephyr-sdk-0.16.5-1 $ ./zephyr-sdk-x86_64-hosttools-standalone-0.9.sh -y -d ~/test/zephyr-sdk-0.16.5-1 $ ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc --version Version: DTC 1.6.0-dirty
正常動作しました。次にディレクトリを移動して、もう一度dtcを実行します。
$ cd ~/test $ mv zephyr-sdk-0.16.5-1 aaa $ cd ~/test/aaa $ ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc --version bash: ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc: 実行できません: 必要なファイルがありません
バイナリは一切変更していないのに動かなくなってしまいました……。バイナリは同一ですから設定もしくはダイナミックリンク周りが怪しそうです。まずはlddでライブラリ参照パスを見ます。
$ ldd ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc linux-vdso.so.1 (0x00007ffd3e302000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbd136b2000) /home/katsuhiro/test/zephyr-sdk-0.16.5-1/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fbd138d9000)
ダイナミックリンカー(ld-linux.so)のパスにhosttoolsをインストールしたパスが含まれています。先ほどhosttoolsのディレクトリごと移動してしまったので、リンカーが見当たらないと怒っているようです。
続きはまた今度にします。
ささやかではありますが台湾東部沖地震に寄付しました。日本の赤十字社→台湾の赤十字(正式名称は中華民国紅十字会)の経路で支援されるようです。
今回調べて初めて知ったのですが、台湾の赤十字社は中国との関係で微妙な位置に立たされているようです。
とまあ中国と台湾間の政治問題によるものみたいです。まあ政治問題はさておいて、私は台湾赤十字の支援活動が誠実に行われていると信じて寄付するのみです。
目次: Linux
AsciiDoc ExtensionはAsciiDocのプレビューはもちろんのこと、AsciiDoc文書に埋め込んだMermaidやPlantUMLのような図形作成用言語の画像もプレビュー可能です。
以前のバージョンではローカルにツールをインストールしてプレビュー画像を生成できました(2022年9月4日の日記参照)が、最近のバージョン(おそらく3.1.0以降?)はKroki(Krokiのサイト)による図形描画に変更されたようです。
AsciiDoc Extensionのデフォルト設定だとhttps://kroki.ioにMermaidやPlantUMLのソースコードを送って、画像を受け取る設定になっています。これで問題なければそのまま使用すれば良いですが、外部のサーバーにソースコードを送りたくない場合はローカルにKrokiサーバーを立ち上げることでローカルネットワーク環境で完結することもできます。素晴らしいですね。
Krokiのローカルサーバー立ち上げについてはDockerが便利なようです。Dockerが良い方はそちらを検索してみてください。
今回はKrokiを単体で立ち上げてみます。……と言ってもKroki自体に特に難しいことはなく、公式サイト(Manual Install :: Kroki Documentation)の説明の通りにやればよいです。PlantUMLを表示させたければGraphvizとPlantUMLをインストールした上で、
$ which dot /usr/bin/dot $ which plantuml /usr/bin/plantuml
GitHub ReleaseページからダウンロードしたKrokiのJARファイルを起動するだけでサーバーとして機能します。Krokiはサーバー機能を持っていて、動作テストにちょうど良いです。
$ java -jar kroki-standalone-server-v0.25.0.jar \ -DKROKI_LISTEN=0.0.0.0:5000
KROKI_LISTENはどのポートで待ち受けるか?の設定です。PlantUML系の設定は特に何も追加しなくてもPlantUMLを認識していました。これはテスト用の簡易サーバー機能なので、本格的に運用する際はアプリケーションサーバーに登録したほうが良いと思います、その設定はまた今度。
Krokiローカルサーバーを立ち上げたら、VSCodeを設定する必要があります。まずAsciiDoc Extensionの設定を開きます。
Asciidoc > Preview: Asciidoctor Attributesの項目にある[Edit in setting.json]のリンクを開きます。
設定の最後辺りに、
"asciidoc.preview.asciidoctorAttributes": {
"kroki-server-url": "http://192.168.1.1:5000"
}
を追加するとローカルサーバーに切り替わるはずです。192.168.1.1の部分はKrokiのローカルサーバーを動作させているIPアドレスを指定します。
ローカルサーバーにて画像生成すると見た目が少し変わります。おそらくですが、インターネット側のKrokiサーバーはデフォルトのデザインを変えていると思われます。下記のAsciidoc文書を入力として確かめます。
This is a sample of PlantUML diagram.
[plantuml]
----
@startuml
box "Box"
participant "App" as app
participant "Library" as lib
endbox
activate app
activate lib
app -> lib : Something()
@enduml
----
デフォルトつまりインターネット上のKrokiサーバーを使用する場合、このような結果になります。
ローカルサーバーを使用する場合、このような結果になります。グレーっぽいデザインから黄色のデザインに変わりました。
Krokiはkroki-standalone-server-v0.25.0.jarで、Krokiを動作させている環境はDebian Testingです。各モジュールのバージョンは、
です。
目次: Arduino
以前(2024年3月24日の日記参照)発注して、全く動ないうえにNMOSが焼ける(2024年4月3日の日記参照)PCBを直してみました。
まずはミスったNMOS 8個を全部外しました。当初はNMOSをきれいに外して再利用できないか?と考えたんですが、ナメた考えだったことがすぐにわかりました。全然外れません、無理だこれ。
次善策としてNMOSの足を切り破壊しながら外しました。代わりのNMOSはOnSemi BSS138を新たに購入します(秋月で売ってる)。本当はOnSemi BSS123ですけど、高周波とか高圧電流とか厳しい信号ではないしBSS123でもBSS138でも大差ありません。
NMOSを外したら修正します。ミスした箇所はNMOSのピン配置ですから、辻褄が合うようにNMOSを付け直せば良いはずです。
PCB側が想定しているピン配置(間違い) Drain 1 | | | NMOS | 3 Source Gate 2 | | NMOS側のピン配置(正しい) Gate 1 | | | NMOS | 3 Drain Source 2 | |
NMOSを裏向きにつけたらどうかとアドバイスも頂いたんですが、ちょうど左周りに60°回転させるとGate/Source/Drainがぴったり合いますので、回転させて付けることにしました。
SOT-23のピン配置は正三角形ではない(1-2間だけ若干狭い)ため、回転させると端子がはみ出してしまいます。私はハンダ付けが上手な訳でもなく、表面実装系の細かいやつは難しいのでハンダをちょっと増やしてごまかします。
できました。斜めに付いてる違和感がすごいのと芋ハンダだらけで長持ちしなさそうです。そもそも手修理ボードは長期運用するつもりがないから今だけ動いてくれればとりあえずヨシ!!
目次: Arduino
以前(2024年3月24日の日記参照)発注したPCBが届いたので、動かしてみたら全く動きませんでした。動かないどころか通電したら通常は0.07Aくらいのはずなのに1.5A近い大電流が流れ続け、しばらくしたらNMOSが焼けて煙が出ました。1万円(部品配置込みで$67)のゴミが爆誕……。
PCのUSBを電源にしてM5Stamp C3も繋いでいたので、PCやM5Stampが壊れる可能性もありました。M5Stampはめちゃくちゃ熱くなっていましたが、幸いなことにどちらも壊れずに済みました。M5Stampは強い子ですね。
ミスした箇所を調べると、どうやらKiCadのNMOSのピン配置と、部品で使ったNMOS(Onsemi BSS-123)のピン配置が違うのが原因のようです。
KiCadは1番ピンがドレイン、BSS-123は1番ピンがゲートなのでゲートとソース/ドレインを逆接続した回路になってしまったということです。Vcc 3.3VとGPIOが短絡していて、GPIOをGNDに繋いだり、GPIOをOutput Lowレベルにすると電源とGNDがショートする危険な状態になっていました。そりゃあNMOSも焼けますよね。これは気づかなかったなあ……。
< | 2024 | > | ||||
<< | < | 04 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | - | - | - | - |
合計:
本日: