回答:
dlopen
はシステムコールではなく、libdl libraryのライブラリ関数です。システムコールのみが表示されstrace
ます。
Linuxおよび他の多くのプラットフォーム(特に実行可能ファイルにELF形式を使用するプラットフォーム)ではdlopen
、でターゲットライブラリを開き、でopen()
メモリにマッピングすることにより実装されますmmap()
。mmap()
ここで本当に重要な部分であり、それはライブラリをプロセスのアドレス空間に組み込んでいるので、CPUはそのコードを実行できます。しかし、あなたはopen()
それをする前にファイルをしなければなりませんmmap()
!
ld-linux
、execve
システムコールの一部としてカーネルによってマップされることが重要だと思います。
dlopenは、共有ライブラリとは何の関係もありません。共有オブジェクトをロードするには、次の2つの方法があります。
main
関数が呼び出される直前に呼び出され、アプリケーションがライブラリの関数を見つけるようにアプリケーションのプロセススペースが設定されます。これにはopen()
、潤滑油を実行してから実行し、その後にmmap()
いくつかのルックアップテーブルを設定します。libdl
、そこから(最初のメソッドを使用して)dlopen()
およびdlsym()
関数。dlopenを使用すると、ライブラリへのハンドルを取得し、dlsymで使用して、特定の関数への関数ポインターを受け取ることができます。この方法は、最初の方法よりもプログラマーにとってはるかに複雑です(リンカーが自動的にそれを行うのではなく、手動でセットアップを行う必要があるため)、また、より脆弱です(コンパイルを取得しないため) -timeは、最初のメソッドで取得するように正しい引数タイプで関数を呼び出していることを確認しますが、利点は、実行時にロードする共有オブジェクト(またはロードするかどうか)を決定できることです。これはプラグインタイプの機能のためのインターフェースです。最後に、dlopenインターフェースは、そのメカニズムが動的リンカーの正確な実装に依存するため、他の方法よりも移植性が低くなります(したがってlibtoolのlibltdl
、これらの違いを抽象化しようとします)。ltrace -S
mmap
glibc 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
呼び出されることがわかります。open
mmap
このすばらしいltrace
ツールは、ライブラリ呼び出しとシステム呼び出しの両方をトレースするため、この場合に何が起こっているのかを調べるのに最適です。
綿密な分析open
により、ファイル記述子3
(stdin、out、errの次の空き記述子)が返されることが示されています。
read
次にそのファイル記述子を使用しますが、TODO why mmap
の引数が4つに制限されており、5番目の引数であるため、どのfdがそこで使用されたのかわかりません。strace
それ3
が予想通りに確認され、宇宙の順序が復元されます。
勇敢な魂はglibcコードに挑戦することもできますがmmap
、簡単なgrep の後、私は怠け者です。
GitHubでボイラープレートをビルドして、この最小限のサンプルでテストしました。
strace
システムコール(つまり、カーネルによって直接実装された機能)について報告します。動的ライブラリはカーネル関数ではありません。dlopen
カーネルではなく、Cライブラリの一部です。実装がdlopen
呼び出されますopen
、それは読むことができるように、ライブラリファイルを開くには(システムコールです)。
ltrace
。
ltrace -S
は、syscalls も示すため、これを分析するのに最適です。unix.stackexchange.com