問題タブ [abi]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - amd64ABIのva_listへのポインター
Linux amd64(x86_64)での可変個引数関数について懸念があります。
私の例はLinuxi386(ia32)で正常にビルドおよび動作しますが、Linux amd64用にビルドすると、GCCは次のようなエラーを生成します。
ここに例があります:
C11ドラフト(ISO / IEC 9899:2011)によると
オブジェクトapは、引数として別の関数に渡すことができます。その関数がパラメーターapを使用してva_argマクロを呼び出す場合、呼び出し元の関数のapの値は不確定であり、apをさらに参照する前にva_endマクロに渡される必要があります。
しかし、後者は追加します
va_listへのポインターを作成し、そのポインターを別の関数に渡すことは許可されています。この場合、元の関数は、他の関数が戻った後、元のリストをさらに使用できます。
ここでAMD64ABIが標準と見なされて間違っているかどうかは、私にはわかりません。
vtest()
最初の呼び出しでポインターを使用するように関数を変更すると問題は解決しますが、内部関数で機能しないものが実際に外部関数で機能するのは間違っていると感じます。
AMD64 ABIの動作が標準に一致している場合、誰かがどこかを見つけることができれば。stdargの使用に関する(同じ)問題を他のABIに提供してくれる人のための追加のポイント。
よろしく
gcc - GCC と LLVM の互換性
私はクロスプラットフォームのプロジェクトに取り組んでおり、OS X では Cocoa ウィンドウを作成するため、clang/llvm で 1 つのセクションをビルドする必要があり、プロジェクトの残りの部分は GCC でビルドされます。これは、メインの実行可能ファイルにリンクされている静的ライブラリにコンパイルされます。例えば
CMake を使用して makefile を生成しています。コンパイラ フラグなどのいくつかの異なるセットを試しましたが-fPIC
、値が 1835455280、1746993968、1648001840 のように出力されます。2 つのコンパイラはバイナリ互換ではないのでしょうか? 関数を無効にすると、問題なく動作します。
visual-studio-2010 - MS Visual C++ で LLP64 の代わりに LP64 を使用する方法
GCC や Intel C++ などの別のコンパイラを使用できることはわかっていますが、さまざまな理由で VC++ を使用したいと考えていLP64
ます。LLP64
Microsoft ヘッダーなどとの互換性に関する要件はなく、ランタイム ライブラリとして LIBC を既に使用しています。
android - Android 4.0.3(MIUI ROM)でネイティブライブラリが読み込まれない
顧客から連絡がありました。AndroidROMをAndroid4.0.3と同等のMIUIに更新すると、私のAndroidアプリが壊れました。LogCatの関連行は次のとおりです。
言うまでもなく、このアプリはアップグレード前に機能していました。したがって、ネイティブライブラリが魔法のように失われることはありませんでした。Android 4.0.3が以前のバージョンのネイティブライブラリの読み込みを拒否する理由はありますか?ライブラリはx86用に構築されていますarmeabi
(ただし、そうではありませんarmeabi-v7a
)。クラッシュレポートには次の行が含まれています。
だからarmeabi
サポートされるべきですよね?
おそらく関連情報:ここ。しかし、バグの状況は、私がここで得たものの逆です。
c++ - 列挙型と列挙型クラスのリンク互換性
列挙型クラスを使用するC++11APIがあるとします。
ここで、このAPIを使用したいとしますが、C++11コンパイラーを持っていません。だから私:
- 列挙
api.hpp
型クラスを変更して、通常の列挙型に変更します。 api.hpp
変更されたものを含み、APIを通常どおりに使用するコードコードを記述します(例:呼び出しf
)。- このコードをC++11以外のコンパイラでコンパイルし、C ++ 11コンパイラでコンパイルされたAPI実装にリンクします(変更されていないものを使用
api.hpp
)。
これはGCCで機能するようですが、一般的には安全ですか、それとも私は火遊びをしていますか(ODR違反など)?
2つのコンパイラがリンク互換であると仮定すると、問題となるのはenumクラスとenumクラスだけです。
c++ - スタンドアロン クラスで public 非仮想メソッドを並べ替えると、ABI が壊れますか?
スタンドアロン クラスでオーバーロードされたパブリックで非仮想の非インライン メソッドの順序を変更すると、ABI が壊れますか?
前:
後:
ありがとう!
c++ - vtablesとこのポインタ
私はvtablesとvpointersの内部動作についてもう少し学ぼうとしていたので、いくつかのトリックを使用してvtableに直接アクセスすることにしました。私は2つのクラスを作成Base
しDerv
、それぞれに2つのvirtual
関数があります(の関数Derv
をオーバーライドしますBase
)。
ここで、コンパイラは各クラスにvtableポインタを追加し、メモリの最初の4バイト(32ビット)を占有します。size_t*
ポインタがサイズの別のポインタを指しているため、オブジェクトのアドレスをにキャストしてこのポインタにアクセスしましたsizeof(size_t)
。これで、vpointerにインデックスを付け、その結果を適切なタイプの関数ポインターにキャストすることで、仮想関数にアクセスできます。これらのステップを関数にカプセル化しました。
メンバー関数の1つがこのように呼び出された場合、たとえばcall(new Base(1, 2), 0)
Base :: foo()を呼び出す場合、ポインターなしで呼び出されるため、何が起こるかを予測することは困難this
です。this
g ++がレジスタに-pointerを格納することを知って、少しテンプレート化された関数を追加することでこれを解決しました(ただし、これにより、コンパイラフラグecx
を使用してコンパイルする必要があります)。-m32
setThisPtr(ptr)
上記のスニペットの行のコメントを解除すると、プログラムとして機能するようになります。
この小さなプログラムを書く過程で、vtablesがどのように機能するかについてより多くの洞察を得て、他の人がこの資料をもう少しよく理解するのに役立つかもしれないので、これを共有することにしました。ただし、まだいくつか質問があります
。1. 64ビットバイナリをコンパイルするときにthis-pointerを格納するために使用されるレジスタ(gcc 4.x)はどれですか。ここに記載されているように、すべての64ビットレジスタを試しました。http://developers.sun.com/solaris/articles/asmregs.html
2. this-pointerはいつ/どのように設定されますか?コンパイラは、オブジェクトを介した各関数呼び出しで、これを行ったのと同じようにthisポインタを設定していると思います。これはポリモーフィズムが実際に機能する方法ですか?(最初にthis-pointerを設定してから、vtableから仮想関数を呼び出しますか?)
c++ - G++ABI互換性リスト
プリロードファイルをUbuntuサーバーにコンパイルしました(x32とx64の2つのファイル)。コンパイルされたファイルがどのOSと互換性があり、互換性のために何を再コンパイルする必要があるかを確認できるリストはどこで入手できますか?
ありがとう!
c++ - 仮想テーブルの変更による迂回に関する質問
Microsoft Detours と同じアプローチを使用して迂回を練習してきました (最初の 5 バイトを jmp とアドレスに置き換えます)。最近、仮想テーブルを変更して迂回することについて読んでいます。前述の方法と比較して、この方法の長所と短所をいくつか挙げて、誰かがこの問題に光を当てることができれば幸いです!
また、パッチを適用した vtable とスタック上のオブジェクトについてもお尋ねしたいと思います。次の状況を考慮してください。
この場合、元の関数 (つまりメソッド)foo->Call()
を呼び出しMyCall(Foo * object)
ながら呼び出すことになります。これは、可能な場合、コンパイラがコンパイル時に仮想呼び出しを決定しようとするためです (間違っている場合は修正してください)。スタック上のオブジェクトを使用する限り (ヒープが割り当てられていない場合)、仮想テーブルにパッチを適用するかどうかは問題ではないということですか?foo2.Call()
Foo::Call(void)
c - sizeof(long long)!=8のアーキテクチャ/ABI
x86/amd64では世界sizeof(long long)
は8です。
ZackWeinbergによる非常に洞察に満ちた8年前のメールを引用させてください。
スコットロバートラッドは書いています:
64ビットAMD64アーキテクチャでは、GCCはと
long long
同じ64ビットとして定義しlong
ます。特定の64ビット命令(乗算)が128ビットの結果を生成することを考えると
long long
、128ビットとして定義するのは論理的ではないでしょうか。いいえ、2つの理由があります。
64ビット'
long long
'の選択は、ほとんどのLP64モデルオペレーティングシステムのABIに書き込まれています。一方的に変更することはできません。これは実際には正しい選択です。これは、'
long
'を最も広い基本積分タイプではないものにする収差を除去するためです。sizeof(long) >= sizeof(size_t)
これは、longlongがlongよりも幅が広いABIによって少なくとも潜在的に破壊されるという仮定に基づいて書かれたコードがたくさんあります 。(これはC99の開発中に非常に論議を呼んだトピックでした。外部の観点から言えば、'
long long
'は、何らかの理由でLP64モデルを実装できないMicrosoftからの圧力により、標準化されただけです。他の誰もが嫌いでした。 ''を作成するという考えは、long
必ずしも最も広い基本的な積分型ではありません。)現在のベストプラクティスは、「拡張積分タイプ」を提供することであるように思われます
__int128
。これは基本的なlong long
積分型ではないため、''の問題はありません(特に、には使用できません )。size_t
zw
long long
最も幅の広い基本一体型です。私が知っている古いアーキテクチャ/ABI以外のアーキテクチャでは64ビット長です。これにより、単純なクロスプラットフォーム(少なくとも多くの32/64ビットアーキテクチャでは)typedefを使用できます。
それは、よりも優れていますintXX_t
。理由は次のとおりです。
- 異なるプラットフォームの64ビット整数に同じ基になる型を使用します
PRId64
冗長な/を回避できます(Visual C ++が/をサポートしているのは2005年以降PRIu64
であることをよく知っています)%lld
%llu
しかし、このソリューションがどれほど移植性があるかは、次の質問への回答で表すことができます。
アーキテクチャ/ABIはどこにありsizeof(long long) != 8
ますか?
最近/最新のものを提供できない場合は、古いものを使用してください。ただし、それらがまだ使用されている場合に限ります。