使用GNU gold链接器引用静态库中的特定符号

问题描述:

使用链接描述文件在地址空间中布置符号时,ld允许 引用来自静态库的特定符号,其语法如下 :使用GNU gold链接器引用静态库中的特定符号

archive.a:object_file.o(.section.symbol_name) 

使用gold而不是ld,似乎这样的指令被忽略。 链接过程成功。但是,当使用此指令将特定 符号放在特定位置gold并使用nm检查生成的符号布局 或查看映射文件时,符号不在预期的 位置中。

我用一个虚拟hello世界程序制作了一个小测试用例,其静态编译为 ,其gcc版本为5.4.0。 C库是musl libc(最后一次在官方git仓库的 master分支上提交)。对于binutils,我还使用官方git仓库master分支上的 最后一次提交。

我使用链接脚本从静态 库(MUSL C库:libc.a)放置一个特定符号(.text.exit)在地址空间 这是一个特定的位置:在.text部分中的第一位置。

我的链接脚本是:

ENTRY(_start) 
SECTIONS 
{ 
    . = 0x10000; 
    .text : 
    { 
     /* Forcing .text.exit in the first position in .text section */ 
     musl/lib/libc.a:exit.o(.text.exit); 
     *(.text*); 
    } 
    . = 0x8000000; 
    .data : { *(.data*) } 
    .rodata : { *(.rodata*) } 
    .bss : { *(.bss*) } 
} 

我的Makefile:

# Set this to 1 to link with gold, 0 to link with ld 
GOLD=1 

SRC=test.c 
OBJ=test.o 
LIBS=musl/lib/crt1.o \ 
    musl/lib/libc.a \ 
    musl/lib/crtn.o 
CC=gcc 
CFLAGS=-nostdinc -I musl/include -I musl/obj/include 
BIN=test 
LDFLAGS=-static 
SCRIPT=linker-script.x 
MAP=map 

ifeq ($(GOLD), 1) 
LD=binutils-gdb/gold/ld-new 
else 
LD=binutils-gdb/ld/ld-new 
endif 

all: 
    $(CC) $(CFLAGS) -c $(SRC) -o $(OBJ) 
    $(LD) --output $(BIN) $(LDFLAGS) $(OBJ) $(LIBS) -T $(SCRIPT) \ 
     -Map $(MAP) 

clean: 
    rm -rf $(OBJ) $(BIN) $(MAP) 

(使用-Map ld/gold标志获得)来编译和链接我检查的地图文件后看看.text.exit的位置。使用ld作为 链接器,它确实在文本部分的第一个位置。使用gold,它不是 (它存在于地址空间的更远处,就好像我的指令不是考虑到 一样)。

现在,虽然既不gold这些工作:

musl/lib/libc.a:exit.o(.text.exit); 
musl/lib/libc.a(.text.exit) 

这工作:

*(.text.exit); 

的是,在gold缺少功能?或者我做错了什么,也许有 使用gold在 存档中引用特定目标文件的特定符号的另一种方法?

当使用链接脚本铺设在地址空间符号,LD允许 指从一个特定的对象文件来静态 库里面的语法如下特定符号:

存档。答:object_file.o(.section伪。symbol_name)

这不完全是什么语法的含义。当在链接描述文件中(或者在某个节点的重新下载或 objdump列表中)看到 “.section.symbol_name”,这是该节的全名,而 只有当您看到类似名称的节时编译时使用 -ffunction-sections选项。鉴于您的脚本 适用于ld,并且如果您只使用完整文件名通配符,则看起来您的musl库确实是使用 -ffunction-sections编译的,但这并不总是假设为 true用于系统库。因此,链接器并不是真的在搜索名为“.text”的 节,该节定义了一个名为“exit”的符号 - 相反,它只是寻找名为“.text.exit”的节。微妙的 区别,但你应该知道它。

现在,虽然这些工作都没有金: musl/lib/libc.a:exit.o(.text.exit); musl/lib/libc.a(.text.exit);

This works: *(.text.exit);

这是黄金缺失的功能吗?或者我做错了什么,也许有 另一种方式来引用一个 存档使用黄金中的特定对象文件的特定符号?

如果你看一下导致-Map输出文件,我怀疑你会看到 目标文件的名称被写成“MUSL/lib目录/文件libc.a(exit.o)”。 这就是您需要在脚本中使用的拼写,并且因为括号内有 ,所以您需要引用它。这:

"musl/lib/libc.a(exit.o)"(.text.exit) 

应该工作。如果你想要的东西,会在这两个接头工作,尝试 是这样的:

"musl/lib/libc.a*exit.o*"(.text.exit) 

或只是

"*exit.o*"(.text.exit) 
+0

非常感谢您使用引号语法工作。我还检查了musl编译标志,实际上,这些包括-ffunction-sections。 –