2

I have some code that is compiled as a shared library and used with a universal driver, which can be used with other shared libraries that are specific to a particular application.

My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.

For example, let's say I have 3 files, the first is driver.cpp, the universal driver:

#include "interface.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
    //perform a function from the shared library
    std::cout << foobar() << std::endl;
}

The second is sharedlibrary.cpp, the specific implementation for one case of many:

#include "interface.h"
char* foobar() {
    return x;
}

Where x is some indicator that this function is defined in sharedlibrary.cpp, or that this function is linked from sharedlibrary.so, or the current stack frame is using the specific binary rather than just being included in driver.cpp.

The last file is interface.h, which provides the interface to the library via extern "C"

extern "C" {
char foobar();
}

I would like to reiterate, for clarity, that I am looking for some indication that this function is being linked from sharedlibrary.so. Many solutions looking for runtime filenames give the executable name using either argv[0] or readlink(), but I have no control over the actual naming of driver.cpp or its executable name. Rather, I can distribute sharedlibrary.so, and would like to be able to use its name from within itself, if possible.

If it helps, I know that a microsoft-specific solution could be to use AfxGetApp()->m_pszAppName to obtain the DLL name. However, I am looking for a linux solution that does not necessarily need to be portable.

EDIT: I do not know or control the names of driver.cpp, sharedlibrary.cpp, or sharedlibrary.h at compile time. I wish to discover the name of sharedlibrary.cpp at run time.

The updated sharedlibrary.cpp with x replaced with the solution looks like this

#include "interface.h"
#include <dlfcn.h>
void func() {
    //Some function that is defined in sharedlibrary.cpp
}

char* foobar() {
    Dl_info DlInfo;
    if(!dladdr((void*)func, &DlInfo)) {
        return "default_name";
    }
    return DlInfo.dli_fname;
}
D Kucher
  • 149
  • 10
  • There is a way to find the available functions from .so file by looking for a symbol using dlsym() but you cannot figure out a type of parameters, I mean you cannot figure out complete signature. – yadhu Jul 20 '18 at 12:51
  • 1
    C and C++ are very different, please use only the correct tags. Thanks : ) – hat Jul 20 '18 at 12:56
  • did you have sharedlibrary.h file also or not? mention it too – HarshGiri Jul 20 '18 at 13:02
  • Correct me if I have understood wrongly, You want to figure out which library contains particular function – yadhu Jul 20 '18 at 13:03
  • @yadhu Yes, but from within the actual shared library at runtime, not externally. The solution must be implemented within sharedlibrary.cpp. – D Kucher Jul 20 '18 at 13:10
  • But you need to load that library to call a function inside – yadhu Jul 20 '18 at 13:12
  • Correct, but there may be other functions within sharedlibrary.cpp that rely on `x`. I would like to know if there is some way to obtain the shared library name at the time the function is called. – D Kucher Jul 20 '18 at 13:17
  • You can read `/proc/self/maps` – n. m. could be an AI Jul 20 '18 at 13:18

3 Answers3

4

Obtaining filename at runtime for a shared library c++

My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.

You can use int dladdr(void *addr, Dl_info *info. It fills a following structure for you:

typedef struct {
    const char *dli_fname;  /* Pathname of shared object that contains address */
    void       *dli_fbase;
    const char *dli_sname;
    void       *dli_saddr;
} Dl_info;

You can pass the address of a function exported by the shared library as the argument addr. Or within such function, you could use the instruction pointer value of the current stack frame - if you know how to obtain it.

I believe you must link with the libdl library.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
0

You can use the buildsystem to generate the dynamic library name for linking and preprocess that inside of a header with a function that return a defined macro, in cmake you can see how to do that here.

Then you use the configured-file to return the defined value in a function that's exported from within the dll.

#include "library_name_macro.h"

auto __dllexport libraryName() -> std::string { return LIBRARY_NAME_MACRO; } 
Tomaz Canabrava
  • 2,320
  • 15
  • 20
0

I hope, I have understood your question correctly. I hope my answer helps. You know the shared library name, you link that shared library to your program, Later in run time you want to figure out whether a particular function is present in library or not and this logic should be part of shared library itself.

Let's take an example that you have shared library called librandom.so, You have linked this library to your application. You can implement the following function in a librandom.so library, You can pass function name which you want to check whether it is present or not. I have not tested this code, there may be errors. The idea I am proposing is library loads itself again to check whether the function is present when this function is called. May not be ideal method but should serve your purpose.

int isFuncPresent(char funcName[])
{
    int isFuncFound = 1;
    void *lib_handle;
    int x;
    char *error;
    lib_handle = dlopen("librandom.so", RTLD_LAZY);

    if (!lib_handle)
    {
       fprintf(stderr, "%s\n", dlerror());
       isFuncFound = 0;
    }

    fn = dlsym(lib_handle, funcName);
    if ((error = dlerror()) != NULL)
    {
       fprintf(stderr, "%s\n", error);
       isFuncFound = 0;
    }
    dlclose(lib_handle);
    return isFuncFound;
}
yadhu
  • 1,253
  • 14
  • 25
  • Apologies for not communicating my problem well. I do not have control over either the name of the driver or the shared library. So I cannot specify a library to open with dlopen(). – D Kucher Jul 20 '18 at 19:25