我有一个庞大的 C 代码库,包含 100 多个二进制文件、3000 多个文件和 30 多个库。积累了大量死代码,我正在寻找识别和删除这些代码的方法。代码很简单 - 没有复杂的宏,并且(很少)自动生成的代码(lex/bison/...)。
在识别“静态”死代码(和变量)方面,gcc 做得很好(使用-Wunused-*
选项识别所有未使用的静态变量、静态函数等)。我的挑战是非静态全局函数和变量(代码库中有很多!)
我在所有对象文件中使用“nm”进行了大量测试,实际上创建了所有已定义全局符号的列表(代码、数据和未初始化的“T”、“D”和“B”类型)。然后我删除了所有“U”符号。该过程识别了所有未引用的全局符号。此时,我必须手动将每个符号设为静态,用 进行编译gcc -Werror -Wunused
,然后查看它是否会引发任何错误。
# Omitting some details for brevity.
nm --undefined-only lib1.a lib2.a ... obj1 obj2.o obj3.o | sort > refs.txt
nm --extern-only --defined-only lib1.a lib2.a ... obj1 obj2.o obj3.o | sort > defs.txt
join -12 -23 -v2 refs.txt defs.txt
我的问题是 - 是否可以使用“nm”(或其他对象分析工具,如objdump
)来识别目标文件中的哪些全局符号也在同一对象内使用。这将通过将全局函数中的死代码与实际使用的全局函数(但可能变为静态)分开来加速死代码消除。
或者,是否有其他现有工具可以完成这项工作?
我建议为此使用 GNU ld 的死符号删除功能。
为此,您需要使用标志编译代码
-fdata-sections -ffunction-sections
,然后链接-Wl,--gc-sections -Wl,--print-gc-sections
。它将打印有关已删除函数的信息。这是示例程序的示例
(
.text.foo
是为未使用的功能生成的部分foo
)。附注:如果您使用这些选项,可能无需手动清理代码库(除了使其更清洁),因为工具链将自动删除死代码。