使用GNU gold链接器

时间:2017-08-03 16:10:06

标签: linker ld binutils linker-scripts gold-linker

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

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

使用gold而不是ld,似乎忽略了这样的指令。该 链接过程成功。但是,使用此指令时要具体说明 使用gold在特定位置的符号,并检查生成的符号布局 使用nm或查看Map文件时,符号不在预期的范围内 位置。

我使用静态编译的虚拟hello world程序制作了一个小测试用例 与gcc 5.4.0的关系。 C库是musl libc(最后提交的 来自官方git存储库的master分支)。对于binutils,我也使用了 最后在官方git存储库的master分支上提交。

我使用链接描述文件从静态放置特定符号(.text.exit) 库(musl C库:libc.a)位于地址空间的特定位置 这是:.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存档?

1 个答案:

答案 0 :(得分:0)

  

使用链接描述文件在地址空间中布置符号时,ld允许   指的是来自静态内部特定目标文件的特定符号   具有以下语法的库:

     

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

这不是语法的意思。当你看到 链接器脚本中的“.section.symbol_name”(或在readelf或 objdump部分列表),这是部分的全名,和 如果你使用的话,你只会看到名称相似的部分 编译时的-ffunction-sections选项。鉴于你的脚本 适用于ld,如果你只使用完整的文件名通配符 黄金,看起来你的musl图书馆确实编译了 -ffunction-sections,但这不是你总能想到的 对系统库来说是真的。所以链接器并没有真正搜索到 名为“.text”的部分,用于定义名为“exit”的符号 - 相反, 它只是寻找一个名为“.text.exit”的部分。微妙 差异,但你应该知道它。

  

现在,虽然这些都不适用于黄金:   MUSL / LIB /文件libc.a:exit.o(.text.exit);   MUSL / LIB /文件libc.a(.text.exit);

     

这有效:   *(。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)