我想获取函数_dl_start的地址(动态链接器的入口点)。我可以使用gdb设置断点。我希望使用readelf找到符号,但我没有。如何获取地址/ gdb如何解析_dl_start?
使用gdb设置断点的示例源(main.cpp)是
int main( int argc, char** argv, char** envp )
{
return 0;
}
我用
编译了它 g++ main.cpp -o teststart
运行程序时的gdb输出是
(gdb) b _dl_start
Function "_dl_start" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (_dl_start) pending.
(gdb) r
Starting program: /tmp/teststart
Breakpoint 1, 0x00007fa7ee8c4fc4 in _dl_start () from /lib64/ld-linux-x86-64.so.2
答案 0 :(得分:4)
_dl_start
符号在ld-linux-x86-64.so.2
(动态加载程序)中,该符号是私有到ld-linux。这意味着从程序内部找到它的唯一方法是做GDB所做的事情:读取ld-linux
的符号表,并在其中搜索“_dl_start”函数(按名称)。直接链接(如马丁建议的那样)不能也不会起作用(正如你已经发现的那样)。
阅读ELF符号表并不是很复杂 - 您只需找到.symtab
和.strtab
部分,并将.symtab
读作Elf64_Sym
条目表。或者使用libelf
(开始here)。
另一个复杂因素是ld-linux
可能被剥离(符号表不是必需的)。如果有规定,GDB和您的程序都无法找到_dl_start
。
最后,您尝试查找_dl_start
的可能性很小:您做意识到此函数在第一条指令之前被称为long 你的程序被执行了。当你点击main
时,_dl_start
已经完成,永远不会再被召唤。
Upate:
我仍然想知道gdb如何在ld-linux中获取_dl_start的地址(它被剥离)
如果ld-linux
被剥离,GDB将 无法在其中找到_dl_start
。既然GDB确实找到了它,那么
ld-linux
实际上并未被剥离,或要验证ld-linux
是否已完全剥离,请运行nm /lib64/ld-linux-x86-64.so.2 | grep _dl_start
和readelf -S /lib64/ld-linux-x86-64.so.2 | grep symtab
。这两个命令都不会产生输出。
要查看GDB从哪里加载符号,您可以使用set print symbol-loading on
命令(在运行可执行文件之前)。
我想调用_dl_start(在准备堆栈并调整辅助向量之后)以创建已存储在内存中的程序的可执行映像(文件表示)...
我不知道可能的工作方式。 _dl_start
在调用之前需要某个状态(例如它的全局变量被清零),因此第二次调用它是非常可能导致断言失败,即使你没有t调整辅助矢量。如果你做以某种非平凡的方式调整辅助向量,那么断言更有可能,这显然是你的目标。
答案 1 :(得分:0)
_dl_start不是程序本身的一部分,它包含在运行时加载器中(正如您从/lib64/ld-linux-x86-64.so.2的输出“... _ dl_start()中看到的那样”) )。 GDB最初无法设置断点,因为它不包含在您的可执行文件中。 如果您想从程序内部或外部了解_dl_start的地址,我有点不清楚?从内部,您应该能够简单地分配它,例如到这样的void *变量:
void* address = dl_start;