You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让链接器优先选择动态库符号而非本地弱符号?

链接器优先选择本地弱符号而非动态库符号问题

我无法让链接器优先选用动态库中的puts符号,反而会使用目标文件a.o中的本地弱符号,无论是使用lld还是GNU ld均存在该问题。重定位被硬编码到本地puts而非通过PLT处理,我并未生成静态可执行文件。

代码与操作过程

# 查看代码内容
tail -n10 {a,main}.c
==> a.c <==
#include <stdlib.h>

__attribute__((weak))
int puts(const char *ignore) {
    abort();
}


==> main.c <==
int puts(const char*);

int main() {
    puts("Should work");
}

# 编译生成目标文件
clang-16 -c {a,main}.c

# 查看main.o的重定位表
readelf -r main.o

Relocation section '.rela.text' at offset 0x180 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000007  000300000002 R_X86_64_PC32     0000000000000000 .L.str - 4
00000000000c  000500000004 R_X86_64_PLT32    0000000000000000 puts - 4

Relocation section '.rela.eh_frame' at offset 0x1b0 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0

# 查看a.o的符号表
readelf --syms a.o   

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS a.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 .text
     3: 0000000000000000    17 FUNC    WEAK   DEFAULT    2 puts
     4: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND abort

# 链接并追踪puts符号
clang-16 -fuse-ld=lld -v -Wl,--trace-symbol=puts /lib/x86_64-linux-gnu/libc.so.6 {a,main}.o
Debian clang version 16.0.6 (++20230710041738+7cbf1a259152-1~exp1~20230710161755.7)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/lib/llvm-16/bin/ld.lld" -pie --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /lib/x86_64-linux-gnu/Scrt1.o /lib/x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/12/crtbeginS.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/12 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/lib -L/usr/lib --trace-symbol=puts /lib/x86_64-linux-gnu/libc.so.6 a.o main.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/12/crtendS.o /lib/x86_64-linux-gnu/crtn.o
/lib/x86_64-linux-gnu/libc.so.6: shared definition of puts
a.o: definition of puts
main.o: reference to puts

# 运行程序
./a.out 
Aborted (core dumped)

# 用gdb查看main函数汇编
gdb -quiet a.out
Reading symbols from a.out...
(No debugging symbols found in a.out)
(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000001780 <+0>: push   %rbp
   0x0000000000001781 <+1>: mov    %rsp,%rbp
   0x0000000000001784 <+4>: lea    -0x11df(%rip),%rdi        # 0x5ac
   0x000000000000178b <+11>:    call   0x1760 <puts>
   0x0000000000001790 <+16>:    xor    %eax,%eax
   0x0000000000001792 <+18>:    pop    %rbp
   0x0000000000001793 <+19>:    ret
End of assembler dump.

内容的提问来源于stack exchange,提问作者Artefacto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:20:56