library path when dynamically loaded?

强颜欢笑 提交于 2019-11-27 11:51:08
Jay Conrod

The dynamic linker actually searches several places to find each dynamic library. These include (from man ld.so):

  • Paths given by the environment variable LD_LIBRARY_PATH
  • Paths baked into the binary load the library under the DT_RUNPATH entry
  • The cache file /etc/ld.so.cache
  • /lib and /usr/lib

If you want to get the path for a specific shared library, I would recommend the dladdr function. From the man page:

The function dladdr() takes a function pointer and tries to resolve name and file where it is located. Information is stored in the Dl_info structure:

typedef struct {
    const char *dli_fname;  /* Pathname of shared object that
                               contains address */
    void       *dli_fbase;  /* Address at which shared object
                               is loaded */
    const char *dli_sname;  /* Name of nearest symbol with address
                               lower than addr */
    void       *dli_saddr;  /* Exact address of symbol named
                               in dli_sname */
} Dl_info;

If no symbol matching addr could be found, then dli_sname and dli_saddr are set to NULL.

dladdr() returns 0 on error, and non-zero on success.

So you just give it a function pointer, and it will give you the name of the file which supplies it and a bunch of other information. So for instance, you could have a constructor in a library call this on itself to find out the full path of the library:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

__attribute__((constructor))
void on_load(void) {
    Dl_info dl_info;
    dladdr((void *)on_load, &dl_info);
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}

This function also works on OS X with the same semantics.

since dl_info.dli_fname not always contain full path in android (see here),we need to parse the /proc/self/maps to obtain the full path.

string GetSelfPath()
{
    string selfPath;
    Dl_info di;
    dladdr((void*)GetSelfPath, &di);
    LOGC("GetSelfPath:%08X,dli_fbase:%08X,dli_saddr:%08X,dli_fname:%s,dli_sname:%s", GetSelfPath, di.dli_fbase, di.dli_saddr, di.dli_fname, di.dli_sname);
    //dl_info.dli_fname not always contain full path in android,see android.googlesource.com/platform/bionic/+/… line 141
    if (strrchr(di.dli_fname, '/') != NULL)
    {
        selfPath=di.dli_fname;
    }
    else selfPath= GetPathByFileName(di.dli_fname);
    LOGC("self path:%s", selfPath.c_str());
    return selfPath;
}

string GetPathByFileName(string targetFilename)
{
    FILE *fp = fopen("/proc/self/maps", "r");
    if (NULL == fp) {
        return "";
    }
    const size_t BUFFER_SIZE = 256;
    char buffer[BUFFER_SIZE] = "";
    char path[BUFFER_SIZE] = "";

    while (fgets(buffer, BUFFER_SIZE, fp)) {
        if (sscanf(buffer, "%*llx-%*llx %*s %*s %*s %*s %s", path) == 1) {
            char *bname = basename(path);
            LOGC("check basename[%s]", bname);
            if (strcasecmp(bname, targetFilename.c_str()) == 0) {
                fclose(fp);
                return path;
            }
        }
    }
    fclose(fp);
    return "";
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!