1

I'm maintaining a C-program, that uses Oracle client libraries. The libraries expect the ORACLE_HOME environment variable to be set, and fail to work without it -- in many cases.

In our situation, the value of the variable is always derived from the location of the shared libraries themselves anyway -- and I'd like to implement setting it from the C-code (using putenv(3)).

But, for that, I need to know, from where a particular shared library used by the program was loaded. So, if ldd, when applied to the executable file, outputs:

libc.so.7 => /lib/libc.so.7 (0x1021000)
libmeow.so.1 => /opt/meow/lib/libmeow.so.1

How can the running process itself find out, that libmeow.so, which it is using, is loaded from /opt/meow/lib?

The answer needn't be universally-portable -- something, that'd work for just Linux and BSD will suffice.

1
  • 1
    Can you tell us what you are trying to achieve. What is the problem that you are trying to solve? Jul 16, 2022 at 16:20

2 Answers 2

1

For Linux you can read and search through pseudo file /proc/<pid>/maps, where <pid> would be self from a program looking at itself. It has lines for each memory mapped item, which should include each shared library, eg

7f63c2c23000-7f63c2dd0000 r-xp 00000000 08:01 136321  /usr/lib64/libc-2.26.so

See man proc for details.


There is also a C api for a program to walk through the list of shared objects it is using. See man dl_iterate_phdr. It provides an example of its use. For your use case it is as simple as this:

#define _GNU_SOURCE
#include <link.h>
#include <stdlib.h>
#include <stdio.h>
static int callback(struct dl_phdr_info *info, size_t size, void *data){
    if(info->dlpi_name[0]!='\0')printf("%s\n", info->dlpi_name);
    return 0;
}
int main(int argc, char *argv[]) {
    dl_iterate_phdr(callback, NULL);
    exit(EXIT_SUCCESS);
}
1
  • The dl_iterate_phdr method is perfect. Works on Linux and BSD. Would, likely, work on Solaris too. Thanks!
    – Mikhail T.
    Jul 17, 2022 at 20:50
0

If you want to get the libraries, linked in particular binary can be found with command ldd. For example:

$ldd /bin/cp
    linux-vdso.so.1 =>  (0x00007fffaf3ff000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003a06a00000)
    librt.so.1 => /lib64/librt.so.1 (0x0000003a06200000)
    libacl.so.1 => /lib64/libacl.so.1 (0x0000003a13000000)
    libattr.so.1 => /lib64/libattr.so.1 (0x0000003a0ea00000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003a05200000)
    libdl.so.2 => /lib64/libdl.so.2 (0x0000003a05a00000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003a04a00000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003a05600000)

From this place you can filter the Oracle libraries and set accordingly ORACLE_HOME variable. All this can be done in script which will run your program with already set variable.

5
  • I know, I can do this. My question was, how to perform this lookup from inside the running program. How would the process do it on itself?
    – Mikhail T.
    Jul 16, 2022 at 20:28
  • @MikhailT., why do not do this in advance, in shell script? Jul 17, 2022 at 17:43
  • because shell-wrappers are ugly. We have enough of them already for programs, which we do not control. But this particular one is ours, and it can do the right thing by itself.
    – Mikhail T.
    Jul 17, 2022 at 19:56
  • @MikhailT., for me changing environment in C program is ugly :D Jul 17, 2022 at 20:06
  • This is something, the program requires -- and should be doing itself. The not doing is ugly -- not, where it is implemented. In my opinion...
    – Mikhail T.
    Jul 17, 2022 at 20:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .