如何在动态打开的共享库条目上设置断点? 在某些上下文中,我用G++编译的实验事务内存模型来检查一个简单的C++程序。我想知道调用register\u tm\u clones的确切位置(通过objdump一个简单的程序可以看到fn)。即使在像int main(){}这样的程序中,也会调用此函数

如何在动态打开的共享库条目上设置断点? 在某些上下文中,我用G++编译的实验事务内存模型来检查一个简单的C++程序。我想知道调用register\u tm\u clones的确切位置(通过objdump一个简单的程序可以看到fn)。即使在像int main(){}这样的程序中,也会调用此函数,c++,linux,gdb,ld,C++,Linux,Gdb,Ld,我想知道在通用程序的整个范围内调用register\u tm\u clones的地方。我在GDB中设置了一个断点,并回溯: Breakpoint 1, 0x00007ffff7c5e6e0 in register_tm_clones () from /usr/lib/libgcc_s.so.1 (gdb) bt #0 0x00007ffff7c5e6e0 in register_tm_clones () from /usr/lib/libgcc_s.so.1 #1 0x00007ffff7f

我想知道在通用程序的整个范围内调用
register\u tm\u clones
的地方。
我在GDB中设置了一个断点,并回溯:

Breakpoint 1, 0x00007ffff7c5e6e0 in register_tm_clones () from /usr/lib/libgcc_s.so.1
(gdb) bt
#0  0x00007ffff7c5e6e0 in register_tm_clones () from /usr/lib/libgcc_s.so.1
#1  0x00007ffff7fe209a in call_init.part () from /lib64/ld-linux-x86-64.so.2
#2  0x00007ffff7fe21a1 in _dl_init () from /lib64/ld-linux-x86-64.so.2
#3  0x00007ffff7fd313a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#4  0x0000000000000001 in ?? ()
#5  0x00007fffffffe390 in ?? ()
#6  0x0000000000000000 in ?? ()
ld linux
在程序中的某个点打开
libgcc
时,会调用它。我确保我们已链接到
libgcc
。是的:

❯ ldd main
    linux-vdso.so.1 (0x00007fff985e4000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f7eb82dc000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007f7eb8196000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f7eb817c000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f7eb7fb6000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f7eb84ec000)
但是。。。我如何知道何时调用它(它肯定不在
main
中)?我知道启动> /COD>是C++程序的真正入口。我们运行
\uu libc\u csu\u init
,然后有一些步骤,我们进入main。我如何设置断点,以便在全局图中查看
ld
何时决定打开
libgcc
,从而查看调用
register\u tm\u clone
的位置

我如何设置断点,以便在全局图中看到ld何时决定打开libgcc,以及由此调用register_tm_克隆的位置

你已经看到了

我认为您的困惑在于不理解动态链接流程运行时会发生什么。大致来说,步骤如下:

  • 内核创建一个新的进程“shell”,并
    mmap
    s将可执行文件放入其中

  • 内核观察到可执行文件具有
    PT_INTERP
    段,并且
    mmap
    s将其中引用的文件也放入进程中。这里,
    PT_INTERP
    的内容是
    /lib64/ld-linux-x86-64.so.2
    ,又名动态加载程序,不要与
    /usr/bin/ld
    (又名静态链接器)混淆

    此外,由于有一个程序解释器,内核将控制权转移给它(而不是在主可执行文件中调用
    \u start
    ),因为主可执行文件还没有准备好运行

  • ld linux
    开始运行时,它首先重新定位自身,然后
    mmap
    s主可执行文件直接链接到的所有库。您可以使用
    readelf-da.out | grep NEEDED
    查看这些库

    注意:由于这些库中的每个库本身可能直接依赖于其他库,因此这个过程是递归重复的

  • 初始化库(通过调用它们的构造函数,该构造函数通常被称为
    \u init
    ,但也可以有不同的名称) 我如何设置断点,以便在全局图中看到ld何时决定打开libgcc,以及由此调用register_tm_克隆的位置

    你已经看到了

    我认为您的困惑在于不理解动态链接流程运行时会发生什么。大致来说,步骤如下:

  • 内核创建一个新的进程“shell”,并
    mmap
    s将可执行文件放入其中

  • 内核观察到可执行文件具有
    PT_INTERP
    段,并且
    mmap
    s将其中引用的文件也放入进程中。这里,
    PT_INTERP
    的内容是
    /lib64/ld-linux-x86-64.so.2
    ,又名动态加载程序,不要与
    /usr/bin/ld
    (又名静态链接器)混淆

    此外,由于有一个程序解释器,内核将控制权转移给它(而不是在主可执行文件中调用
    \u start
    ),因为主可执行文件还没有准备好运行

  • ld linux
    开始运行时,它首先重新定位自身,然后
    mmap
    s主可执行文件直接链接到的所有库。您可以使用
    readelf-da.out | grep NEEDED
    查看这些库

    注意:由于这些库中的每个库本身可能直接依赖于其他库,因此这个过程是递归重复的


  • 初始化库(通过调用它们的构造函数,通常称为
    \u init
    ,但也可以有不同的名称)您的问题不清楚:您已经看到了调用它的确切位置。另外,
    ld!=ld linux
    ,请不要混淆它们,以免混淆每个人。抱歉,我应该更清楚我的要求。我的意思是我想确切地知道,从
    \u开始
    到程序结束,调用
    register\u tm\u clones
    的位置。另外,我想我不熟悉
    ld
    ldlinux
    之间的区别。你能给我解释一下区别吗?这样我就可以编辑问题陈述了?我已经更新了问题,使我要问的问题更清楚。你的问题不清楚:你已经看到了它的确切名称。另外,
    ld!=ld linux
    ,请不要混淆它们,以免混淆每个人。抱歉,我应该更清楚我的要求。我的意思是我想确切地知道,从
    \u开始
    到程序结束,调用
    register\u tm\u clones
    的位置。另外,我想我不熟悉
    ld
    ldlinux
    之间的区别。你能给我解释一下区别吗?这样我就可以编辑问题陈述了?我已经更新了问题,使我要问的问题更清楚。我明白了。谢谢你的详细解释!我不确定动态链接器何时完成整个mmaping。我一直认为
    \u start
    才是程序的真正开始。因此,如果我没有弄错的话(只是总结一下):动态链接器会映射所有需要的共享库,运行它们的
    \u init
    (或任何调用),然后在主可执行文件中调用
    \u start
    ,对吗?@OneRaynyDay是的,对
    \u start
    是程序的实际开始,但是
    ld linux
    运行