7

次の関数を検討してください。

extern void test1(void);
extern void test2(void) {
    test1();
}

-fpicこれは、 amd64 Linuxなしで gcc が生成するコードです。

test2:
    jmp test1

でコンパイルすると-fpic、gcc は PLT を介して明示的に呼び出し、シンボル挿入を有効にします。

test2:
    jmp test1@PLT

ただし、これは位置に依存しないコードには厳密には必要ないため、サポートしたくない場合は省略できます。必要に応じて、リンカはジャンプ ターゲットを PLT シンボルに書き換えます。

ソース コードを変更したり、コンパイルされたコードを共有ライブラリに適さないものにしたりせずに、PLT を明示的に経由する代わりに、関数呼び出しをターゲットに直接送るにはどうすればよいでしょうか?

4

2 に答える 2

3

ソースコードを変更できない場合は、大きなハンマーを使用できます: -Bsymbolic リンカーフラグ:

共有ライブラリを作成するときは、グローバル シンボルへの参照を共有ライブラリ内の定義にバインドします (存在する場合)。通常、共有ライブラリにリンクされたプログラムが共有ライブラリ内の定義を上書きする可能性があります。このオプションは、共有ライブラリをサポートする ELF プラットフォームでのみ意味があります。

ただし、ライブラリの一部がシンボル挿入に依存している場合は壊れることに注意してください。エクスポートする必要のない関数を非表示にするか (注釈を付けて)、非表示のエイリアス__attribute__((visibility("hidden")))を介して呼び出すことをお勧めします(制御された方法で PLT を使用しないライブラリ内呼び出しを行うように特別に設計されています)。

于 2016-11-10T16:15:43.550 に答える