Joerg Schilling wrote:
> Is there a way to reliably retrieve the path to a library?
> 
> I tried to opendir("/proc/<pid>/path/")
> and readdir()/readlink() the entries. If all library 
> names differ, this allows to find the path to any lib of
> interest.
> 
> Unfortunately, this does not help if there are two 
> libraries with the same name (e.g. /tmp/libm.so.2
> and /lib/libm.so.2). Is there a way to get the 
> path that is related to a handle returned by dlopen()?

You can use dlinfo() to get the origin of the dlopen()
caller, together with the pathnames that were opened:

chaz 1861. pwd
/home/rie/joerg
chaz 1862. mkdir one two
chaz 1863. cat null.c
void null(){}
chaz 1864. cc -G -o one/null.so.1 -Kpic null.c
chaz 1865. cc -G -o two/null.so.1 -Kpic null.c
chaz 1866. cat main.c
#include <dlfcn.h>
#include <link.h>
#include <stdio.h>
#include <limits.h>

void main()
{
         void    *handle;
         Link_map *lmp;
         char    origin[PATH_MAX];

         (void) dlinfo(RTLD_SELF, RTLD_DI_ORIGIN, origin);
         (void) printf("origin: %s\n", origin);

         handle = dlopen("one/null.so.1", RTLD_LAZY);
         (void) dlinfo(handle, RTLD_DI_LINKMAP, &lmp);
         (void) printf("name: %s/%s\n", origin, lmp->l_name);

         handle = dlopen("two/null.so.1", RTLD_LAZY);
         (void) dlinfo(handle, RTLD_DI_LINKMAP, &lmp);
         (void) printf("name: %s/%s\n", origin, lmp->l_name);
}
chaz 1883. cc -o main main.c
chaz 1884. ./main
origin: /home/rie/joerg
name: /home/rie/joerg/one/null.so.1
name: /home/rie/joerg/two/null.so.1


Or, you could retrieve a known symbol from the handle, and
get the associated address information from dladdr():


chaz 1902. cat main.c
#include <dlfcn.h>
#include <stdio.h>

void main()
{
         void    *handle;
         void    *fptr;
         Dl_info dli;

         handle = dlopen("one/null.so.1", RTLD_LAZY | RTLD_FIRST);
         fptr = (void *)dlsym(handle, "null");
         (void) dladdr(fptr, &dli);
         (void) printf("name: %s\n", dli.dli_fname);

         handle = dlopen("two/null.so.1", RTLD_LAZY | RTLD_FIRST);
         fptr = (void *)dlsym(handle, "null");
         (void) dladdr(fptr, &dli);
         (void) printf("name: %s\n", dli.dli_fname);
}
chaz 1903. cc -o main main.c
chaz 1904. ./main
name: /home/rie/joerg/one/null.so.1
name: /home/rie/joerg/two/null.so.1


-- 

Rod.

Reply via email to