16

の分析this question Linuxでの動的ロード(dlopen)のコンテキストでの弱いシンボル解決の動作についていくつか知りました。今私はこれを支配する仕様を探しています。動的ロードと弱いシンボルの解決

an exampleとしましょう。ライブラリーb.soc.soをこの順序で動的にロードするプログラムaがあるとします。 c.soが他の2つのライブラリfoo.so(この例では実際にlibgcc.so)とbar.so(実際にはlibpthread.so)に依存している場合は、bar.soでエクスポートされたシンボルを使用してfoo.soの弱いシンボルの結合を満たすことができます。しかし、b.sofoo.soにも依存しますが、bar.soにない場合、これらの弱い記号は明らかにbar.soとリンクされません。 foo.soインクは、ab.soからのシンボルとそのすべての依存関係を探すように見えます。

そうでなければ、c.soをロードするとfoo.soの動作が変更される可能性があります。b.soは既にライブラリを使用しています。一方、私が始めた問題では、これはかなり問題を引き起こしたので、この問題を回避する方法があるのだろうかと思います。そして、方法を見つけ出すためには、まず、これらの場合のシンボル解像度がどのように指定されているかについての正確な詳細について、十分に理解しておく必要があります。

これらのシナリオで正しい動作を定義するための仕様またはその他の技術文書は何ですか?

+0

あなたは[このPDF](http://refspecs.linuxbase.org/elf/elf.pdf)を見ましたか?興味深いデータがたくさんありますが、探しているものが含まれているかどうかは不明です。 – rodrigo

+0

@rodrigo:これはこれか類似しているかどうかはわかりませんが、見つかったすべてのELFドキュメントは、動的にリンクされたオブジェクトに関連するリンクではなく、バイナリの実行前にダイナミックリンクのみを記述します。それは長い文書で、私は間違った場所を見ているかもしれませんが、これまでのところ、私が探しているものではないようです。 – MvG

+0

そしてこの[Drepper post](http://www.sourceware.org/ml/libc-hacker/2000-06/msg00029.html)とその多かれ少なか[関連文書](http:// www。 akkadia.org/drepper/dsohowto.pdf)(セクション1.5.2を参照)?私がそれを解釈するので、弱い記号は静的リンクのためだけに使用されます。だから、 'dlopen()'は弱い記号と強い記号との間に違いはありません。 – rodrigo

答えて

11

残念ながら、権威ある文書はソースコードです。 Linuxのほとんどのディストリビューションはglibcまたはそのフォーク(eglibc)を使用しています。次のように両方のソースコード、(dlopenの文書化すべきファイル)を読み込み:

マニュアル/ libdl.texi

ELF specificationおよびPOSIX標準から引き出すことができるがあるどのような技術仕様
@c FIXME these are undocumented: 
@c dladdr 
@c dladdr1 
@c dlclose 
@c dlerror 
@c dlinfo 
@c dlmopen 
@c dlopen 
@c dlsym 
@c dlvsym 

。 ELF仕様は、弱い記号を意味のあるものにするものです。 POSIXは実際にはspecification for dlopen()です。

これは、ELF仕様の最も重要な部分であるとわかりました。

リンクエディタでアーカイブライブラリを検索すると、定義されていないグローバルシンボルの定義を含むアーカイブ のメンバーが抽出されます。 メンバーの定義は、グローバルシンボルまたはウィークシンボルのいずれかです。

ELF仕様では動的ローディングが参照されないため、この段落の残りの部分は私自身の解釈です。私が上記の関連性があることが判明した理由は、解決するシンボルが単一の「いつ」に起こるかということです。この例では、プログラムaが動的にb.soをロードすると、ダイナミックローダーは未定義シンボルの解決を試みます。これは、グローバルシンボルまたはウィークシンボルのいずれかで終了する可能性があります。プログラムが動的にc.soをロードすると、ダイナミックローダーは未定義のシンボルを解決しようとします。記述したシナリオでは、b.soのシンボルは弱いシンボルで解決されました。解決されると、それらのシンボルはもはや定義されなくなりました。グローバルシンボルまたはウィークシンボルが定義されているかどうかは関係ありません。彼らは既にc.soがロードされるまでには未定義ではありません。

ELF仕様では、リンクエディタが何であるか、またはリンクエディタがオブジェクトファイルを結合する必要があるかどうかを正確に定義することはできません。ドキュメントにはダイナミックリンクが念頭に置かれているため、おそらく問題はありません。

POSIXでは、dlopen()の機能の一部を説明していますが、質問の内容を含め、実装まではかなりの時間がかかります。 POSIXは、一般にELF形式や弱い記号を参照しません。 dlopen()を実装しているシステムでは、弱い記号の概念は必要ありません。

http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html

POSIX準拠は別の規格、標準のLinuxベースの一部です。 Linuxディストリビューションは、これらの規格に従うことを選択することも、しないこともあります。たとえば、私は、オープングループによる正式なUnix認定はかなり高価であることを理解しています。そのため、「Unixライク」システムが豊富にあります。

Wikipedia article for dynamic loadingでは、dlopen()の標準準拠に関する興味深い点があります。 dlopen()はPOSIXの命令通りにvoid *を返しますが、ISOが規定しているようにCはvoid *がオブジェクトへのポインタであり、そのようなポインタは必ずしも関数ポインタと互換性がないと言います。であるため、

事実は、機能と ポインタをオブジェクトとの間の任意の変換は(本質的に非ポータブル) 実装拡張と見なさなければならないことに変わりはない、と直接 変換のための「正しい」方法は存在しないことPOSIX規格とISO規格 はお互いに矛盾しています。

矛盾して存在する標準とそこにある標準文書は、とにかく意味がありません。 Ulrich Drepperは、Open Groupとその "仕様"に対する彼の軽蔑について書いています。

http://udrepper.livejournal.com/8511.html

同様の感情はロドリゴによって連結された後に発現されます。

私はこの変更を行った理由

は、より適合を本当にないです (それはうれしいですが、誰も以来、何の理由が古い 行動について不平を言っていません)。

これを調べたところ、この点については、dlopen()には正しいか間違った振る舞いがないという質問に対して適切な回答があると思います。恐らく、検索がシンボルを解決すると、それはもはや未定義ではなくなり、その後の検索ではダイナミックローダーは既に定義されたシンボルを解決しようとしません。

最後に、コメントに記載されているとおり、元の投稿に記載されている内容は正しくありません。以前に動的にロードされた共有ライブラリの未定義シンボルを解決するには、動的にロードされた共有ライブラリを使用できます。実際、これは動的にロードされたコードの未定義のシンボルに限定されません。次に、実行可能ファイル自体に、動的ロードによって解決される未定義のシンボルがある例を示します。

main.cの

#include <dlfcn.h> 

void say_hi(void); 

int main(void) { 
    void* symbols_b = dlopen("./dyload.so", RTLD_NOW | RTLD_GLOBAL); 
    /* uh-oh, forgot to define this function */ 
    /* better remember to define it in dyload.so */ 
    say_hi(); 
    return 0; 
} 

dyload。c

#include <stdio.h> 
void say_hi(void) { 
    puts("dyload.so: hi"); 
} 

コンパイルして実行します。

gcc-4.8 main -fpic -ldl -Wl,--unresolved-symbols=ignore-all -o main 
gcc-4.8 dyload.c -shared -fpic -o dyload.so 
$ ./main 
dyload.so: hi 

メイン実行可能ファイル自体がPICとしてコンパイルされています。

+0

これは私が卓越した答えと呼ぶものです! – paulotorrens

関連する問題