确定_dl_start的地址

时间:2012-08-13 09:35:08

标签: gdb elf

我想获取函数_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

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确实找到了它,那么

  1. 您的ld-linux实际上并未被剥离,或
  2. 安装了glibc,你有“单独的debuginfo”package
  3. 要验证ld-linux是否已完全剥离,请运行nm /lib64/ld-linux-x86-64.so.2 | grep _dl_startreadelf -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;