【问题标题】:Linking RVCT libraries with GCC将 RVCT 库与 GCC 链接
【发布时间】:2012-08-31 10:18:57
【问题描述】:

我正在尝试将使用RVCT 2.2 编译的静态第三方库与使用GCC 编译的测试程序链接(arm-none-linux-gnueabi-gcc Sourcery G++ Lite 2011.03-41)。

如果我与-static 链接,一切正常。但是,如果我不使用-static,我会收到很多类似以下的投诉:

foolib.a(foo.o): In function `foofunc':
foo.c:(.text+0x4c8): undefined reference to `__aeabi_memcpy'
foolib.a(bar.o): In function `barfunc':
bar.c:(.text+0xa54): undefined reference to `__aeabi_memclr4'

memcpymemset 都应该存在于 libc 中。 显然,如果我使用 -staticGCC 可以以某种方式检测并解决此问题。有人可以解释发生了什么吗?我假设 GCC 动态链接到 libc,除非我添加 -static 标志,但不应该在共享 libc 库中定义 __aeabi_memcpy 和类似的东西吗?


编辑:
为了让人们自己测试,我现在创建了一个简约的测试用例,如下所示:

//foo.c
#include <string.h>

void foo(void *dst, void *src, int num) {
    memcpy(dst, src, num);
}

该文件使用 RVCT 2.2 编译和归档如下:

armcc.exe --arm -c --apcs=/noswst/interwork foo.c -o foo.o
armar.exe --create foo.a foo.o

这个库然后与以下测试程序链接:

//bar.c
#include <stdio.h>
extern void foo(void *dst, void *src, int num);
int main(int argc, char *argv[]) {
    int a[10], b[10], i;

    for (i = 0; i < 10; i++) {
            a[i] = i;
    }

    foo(b, a, sizeof(a));

    for (i = 0; i < 10; i++) {
            if (a[i] != b[i]) {
                    printf("Diff at %d: %d != %d\n", i, a[i], b[i]);
                    return 1;
            }
    }
    printf("Success!\n");
    return 0;
}

使用以下命令:

arm-none-linux-gnueabi-gcc -Wall bar.c foo.a -o bar

它给出以下输出(除非-static 也被使用):

foo.a(foo.o): In function `foo':
foo.c:(.text+0x0): undefined reference to `__aeabi_memcpy'
arm-none-linux-gnueabi/bin/ld: bar: hidden symbol `__aeabi_memcpy' isn't defined
arm-none-linux-gnueabi/bin/ld: final link failed: Nonrepresentable section on output
collect2: ld returned 1 exit status

如果您没有 RVCT,可以从 http://dl.dropbox.com/u/14498565/foo.a 下载二进制 foo.a。

【问题讨论】:

  • 工具链编译时是否支持共享库?我记得有一次我自己看到过一个问题,我们没有编译支持共享库的工具链。
  • 不确定,它是 CodeSourcery 网站上提供的预编译二进制文件。我可以用它创建共享库,所以我认为它支持它。
  • 你在使用类似 -nodefaultlibs 的东西吗?如果是这样,您可能需要手动链接 libgcc_s。
  • 这篇文章说arm编译器可以将memcpy链接到一个特别优化的。 infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/…
  • @jszakmeister 不,我用arm-none-linux-gnueabi-gcc -Wall -O2 testprog.c library.a -o testprog 编译,加上-static 让它工作。

标签: gcc linker arm static-linking


【解决方案1】:

在与@Leo 相处一段时间后,我想我明白发生了什么。似乎 foo.o 的编译方式需要 static 链接到 __aeabi_memcpy。用arm-none-linux-gnueabi-objdump -t 看 foo.o,我看到了这个:

foo.o:     file format elf32-littlearm

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 foo.c
00000000 l    d  .text  00000000 .text
00000000 l       *ABS*  00000000 BuildAttributes$$THUMB_ISAv1$ARM_ISAv4$M$PE$A:L22$X:L11$S22$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$EBA8$REQ8$PRES8$EABIv2
00000000 l     O .debug_frame$$$.text   00000000 C$debug_frame$$$.text7
00000000  w    F *UND*  00000000 .hidden Lib$$Request$$armlib
00000000       F *UND*  00000000 .hidden __aeabi_memcpy
00000000 g     F .text  00000004 .hidden foo

注意命令行中的-t...这是为了向我们展示静态符号(非共享)。在 foo.o 上运行 arm-none-linux-gnueabi-objdump -T 会显示:

foo.o:     file format elf32-littlearm

/home/jszakmeister/.local/sourcery-arm-gnueabi/bin/arm-none-linux-gnueabi-objdump: foo.o: not a dynamic object
DYNAMIC SYMBOL TABLE:
no symbols

所以__aeabi_memcpy 正在寻求通过静态链接解决,这就是使用-static 有效的原因。我相信如果您编译 foo.o 的方式稍有不同,以便它需要一个共享的 C 库,那么您可以在不指定 -static 的情况下链接到 foo.a。不幸的是,我不熟悉 RVCT 编译器,或者我会告诉你怎么做。

FWIW,使用 strace 我可以看到它确实链接到共享 C 库,但没有解析链接。我还使用了--sysroot=/path/to/code/sourcery/toolchain/arm-none-linux-gnueabi/libc 命令行选项来确保它找到了正确的 C 库。

【讨论】:

  • 太棒了!这似乎确实可以解释正在发生的事情。我想我将不得不调查 RVCT 编译器标志。
【解决方案2】:

这些是运行时 ABI 定义的辅助函数: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043c/IHI0043C_rtabi.pdf

解决方法可能是实现您自己的版本(使用 libc memcpy 和 memset),但也可能是这里发生了更微妙的链接问题,可能会进一步绊倒您。很难说没有访问目标文件。

【讨论】:

  • 奇怪的是,如果提供-static,GCC 似乎可以自行解决这个问题。我现在添加了示例代码和目标文件,以防您想试验。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多