GCC
2020年11月17日
以前、「GCCの最適化による予期せぬ無限ループの発生」という記事を書きました。この時は -fno-builtin-malloc や __asm __volatile("":::"memory"); などで対策できました。
しかし今回、現状最新の GCC 10 で、memset、しかもナイーブな *(char *)s++ = (char)c; みたいな実装ではなく、NetBSD の本格的な実装のもので発生し、-fno-builtin や -fno-builtin-memset、-ffreestanding などでも抑制できず、-fno-tree-loop-distribute-patterns というあまり一般的ではないオプションが必要になりました。
これは一見 GCC のオプションが効いてない、バグのように思えますが、調べて見ると GCC の仕様に根差した問題であることがわかりました。
続きを読む
しかし今回、現状最新の GCC 10 で、memset、しかもナイーブな *(char *)s++ = (char)c; みたいな実装ではなく、NetBSD の本格的な実装のもので発生し、-fno-builtin や -fno-builtin-memset、-ffreestanding などでも抑制できず、-fno-tree-loop-distribute-patterns というあまり一般的ではないオプションが必要になりました。
これは一見 GCC のオプションが効いてない、バグのように思えますが、調べて見ると GCC の仕様に根差した問題であることがわかりました。
続きを読む
2020年08月26日
GNU ld(リンカ)には、EXCLUDE_FILE というフィルタ機能があり、特定のファイル(*.o オブジェクトファイルだけではなく、ライブラリの *.a アーカイブファイルも)を入力ファイルのワイルドカード指定から除外することができます。
この構文には単一セクションの場合は問題ありませんが、複数セクションを指定する場合に非直感的な仕様があることがわかったので紹介します。
続きを読む
この構文には単一セクションの場合は問題ありませんが、複数セクションを指定する場合に非直感的な仕様があることがわかったので紹介します。
続きを読む
2020年04月15日
RISC-V のベクトル拡張は現在策定中の仕様です。最新安定板はバージョン 0.8 で、一つ前は 0.7.1 でした。そのためインターネット上には古い情報と新しい情報が混在しています。
この記事もすぐに古くなると思いますが、開発版の 0.9.x ベースの GCC ツールチェーンの動作確認ができたので、シェルスクリプト化して公開します。
続きを読む
この記事もすぐに古くなると思いますが、開発版の 0.9.x ベースの GCC ツールチェーンの動作確認ができたので、シェルスクリプト化して公開します。
続きを読む
2019年09月13日
コンパクトな独自の libc を実装していて、GCC のテストを通したところ、WARNING: program timed out. が原因による FAIL が多発しました。調べた結果、非常に意外な結果だったのでメモします。
続きを読む
続きを読む
2019年04月22日
とある開発中のプロジェクトで、GCC/Clang のインラインアセンブラが意図しない不正コードを生成し、バグではないか?と調査しました。
その結果、これはどうやら正しい仕様らしい、しかし非常に間違いやすく混乱しやすいケースだと思ったのでメモしておきます。
解決策だけを先に言いますと、GCC/Clang のインラインアセンブラを、可能ならば常に 1 文に 1 命令のスタイルで記述するようにすれば、この類の混乱は避けられそうです。
続きを読む
その結果、これはどうやら正しい仕様らしい、しかし非常に間違いやすく混乱しやすいケースだと思ったのでメモしておきます。
解決策だけを先に言いますと、GCC/Clang のインラインアセンブラを、可能ならば常に 1 文に 1 命令のスタイルで記述するようにすれば、この類の混乱は避けられそうです。
続きを読む
2018年12月14日
GNU ld には wrap という機能があります。これはリンク時に、未定義(Undefined)のシンボル foo を __wrap_foo として解決し、元のシンボルを __real_foo として解決するという機能です。これを利用すると、バイナリ提供のライブラリ関数を差し替えることが可能になります。
C での使用例はネット上にたくさん存在しますが、C++ の例がほとんど見つからなかったのでメモしておきます。
続きを読む
C での使用例はネット上にたくさん存在しますが、C++ の例がほとんど見つからなかったのでメモしておきます。
続きを読む
2018年11月08日
GCC 5 以降の C++ ライブラリ、libstdc++ はデフォルトの ABI が変更されているため、それ以前の g++ でコンパイルしたバイナリとは(デフォルトでは)リンク互換性がありません。ただし、旧 ABI もサポートしているので、Dual ABI サポートのライブラリとなっています。
これについてまとまった日本語情報が見当たらなかったのでまとめてみます。
続きを読む
これについてまとまった日本語情報が見当たらなかったのでまとめてみます。
続きを読む
2018年09月20日
タイトルが本記事の内容のほぼ全てです。自分で libgcc をビルドするという奇特(誤用)な人以外には関係無い話ですが(※)、まあこんなこともあるんだなと。
おそらく Linux (aarch64-linux-gnu) ターゲット等でも共通だと思うのですが、現象を確認したのはベアメタル (aarch64-elf) ターゲットで、GCC 5.1/6.3 です。7.2 では発生しませんでした。(4 系でも発生すると思いますが、そもそも AArch64 のサポートが 4.8 からなので、枯れてるとは言い難い 4 系の使用自体が現在では非推奨だと思います。)
続きを読む
おそらく Linux (aarch64-linux-gnu) ターゲット等でも共通だと思うのですが、現象を確認したのはベアメタル (aarch64-elf) ターゲットで、GCC 5.1/6.3 です。7.2 では発生しませんでした。(4 系でも発生すると思いますが、そもそも AArch64 のサポートが 4.8 からなので、枯れてるとは言い難い 4 系の使用自体が現在では非推奨だと思います。)
続きを読む
2018年01月30日
glibc のテストスイートを確認していた所、string/test-string.h にて以下のようなシンボルが使われていたのですが、このシンボルの出所が全くわからなくてしばらく悩んだので、その正体をメモしておきます。
extern impl_t __start_impls[], __stop_impls[];続きを読む
2017年02月01日
手元にあった弊社製の古い評価ボード KZM-ARM11-01(※1) で、musl libc のテストスイートを、開発中のバージョンの exeGCC(※2) でコンパイルして動かしてみた所、最適化オプション Os だと一部テストが FAIL するが、O2 だと PASS するという現象が発生しました。それだけだとよく聞くような話ですが、分割コンパイルしていて、別ファイルのコードを変更すると、アセンブラソースもオブジェクトファイルも全く同じなのにリンクすると期待通り動かなくなるなど、奇妙な挙動にだいぶ悩まされました。
続きを読む
続きを読む
2015年10月09日
GNU ld が ARM ターゲットのプログラムのリンク時に以下のような警告を出すケースに遭遇しました。(XXX.out は ELF ファイル名)
続きを読む
C:/PATH/TO/ld.exe: XXX.out: warning: sh_link not set for section `.ARM.exidx'普通は出ない珍しい警告で、日本語ではほとんど情報が無くて調査に苦労したので、メモしておきます。
続きを読む
2015年07月15日
不具合原因の詳細や、根本的な対策まではわかっていませんが、とりあえず現象と回避策を整理がてら記しておきます。
- 現象
Ubuntu 14.04/15.04 64bit (x86_64)上で Windows で動作する sh-*-elf ターゲットのクロス gcc を、Ubuntu の MinGW ツールチェーンでカナディアンクロスビルドすると、その gcc で特定パターンをコンパイルした時に、コンパイラ内部エラー(ICE)が発生する不具合がある。
gcc 4.8.4/4.8.5/4.9.2/4.9.3 で確認。32bit (x86) exe でも 64bit (x64) exe でも同じ結果。4.9.x が特に起こりやすく、libgcc の fp-bit.c コンパイル時に ICE が発生する。(後述するが、再現コードも作成できた。)4.8.x でも locale-inst.cc に -O2 以上の最適化で発生する。これらは Linux 上でネイティブ動作する sh のクロス gcc では発生しない。ソースや依存ライブラリ、configure 時のオプション等は、host の設定以外は全て Windows 向けと同じ。(また、Ubuntu 14.04 と 15.04 ではネイティブ、MinGW 共に gcc のバージョンが異なるが、あまり関係無いようだ。)
- 現状の回避策
32bit の Ubuntu (i386)上でカナディアンクロスビルドする。
- 原因の予想
おそらく gcc のカナディアンクロスビルドシステムにバグがある。特に、64bit Linux のネイティブ gcc は long が 64bit なのだが、MinGW gcc は 32bit でも 64bit でも long が 32bit (LLP64 モデル)なので、(gcc が LP64 モデルの Linux 上で使われてきた歴史を考えても)そのようなマイナーなパターンの対策は不十分な可能性が高い。また、sh のバックエンドの sh.md ファイルの記述のしかたにも問題があると思われる。具体的には、Tbit 操作のために 0x80000000 という定数が必要なようなのだが、md ファイル内では 10 進符号付整数しか記述できないようで、(const_int -2147483648) という、32bit の INT_MAX(2147483647)を超える即値が記述されている ※1。さらにややこしいことに、md ファイルは、genrecog という gcc の内部ツールにより、insn-recog.c に変換されてビルドされるのだが、この genrecog はビルド途中でネイティブ gcc でビルドされて作られ、一方 insn-recog.c は MinGW gcc でビルドされるのだが、その際の long の長さの違いが考慮されていない可能性が高い。
※1 C コンパイラは、通常はトークン単位で処理を行うため、仮に - が付いていても、- と 2147483648 は独立して処理されるので、問題が起こることがある。そのため INT_MIN は、通常は (-INT_MAX-1) のように定義されることが多く、MinGW gcc の limits.h もそうなっている。
詳細は以下になります。
続きを読む
- 現象
Ubuntu 14.04/15.04 64bit (x86_64)上で Windows で動作する sh-*-elf ターゲットのクロス gcc を、Ubuntu の MinGW ツールチェーンでカナディアンクロスビルドすると、その gcc で特定パターンをコンパイルした時に、コンパイラ内部エラー(ICE)が発生する不具合がある。
gcc 4.8.4/4.8.5/4.9.2/4.9.3 で確認。32bit (x86) exe でも 64bit (x64) exe でも同じ結果。4.9.x が特に起こりやすく、libgcc の fp-bit.c コンパイル時に ICE が発生する。(後述するが、再現コードも作成できた。)4.8.x でも locale-inst.cc に -O2 以上の最適化で発生する。これらは Linux 上でネイティブ動作する sh のクロス gcc では発生しない。ソースや依存ライブラリ、configure 時のオプション等は、host の設定以外は全て Windows 向けと同じ。(また、Ubuntu 14.04 と 15.04 ではネイティブ、MinGW 共に gcc のバージョンが異なるが、あまり関係無いようだ。)
- 現状の回避策
32bit の Ubuntu (i386)上でカナディアンクロスビルドする。
- 原因の予想
おそらく gcc のカナディアンクロスビルドシステムにバグがある。特に、64bit Linux のネイティブ gcc は long が 64bit なのだが、MinGW gcc は 32bit でも 64bit でも long が 32bit (LLP64 モデル)なので、(gcc が LP64 モデルの Linux 上で使われてきた歴史を考えても)そのようなマイナーなパターンの対策は不十分な可能性が高い。また、sh のバックエンドの sh.md ファイルの記述のしかたにも問題があると思われる。具体的には、Tbit 操作のために 0x80000000 という定数が必要なようなのだが、md ファイル内では 10 進符号付整数しか記述できないようで、(const_int -2147483648) という、32bit の INT_MAX(2147483647)を超える即値が記述されている ※1。さらにややこしいことに、md ファイルは、genrecog という gcc の内部ツールにより、insn-recog.c に変換されてビルドされるのだが、この genrecog はビルド途中でネイティブ gcc でビルドされて作られ、一方 insn-recog.c は MinGW gcc でビルドされるのだが、その際の long の長さの違いが考慮されていない可能性が高い。
※1 C コンパイラは、通常はトークン単位で処理を行うため、仮に - が付いていても、- と 2147483648 は独立して処理されるので、問題が起こることがある。そのため INT_MIN は、通常は (-INT_MAX-1) のように定義されることが多く、MinGW gcc の limits.h もそうなっている。
詳細は以下になります。
続きを読む
2015年03月16日
タイトルでほぼ終わりなのですが、binutils 2.22 以降では、以下のようにアセンブラのみで書かれた関数には %function 属性を付けないと、正しく ARM コードと thumb コードで interworking できないのでちゃんと付けましょう、というだけの話です…が、原因がわかるまでけっこう悩んだので経緯をメモしておきます。
。。。。 .global foo .type foo, %function foo: 。。。。続きを読む
2015年02月25日
前回の記事では、GDB のシミュレータを使用してクロス GCC の dejagnu testsuite を通す方法を紹介しました。
Linux上でビルドしたGCCクロスコンパイラを(簡易)テストする方法
しかし、ARM ターゲット(arm-none-eabi)だと、この方法では上手く行きませんでした。どうもいろいろ調べてみると、GDB のシミュレータは ARM11 ぐらいまでしか対応してないようで(この時のターゲット CPU は Cortex-A9)、それ以上新しい ARM の場合は QEMU ユーザーモード(Linux アプリ実行環境)を使用してテストを実行するようです。これもほとんどウェブ上に情報が無く、非常に苦労したので、その時のメモを公開します。
(弊社の exeGCC の前任者の方が残してくださった技術メモやスクリプトには非常に助けられました。この場を借りてお礼申し上げます。)
続きを読む
Linux上でビルドしたGCCクロスコンパイラを(簡易)テストする方法
しかし、ARM ターゲット(arm-none-eabi)だと、この方法では上手く行きませんでした。どうもいろいろ調べてみると、GDB のシミュレータは ARM11 ぐらいまでしか対応してないようで(この時のターゲット CPU は Cortex-A9)、それ以上新しい ARM の場合は QEMU ユーザーモード(Linux アプリ実行環境)を使用してテストを実行するようです。これもほとんどウェブ上に情報が無く、非常に苦労したので、その時のメモを公開します。
(弊社の exeGCC の前任者の方が残してくださった技術メモやスクリプトには非常に助けられました。この場を借りてお礼申し上げます。)
続きを読む
2015年02月24日
PC Linux ホスト上で、sh の評価ボードなどホストと異なる環境をターゲットにした、GCC のクロスコンパイラ ※ をビルドするのは比較的簡単で、ウェブ上にも情報はたくさんあるのですが、それをテストする方法がなかなかわからず苦労しました。その時のメモです。
※ この記事では newlib を使用した bare-metal target、いわゆる OS レスの環境をターゲットにしたクロスコンパイラの、ソフトウェア CPU シミュレータを使用した簡易テスト方法を扱います。GCC のビルド環境や、dejagnu などの(通常のネイティブ GCC の)テスト環境は、既に整っているものとします。
続きを読む
※ この記事では newlib を使用した bare-metal target、いわゆる OS レスの環境をターゲットにしたクロスコンパイラの、ソフトウェア CPU シミュレータを使用した簡易テスト方法を扱います。GCC のビルド環境や、dejagnu などの(通常のネイティブ GCC の)テスト環境は、既に整っているものとします。
続きを読む
???次のページへ