2011-07-13 6 views
10

私は/* .. */内で次のdlopenに与えられた相対パスに対応する絶対ライブラリファイル名を取得する方法は?私のプログラムで

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

のようなコードを持って、私はlibnameがマップされた仮想メモリアドレスを見つけるために、メモリ・マップ・ファイル/proc/self/mapsを読む必要があると私はまた、開く必要がありますライブラリを使用して、その中の特定のセクションを見つけます。このためには、dlopenという絶対名が必要です(キャッシュファイルのldconfigなど)。そのファイル名をどのように受け取ることができますか?


これは私が最後になってしまったものです(はい、これはC++のコードで、dlopenはC++とCの両方で使用されており、私の質問は、両方の対象であるため、それにもかかわらず、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を使用しました。それはうまく動作します!私は機能pathfind()を使用していると考えることができます

答えて

8

あなたは、pは型Link_mapである

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

を使用することができます**

が唯一の解決策は、システムのアルゴリズムを模倣することで詳細

+0

ありがとう。私はそれをし、それは動作します。私はすぐに私の最終的な道を示すでしょう。 –

0

一つのオプション:

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

DLが3つのいずれかの場所からロードすることができます。現在のディレクトリ、幹部が置かれたディレクトリとLD_LIBRARY_PATH - あなたは最後の二つを確認することができます -を入力し、別の文字列を検索してください。のgetenv("LD_LIBRARY_PATH")にはpathfindを使用してください。

+0

'pathfind'はどこにありますか?私はPosixのドキュメントやLinuxのドキュメントで見つけることができません。ありがとう。 –

1

のマニュアルdlinfoを参照してください。それは音として(いつものように、悪魔は 詳細であるが)これがない として困難である:

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]の代わりにの代わりに ライブラリの名前を使用して、の代わりに をスローするのではなく、適切なデフォルトに設定します。そこには がおそらく特別なケースではありませんが、上記のものは で実行可能ファイルを見つけることができます。 (splitisAbsoluteは、われわれのライブラリにある他の の関数です。

関連する問題