Reputation: 15143
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).
Upvotes: 114
Views: 129939
Reputation: 1152
If you have patchelf it can also print rpath in a pretty format:
> patchelf --print-rpath /path/to/elf
$ORIGIN:$ORIGIN/../../lib
Upvotes: 3
Reputation: 213516
The question is specifically about RPATH
, but modern linkers use RUNPATH
instead. See this answer -- there is a subtle semantic difference between the two.
The answer is updated to print either.
#include <assert.h>
#include <stdio.h>
#include <elf.h>
#include <link.h>
int main()
{
const ElfW(Dyn) *dyn = _DYNAMIC;
const ElfW(Dyn) *rpath = NULL;
const ElfW(Dyn) *runpath = 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_RUNPATH) {
runpath = dyn;
} else if (dyn->d_tag == DT_STRTAB) {
strtab = (const char *)dyn->d_un.d_val;
}
}
assert(strtab != NULL);
if (rpath != NULL) {
printf("RPATH: %s\n", strtab + rpath->d_un.d_val);
} else if (runpath != NULL) {
printf("RUNPATH: %s\n", strtab + runpath->d_un.d_val);
}
return 0;
}
Upvotes: 69
Reputation: 32392
For the record, here are a couple of commands that will show the rpath
/ runpath
header.
objdump -x binary-or-library |grep 'R.*PATH'
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
.
Upvotes: 199
Reputation: 307
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
Upvotes: 2
Reputation: 324445
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.
Upvotes: 6