2016-05-04 6 views
1

enter image description hereld-linux.so *自体はどのようにリンクされて読み込まれていますか?ただ、好奇心によって

自体がリンクされ、ロードされたld-linux.so*、どのようにLinuxの動的リンカ/ローダのですか?

  1. 上のスクリーンショットはfilelddは矛盾する結果を与えるように見えることを示しています。一つはが静的​​をリンクさと言う、他はが動的をリンク言います。

  2. ローダーはどのようにロードされますか?

答えて

2
  1. ld-linux.so*、他のライブラリに依存しません。これは、メモリにロードされると単独で実行可能です。

  2. ldd

    が、それは、ローダを経由してオブジェクトファイルをロードし、スクリプトで、ローダは、オブジェクトが動的または静的にリンクされているかどうかをチェックする、これを試してみてください。

LD_TRACE_LOADED_OBJECTS = 1/lib64に/ LD-Linuxベースx86-64.so.2 /lib64/ld-linux-x86-64.so.2

  • fileマジックナンバーまたは図にELFヘッダを読み取り、
      がオブジェクトが動的かどうかそれは、すべての動的にリンクされたオブジェクトが持っている必要があり .interp部を持たないため、静的にリンクされ、 ldd

    の出力異なる値がIMO、ld-linux.soは、リンクされた静的であることができます。

  • +0

    LD_TRACE_LOADED_OBJECTS = 1 /lib64/ld-linux-x86-64.so.2/lib64に/ LD-linuxの-のx86-64を得たのか分かりません。 so.2はローダー自体をロードし、ロードされるオブジェクトの数をカウントします。ところで、一般的に、ローダー/lib64/ld-linux-x86-64.so.2自体はどうやってメモリに入りますか? –

    +2

    カーネルはローダーをロードします。 –

    +1

    ローダーはopen()とmmap()コールを使用します –

    1

    @Zang MingJie

    あなたの答えは私をたくさん助けたが、次の言葉は何人かの人々混乱させる可能性がある:それは持っていないため、

    IMO、ld-linux.soが静的リンクされているがすべての動的リンクオブジェクトに必要な.interp>セクション。

    私たちは、「共有オブジェクト」と呼ばれる一種が、このように生成され、二つの部分に「すべての動的リンクされたオブジェクト」を分ける必要があります。

    gcc -c -o test.o test.c -fPIC 
    ld -o test.so test.o -shared 
    

    別の種類は、「ダイナミックリンクされた実行可能ファイル」と呼ばれます。

    gcc -c -o test.o test.c -fPIC 
    ld -o test.so test.o 
    

    2点が重要である:動的にリンクされている間

    1、共有オブジェクトは、no 'を.iNTERP' の部分を持っています実行可能ファイルがあります。

    2、LinuxカーネルはELFファイルがelfヘッダーで示されたEXECかDYNかどうかは気にしません。彼は最初に.INTERPセグメントを検索します。失敗した場合は、すべてのLOADタイプのセグメントをmmap()し、実行可能ファイルまたは共有オブジェクトをロードしているかどうかにかかわらず、コントロールをeheader-> e_entryに渡します。

    ld-linux.soは共通の共有オブジェクトであるため、彼女が.INTERPセグメントを所有していないのは珍しいことではありません。実行可能ファイルとして実行できるのは奇妙ではありません。すべての共有オブジェクトは可能です。このような

    ライトコード:

    void foobar(void){ while(1); } 
    

    (上記のコマンドラインを使用して)共有オブジェクトにコンパイル。 実行して:あなたは、プロセスが死んでループに陥ってしまいます

    gdb ./test.so 
    

    。 これを中止するにはCtrl-Cを使用します。 「カーネル変数の値を関連さ

    (gdb) p $eip 
    $1 = (void (*)()) 0x80000183 <foobar+3> 
    (gdb) 
    

    あなたはLinuxカーネルに精通している場合、あなたは0x80000000のを知っている必要があります:あなたは

    Program received signal SIGINT, Interrupt. 
    foobar (void) at test.c:1 
    1  while(1); 
    (gdb) 
    

    あなたがより遠くに行くことができます(GCCの-gオプションが必要)が表示されますmmap_min_addr '。 test.soは共有オブジェクトであるため、ロードアドレスはゼロであるため、カーネルは彼女のデフォルトの仮想アドレスを見つけました。つまり0x804000ではなく0x80000000です。

    私は私がオフトピック...

    +0

    あなたの説明をありがとう!そんなに話題ではありません。 –

    関連する問題