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年03月02日
Ubuntu などの最近の Linux ディストリビューションは、MinGW 環境をターゲットにしたクロスコンパイラが標準パッケージに含まれているので、非常に簡単に Windows 向けのバイナリをコンパイルすることが可能です。Windows 上で MinGW + MSYS あるいは cygwin で、Linux を前提としたツールをコンパイルするのはそれなりに大変なので、Linux 環境でクロスコンパイルしている方も多いと思います。私も愛用しています。
わかってしまえば非常にマヌケな話なのですが、ビルドしたバイナリを Linux 上でテストまでしたいなと思い、何気なく wine(Windows API 互換レイヤー)をインストールして色々検証していて、久しぶりにビルドしてみたら、突然全く触ってないあたりのクロスコンパイル(正確には configure)が失敗するようになり、原因の究明に苦労したので、その時のメモです。
続きを読む
わかってしまえば非常にマヌケな話なのですが、ビルドしたバイナリを Linux 上でテストまでしたいなと思い、何気なく wine(Windows API 互換レイヤー)をインストールして色々検証していて、久しぶりにビルドしてみたら、突然全く触ってないあたりのクロスコンパイル(正確には configure)が失敗するようになり、原因の究明に苦労したので、その時のメモです。
続きを読む
2015年02月26日
GNU make には、暗黙のルールの連鎖で中間ファイルを生成したら、自動的に削除するという仕様があるのですが、これと WIndows のファイルシステムの、ファイル名の大文字小文字を区別しないという仕様が組み合わさると、ファイルが削除されてしまうという現象があり、実際ハマったのでメモしておきます。
10.4 Chains of Implicit Rules
(make 3.79.1: 新堂安孝氏による日本語訳):10.4 暗黙のルールの連鎖
続きを読む
10.4 Chains of Implicit Rules
(make 3.79.1: 新堂安孝氏による日本語訳):10.4 暗黙のルールの連鎖
続きを読む
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 の)テスト環境は、既に整っているものとします。
続きを読む
2015年02月16日
Ubuntu 14.04 64bit で実行される、とあるプロダクトのビルドスクリプトの一部で、大量にファイルが存在するディレクトリを cp -r * でアーカイブしようとした所、一部のファイルがコピーされないという現象に悩みました。当初は HDD やファイルシステムの障害を疑ったりもしたのですが、結局は bash によりワイルドカードが展開され、cp に渡されたコマンドライン引数が長すぎて、途中で切れていたのが原因のようです。(エラーが何も出ないのが不思議なのですが…。)
続きを読む
続きを読む
2014年11月17日
2014年09月18日
前回の記事で、GNU CPP の独自拡張 #include_next 指令を紹介しました。
「GNU CPP(GCC)の独自拡張#include_next指令」
このドキュメントは簡単な概要と例だけなので、ちょっと複雑なケースになると、この挙動は仕様なのか?バグなのか?という判断が難しくなります。
この間、私が悩んだ疑問は、過去に以下の ML で取り上げられた疑問とほぼ同じものでした。
gcc-help ML: #include_next: wrong search order?
この疑問を単純化して解説した後、私なりの解釈を説明します。
続きを読む
「GNU CPP(GCC)の独自拡張#include_next指令」
このドキュメントは簡単な概要と例だけなので、ちょっと複雑なケースになると、この挙動は仕様なのか?バグなのか?という判断が難しくなります。
この間、私が悩んだ疑問は、過去に以下の ML で取り上げられた疑問とほぼ同じものでした。
gcc-help ML: #include_next: wrong search order?
この疑問を単純化して解説した後、私なりの解釈を説明します。
続きを読む
2014年09月11日
Warp の挙動を調べている時に、GCC のプリプロセッサの #include_next 指令の挙動にかなり悩んだので、備忘録も兼ねてドキュメントの日本語訳をアップロードします。
厳密な仕様が無く、あまり有名でもない(?)独自拡張なので(ARM CC や IBM XL C/C++ など、一応 GCC 以外のコンパイラのプリプロセッサにも取り入れられているようですが)、情報が少なく、実際にいろいろ動かして実験してみないと挙動がよくわからず、かなり混乱しました。以下の翻訳もあまり自信が無いので、何かお気づきの点があれば、コメント欄にてご指摘いただけると幸いです。(ただし、現在スパムコメントがあまりにも多いため、半角英数字のみのコメント、国外の IP アドレスからのコメント、改行が 10 個以上あるコメントは受け付けない設定になってます。ご注意ください。)
ちなみにこの記事は、問題を理解してもらうための布石で、実際に悩んだ問題は、また後日に解説します。
続きを読む
厳密な仕様が無く、あまり有名でもない(?)独自拡張なので(ARM CC や IBM XL C/C++ など、一応 GCC 以外のコンパイラのプリプロセッサにも取り入れられているようですが)、情報が少なく、実際にいろいろ動かして実験してみないと挙動がよくわからず、かなり混乱しました。以下の翻訳もあまり自信が無いので、何かお気づきの点があれば、コメント欄にてご指摘いただけると幸いです。(ただし、現在スパムコメントがあまりにも多いため、半角英数字のみのコメント、国外の IP アドレスからのコメント、改行が 10 個以上あるコメントは受け付けない設定になってます。ご注意ください。)
ちなみにこの記事は、問題を理解してもらうための布石で、実際に悩んだ問題は、また後日に解説します。
続きを読む
2014年09月05日
たまには役に立ちそうなネタも書かないとということで、この間社内で話題※になった、glibc 環境の Linux の動的リンカに共有ライブラリのデバッグ時に有益な情報を出力させる方法を紹介します。
※ この Tips は、弊社の PARTNER-AP(JTAG-ICE デバッガではなく、Linux アプリをデバッグするためのアプリデバッガ)案件で役に立った実績のある Tips なので、glibc と共有ライブラリを使用するような、比較的リッチな Linux 環境において有効です。(デバッガとは無関係で、純粋に Linux 環境でのデバッグ機能の紹介となります。)
続きを読む
※ この Tips は、弊社の PARTNER-AP(JTAG-ICE デバッガではなく、Linux アプリをデバッグするためのアプリデバッガ)案件で役に立った実績のある Tips なので、glibc と共有ライブラリを使用するような、比較的リッチな Linux 環境において有効です。(デバッガとは無関係で、純粋に Linux 環境でのデバッグ機能の紹介となります。)
続きを読む
2014年08月27日
マニアックなネタが続いて申し訳ありません。またプリプロセッサの話です。
前回:C/C++プリプロセッサの挙動の違い(defined編)
前々回:米Facebook社のC/C++プリプロセッサWarpをWindows環境でビルド
Warp の挙動を調べていて、以下のような、マクロ展開後にコメントが生成されるようなコードが通らない事に気が付きました。
(元は MinGW GCC の x86_64-gdcproject-mingw32/x86_64-gdcproject-mingw32/sysroot/mingw/include/wtypes.h ヘッダ)
前回:C/C++プリプロセッサの挙動の違い(defined編)
前々回:米Facebook社のC/C++プリプロセッサWarpをWindows環境でビルド
Warp の挙動を調べていて、以下のような、マクロ展開後にコメントが生成されるようなコードが通らない事に気が付きました。
(元は MinGW GCC の x86_64-gdcproject-mingw32/x86_64-gdcproject-mingw32/sysroot/mingw/include/wtypes.h ヘッダ)
$ cat gen_cpp_comment.c #define _VARIANT_BOOL /##/ $ ./warp.exe --stdout gen_cpp_comment.c # 1 "gen_cpp_comment.c" # 1 "i:\test\warp//" # 1 "<command-line>" # 1 "gen_cpp_comment.c" gen_cpp_comment.c(2) : ## cannot appear at end of macro text続きを読む
2014年08月21日
2014年08月12日
Warp は Facebook 社が D 言語の作者 Walter Bright 氏と協力して開発した C/C++ プリプロセッサで、自社のビルドシステムの高速化のために開発したそうです。D 言語で書かれていて、非常に緩い Boost Software License 1.0 で GitHub に公開されています。
「Under the Hood: warp, a fast C and C++ preprocessor」
https://code.facebook.com/posts/476987592402291/under-the-hood-warp-a-fast-c-and-c-preprocessor/
https://github.com/facebook/warp
Cent OS 6 以外では動作確認されていないそうですが、いろいろ試行錯誤した結果、Windows の MSYS + GDC(D Programming Language for GCC)環境で、とりあえず warp の生成までは成功したので、その時のメモです。(builtin_defines.sh というシェルスクリプトが git リポジトリに入っていないようで、ドライバプログラム warpdrive の生成は失敗しました。)
続きを読む
「Under the Hood: warp, a fast C and C++ preprocessor」
https://code.facebook.com/posts/476987592402291/under-the-hood-warp-a-fast-c-and-c-preprocessor/
https://github.com/facebook/warp
Cent OS 6 以外では動作確認されていないそうですが、いろいろ試行錯誤した結果、Windows の MSYS + GDC(D Programming Language for GCC)環境で、とりあえず warp の生成までは成功したので、その時のメモです。(builtin_defines.sh というシェルスクリプトが git リポジトリに入っていないようで、ドライバプログラム warpdrive の生成は失敗しました。)
続きを読む