如何仅导出程序中已使用函数的动态符号?
问题描述
在x86_64 Linux环境中,我使用-rdynamic作为gcc的链接器选项,导出程序中已使用的符号,以便程序发生SEGV或其他异常时,通过glibc的backtrace()生成回溯信息排查问题。程序依赖静态库,这些库中可能包含未使用的函数,而这些未使用函数又依赖其他静态库。程序和库编译时使用-ffunction-sections,链接器使用-Wl,--gc-sections -Wl,--as-needed,此前该参数组合可正常编译,无引用错误。
但升级到binutils-2.22后,突然出现引用错误,必须包含未使用函数依赖的所有库才能编译通过。推测当前链接器的行为是:只要目标文件中至少有一个函数被引用,就会将该文件内所有函数标记为必需。gold、mold等其他链接器也有相同行为,这应该是标准行为,而binutils-2.22之前的ld.bfd未按此规则工作,但那个旧行为刚好符合我的需求。
现在我想复现2.22之前的行为,打算通过-Wl,--dynamic-list手动指定要导出的符号,但不知道如何获取已使用函数的列表?
※ 这看似是XY问题,实际需求是生成带函数名的回溯信息,-rdynamic只是权宜之计。我需要程序发生SEGV时生成回溯,目前通过预加载libSegFault.so实现,它会调用backtrace(),否则我直接使用libbacktrace即可。
最小复现示例
main.c
extern int give_747(void); int main(void) { return give_747(); }
lib1.c(未使用)
int return_123 (void) { return 123; }
lib2.c
#include <execinfo.h> #include <stdlib.h> #include <unistd.h> #include <backtrace.h> extern int return_123(void); static int cb (void *data, uintptr_t pc, const char *filename, int lineno, const char *function) { printf("%s:%d(%s)[%p]\n", filename, lineno, function, (void*)pc); } int give_747(void) { void *bt[4] = {0}; static struct backtrace_state *bts = NULL; backtrace(bt, 4); printf("backtrace_symbols_fd():\n"); backtrace_symbols_fd(bt, 4, STDOUT_FILENO); printf("\nlibbacktrace:\n"); bts = backtrace_create_state(NULL, 0, NULL, NULL); backtrace_full(bts, 0, cb, NULL, NULL); printf("\n"); return 747; } int return_246(void) { int tmp = return_123(); return tmp+tmp; }
Makefile
main: main.o lib2.a $(CC) -Wl,--gc-sections -Wl,--as-needed $^ -o $@ -L/path/to/libbacktrace/lib -lbacktrace maindyn: main.o lib2.a $(CC) -Wl,--gc-sections -Wl,--as-needed -rdynamic $^ -o $@ -L/path/to/libbacktrace/lib -lbacktrace %.o: %.c $(CC) -I/path/to/libbacktrace/include -ggdb -O3 -ffunction-sections -c $< -o $@ lib1.a: lib1.o ar curs $@ $^ lib2.a: lib2.o ar curs $@ $^
链接错误输出
cc -Wl,--gc-sections -rdynamic main.o lib2.a -o maindyn -L/path/to/libbacktrace/lib -lbacktrace lib2.a(lib2.o): In function `return_246': /home/syukri/playground/gcsections/lib2.c:30: undefined reference to `return_123' collect2: error: ld returned 1 exit status make: *** [maindyn] Error 1
内容的提问来源于stack exchange,提问作者syockit
相关产品推荐
相关产品推荐

