RPATHが設定されていても、この実行可能ファイルが相対パスモジュールライブラリをロードしないのはなぜですか?

RPATHが設定されていても、この実行可能ファイルが相対パスモジュールライブラリをロードしないのはなぜですか?

この質問はプログラミングの側面に関連していますが、何が起こっているのか理解しようとするほど、Unix / LinuxRPATHに関連している可能性があります。 Unix/Linux と関連があるとします。$ORIGIN(私の質問はスタックオーバーフローでも大きな関心を集めていません。)質問のプログラミングに関する側面をできるだけ多く取り除きます(例:CMakeLists.txt)。しかし、回答者が関連性があると言えば。

実行可能ファイルがあるサブディレクトリからモジュールライブラリ(または別の方法で呼び出される「共有ライブラリ」または「プラグインライブラリ」)をロードする実行可能ファイルを作成しました。ディレクトリ構造は次のとおりです。

build/
├── main  # the executable
└── plugins
    └── libmy-plugin.so

この質問のプログラミングの観点からある程度距離を置くために完全なCコードを表示しないでください(誰かがこのサイトのトピックから質問を取り出さないと言う場合を除き)。しかし、実際にはモジュールライブラリをロードする「hello-world」と同じですが、1つの違いがあります。相対パスからプラグインライブラリをロードすることです。具体的にロードされるplugins/libmy-plugin.so最小コードスニペットは次のとおりです。

const char* plugin = "plugins/libmy-plugin.so";
void* handle = dlopen(plugin, RTLD_NOW);

マニュアルページには次のようdlopenに記載されています。

dlopen() 関数は、null で終わる文字列ファイル名で指定された動的共有オブジェクト (共有ライブラリ) ファイルをロードし、ロードされたオブジェクトの不透明な「ハンドル」を返します。ファイル名がNULLの場合、返されたハンドルは次の操作に使用されます。メインファイルプログラム。ファイル名にスラッシュ( "/")が含まれている場合(相対または絶対)、パス名として解釈されます。

マニュアルページには次のようld-linux.soに記載されています。

$ORIGIN (またはそれに対応する ${ORIGIN})
これは、プログラムまたは共有オブジェクトを含むディレクトリに展開されます。したがって、somedir / appにあるアプリケーションは、
gcc -Wl,-rpath,'$ORIGIN/../lib'
somedirがディレクトリ階層のどこにあるかに関係なく、somedir / libで関連する共有オブジェクトを見つけるようにコンパイルできます。これは特別なディレクトリにインストールする必要はありませんが、任意のディレクトリに展開し、それでも自分の共有オブジェクトを見つけることができる「ターンキー」アプリケーションを作成するのに役立ちます。

確認方法がわかる限り、私がコンパイルしたバイナリは次のようにRPATH設定されています$ORIGIN

$ objdump -x ./build/main | grep PATH
  RUNPATH              $ORIGIN
$
$ readelf -d ./build/main

Dynamic section at offset 0x2d98 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN]
...

私が読んだところによれば、$ORIGIN「プログラムを含むディレクトリに展開」し、「ファイル名にスラッシュ( "/」)が含まれている場合(相対または絶対)、パス名として解釈されます。これは次のことを意味するはずです。プログラムRPATHスラッシュ(および相対パス)を含むファイル名で$ORIGIN呼び出すように設定されている場合、dlopen()そのモジュールライブラリの検索パスはプログラムを含むディレクトリと相対的でなければなりません。

しかし、それは私が観察したものではありません。私が実際に観察したのは、私のCWDが実行可能ファイルを含むディレクトリである場合、実行可能ファイルはモジュールライブラリのみを見つけることです。別のディレクトリにあり、実行可能ファイルへの完全な相対/絶対パスを指定すると、モジュールライブラリが見つかりません(そして設定の影響を受けないようですLD_LIBRARY_PATH)。

$ ./build/main
failed loading plugins/libmy-plugin.so: plugins/libmy-plugin.so: cannot open shared object file: No such file or directory
$
$ LD_LIBRARY_PATH=./build ./build/main
failed loading plugins/libmy-plugin.so: plugins/libmy-plugin.so: cannot open shared object file: No such file or directory
$
$ LD_LIBRARY_PATH=/home/user/dev/cmake-learn/rpath/build/ ./build/main
failed loading plugins/libmy-plugin.so: plugins/libmy-plugin.so: cannot open shared object file: No such file or directory
$
$ cd build/
$ ./main
all good
$

私はこれがプログラミング問題かUnix / Linux問題か頭の中に来て行ったと言っています。前述のように、これがUnix / Linuxモジュールの検索パスに関連しているという不特定の感じがしました。コミュニティでは、これが実際にプログラミングの質問だと思います。スタックオーバーフローについてもう一度試してみましょう。
(Stack Overflowに関する私の元の質問に対するコメントの作成者は、検索パスが常にCWDに対して相対的であると言いましたが、これは完全に説明的な答えではないため、コメント付きのマニュアルページのセクションを読んだものとその声明を一致させることはできません。)

答え1

私にとって、これはファイル名がそこで検索されていないか(「.」に相対的であるか「/」から来ます)、そこにはなく、すべてのパスメカニズムで検索されることを意味しますman dlopen/

おそらく使用dlopen("libmy-plugin.so",)し、提供する必要があると予想する必要があります。-Wl,-rpath,'$ORIGIN/plugins'

関連情報