【问题标题】:How does a loader allocate/deallocate static data from a dynamic module加载器如何从动态模块分配/释放静态数据
【发布时间】:2016-03-30 18:11:09
【问题描述】:

链接器专家的问题。我一直在使用 Matlab 中的 mex 文件,并且遇到了很多无法解释的崩溃,所以我想深入挖掘一下。

您能否向我解释一下,当加载(卸载)动态模块时,如何在进程的虚拟内存空间中分配(释放)静态数据?

我假设这发生在 _init()_fini() 函数中。但是,BSS 段是否在堆空间中分配了一块内存,以及其他动态内存分配?

动态模块中的全局数据呢?符号名称是否可能与主可执行文件发生冲突?

感谢您阐明这些问题。如果我必须选择一个平台,我希望听取 ELF 专家的意见,因为我的大部分开发工作都是在 Linux 上完成的。

【问题讨论】:

    标签: c++ linker loader mex elf


    【解决方案1】:

    您能解释一下在加载(卸载)动态模块时如何在进程的虚拟内存空间中分配(释放)静态数据吗?

    这部分很简单:每个ELF 文件都有PT_LOAD 段,您可以在readelf -Wl foo.so 的输出中看到这些段。加载共享对象时,这些段中的每一个都被mmap 分配到地址空间中,并充当该共享对象中任何静态数据的“分配”。

    foo.so 被卸载时,数据(和代码)通过munmap 系统调用处理。

    我假设这发生在 _init() 和 _fini() 函数中

    这个假设是不正确的。 _init_fini 是关于动态 初始化(例如,C++ 中的类类型的全局变量具有非平凡的构造函数/析构函数)。在调用_init 时,所有全局变量的内存都已通过mmap“保留”。

    但是 BSS 段

    .bss 部分包含在其他已初始化(可写)数据所在的同一 PT_LOAD 段中。这就是为什么在ElfXX_Phdr 中有一个单独的p_fileszp_memszp_filesz“覆盖”初始化数据,并且(更大的)p_memsz 导致mmap 为这两个初始化“分配”空间和.bss 数据。

    动态模块中的全局数据呢?

    怎么样?我在上面介绍了初始化数据。

    符号名称是否可能与主可执行文件发生冲突?

    当然。您可以在a.out 中定义int foo = 42;,在foo.so 中定义int foo = 24;。通常的规则是如果fooa.out的动态符号表中可见,那么无论从哪里引用foo都会被使用。

    a.out 没有导出foo(如果它没有与-rdymamic 链接并且 没有链接到foo.so),或者当foo.so-Bsymbolic.

    【讨论】:

    • 感谢@EmployedRussian,我在动态符号表上挖掘了更多,似乎只有在指定 -rdynamic 时才会将全局符号导出到动态符号表中。通常它们不会被导出,因此动态模块无法从可执行文件中访问它们。这是正确的吗?
    • @DKWH 有 3 种方法(据我所知)从 a.out 导出符号:(1)您链接到 -rdynamic(或 -E,或 --export-dynamic ) 或 (2) 您直接链接到使用该符号的 foo.so 或 (3) 您在链接器版本脚本中导出该符号。
    猜你喜欢
    • 1970-01-01
    • 2011-09-06
    • 2011-11-18
    • 2013-08-29
    • 2018-06-05
    • 1970-01-01
    • 2012-01-08
    • 2012-05-07
    相关资源
    最近更新 更多