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