在链接之前删除死代码

时间:2017-03-29 20:51:18

标签: linker undefined-symbol dead-code link-time-optimization

在由几个静态链接的目标文件组成的项目中,我将使用单独的实现替换其中一个。我想在实现替换目标文件提供的每个符号之前测试我的代码,所以我使用-Wl,--unresolved-symbols=ignore-all让链接器不要抱怨丢失的符号。

但是当我测试代码时,它只是在尝试使用其中一个未定义的符号时崩溃。因此,我正在寻找一种方法来告诉链接器“请在链接之前删除所有未引用的代码,然后告诉我,如果在从入口点可到达的代码中,仍然存在未引用的符号”。这可能吗?

1 个答案:

答案 0 :(得分:3)

根据评论密切写出答案,因为我在自己的代码库中找到了这个用法,并检查该方法对我来说是否正常。

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