在一个由几个静态链接的目标文件组成的项目中,我将其中一个替换为单独的实现。我什至想在我实现替换的目标文件提供的每个符号之前测试我的代码,所以我使用-Wl,--unresolved-symbols=ignore-all
链接器不抱怨丢失的符号。
但是当我测试代码时,它在尝试使用未定义的符号之一时会崩溃。因此,我正在寻找一种方法来告诉链接器“请在链接之前删除所有未引用的代码,然后告诉我在从入口点可到达的代码中是否还有未引用的符号”。那可能吗?
在一个由几个静态链接的目标文件组成的项目中,我将其中一个替换为单独的实现。我什至想在我实现替换的目标文件提供的每个符号之前测试我的代码,所以我使用-Wl,--unresolved-symbols=ignore-all
链接器不抱怨丢失的符号。
但是当我测试代码时,它在尝试使用未定义的符号之一时会崩溃。因此,我正在寻找一种方法来告诉链接器“请在链接之前删除所有未引用的代码,然后告诉我在从入口点可到达的代码中是否还有未引用的符号”。那可能吗?
由于我在自己的代码库中发现了此方法的用途并检查了该方法是否适合我,因此根据评论紧密地编写了一个答案。
int do_things(void);
int application_main(void)
{
return do_things();
}
int test_main(void)
{
return 42;
}
int main(void)
{
return test_main();
}
布局大致反映了我的用例。一个给定的 IR 块可能有两个入口点,一个用于运行单元测试,一个用于执行代码的用途。单元测试需要整个模块所需的符号子集。能够在不构建其他所有内容的情况下构建单元测试部分是一个优势。
Deadstripping 比我之前的-Wl,--unresolved-symbols=ignore-all
clang demo.c # undefined reference to `do_things'
clang -O3 demo.c # undefined reference to `do_things'
clang demo.c -c -emit-llvm -o demo.bc # OK
llvm-nm demo.bc
---------------- T application_main
U do_things
---------------- T main
---------------- T test_main
clang demo.bc # undefined reference to `do_things'
opt -o stripped.bc -internalize -internalize-public-api-list=main -globaldce demo.bc
llvm-nm stripped.bc
---------------- T main
---------------- t test_main
clang stripped.bc # OK
公共符号列表可以从 ir 文件(至少在我的情况下)派生,因此 opt 调用实际上是
opt -internalize -internalize-public-api-list=`llvm-nm -extern-only -defined-only -just-symbol-name some-file.bc` -globaldce -O2