12

私のプログラムには、次のようなコードがあります

/* libname may be a relative path */
void loadLib(char const *libname) {
   void *handle = dlopen(libname);
   /* ... */
   dlclose(handle);
}

/* .. */で、メモリ マップ ファイルを読み取って、マップ/proc/self/maps先の仮想メモリ アドレスを見つけるlibname必要があります。また、ライブラリを開いてその中の特定のセクションを見つける必要もあります。このためには、さまざまな場所 (キャッシュ ファイルdlopenなど) を検索して見つかった絶対名が必要です。ldconfigそのファイル名を受け取るにはどうすればよいですか?


これが私が最終的に得たものです(はい、これはC++コードですが、CタグはdlopenC++とCの両方で使用され、私の質問は両方に適格であり、POSIXはCに対してそれを指定しているため、この質問には意味があります. )。

   boost::shared_ptr<void> dl;
   if(void *handle = dlopen(libfile, RTLD_LAZY)) {
      dl.reset(handle, &dlclose);
   } else {
      printdlerr();
      return -1;
   }

   /* update sofile to be an absolute file name */
   {
      struct link_map *map;
          dlinfo(dl.get(), RTLD_DI_LINKMAP, &map);
      if(!map) {
         return -1;
      }
      char *real = realpath(map->l_name, NULL);
      if(!real)
         return -1;
      sofile.reset(real, &free);
   }

libfile相対/プレーンファイル名です。マップはプレーンでないファイル名を生成します (つまり、そうではありませんfoo.soが、そうかもしれません./foo.so)。その後realpath、最終的な絶対パス名を取得していました。それはうまく機能します!

4

3 に答える 3

10

あなたが使用できる

... dlinfo(handle, RTLD_DI_LINKMAP, p)
p->l_name ...

p は Link_map** 型です

詳細については、man dlinfo を参照してください

于 2011-07-13T09:39:30.637 に答える
1

唯一の解決策は、システムのアルゴリズムを模倣することです。これは思ったほど難しくはありません (ただし、いつものように、悪魔は細部に宿っています): 私は以下を使用して、実行可能パスを見つけます。

std::string retval = our_argv0;
if ( !isAbsolute( retval ) )
{
    char const* tmp = getenv( "PATH" );
    if ( tmp == NULL )
        throw std::runtime_error( "$PATH not set" );
    std::vector<std::string> dirs( split( std::string( tmp ), ":" ) );
    std::vector<std::string>::const_iterator i = dirs.begin();
    while ( i != dirs.end() 
            && ! access( (*i + '/' + retval).c_str(), X_OK ) == 0)
        ++ i;
    if ( i == dirs.end() )
        throw std::runtime_error("Cannot find load path");
    retval = *i + '/' + retval;
}
return std::string(
    retval.begin(),
    std::find( retval.rbegin(), retval.rend(), '/' ).base() );

argv[0]の代わりに、のLD_LIBRARY_PATH代わりにライブラリの名前を使用し、PATH設定されていない場合はスローする代わりに適切なデフォルトを使用して、ライブラリに適応させることができるはずです。おそらく処理しない特殊なケースがありますが、上記の方法で実行可能ファイルを見つけることができます。(splitisAbsoluteはライブラリ内の他の関数であり、明らかなことを行います。)

于 2011-07-13T09:45:50.667 に答える
0

私が考えることができる1つのオプションは、 function を使用することですpathfind():

char *pathfind(const char *path, const char *name, const char *mode);

DL は、次の 3 つの場所のいずれかからロードできます: 現在のディレクトリ、exec が配置されたディレクトリ、および LD_LIBRARY_PATH (最後の 2 つを確認できpathfindますgetenv("LD_LIBRARY_PATH")) path

于 2011-07-13T09:19:01.240 に答える