有没有一种编程方法可以检查 Linux 上当前的 rpath?

发布于 2024-09-01 13:18:08 字数 291 浏览 7 评论 0原文

我知道可以使用 readelf -d elf> | grep RPATH 从 shell 检查给定的二进制文件,但是是否可以在进程中执行此操作?

就像(我完全编造的系统调用):

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

我正在尝试诊断我们的代码库中的一些可疑的SO链接问题,并且希望如果可能的话以这种方式检查RPATH(我宁愿不必生成外部脚本) 。

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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

朦胧时间 2024-09-08 13:18:08

作为记录,这里有几个命令将显示 rpath / runpath 标头。

objdump -x binary-or-library |grep 'R.*PATH'

也许更好的方法如下:

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

第二个命令还列出了对其他库的直接依赖项,后跟 rpath。

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.

对岸观火 2024-09-08 13:18:08

这个问题具体是关于 RPATH 的,但现代链接器使用 RUNPATH 代替。请参阅此答案 - 两者之间存在细微的语义差异。

答案已更新为打印。

#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;
}

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;
}
青衫儰鉨ミ守葔 2024-09-08 13:18:08

您还可以使用:

chrpath -l binary-or-library

You can also use:

chrpath -l binary-or-library
时间海 2024-09-08 13:18:08

为了方便起见,我将其用作 shell 函数:

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

这会消耗来自 elfutilseu-readelf 输出,例如:

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

并发出

 /some/path/to/lib

它应该与 binutils readelf 一起正常工作code> 也代替 elfutils eu-readelf

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.

笑忘罢 2024-09-08 13:18:08

如果你有 patchelf 它也可以以漂亮的格式打印 rpath:

> patchelf --print-rpath /path/to/elf
$ORIGIN:$ORIGIN/../../lib

If you have patchelf it can also print rpath in a pretty format:

> patchelf --print-rpath /path/to/elf
$ORIGIN:$ORIGIN/../../lib
酷到爆炸 2024-09-08 13:18:08

有一个办法。遵循 man dlinfo [1] 中的示例代码,但使用 NULL 作为 dlopen() 的第一个参数。

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文