链接特定库的部分

时间:2013-11-18 09:06:55

标签: gcc ld

我有一个用于微控制器的GCC项目。运行时中有一些函数必须替换才能适应环境:

_write_r
_sbreak_r

我已在sys.c文件中实现了这些功能。当我将文件sys.o与我的项目链接时,它按预期工作。但是当我将sys.o添加到库bsp.a并将库与我的项目链接时,libc.a实现优先,我的替换不再起作用。

如何在从libc获取定义之前控制它首先链接我的库的链接器?我更喜欢链接器脚本控制此优先级的解决方案。

编辑: GCC由开发环境调用,用于链接阶段。它控制ld调用,并且无法直接控制ld命令行参数。

编辑: CPU是Cotex-M3 NXP LPC1788。

当我使用-v选项运行gcc链接命令时,我得到以下信息:

c:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4/collect2.exe
--sysroot=arm\bin\../arm-none-eabi
-X
-o bin/test.elf
-n arm/bin/../lib/gcc/arm-none-eabi/4.7.4/armv7-m/crti.o arm/bin/../lib/gcc/arm-none-eabi/4.7.4/armv7-m/crtbegin.o arm/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/armv7-m/crt0.o
-LD:/mylibs
-LC:\arm\lib
-Lc:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4/armv7-m
-Lc:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/armv7-m
-Lc:/arm/bin/../arm-none-eabi/lib/armv7-m
-Lc:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4
-Lc:/arm/bin/../lib/gcc
-Lc:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib
-Lc:/arm/bin/../arm-none-eabi/lib @C:\Users\harper\AppData\Local\Temp\cc9FN35g
--start-group -lgcc -lc --end-group
c:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4/armv7-m/crtend.o
c:/arm/bin/../lib/gcc/arm-none-eabi/4.7.4/armv7-m/crtn.o
-T src\LPC1788_Flash.ld

--start-group -gcc -lc --end-group显然有一个collect2.exe参数。但是还没有可能添加我的库。

文件LPC1788_Flash.ld具有以下内容:

ENTRY(Reset_Handler)
MEMORY {
  FLASH (rx) : ORIGIN = 0, LENGTH = 512K
  RAM (xrw) : ORIGON = 0x10000000, LENGTH = 64K
}
SECTIONS {
  // a lot of input and output sections, like ...
  .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) } >FLASH
  .data : { ... } >RAM
  .bss : { ... } >RAM
  /DISCARD/ : {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
}

2 个答案:

答案 0 :(得分:0)

这很简单:
glibc库本身就面临这个问题:大多数函数需要静态链接,但有些可以动态使用并在共享对象中使用。
此外,静态存档具有Glibc共享对象中的一些功能的副本。

因此,在所有平台上都可以使用Glibc作为默认值,使用静态版本的Glibc安装链接器脚本。无论操作系统是什么,该文件都位于/lib/libc.so(或/lib64/libc.so,如果您使用的是64位)下。它包含这个:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a  AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )

我不知道您使用的是哪个libc(可以是μClibc),但文件libc.so永远不会导致二进制文件(如果存在)。

因此,您需要修改它或创建它:

OUTPUT_FORMAT(the_format_used_by_your_micro-controller_architecture)
GROUP( /the_path_to_your_custom_library_binary /the_path_your_libc_binary AS_NEEDED ( /the path the_path_your_interpreter_binary ) )

您在GROUP()内指定的顺序:如果两个库二进制文件中都存在exports-symbols,那么它们将由GROUP()中的第一个二进制文件提供。

答案 1 :(得分:0)

如果要使用自定义库的源文件的定义,则必须确保在加载系统库之前加载(库的)相应的目标文件以解析外部。

这可以通过明确引用该文件的符号来完成。

extern int _write_r();
void *magic = &_write_r;

应放置此代码,以便编译器不会因优化而忽略它。

遗憾的是,使用链接描述文件构建包含系统库的自定义库的组是不可能的。链接器脚本的GROUP定义在内置规则定义的组之后处理。