Is there a programmatic way to inspect the current rpath on Linux?

LinuxRpath

Linux Problem Overview


I'm aware that it is possible to use readelf -d <elf> | grep RPATH to inspect a given binary from the shell, but is it possible to do this within a process?

Something like (my completely made up system call):

  /* get a copy of current rpath into buffer */
  sys_get_current_rpath(&buffer);

I'm trying to diagnose some suspect SO linking issues in our codebase, and would like to inspect the RPATH this way if possible (I'd rather not have to spawn an external script).

Linux Solutions


Solution 1 - Linux

For the record, here are a couple of commands that will show the rpath header.

objdump -x binary-or-library |grep RPATH

Maybe an even better way to do it is the following:

readelf -d binary-or-library |head -20

The second command also lists the direct dependencies on other libraries followed by rpath.

Solution 2 - Linux

#include <stdio.h>
#include <elf.h>
#include <link.h>

int main()
{
  const ElfW(Dyn) *dyn = _DYNAMIC;
  const ElfW(Dyn) *rpath = NULL;
  const char *strtab = NULL;
  for (; dyn->d_tag != DT_NULL; ++dyn) {
    if (dyn->d_tag == DT_RPATH) {
      rpath = dyn;
    } else if (dyn->d_tag == DT_STRTAB) {
      strtab = (const char *)dyn->d_un.d_val;
    }
  }

  if (strtab != NULL && rpath != NULL) {
    printf("RPATH: %s\n", strtab + rpath->d_un.d_val);
  }
  return 0;
}

Solution 3 - Linux

You can also use:

chrpath -l binary-or-library

Solution 4 - Linux

Here's what I use for convenience, as a shell function:

function getrpath {
    eu-readelf -d "${1:?}" | sed -e '/RUNPATH/{s~.*\[\(.*\)\]~\1~;n};d'
}

This consumes eu-readelf output from elfutils like:

Type              Value
NEEDED            Shared library: [libpq.so.5]
NEEDED            Shared library: [libc.so.6]
RUNPATH           Library runpath: [/some/path/to/lib]
....

and emits

 /some/path/to/lib

It should work fine with binutils readelf instead of elfutils eu-readelf too.

Solution 5 - Linux

There is a way. Follow the example code in man dlinfo [1], but use NULL as the first parameter of dlopen().

[1] https://man7.org/linux/man-pages/man3/dlinfo.3.html

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJusticleView Question on Stackoverflow
Solution 1 - LinuxMichael DillonView Answer on Stackoverflow
Solution 2 - LinuxEmployed RussianView Answer on Stackoverflow
Solution 3 - LinuxOscar AndreassonView Answer on Stackoverflow
Solution 4 - LinuxCraig RingerView Answer on Stackoverflow
Solution 5 - LinuxDanielView Answer on Stackoverflow