我正在编写一个定制的动态加载器,奇怪的是,当我try 在.interp部分中指定动态加载器的可执行文件上运行GDB时,我似乎无法在动态加载器代码中设置断点.整个过程大致如下所示:

$ gdb ./a
Reading symbols from ./a...
(gdb) b ld_stage1_entry
Function "ld_stage1_entry" not defined.
Make breakpoint pending on future shared library load? (y or [n]) 

动态加载器是用-g标志编译的,当正常运行时,它成功地执行了它的操作.

我假设这里的问题是GDB不知何故没有从动态加载器读取符号(毕竟我是说我正在调试./a可执行文件).我的问题是,有没有办法告诉gdb在调试时寻找动态加载器符号,或者至少有一些方法可以单步执行动态加载器代码?

我知道调试我的动态加载器的一种方法是将其作为可执行文件运行,传递程序作为参数运行,如下所示:

gdb ./ld.so ./a

但在这个过程中,早期阶段的一些细节是不同的,我理想地希望有一种方法来调试它,它将由Linux从.interp节运行.


EDIT:你可以try 用glibc重现它,但是glibc没有为它的动态加载器提供调试符号,所以我不指望任何人能够调试它.要进行重现,您可以克隆我的动态加载器from github,并使用以下命令编译一个示例:

./build.py --ld -t tests/hello.c

动态加载程序的位置在lib文件夹中../a文件应该在ciabatta文件夹中.

推荐答案

我假设这里的问题是GDB不知何故没有读到符号

有点.问题是GDB不知道大约any个动态加载的代码--它从动态加载程序itself得到关于这些代码的通知(以及代码在内存中的哪个位置加载,从哪个文件加载,等等).

您想要做的是使用starti命令,该命令应该在第一个用户空间指令时停止.对于动态链接的程序,这将是动态加载器中的start符号.从那里,您应该能够设置您想要的任何断点.

PS ./build.py --ld -t tests/hello.c在Fedora 37上失败,出现以下错误:

/usr/bin/ld: /tmp/loader-self-reloc-47a291.o: relocation R_X86_64_32S against `.rodata.str1.16' can not be used when making a shared object; recompile with -fPIC

需要进行以下修复才能构建它:

diff --git a/build.py b/build.py
index 7c30718..bb4ffbf 100755
--- a/build.py
+++ b/build.py
@@ -88,7 +88,7 @@ def compile_obj(output, inputs, additional_flags=[]):
     compile(output, inputs, ['-c -fpic'] + additional_flags)

 def compile_exe(output, inputs, additional_flags=[]):
-    compile(output, inputs, ['-pie'] + additional_flags)
+    compile(output, inputs, ['-pie', '-fPIE'] + additional_flags)

 def compile_shared(output, inputs, additional_flags=[]):
     compile(output, inputs, ['-shared'] + additional_flags)
@@ -134,6 +134,7 @@ cc_includes.append('include/linux')
 cc_flags_push()
 cc_defines_push()
 cc_flags.extend([
+    '-fPIC',
     '-fno-stack-protector',
     '-fno-builtin',
     '-Wl,-e,_dlstart',

使用上述修复后,GDB会话如下所示:

(gdb) starti
Starting program: /home/ciabatta/a
warning: Unable to find dynamic linker breakpoint function.

Program stopped.
0x00007ffff7ff70c0 in _dlstart () from lib/ld-cia.so
(gdb) b ld_stage1_entry
Breakpoint 1 at 0x7ffff7ff70f3: file loader/loader-self-reloc.c, line 30.
(gdb) c
Continuing.

Breakpoint 1, ld_stage1_entry (sp=0x7fffffffdea0, dynv=0x7ffff7ffded0) at loader/loader-self-reloc.c:30
30          _dbg_print_string("Entered dynamic loader\n");
(gdb)

C++相关问答推荐

Pure Win32 C(++)-除了替换控件的窗口程序之外,还有其他方法可以在输入时禁用按钮吗?

有效地计算由一组点构成的等边三角形和等腰三角形的数量

如何在Visual Studio代码中关闭此函数名称显示功能?

如何一次获取一个字符

有没有可能我不能打印?(C,流程)

在c++中使用堆栈的有效括号

向上强制转换C中的数值类型总是可逆的吗?

为什么此共享库没有预期的依赖项?

FRIDA-服务器成为端口扫描的目标?

一旦运行长度超过2,编译器是否会优化";strnlen(mystring,32)>;2";以停止循环?

如何在POSIX-UEFI中获得输入?

不使用任何预定义的C函数进行逐位运算

Malloc和对齐

浮点正零何时不全为零?

Leet代码运行时错误:代码不会在Leet代码上编译,而是在其他编译器中编译,如netbeans和在线编译器

atoi函数最大长-长误差的再创造

根据输入/输出将 C 编译过程分为预处理、编译、汇编和链接步骤

为什么<到达*时不会转换为>?

添加/删除链表中的第一个元素

初始化动态分配的布尔二维数组的最佳方法是什么?