はじめに
QEmu-3.1以降でArm向けの機能がより強化されてきています。
例えば、ハイエンド向けのAArch64に対するScalable Vector Extention (SVE)命令のサポートや組込みシステム向けのCortex-M関連機能の強化がなされています。
本稿では, CentOS7/RHEL7環境上にGCC8/QEmu-3.1を用いたELFバイナリ用開発・実行環境を構築する手順を説明します。
ツール・ライブラリ一覧
本稿で構築するツール, ライブラリの一覧を以下に示します。
ツール/ライブラリ名 | 版数 | 概要 | ソースアーカイブ取得元URL |
---|---|---|---|
GNU MP | 6.1.0 | 多倍長整数演算ライブラリ | ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 |
MPFR | 3.1.4 | 多精度浮動小数演算ライブラリ | ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2 |
MPC | 1.0.3 | 任意精度複素数演算ライブラリ | ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz |
ISL | 0.18 | 整数集合操作ライブラリ | ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2 |
Binutils | 2.31 | アセンブラ/リンカなどの実行バイナリ生成・操作ツール群 | https://ftp.gnu.org/gnu/binutils/binutils-2.31.tar.gz |
GCC | 8.2.0 | コンパイラ本体 | https://ftp.gnu.org/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.gz |
NEWLIB | 3.0.0 | 組込みシステム向け標準Cライブラリ | ftp://sourceware.org/pub/newlib/newlib-3.0.0.tar.gz |
GNU Debugger | 8.2 | デバッガ | https://ftp.gnu.org/gnu/gdb/gdb-8.2.tar.gz |
QEMU | 3.1.0 | エミュレータ | https://download.qemu.org/qemu-3.1.0.tar.xz |
ELFバイナリ用クロスコンパイル環境構築手順の概要
GCCを使用したELFバイナリ用のクロスコンパイル環境構築手順は以下の通りになります。
- コンパイル用の一時ディレクトリを作成する
- コンパイラ構築に必要なコマンド群をインストールする
- ソースアーカイブを収集する
- コンパイル作業時に指定するパラメタをシェル変数に設定する
- コンパイラの動作に必要なGNU MPライブラリを作成する
- コンパイラの動作に必要なMPFRライブラリを作成する
- コンパイラの動作に必要なMPCライブラリを作成する
- コンパイラの動作に必要なISLライブラリを作成する
- ターゲット用のバイナリを生成するために必要なbinutilsを生成する
- ターゲット用の標準Cライブラリを構築するためのCコンパイラを生成する
- ターゲット用の標準Cライブラリを構築する
- ターゲット用の標準Cライブラリを使用するC/C++コンパイラを生成する
- ターゲット用のバイナリを実行するエミュレータを生成する
- ターゲット用のバイナリをデバッグするためのデバッガを生成する
コンパイル用の一時ディレクトリを作成する
本稿では, GCCのクロスコンパイラを構築するための一時ディレクトリを生成します。
ソースアーカイブをダウンロードするディレクトリ, ソースアーカイブを展開するディレクトリ, コンパイラ構築処理用の一時ディレクトリをそれぞれ独立したディレクトリとして用意します。
カレントディレクトリに以下のようなディレクトリを作成します。
ディレクトリ名 | 用途 |
---|---|
downloads | ソースアーカイブをダウンロードするディレクトリ |
src | ソースアーカイブを展開するディレクトリ |
build | コンパイラ構築処理用の一時ディレクトリ |
コンパイラ構築に必要なコマンド群をインストールする
コンパイル環境構築に必要なコマンド群をインストールします。
一部のコマンドは, Extra Packages for Enterprise Linux (EPEL)から導入する必要があります。 リポジトリに優先順位を設定するyum-prioritiesや構築時に必要なツール群を導入するための支援ツールであるyum-utilsをインストール後, EPELを導入するためのパッケージ ( epel-release )をインストールします。
また, ソースアーカイブのダウンロードに使用するwget, GNU tar, および, GNU makeコマンドをインストールしておきます。
本稿では, sudoコマンドによって, 管理者権限でコマンドを実行可能に設定されていることを前提にしています。 必要に応じて, 別途sudoコマンドの設定を行ってください。
以下のコマンドを入力します。本稿では, $をコマンドプロンプトとして表記しています。
$ sudo yum install -y yum-priorities yum-utils
$ sudo yum install -y epel-release
$ sudo yum install -y wget tar make
次に, 基本的な開発環境を導入します。
$ sudo yum groupinstall -y "Development tools"
さらに, 実行環境エミュレータであるQEmuを構築するために必要なライブラリ群をインストールします。
$ sudo yum install -y giflib-devel libpng-devel libtiff-devel gtk3-devel \
ncurses-devel gnutls-devel nettle-devel libgcrypt-devel SDL2-devel \
gtk-vnc-devel libguestfs-devel curl-devel brlapi-devel bluez-libs-devel \
libusb-devel libcap-devel libcap-ng-devel libiscsi-devel libnfs-devel \
libcacard-devel lzo-devel snappy-devel bzip2-devel libseccomp-devel \
libxml2-devel libssh2-devel xfsprogs-devel mesa-libGL-devel mesa-libGLES-devel \
mesa-libGLU-devel mesa-libGLw-devel spice-server-devel libattr-devel \
libaio-devel sparse-devel gtkglext-libs vte-devel libtasn1-devel \
gperftools-devel virglrenderer device-mapper-multipath-devel \
cyrus-sasl-devel libjpeg-turbo-devel glusterfs-api-devel \
libpmem-devel libudev-devel capstone-devel numactl-devel \
librdmacm-devel libibverbs-devel libibumad-devel libvirt-devel \
gcc-objc iasl \
ceph ceph-base ceph-common ceph-devel-compat ceph-fuse \
ceph-libs-compat ceph-mds ceph-mon ceph-osd ceph-radosgw ceph-resource-agents \
ceph-selinux ceph-test cephfs-java libcephfs1-devel libcephfs_jni1-devel \
librados2-devel libradosstriper1-devel librbd1-devel librgw2-devel \
python-ceph-compat python-cephfs python-rados python-rbd rbd-fuse \
rbd-mirror rbd-nbd
最後に, クロスコンパイラやQEmuの構築に必要なコマンド群をインストールします。
$ sudo yum-builddep -y binutils gcc gdb qemu-kvm texinfo-tex texinfo
ソースアーカイブを収集する
downloadsディレクトリに, ソースアーカイブをダウンロードします。
以下のコマンドを入力してください。
$ pushd downloads
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
$ wget https://ftp.gnu.org/gnu/binutils/binutils-2.31.tar.gz
$ wget https://ftp.gnu.org/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.gz
$ wget ftp://sourceware.org/pub/newlib/newlib-3.0.0.tar.gz
$ wget https://ftp.gnu.org/gnu/gdb/gdb-8.2.tar.gz
$ wget https://download.qemu.org/qemu-3.1.0.tar.xz
$ popd
コンパイル作業時に指定するパラメタをシェル変数に設定する
クロスコンパイラ構築時は, インストール先ディレクトリなどを複数回指定することになります。 そこで各工程で指定するパラメタをシェル変数として設定しておきます。
本稿では, クロスコンパイラをホームディレクトリ直下のcross/gcc-elf/アーキテクチャ名/構築日
ディレクトリに配置することにします。
変数名 | 意味 |
---|---|
TODAY | コンパイル時の日付 (インストール先ディレクトリの指定に使用) |
CPU | コンパイラが生成するコードのCPUアーキテクチャ |
TARGET | コンパイラが生成するコードを実行可能な環境 |
QEMU_CPU | QEMUエミュレータのCPU名 |
CPU_NR | コンパイラを作成する環境での搭載プロセッサ数 |
SMP_OPT | makeに指定する並行ビルドオプション |
CROSS | クロスコンパイラを導入するディレクトリ |
SYSROOT | ターゲット用の標準Cライブラリを導入するディレクトリ |
TARGET
, HOST
やQEMU_CPU
には, 以下を指定します。
CPUアーキテクチャ | TARGET | HOST | QEMU_CPU |
---|---|---|---|
AArch64 | aarch64-elf | aarch64-elf | aarch64 |
AArch32 (浮動小数点演算プロセッサ使用) | arm-eabihf | arm-eabihf | arm |
IA32 | i686-elf | i686-elf | i386 |
RISC-V 32bit | riscv32-elf | riscv32-elf | riscv32 |
RISC-V 64bit | riscv64-elf | riscv64-elf | riscv64 |
X64 | x86_64-elf | x86_64-elf | x86_64 |
AArch64向けのコンパイラを作成する場合, 以下のように入力します。
$ TODAY=`date "+%F"`
$ CPU=aarch64
$ TARGET=aarch64-elf
$ QEMU_CPU=aarch64
$ CPU_NR=`nproc`
$ SMP_OPT="-j${CPU_NR}"
$ PROGRAM_PREFIX="--program-prefix=${TARGET}-"
$ WORKDIR=`pwd`
$ SRCDIR=${WORKDIR}/src
$ BUILDDIR=${WORKDIR}/build
$ DOWNLOADDIR=${WORKDIR}/downloads
$ CROSS=${HOME}/cross/gcc-elf/${CPU}/${TODAY}
$ SYSROOT=${CROSS}/rfs
また, コンパイラ構築時に必要な一時ディレクトリを以下のように作成しておきます。
$ rm -fr ${CROSS} ${BUILDDIR} ${SRCDIR}
$ mkdir -p ${CROSS}
$ mkdir -p ${BUILDDIR}
$ mkdir -p ${SRCDIR}
さらに, ターゲット用の標準Cライブラリを導入するディレクトリを作成しておきます。
$ mkdir -p ${SYSROOT}
コンパイラの動作に必要なGNU MPライブラリを作成する
ここでは, GNUコンパイラが最適化処理を実行するために必要な多桁整数演算ライブラリ (GMP)を導入します。 GNUコンパイラは, GMPをコンパイラ内部の定数のたたみ込み処理 (constant folding)などに使用します。
本ライブラリは, クロスコンパイラ自身が使用するため構築環境向けにライブラリを構築します。
共有ライブラリ版を生成するとクロスコンパイラの動作時にLD_LIBRARY_PATH
環境変数の設定が必要となるため静的ライブラリのみを生成します。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/gmp-6.1.0.tar.bz2
$ popd
$ mkdir -p ${BUILDDIR}/gmp-6.1.0
$ pushd ${BUILDDIR}/gmp-6.1.0
$ ${SRCDIR}/gmp-6.1.0/configure \
--prefix=${CROSS} \
--enable-cxx \
--disable-shared \
--enable-static
$ gmake ${SMP_OPT}
$ gmake install
$ popd
コンパイラの動作に必要なMPFRライブラリを作成する
ここでは, GNUコンパイラが最適化処理を実行するために必要な任意精度浮動小数点演算ライブラリ (MPFR)を導入します。 GNUコンパイラは, MPFRをコンパイラ内部で定数を引数とした超越関数 (指数関数,対数関数,三角関数,逆三角関数など )をコンパイル時に計算する用途などで使用します。
本ライブラリはクロスコンパイラ自身が使用するため構築環境向けにライブラリを構築します。
共有ライブラリ版を生成するとクロスコンパイラの動作時にLD_LIBRARY_PATH
環境変数の設定が必要となるため静的ライブラリのみを生成します。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/mpfr-3.1.4.tar.bz2
$ popd
$ mkdir -p ${BUILDDIR}/mpfr-3.1.4
$ pushd ${BUILDDIR}/mpfr-3.1.4
$ ${SRCDIR}/mpfr-3.1.4/configure \
--prefix=${CROSS} \
--with-gmp=${CROSS} \
--disable-shared \
--enable-static
$ gmake ${SMP_OPT}
$ gmake install
$ popd
コンパイラの動作に必要なMPCライブラリを作成する
ここでは, GNUコンパイラが最適化処理を実行するために必要な任意精度複素数演算ライブラリ (MPC)を導入します。 本ライブラリはクロスコンパイラ自身が使用するため構築環境向けにライブラリを構築します。
共有ライブラリ版を生成するとクロスコンパイラの動作時にLD_LIBRARY_PATH
環境変数の設定が必要となるため静的ライブラリのみを生成します。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/mpc-1.0.3.tar.gz
$ popd
$ mkdir -p ${BUILDDIR}/mpc-1.0.3
$ pushd ${BUILDDIR}/mpc-1.0.3
$ ${SRCDIR}/mpc-1.0.3/configure \
--prefix=${CROSS} \
--with-gmp=${CROSS} \
--with-mpfr=${CROSS} \
--disable-shared \
--enable-static
$ gmake ${SMP_OPT}
$ gmake install
$ popd
コンパイラの動作に必要なISLライブラリを作成する
GNUコンパイラは, ソースコード中のループに対して生成されるコードを最適化するために, 多面体最適化手法 ( Polyhedral Optimization )を使用します。最適化処理時にループ中の変数が使用される範囲を計算するために, 整数集合演算用のライブラリを使用しています。
ここでは, GNUコンパイラが最適化処理を実行するために必要な整数集合演算ライブラリ (ISL)を導入します。 本ライブラリはクロスコンパイラ自身が使用するため構築環境向けにライブラリを構築します。
共有ライブラリ版を生成するとクロスコンパイラの動作時にLD_LIBRARY_PATH
環境変数の設定が必要となるため静的ライブラリのみを生成します。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/isl-0.18.tar.bz2
$ popd
$ mkdir -p ${BUILDDIR}/isl-0.18
$ pushd ${BUILDDIR}/isl-0.18
$ ${SRCDIR}/isl-0.18/configure \
--prefix=${CROSS} \
--disable-silent-rules \
--with-gmp=system \
--with-gmp-prefix=${CROSS} \
--disable-shared \
--enable-static
$ gmake ${SMP_OPT}
$ gmake install
$ popd
ターゲット用のバイナリを生成するために必要なbinutilsを生成する
GNUコンパイラは, 生成したアセンブリコードから実行可能なバイナリ形式にアセンブル, リンクするためのアセンブラ, リンカとして, GNU binutilsを使用します。
ここでは, GNU コンパイラから使用されるターゲット用のGNU binutilsを導入します。
binutilsは, クロスプラットフォーム汎用ライブラリであるlibibertyを生成します。
共有ライブラリ版をlibiberty生成するとクロスコンパイラの動作時にLD_LIBRARY_PATH
環境変数の設定が必要となるため, configureのオプションに--disable-shared
を付けて静的ライブラリ版のみを生成します。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/binutils-2.31.tar.gz
$ popd
$ mkdir -p ${BUILDDIR}/binutils-2.31
$ pushd ${BUILDDIR}/binutils-2.31
$ ${SRCDIR}/binutils-2.31/configure \
--prefix=${CROSS} \
--target=${TARGET} \
"${PROGRAM_PREFIX}" \
--with-local-prefix=${CROSS}/${TARGET} \
--disable-shared \
--disable-werror \
--with-sysroot=${SYSROOT} \
--disable-nls
$ gmake ${SMP_OPT}
$ gmake install
$ popd
ターゲット用の標準Cライブラリを構築するためのCコンパイラを生成する
典型的な場合, C言語でアプリケーションプログラムを作成する際は, 標準Cライブラリが提供する各種ライブラリ関数を使用します。
しかしながら, 標準Cライブラリ自身がC言語で記載されているため, 標準Cライブラリを含めたクロスコンパイル環境を構築するためには, まず標準Cライブラリに依存しないクロスコンパイラ (Free Standing環境向けコンパイラ )を構築し, これを用いて標準Cライブラリを構築する必要があります。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/gcc-8.2.0.tar.gz
$ popd
$ mkdir -p ${BUILDDIR}/gcc-8.2.0
$ pushd ${BUILDDIR}/gcc-8.2.0
$ ${SRCDIR}/gcc-8.2.0/configure \
--prefix=${CROSS} \
--target=${TARGET} \
--with-local-prefix=${CROSS}/${TARGET} \
--enable-languages="c" \
--disable-bootstrap \
--disable-werror \
--disable-shared \
--disable-multilib \
--with-newlib \
--without-headers \
--disable-lto \
--disable-threads \
--disable-decimal-float \
--disable-libatomic \
--disable-libitm \
--disable-libquadmath \
--disable-libvtv \
--disable-libcilkrts \
--disable-libmudflap \
--disable-libssp \
--disable-libmpx \
--disable-libgomp \
--disable-libsanitizer \
--with-gmp=${CROSS} \
--with-mpfr=${CROSS} \
--with-mpc=${CROSS} \
--with-isl=${CROSS} \
--disable-nls
$ gmake ${SMP_OPT}
$ gmake install
$ popd
また, ビルド環境のgccとの混乱を避けるため, ターゲット用のプレフィクスなしにコンパイラが呼び出されないようにします。
以下のコマンドを入力します。
$ pushd ${CROSS}/bin
$ rm -f cpp gcc gcc-ar gcc-nm gcc-ranlib gcov
$ popd
ターゲット用の標準Cライブラリを構築する
ここでは, 前節で構築したクロスコンパイラを使用してターゲット用の標準Cライブラリを生成します。
本稿では, 組み込みシステムなどのベアメタル環境向けに使用されているnewlib
を構築します。
newlibは, システムコールなどのサポートを行うボードサポートパッケージと標準Cライブラリが独立したロードモジュールとして構成されているため, OSを使用しない環境でも標準Cライブラリ関数の多くを利用することが可能です。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/newlib-3.0.0.tar.gz
$ popd
$ mkdir -p ${BUILDDIR}/newlib-3.0.0
$ pushd ${BUILDDIR}/newlib-3.0.0
$ ${SRCDIR}/newlib-3.0.0/configure \
--prefix=/usr \
--target=${TARGET}
$ gmake ${SMP_OPT}
$ gmake DESTDIR=${SYSROOT} install
$ popd
newlibは, インストール先のディレクトリ配下に, configureの--target
オプションで指定されたターゲット名を持ったディレクトリを生成し, その直下にヘッダとライブラリをインストールします。
そこで, ヘッダとライブラリの位置を補正して, クロスコンパイラからヘッダやライブラリを参照できるようにします。 以下のコマンドを入力します。
$ pushd ${SYSROOT}
$ rm -fr ${SYSROOT}/usr/include ${SYSROOT}/usr/lib ${SYSROOT}/usr/lib64
$ mv usr/${TARGET}/* usr
$ rmdir usr/${TARGET}
$ popd
標準Cライブラリを使用するC/C++コンパイラを生成する
ターゲット用の標準Cライブラリを使用してプログラムを構築するためのC/C++コンパイラを構築します。
ここでは, 組込みシステムでも重要となってきている標準Cに近年取り込まれた仕様やセキュアプログラミングを支援する以下の機能を有効にしてコンパイルします。
- ISO/IEC WDTR 24732 Decimal Floating-point Arithmetic (十進浮動小数点算術演算) (--enable-decimal-float)
- 4倍精度算術演算 (--enable-libquadmath)
- バッファー・オーバーフロー, ヒープ領域不正使用検出機構 ( --enable-libmudflap )
- Stack Smashing Protector (SSP) (バッファーオーバーフロー攻撃検出機構) ( --enable-libssp )
- Thread Local Storage機能 ( --enable-tls )
- C/C++コンパイラとリンク時最適化機能 (LTO) (--enable-languages="c,c++,lto")
リンク時最適化機能は, AArch64などUnified Extensible Firmware Interface (UEFI)を持った組み込みシステムの構築時に必要な機能です。
また、前節で導入した標準Cライブラリをヘッダ・ライブラリ検索先に指定します (
--with-sysroot=${SYSROOT} )。
なお, newlibはスレッドライブラリを提供していませんのでスレッド並列関連の機能は無効にしています。
以下のコマンドを入力します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/gcc-8.2.0.tar.gz
$ popd
$ mkdir -p ${BUILDDIR}/gcc-8.2.0
$ pushd ${BUILDDIR}/gcc-8.2.0
$ ${SRCDIR}/gcc-8.2.0/configure \
--prefix=${CROSS} \
--target=${TARGET} \
--with-local-prefix=${CROSS}/${TARGET} \
--enable-languages="c,c++,lto" \
--disable-bootstrap \
--disable-werror \
--disable-shared \
--disable-multilib \
--with-newlib \
--disable-threads \
--disable-libatomic \
--disable-libitm \
--disable-libvtv \
--disable-libcilkrts \
--disable-libmpx \
--disable-libgomp \
--disable-libsanitizer \
--with-gmp=${CROSS} \
--with-mpfr=${CROSS} \
--with-mpc=${CROSS} \
--with-isl=${CROSS} \
--enable-decimal-float \
--enable-libquadmath \
--enable-libmudflap \
--enable-libssp \
--enable-tls \
--with-sysroot=${SYSROOT} \
--disable-nls
$ gmake ${SMP_OPT}
$ gmake install
$ popd
ビルド環境のgccとの混乱を避けるため, ターゲット用のプレフィクスなしにコンパイラが呼び出されないようにします。
以下のコマンドを入力します。
$ pushd ${CROSS}/bin
$ rm -f cpp gcc gcc-ar gcc-nm gcc-ranlib gcov
$ popd
ターゲット用のバイナリを実行するエミュレータを生成する
次に, ターゲット用のバイナリをビルド環境上で実行するためのエミュレータを生成します。
近年では, 組込み分野でもエミュレータを用いた実機レス開発が進んでいます。
本稿では, オープンソースのエミュレータであるQEmu
を使用することにします。
以下のコマンドを入力して, QEmu
を導入します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/qemu-3.1.0.tar.xz
$ popd
$ mkdir -p ${BUILDDIR}/qemu-3.1.0
$ pushd ${BUILDDIR}/qemu-3.1.0
$ ${SRCDIR}/qemu-3.1.0/configure \
--prefix=${CROSS} \
--interp-prefix=${SYSROOT} \
--target-list="${QEMU_CPU}-softmmu,${QEMU_CPU}-linux-user" \
--enable-system \
--enable-user \
--enable-linux-user \
--enable-tcg-interpreter \
--disable-werror
$ gmake ${SMP_OPT}
$ gmake install
$ popd
ターゲット用のバイナリをデバッグするためのデバッガを生成する
最後に, ターゲット用のバイナリをデバッグするためのデバッガを生成します。
また, QEMUターゲットをgdbでリモートデバッグする際に発生する
Remote 'g' packet reply is too long
エラーを回避するためのパッチを適用します。
適用するパッチの内容は, 以下の通りです。
--- gdb-8.2.orig/gdb/remote.c 2018-09-05 16:44:28.000000000 +0900
+++ gdb-8.2/gdb/remote.c 2018-11-05 15:30:39.745920969 +0900
@@ -8034,9 +8034,21 @@
buf_len = strlen (rs->buf);
/* Further sanity checks, with knowledge of the architecture. */
- if (buf_len > 2 * rsa->sizeof_g_packet)
- error (_("Remote 'g' packet reply is too long (expected %ld bytes, got %d "
- "bytes): %s"), rsa->sizeof_g_packet, buf_len / 2, rs->buf);
+ if (buf_len > 2 * rsa->sizeof_g_packet) {
+
+ rsa->sizeof_g_packet = buf_len;
+ for(i = 0; i < gdbarch_num_regs(gdbarch); i++){
+
+ if (rsa->regs[i].pnum == -1)
+ continue;
+
+ if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
+ rsa->regs[i].in_g_packet = 0;
+ else
+ rsa->regs[i].in_g_packet = 1;
+ }
+ }
+
/* Save the size of the packet sent to us by the target. It is used
as a heuristic when determining the max size of packets that the
上記のパッチを${WORKDIR}
配下にgdb-8.2-qemu-x86-64.patch
という名前で保存した上で, 以下のコマンドを実行します。
$ pushd ${SRCDIR}
$ tar xf ${DOWNLOADDIR}/gdb-8.2.tar.gz
$ popd
$ pushd ${SRCDIR}/gdb-8.2
$ patch -p1 < ${WORKDIR}/gdb-8.2-qemu-x86-64.patch
$ popd
$ mkdir -p ${BUILDDIR}/gdb-8.2
$ pushd ${BUILDDIR}/gdb-8.2
$ ${SRCDIR}/gdb-8.2/configure \
--prefix=${CROSS} \
--target=${TARGET} \
--with-local-prefix=${CROSS}/${TARGET} \
--program-prefix="${TARGET}-" \
--disable-werror \
--disable-nls
$ gmake ${SMP_OPT}
$ gmake install
$ popd
クロスコンパイラ導入先ディレクトリへのシンボリックリンクの設定
以下のコマンドを実行して, 構築したコンパイル環境へのシンボリックリンクを作成します。
$ rm -f ${CROSS_PREFIX}/current
$ pushd ${CROSS_PREFIX}
$ ln -sv ${TODAY} current
$ popd
以上により, ${HOME}/cross/gcc-elf/アーキテクチャ名/current/bin
を環境変数PATH
に追加することで, クロスコンパイル環境を利用可能となります。
SVE命令を体験してみましょう
GCC-8からコンパイラがAArch64のSVE命令を使用したベクトル最適化に対応しており, また, QEmu-3.1からSVE命令をシステムエミュレータ, ユーザランドエミュレータの双方で解釈可能となりました。
そこで上記のクロスコンパイル環境を利用してSVE命令を体験してみましょう。
姫野ベンチマーク ( http://accc.riken.jp/supercom/documents/himenobmt/ )をダウンロードします。
ダウンロードしたソースファイルをhimenoBMTxps.c
という名前でカレントディレクトリに保存し, 以下のコマンドを実行して, プログラムを構築します。
$ OLD_PATH=${PATH}
$ PATH=${HOME}/cross/gcc-elf/aarch64/current/bin:${PATH}
$ aarch64-elf-gcc -D_POSIX_SOURCE -DSMALL -O3 -march=armv8.2-a+sve --specs=rdimon.specs himenoBMTxps.c -o himenoS
上記手順でコンパイルするとArm版QEmuのsemihosting機能を使用したバイナリが生成されます。
以下のコマンドを実行することで, QEmuのユーザランドエミュレーション機能を用いてSVE命令を使用した姫野ベンチマークを実行することができます。
$ qemu-aarch64 ./himenoS
実行結果の例は以下の通りです。
$ qemu-aarch64 ./himenoS
mimax = 65 mjmax = 65 mkmax = 129
imax = 64 jmax = 64 kmax =128
Start rehearsal measurement process.
Measure the performance in 3 times.
MFLOPS: 49.403088 time(s): 1.000000 3.288634e-03
Now, start the actual measurement process.
The loop will be excuted in 180 times
This will take about one minute.
Wait for a while
Loop executed for 180 times
Gosa : 1.752712e-03
MFLOPS measured : 64.438810 cpu : 46.000000
Score based on Pentium III 600MHz : 0.785839
備考 クロス環境構築用シェルスクリプト
上記のクロスコンパイル環境を構築するシェルスクリプトを
https://github.com/takeharukato/mkcross
にて公開しています。当該のスクリプトでは上記手順に加え, LLVMやX64/AArch64環境向けのUEFIの構築も行えます。
UEFIを使用した開発を行う方はこちらも参照ください。