运行 独立共享库时 gdb 不加载符号

gdb not loading symbols when running standalone shared library

我有一个 PIC 共享库,它也有一个主要功能

#include <dtest2.h>
#include <stdio.h>
extern const char elf_interpreter[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";

int dtestfunc1(int x,int y) {
  int i=0;
  int sum = 0;
  for(i=0;i<=x;i++) {
    sum+=y;
    sum+=dtestfunc2(x,y);

  }
  return sum;
}

int main (int argc, char const* argv[])
{
  printf("starting sharedlib main\n");
  int val = dtestfunc1(4,5);
  printf("val = %d\n",val);
  _exit(0);
}

此库链接到另一个共享库 libdtest2,该库具有从 dtestfunc1 调用的 dtestfunc2 的实现。

如果我 运行 gdb 直接在 dtestfunc1 上使用

gdb libdtest1.so

libdtest2.so 的符号未由 gdb 加载。因此,我无法进入 dtestfunc1,如果我按 s,函数就会执行并退出。

如果我创建一个在共享库上调用 dlopen 的驱动程序,gdb 会在执行 dlopen 后正确加载符号并且一切正常。

  1. 为什么 gdb 在这两种情况下的行为不同?
  2. 如果我直接在共享库上 运行ning gdb,如何手动将 gdb 指向共享库?

注意:这是一个玩具示例,反映了我在更大的共享库中遇到的问题。我所有的二进制文件和库都是使用 -ggdb3 标志编译的。

编辑:我的共享库 运行 可用。我使用源代码中的外部定义添加了正确的解释器路径。我用 gcc -ggdb3 -O0 -shared -Wl,-soname,libdtest1.so.1 -ldtest2 -L/usr/lib -Wl,-e,main -o libdtest1.so.1.0 dtest1.o 编译了它。 我可以 运行 它并执行 perfectly.Running 共享库不是这里的问题。

简单的修复....使用(对于 gcc)参数“-ggdb”重新编译库然后它将具有 gdb 可用的所有符号。

Why is gdb behaving differently in both these cases?

因为您没有为 GDB 正确构建 libdtest1.so

特别是,您的 libdtest1.so 在其动态部分缺少 DT_DEBUG 条目,您可以这样确认:

readelf -d libdtest1.so | grep DEBUG

你应该什么也看不到。在正确构建的可运行 libdtest1.so(您可以使用 -pie 标志构建)中,输出应如下所示:

 0x00000015 (DEBUG)                      0x0

运行时加载程序更新 DT_DEBUG 以指向它的 r_debug 结构,然后允许 GDB 找到其他加载的共享库。没有 DT_DEBUG,GDB 找不到它们。

更新:

After adding the pie flag my build command is gcc -ggdb3 -O0 -pie -shared -Wl,-soname,libdtest1.so.1 -ldtest2 -L/usr/lib -Wl,-e,main -o libdtest1.so.1.0 dtest1.c -I. The DEBUG section is still missing

术语:它不是 DEBUG 部分。这是 .dynamic 部分中的 DT_DEBUG 条目。

它仍然缺失,因为 -shared 覆盖了 -pie。从 link 行中删除 -shared

您也不需要 -Wl,-e,main,也不需要指定 .interp -- GCC 会为您完成。

正确的link命令:

gcc -ggdb3 -O0 -pie -rdynamic dtest1.c -I. -Wl,-soname,libdtest1.so.1 \
  -L/usr/lib -ldtest2 -o libdtest1.so.1.0

(link 行中源和库的顺序很重要,你的错了。)

额外奖励:您的主将获得正确的 argcargv[],而不是您现在获得的虚假值。