给定一个公开符号的目标文件,我如何确定该符号是否也在内部使用?
我的目标是死功能检测。我已经有能力(通过readelf
)查找它是否从另一个目标文件中使用,但是当它仅在内部使用时会失败。
如果重要的话,我正在使用 C++
给定一个公开符号的目标文件,我如何确定该符号是否也在内部使用?
我的目标是死功能检测。我已经有能力(通过readelf
)查找它是否从另一个目标文件中使用,但是当它仅在内部使用时会失败。
如果重要的话,我正在使用 C++
它实际上取决于您的编译器如何处理内部编译单元调用,但有一些建议。
首先,如果您正在优化,编译器可能会内联您的函数,即使它们没有标记inline
。always_inline
实际上,如果函数用属性标记,它会努力这样做。因此,即使函数 f 确实调用了函数 g,也没有证据表明函数f调用了函数g 。请注意,如果g本身是一个外部可访问的函数,则编译器可能会生成两次(或更多次)其代码,首先以自己的名称用于外部调用,然后内联到f的目标代码(和其他调用函数)。
因此,避免优化并以某种方式抑制always_inline
. 您甚至可以明确指定-fno-inline
以防止内联。
其次,您的目标架构可能具有相关的调用和分支指令。如果您的f和g被放置在它们共同的代码段中,编译器可能会利用这一点。它是非内联函数的默认值。在这种情况下,编译器在编译时就知道调用位置与被调用者开头之间的偏移量,并可以生成相对调用或跳转指令;无需进一步搬迁。一些编译器可能会发出“无操作”重定位,但有些不会。无重定位意味着该符号未被引用。
所以,使用-ffunction-sections
(和用于数据-fdata-sections
)。然后将每个函数放入其自己的部分,编译器别无选择,只能为链接器生成重定位以进行修复(从而使被调用者的符号被引用)。
请注意,如果在调用时使用-ffunction-sections
然后指定,编译器将丢弃所有未引用的部分。如果您随后添加,您将获得生成的模块图。废弃的功能不会显示在地图中。--gc-sections
ld
-M
作为旁注,请记住,在某些情况下,静态分析无法检测到永远无法调用函数。例如,在编写良好的 C++ 程序__cxa_pure_virtual
中永远不会被调用,但在所有抽象类的虚函数表中都会引用它。此外,即使在整个程序中没有对该虚函数的单个调用,普通虚函数的覆盖也将通过虚函数表引用并链接。符号分析无法检测到这些情况。