13

次の変更点がある非エキゾチックなアーキテクチャ/OS/コンパイラはありますか?

void func(void *, int, int)

に:

int func(void *, int, int)

ABIを壊しますか?(つまり、共有ライブラリの「void」バージョン用にコンパイルされたプログラムは、「int」バージョンで実行すると壊れます)

4

1 に答える 1

10

いくつかのコメントはノーと言っています、そして私たちは少しの理由でそれを強化することができます。最もよく知られているABIでは、宣言付きの関数は、結果がスクラッチレジスタとして返されるvoid func(void *, int, int)レジスタを使用できます。int保存して復元する必要はありません。結果が返されるレジスタを使用するには、宣言付きの関数int func(void *, int, int)必要です。int他の点では、これらの宣言は同一です。したがって、anの実装のマシンコードは、int func(void *, int, int)を満たすマシンコードでもありますvoid func(void *, int, int)

言い換えると、呼び出し元には、リターンレジスタに結果を故意に返すマシンコードと、そのレジスタにスクラッチ計算を残してしまうコードを区別する方法がありません。

この推論では、呼び出された関数がABIの背後に隠れている必要があることに注意してください。これは、ABIによって指定されたバイナリ動作に依存しています。呼び出された関数のコンパイル時に呼び出された関数のソースが表示されている場合(または呼び出しの実装方法に影響を与える可能性のある実装の他の部分)、最適化により、ABIをバイパスする動作が発生する可能性があります(たとえば、呼び出されたルーチンを監視するリターンレジスタを使用しないため、呼び出し元でそれを使用して、呼び出し中に変更されないままであると予想される値を保持します)。

これは共有ライブラリ用であると言うので、おそらく安全です。共有ライブラリは個別にコンパイルされ、そのソースは呼び出し元が利用できません。ただし、サイドチャネルを検討する必要があります。たとえば、共有ライブラリは、ソースを共有し、ライブラリ間の呼び出しを含む一連のライブラリの一部である可能性があります。この場合、誰かがソースを表示してコンパイルされた古いバージョンの共有ライブラリと、voidソースを含む新しいバージョンの共有ライブラリを持っている可能性がありintます。(そして、これでさえ、複数のコンパイルユニット間で情報を統合する珍しいソースコードの配置または豪華なコンパイラが必要です。)

于 2013-03-26T02:18:29.197 に答える