2012-04-03 10 views
6

私は組み込みプラットフォーム向けに開発しています。共有ライブラリを動的にリンクする方法を検討するのは苦労しています。私はbFLTファイル形式を使用しており、実行可能ファイルと共有ライブラリがロードされている場所を制御することはできません。位置独立コード、共有ライブラリ、コードベニア - それらを連携させる

ローダーは共有ライブラリと実行可能ファイルを正しくメモリにロードし、実行時に実行可能ファイルのGOTを変更して共有ライブラリにリンクします。

私は正常に関数のアドレスを取得することができますし、その場所でコードを逆アセンブルするのが正しいことを知っています。しかし、関数を呼び出そうとすると、すべてがクラッシュします。

共有ライブラリ関数を呼び出すときにGCCが 'コードベニア'を追加し、関数が呼び出されたときに迂回し、実際に関数のアドレスに分岐しません。コードベニアが分岐するアドレスは、実行可能バイナリ内の再配置のリストに表示されないため、正しく再配置されません。

ベニヤの分解は、次のようになります。私は、関数のアドレスを取得し、関数ポインタに入れて(そのため、「コードベニヤ」をバイパスして)、それを呼び出す場合

000008d0 <__library_call_veneer>: 
8d0: e51ff004 ldr pc, [pc, #-4] ; 8d4 <__library_call_veneer+0x4> 
8d4: 03000320 .word 0x03000320 ; This address isn't correctly relocated! 

、共有ライブラリは完全に機能します。例えばので

#define DIRECT_LIB_CALL(x, args...) do { \ 
     typeof(x) * volatile tmp = x; \ 
     tmp(#args); \ 
    } while (0) 

DIRECT_LIB_CALL(library_call); /* works */ 
library_call(); /* crashes */ 

はどちらかへの道は、GOTに位置アドレスに直接コードベニヤとブランチを作るか、何らかの方法でそのコードベニヤ分岐アドレスをしないためにGCCを伝える、あります実行する再配置のリストに表示されますか?

+0

extern Cを使用してライブラリのプロトタイプを宣言していますか? –

+0

私はCの下でコンパイルしていますので、extern "C"は冗長でしょうか? – tangrs

+1

ベニアは、ARMシステム上で必要以上に必要とされるため、ベニアを実行するのが適切です。しかし、アドレスを更新しないのは...あなたのファイル形式を見ると、http://docs.blackfin.uclinux.org/doku.php?id=toolchain:executable_file_formatsとhttp://docs.blackfin.uclinux.org /doku.php?id=toolchain:creating_librariesが表示されます。競合する共有ライブラリIDがあるか、リンクフラグを変更する必要があるようです(ここで説明しています)。申し訳ありませんが、ずっと助けてくれることはありません –

答えて

2

この問題の回避策が見つかりました。それは最高の方法やクリーンな方法ではありませんが、私の場合は仕事をします。

シンボルを__wrap_symbolにリダイレクトする私のリンカーで--wrapオプションを利用しました。これで、正しく再配置されたアドレスをPCにロードするASMファイルを自動的に生成するawkスクリプトを設定しました。ライブラリ呼び出しはすべてこのコードにリダイレクトされます。基本的に私がしたことは、自分のコードベニアを作ることでした。生成されたコード単板は参照されていなかったので、単純に最適化されました。

さらに、.textセクションのすべてが正しく再配置されなかったため、私のベニアを.dataセクションに配置する必要がありました。私が作業しているプラ​​ットフォームはコードとデータを区別しないので、このハックの回避策が機能します。

Here's a link私はあなたが詳細を調べることができる場所に取り組んでいます。

+0

いい仕事です。適切なベニアサポートを追加するために、自作SDKの作者に機能要求を提出します...分岐の限界のためにARMプラットフォームのためのかなり基本的なことです... –

関連する問題