【问题标题】:gdb not loading symbols when running standalone shared library运行独立共享库时gdb不加载符号
【发布时间】:2015-06-19 20:27:18
【问题描述】:

我有一个 PIC 共享库,它也有一个 main 函数

#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 的实现。

如果我使用

直接在 dtestfunc1 上运行 gdb
gdb libdtest1.so

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

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

  1. 为什么 gdb 在这两种情况下表现不同?
  2. 如果我直接在共享库上运行 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 编译它。 我可以运行它并且它完美地执行。运行共享库不是这里的问题。

【问题讨论】:

  • 我的 gdb 生锈了,但是是 file 命令会手动执行此操作(问题 #2)。如果是这样,您可以使用.gdbinit 文件来简化操作。

标签: c linux gdb shared-libraries


【解决方案1】:

为什么 gdb 在这两种情况下表现不同?

因为您没有正确构建 libdtest1.so 以便 GDB 使用它。

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

readelf -d libdtest1.so | grep DEBUG

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

 0x00000015 (DEBUG)                      0x0

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

更新:

添加 pie 标志后,我的构建命令是 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. DEBUG 部分仍然缺失

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

它仍然丢失,因为-shared 覆盖了-pie。从链接行中删除-shared

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

正确的链接命令:

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

(链接行上的源和库的顺序很重要,你的错误。)

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

【讨论】:

  • 我已确保我的库是可运行的。我可以运行它并且它不会崩溃。我用gcc -ggdb3 -O0 -shared -Wl,-soname,libdtest1.so.1 -ldtest2 -L/usr/lib -Wl,-e,main -o libdtest1.so.1.0 dtest1.o 编译它。作为旁注,我为什么要问一个问题,如果我在运行程序时它立即崩溃,为什么 gdb 不进入函数?
  • @MIkhail 我已经更新了答案。 “我为什么要问这个问题……” 我不知道。为什么你会问一个问题而忽略回答它所需的基本细节(构建命令)?
  • 我明白了。我很抱歉。
  • 添加 pie 标志后,我的构建命令是 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. 。 DEBUG 部分仍然缺失。知道为什么它仍然失踪吗?
  • 谢谢。所以现在有 DT_DEBUG 部分:) :)。但我现在无法将共享库与其他二进制文件链接。当我将它与-ldtest1 标志链接时,它会给出undefined reference to dtestfunc1 错误。
【解决方案2】:

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

【讨论】:

  • 所有的二进制文件都是用-ggdb编译的
  • 这是一个完全虚假的答案。
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多