Search code examples
lddynamic-linkingsqlapi++tdsodbc

SQLAPI++: Get path to shared library loaded by executable


SQLAPI++ has an unusual feature where you set a string to tell it where to find the ODBC shared library. In my case this is libtdsodbc.so, and my application actually links that library at build time, but at runtime this is not enough for SQLAPI++ to work.

My code is:

  SAConnection conn;
  conn.setOption("ODBC.LIBS") = "libtdsodbc.so";
  conn.Connect("SERVER=...", "", "", SA_ODBC_Client);

ODBC.LIBS is documented like this:

Forces SQLAPI++ Library to use specified ODBC manager library.

The above code works if you set LD_LIBRARY_PATH to a directory containing libtdsodbc.so. But if you don't, Connect() fails:

libtdsodbc.so: cannot open shared object file: No such file or directory

DBMS API Library 'libtdsodbc.so' loading fails
This library is a part of DBMS client installation, not SQLAPI++
Make sure DBMS client is installed and
this required library is available for dynamic loading

Linux/Unix:
1) The directories in the user's LD_LIBRARY_PATH environment variable
2) The list of libraries cached in /etc/ld.so.cache
3) /usr/lib, followed by /lib

It works again if you set ODBC.LIBS to a full path rather than just a filename. But how can the application know which path?

My application (outside of SQLAPI++) finds libtdsodbc.so via its RUNPATH which is set at build time. This path is not a system path like /usr/lib. I'd like to have SQLAPI++ use the same library which is loaded in the application at runtime.

One idea is for the application to inspect its own RUNPATH, search for libtdsobc.so, and use that path. But this requires quite a bit of fiddly code to basically reimplement what ld.so already does.

I don't want to bake the path into the executable at build time separately from RUNPATH, because I sometimes edit RUNPATH before deployment (and then I'd need to edit two things).

Ideally I would like to tell SQLAPI++ to just use the library which is already loaded. I can figure this path out by running lsof -p PID | grep libtdsodbc.so but running shell commands from within the executable is not a good solution (and again I would rather not reimplement lsof).


Solution

  • You could either use dl_iterate_phdr (the link also includes a sample code which prints out lib names) or manually parse /proc/self/maps.