GCC
組み込み開発
QEMU
aarch64
SVE

GCC-8/QEmu-3.1を用いたSVE対応版ELFバイナリ用クロスコンパイル環境構築メモ


はじめに

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バイナリ用のクロスコンパイル環境構築手順は以下の通りになります。


  1. コンパイル用の一時ディレクトリを作成する

  2. コンパイラ構築に必要なコマンド群をインストールする

  3. ソースアーカイブを収集する

  4. コンパイル作業時に指定するパラメタをシェル変数に設定する

  5. コンパイラの動作に必要なGNU MPライブラリを作成する

  6. コンパイラの動作に必要なMPFRライブラリを作成する

  7. コンパイラの動作に必要なMPCライブラリを作成する

  8. コンパイラの動作に必要なISLライブラリを作成する

  9. ターゲット用のバイナリを生成するために必要なbinutilsを生成する

  10. ターゲット用の標準Cライブラリを構築するためのCコンパイラを生成する

  11. ターゲット用の標準Cライブラリを構築する

  12. ターゲット用の標準Cライブラリを使用するC/C++コンパイラを生成する

  13. ターゲット用のバイナリを実行するエミュレータを生成する

  14. ターゲット用のバイナリをデバッグするためのデバッガを生成する


コンパイル用の一時ディレクトリを作成する

本稿では, 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, HOSTQEMU_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を使用した開発を行う方はこちらも参照ください。