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

标签 c linux gdb shared-libraries

我有一个 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

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

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

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

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

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

最佳答案

Why is gdb behaving differently in both these cases?

因为你没有构建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 找不到它们。

更新:

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部分。这是一个DT_DEBUG.dynamic 中输入部分。

它仍然缺失,因为 -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[] ,而不是你现在得到的虚假值。

关于c - 运行独立共享库时 gdb 不加载符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30946735/

相关文章:

python - 以 Root 身份执行 Python 脚本(seteuid 与 c-wrapper)

c - 将 char* 传递给 c 中的 const char*

Android,是否必须在 Linux 中使用 JNI?

c++ - 无法访问 C++ vector 下的内存

c++ - 为什么c++ pthread会自行退出而不导致进程崩溃?

c - 为什么 scanf 接受 "%f"格式说明符的字符?

c - Qt多线程应用程序卡住并且多个线程等待相同的互斥体

linux - 我可以用什么来捕获我在 bash 中运行的每个命令(a-la 历史)

linux - getuid指的是哪里?

linux - 为什么 gdb 回溯系统调用地址与系统调用表地址不同