丢弃理论上已使用但技术上未使用的功能



是否可以以某种方式丢弃输出文件(.exe/.elf(中的函数/符号,即使它可以被调用?

比方说,第三方图书馆做的事情是这样的:

int lib_func_get(int c) {
if (c < 5) {
return foo();
} else {
return bar()
}
}

你肯定知道,c从来都不是<5,那么我想从我的可执行文件中省略/删除foo((以减少二进制大小。

我该怎么做?也许可以借助链接器脚本并丢弃.text.foo

GCC的链接器对此有一个类似的部分/DISCARD/,但链接失败是因为使用了以下函数:

refers [symbol], which is defined in a discarded section

我的问题的背景是减少嵌入式应用程序的二进制大小,尤其是引导程序,在这种情况下,你不能重新编译第三方库,或者该库是工具链的一部分(例如libgcc(,你不想修改和重建整个工具链。

我知道,这可能是一个棘手的方法,但我想这样做。

在问题是本地的情况下,最好的方法是提供编译器提示:

#define ASSUME(cond) do {      
if (!(cond))               
__builtin_unreachable(); 
} while (0)
int lib_func_get(int c) {
ASSUME(c >= 5);
if (c < 5) {
return foo();
} else {
return bar()
}
}

这将删除函数定义和周围的代码。

否则,您可以在链接时覆盖符号:

$ gcc tmp.c -Wl,--defsym=printf=0
$ objdump -d tmp.c | grep printf
113d:   e8 be ee ff ff          callq  0 <printf>

是否可以以某种方式丢弃输出文件(.exe/.elf(中的函数/符号,即使它可以被调用?

否。

你肯定知道,c从来都不是<5,那么我想省略/删除foo((。。。我该怎么做?

因此重构代码并删除对foo()的调用。


将符号标记为弱符号,并用调用abort的实现替换它,或者如果你真的很勇敢,只返回。类似地,您可以使用--wrap。例如:

objcopy --weak-symbols=foo the_lib_with_foo.o the_lib_with_weak_foo.o
echo 'void foo() { return; }' | gcc -xc - -o foo.o 
gcc foo.o the_lib_with_weak_foo.o -o the_exe.out

这有点依赖,但也有编译器具有类似的功能。

例如,DIAB编译器有一个功能(至少在NXP目标上(,可以将每个函数和全局变量放在单独的ELF部分中(从*.c->*.o(。在链接器中,还有另一个选项,可以删除未使用的部分。

不过,还有一个缺点,对于非常大的文件,您可能会用完ELF部分,因为您最多有65536个部分。

最新更新