列出gcc或clang对象文件中的内部引用

时间:2015-03-26 16:27:08

标签: gcc clang object-code

给定一个公开符号的目标文件,如何确定该符号是否也在内部使用?

我的目标是死函数检测。我已经有能力(通过readelf)来查找是否从另一个目标文件中使用它,但是当它仅在内部使用时会失败。

如果重要,我正在使用C ++

1 个答案:

答案 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,但是在所有抽象类的虚函数表中都会引用它。此外,即使在整个程序中没有单个调用该虚函数,也将通过虚函数表引用普通虚函数的覆盖并进行链接。符号分析无法检测到这些情况。