Linker 在链接之前删除死代码

Linker 在链接之前删除死代码,linker,undefined-symbol,dead-code,link-time-optimization,Linker,Undefined Symbol,Dead Code,Link Time Optimization,在一个由几个静态链接的对象文件组成的项目中,我将用一个单独的实现替换其中的一个。我想在实现替换的对象文件提供的每个符号之前测试我的代码,因此我使用-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块可能有两个入口点,一个用于运行单元测试,另一个用于执行代码的任何用途。单元测试需要整个模块所需的符号子集。能够构建单元测试部件而无需构建其他所有部件有一个优势

死区剥离是对我以前的
-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

目标文件是从生成的LLVM IR(而不是C代码)生成的,如果这有区别的话。通过opt传递IR就足够了吗?听起来像是死区剥离,然后像正常情况下那样链接会做这个技巧,我不认为
opt
有帮助,因为
opt
一次只看一个模块,对吗?我想使用llvm链接将各种IR放在一起,然后opt(特别是-dce,-globaldce)剥离。将IR转换为目标代码。然后链接器会得到一个文件,并且仍然会对实际可访问的符号发出警告。嗯,这可能会起作用,但很难集成到现有的构建系统中(在最终链接它们之前,它会将每个
.ll
文件编译成
.o
文件)。