Linuxでライブラリをロードするために使用されるシステムコールは何ですか?


23

strace出力、実行可能ファイルが呼び出すことをライブラリへのパスが呼び出しですopen()。これは、動的にリンクされる実行可能ファイルで使用されるシステムコールですか?どうdlopen()open()プログラムの実行に役割を果たすとは思いませんでした。

回答:


33

dlopenはシステムコールではなく、libdl libraryのライブラリ関数です。システムコールのみが表示されstraceます。

Linuxおよび他の多くのプラットフォーム(特に実行可能ファイルにELF形式を使用するプラットフォーム)ではdlopen、でターゲットライブラリを開き、でopen()メモリにマッピングすることにより実装されますmmap()mmap()ここで本当に重要な部分であり、それはライブラリをプロセスのアドレス空間に組み込んでいるので、CPUはそのコードを実行できます。しかし、あなたはopen()それをする前にファイルをしなければなりませんmmap()


2
「mmap()は本当に重要な部分です」:そして、動的リンカーは再配置、初期化などを行う必要があります(ただし、これはシステムコールレベルでは見られません)。
ysdx

1
ライブラリのロードはライブラリ関数によって行われるため、実行可能ファイル自体を追加しld-linuxexecveシステムコールの一部としてカーネルによってマップされることが重要だと思います。
カスペルド

この答えによるmmap。また、各ライブラリを「オープン」した後、mmap呼び出しの前に(832)バイトが読み取られるため、ライブラリが有効であることを確認していることに注意してください。
ヨハン

@kasperdでは、Linuxカーネルはダイナミックローダーを認識していますか?アプリケーションの実行時に呼び出されますか?または、アプリケーション自体がそれを行いますか?後者の場合、別の実行可能ファイルはアプリケーションのメモリにどのようにアクセスできますか?
-Melab

@Melabはい、カーネルは動的リンカーを認識しています。カーネルは、実行可能ファイルのヘッダーから動的リンカーへのパスを読み取ります。そして、カーネルは両方をメモリにマップします。カーネルが最初に制御を転送するエントリポイントがリンカまたは実行可能ファイル内にあるかどうかはわかりません。私がそれを実装していた場合、おそらく実行可能ファイルのエントリポイントを指すスタック上のリターンアドレスを使用して、リンカーのエントリポイントにカーネル転送制御を行うことになります。
カスペルド

5

dlopenは、共有ライブラリとは何の関係もありません。共有オブジェクトをロードするには、次の2つの方法があります。

  1. 特定の共有ライブラリの関数を使用することを、コンパイル時リンカー(ld、通常はコンパイラを介して呼び出されますが)に伝えます。このアプローチでは、コンパイル時リンカーの実行時にライブラリの名前を知る必要がありますが、プログラムに静的にリンクされているかのようにライブラリの関数を呼び出すことができます。アプリケーションが実行されると、動的ランタイムリンカー(ld.so)がmain関数が呼び出される直前に呼び出され、アプリケーションがライブラリの関数を見つけるようにアプリケーションのプロセススペースが設定されます。これにはopen()、潤滑油を実行してから実行し、その後にmmap()いくつかのルックアップテーブルを設定します。
  2. コンパイル時リンカーににリンクすることを伝えlibdl、そこから(最初のメソッドを使用して)dlopen()およびdlsym()関数。dlopenを使用すると、ライブラリへのハンドルを取得し、dlsymで使用して、特定の関数への関数ポインターを受け取ることができます。この方法は、最初の方法よりもプログラマーにとってはるかに複雑です(リンカーが自動的にそれを行うのではなく、手動でセットアップを行う必要があるため)、また、より脆弱です(コンパイルを取得しないため) -timeは、最初のメソッドで取得するように正しい引数タイプで関数を呼び出していることを確認しますが、利点は、実行時にロードする共有オブジェクト(またはロードするかどうか)を決定できることです。これはプラグインタイプの機能のためのインターフェースです。最後に、dlopenインターフェースは、そのメカニズムが動的リンカーの正確な実装に依存するため、他の方法よりも移植性が低くなります(したがってlibtoolのlibltdl、これらの違いを抽象化しようとします)。

面白い; バイナリファイルをメモリにロードすることは難しい部分ではないため、動的にロードされるライブラリは動的にリンクされるライブラリと呼ばれる方が適切です。動的ライブラリをロードするように要求するとき、私は実際にライブラリをリンクする(またはリンクを解除する)アドレス空間に(またはそこから)求めています。
ドミトリー

4

現在、ほとんどのオペレーティングシステムは、1987年後半にSunOS-4.0によって導入された共有ライブラリのメソッドを使用しています。このメソッドは、mmap()によるメモリのマッピングに基づいています。

1990年代初期に、Sunは古いa.outベースのコード(当時のSolarisはすでにELFベースだった)をFreeBSDの人々に寄付し、このコードは他の多くのシステム(Linuxを含む)に引き渡されたという事実を考えて、プラットフォーム間に大きな違いがない理由を理解できます。


3

ltrace -Smmapglibc 2.23で使用されている最小限の例の分析

glibc 2.23、Ubuntu 16.04では、以下latrace -Sで使用する最小限のプログラムで実行しますdlopen

ltrace -S ./dlopen.out

ショー:

dlopen("libcirosantilli_ab.so", 1 <unfinished ...>
SYS_open("./x86_64/libcirosantilli_ab.so", 524288, 06267650550)      = -2
SYS_open("./libcirosantilli_ab.so", 524288, 06267650550)             = 3
SYS_read(3, "\177ELF\002\001\001", 832)                              = 832
SYS_brk(0)                                                           = 0x244c000
SYS_brk(0x246d000)                                                   = 0x246d000
SYS_fstat(3, 0x7fff42f9ce30)                                         = 0
SYS_getcwd("/home/ciro/bak/git/cpp-cheat"..., 128)                   = 54
SYS_mmap(0, 0x201028, 5, 2050)                                       = 0x7f1c323fe000
SYS_mprotect(0x7f1c323ff000, 2093056, 0)                             = 0
SYS_mmap(0x7f1c325fe000, 8192, 3, 2066)                              = 0x7f1c325fe000
SYS_close(3)                                                         = 0
SYS_mprotect(0x7f1c325fe000, 4096, 1)                                = 0

したがって、すぐに+ がdlopen呼び出されることがわかります。openmmap

このすばらしいltraceツールは、ライブラリ呼び出しとシステム呼び出しの両方をトレースするため、この場合に何が起こっているのかを調べるのに最適です。

綿密な分析openにより、ファイル記述子3(stdin、out、errの次の空き記述子)が返されることが示されています。

read次にそのファイル記述子を使用しますが、TODO why mmapの引数が4つに制限されており、5番目の引数であるため、どのfdがそこで使用されたのかわかりませんstraceそれ3が予想通りに確認され、宇宙の順序が復元されます。

勇敢な魂はglibcコードに挑戦することもできますがmmap、簡単なgrep の後、私は怠け者です。

GitHubでボイラープレートをビルドして、この最小限のサンプルでテストしました。


2

straceシステムコール(つまり、カーネルによって直接実装された機能)について報告します。動的ライブラリはカーネル関数ではありません。dlopenカーネルではなく、Cライブラリの一部です。実装がdlopen呼び出されますopen、それは読むことができるように、ライブラリファイルを開くには(システムコールです)。


5
ライブラリ呼び出しはを使用して確認できますltrace
カスペルド

@kasperd ltrace -Sは、syscalls も示すため、これを分析するのに最適です。unix.stackexchange.com
Ciro Santilli新疆改造中心法轮功六四事件
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.