Interface 2022年7月号第3部第3章の内容を(今更)実践したので内容をメモします。
なお、誌面ではmacOSを用いて仮想マイコンの実験を行っていますが、本記事ではUbuntu 22.04 LTSを用いて実験します。
ARMツールチェーンのインストール
仮想マイコン上で動作するバイナリを開発する為に、ツールチェーンを公式サイトからダウンロードします。
$ curl -OL https://developer.arm.com/-/media/Files/downloads/gnu/11.2-2022.02/binrel/gcc-arm-11.2-2022.02-aarch64-arm-none-linux-gnueabihf.tar.xz $ tar Jxfv gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf.tar.xz
/path/to/gcc-arm-xx-x86_64-aarch64-none-elf/bin
にパスを通し、任意の場所でコマンドが使えるようにして、インストールを終了します。
補足1
- none: ベアメタル(OSを持たないプラットフォーム)上で動作するバイナリの生成を意味する
OS上で動作するバイナリであれば、標準Cライブラリを使用でき、実行時にはインタプリタによって仮想メモリ上にバイナリが配置されますが、 ベアメタル上で動作するバイナリは、標準Cライブラリを使用できず、実行前に物理メモリ(ROM)上にバイナリが直接配置されます。
補足2
Ubuntuの公式レポジトリで提供されているパッケージ(gcc-arm-none-eabi)では、64bitARMを対象としたプログラムはコンパイルできないようなので、注意が必要です。
ARM64プログラムのクロスコンパイル
下記コマンドでプログラムを生成します。 (引用の範囲を逸脱するため、プログラムのソースコードは省略)
$ aarch64-none-elf-gcc -g -c -static start.S -o start.o $ aarch64-none-elf-gcc -g -c -static main.c -o main.o $ aarch64-none-elf-ld -Ttext 0x40080000 -o out.elf start.o main.o $ aarch64-none-elf-objcopy -O binary out.elf out.img
これらのコマンドについて(自分の分かる範囲で)解説します。
aarch64-none-elf-gcc -g -c -static start.S -o start.o
、aarch64-none-elf-gcc -g -c -static main.c -o main.o
ソースコードやアセンブリをオブジェクトファイルへアセンブルするコマンドです。
-static
オプションは、Man page曰く共有ライブラリとのリンクを抑制するとのことです。
直観的には、「OSの無い環境では動的リンカも存在しないので、共有(動的)ライブラリを使わないようにする必要がある」と理解できるのですが、
一方で、「そもそも(少なくとも今回の場合は)共有ライブラリを使用していないので、-static
オプションは不要なのでは」という疑問があります。
実際に、-static
オプションがある場合と無い場合のout.elf
ファイルにおけるreadelf
の出力をdiffしてみたのですが、目立った違いはありませんでした。
(せいぜいファイル名の違いによって.strtabセクションの内容が違っていた程度)
結論としては、少なくとも今回の場合は-static
オプションは不要ではないかと思われるのですが、とりあえず-static
オプションを付けたまま話を続けます。
aarch64-none-elf-ld -Ttext 0x40080000 -o out.elf start.o main.o
オブジェクトファイルstart.o
とmain.o
をリンクするコマンドです。
-Ttext 0x40080000
は、Man Page曰く出力ファイルにおける.textセクションの絶対アドレスを指定するオプションです。
Interfaceの記事曰く、
QEMUではプログラムが0x40080000に配置される
そうなので、プログラムの本体である.textセクションがQEMUにて最初に読み込まれるよう調整するためのオプションだと思われます。
aarch64-none-elf-objcopy -O binary out.elf out.img
out.elf
をout.img
へ変換する処理をしています。
(なぜelfファイルからimgファイルへの変換が必要なのか、そもそもimgファイルが何なのかは現状よく分かってないです…。)
QEMUでバイナリを実行
$ qemu-system-aarch64 -cpu cortex-a57 -machine virt -kernel out.img -monitor stdio
上記コマンドでHello worldが出力されたコンソールが現れれば、誌面の実験の再現には成功です。
参考サイト
環境
Ubuntu 22.04 LTS