我正在从事一个项目,该项目涉及使用LD_PRELOAD覆盖在运行时从共享对象动态链接的符号,例如:
LD_PRELOAD=/some_library.so ./myapp
在运行可执行文件时,我得到了一个分段错误,但只有在我在GDB之外运行它时才会得到这个错误。另一个细节是,我正在使用bfd查找可执行文件中的符号地址--这个地址与我使用objdump -d ./myapp找到的地址相匹配,但是当我在运行时不使用GDB调用该地址时,它会出现分段错误。我很乐意添加关于确切用例的代码/更多细节,但我的问题是: GDB如何改变动态链接行为?我怀疑我试图覆盖的符号在运行时被重新定位到另一个内存区域,但我不知道该进程是如何工作的,也不知道如何查找重新定位的地址(除了运行时使用gdb之外)。
我试过手动查找符号:
root@server:/workspace/test_apps# objdump -dC ./myapp | grep -i myfunction 0000000000001b65 <__sti____myFunction()>:
在我的LD_PRELOADED库中,我试图这样称呼它:
void (*myFunc)(void) =
(void(*)(void)) 0x1b65;
myFunc();如果我在没有预加载库的情况下使用gdb查找相同的符号,我会看到一些有趣的东西:
root@server:/workspace/test_apps# gdb --args env
LD_PRELOAD=/some_library.so ./myapp
(gdb) info functions
...
0x0000000000001b65 __sti____myFunction()但是,如果我使用GDB运行它,然后查找该符号,它将被重新定位到一个不同的地址:
root@server:/workspace/test_apps# gdb --args env LD_PRELOAD=/some_library.so ./myapp
(gdb) run
(gdb) info functions
...
0x0000555555555b65 __sti____myFunction()我要注意的最后一点是,如果我使用这个新地址(0x0000555555555b65)来调用函数,而不是前面查找的地址(0x1b65),它可以工作(没有段错误),但只在gdb上下文中工作。在GDB之外,这两个地址都不工作。
发布于 2022-11-29 15:00:25
在运行可执行文件时,我得到了一个分段错误,但只有在我在GDB之外运行它时才会得到这个错误。
应用程序只在GDB之外崩溃并不完全不寻常--调试确实会改变时间,并且(默认情况下)禁用ASLR。
您应该能够从“外部”GDB收集core转储,然后用GDB:gdb ./myapp core调试该core。
gdb --args env ...
这不是你想做的--你要求GDB调试env二进制文件。
在您的情况下调用GDB的正确方法是:
gdb -q ./myapp
(gdb) set env LD_PRELOAD /some_library.so
(gdb) run或者,在一个命令中:gdb -ex 'set env LD_PRELOAD /some_library.so' -ex run ./myapp
注意:根据some_library.so定义的函数,这可能仍然不起作用(可能会干扰GDB为输出重定向而调用的shell )。您可能还必须使用set startup-with-shell off (文档)。
也请参阅这个相关的回答。
void (*myFunc)(void) = (void(*)(void)) 0x1b65;
您有一个饼可执行文件,它在运行时被重新定位到0x555.地址。当然,0x1b65不能工作--这不是应用程序实际运行的地址。
要简化调试,请使用myapp重新构建-no-pie二进制文件(如果可以的话)。
https://stackoverflow.com/questions/74615477
复制相似问题