在ARM交叉编译时如何选择要链接的静态库?

时间:2014-07-07 17:20:15

标签: linux gcc arm

我在Ubuntu(arm-linux-gnueabi-gcc)中有一个ARM交叉编译器,默认的架构是ARMv7。但是,我想编译一个ARMv5二进制文件。我这样做是通过给编译器-march=armv5te选项。

到目前为止,这么好。由于我的ARM系统使用BusyBox,我必须编译静态链接的二进制文件。所以我给gcc -static选项。

但是,我遇到了 libc.a 的问题,链接器链接到我的ARMv5二进制文件。此文件使用ARMv7体系结构选项进行编译。所以,即使我用ARMv5交叉编译我的ARM二进制文件,我也无法在基于BusyBox的ARMv5盒子上运行它。

  1. 我该如何解决这个问题?
  2. 我在哪里可以获得ARMv5 libc.a 静态库,如何链接它?
  3. 提前谢谢。

1 个答案:

答案 0 :(得分:1)

您有两个选择,

  1. 获取正确的编译器。
  2. 写自己的' C'库。
  3. 获取正确的编译器。

    让编译器与您的系统匹配,始终最安全。这适用于x86 Linux和各种发行版。如果不同的编译器工作,你很幸运。交叉编译时更加困难,因为编译器不会自动同步。尝试在2014 Ubuntu系统上编译的1999 x86 Mandrake Linux上运行程序。

    除了指令兼容性(已经确定)之外,还有ABI和OS依赖性。具体来说, armv7 很可能是 hardfloat (具有浮点FPU 和注册调用约定),你需要一个 softfloat (模拟FPU)。特定的 glibc (或 ucLibc )具有Linux操作系统的特定调用和期望。例如, threads 的工作方式随着时间的推移而发生了变化。

    自己编写

    您始终可以使用-fno-builtin-ffreestanding以及-static。然后你不能使用任何 libc 函数,但你可以program them your self

    有外部来源,例如Mark Martinec's snprintf和像write()这样易于实施的构建模块,

    #define _SYS_IOCTL_H 1
    #include <linux/unistd.h>
    #include <linux/ioctl.h>
    static inline int write(int fd, void *buf, int len)
    {
        int rval;
            asm volatile ("mov      r0, %1\n\t"
                    "mov    r1, %2\n\t"
                    "mov    r2, %3\n\t"
                    "mov    r7, %4\n\t"
                    "swi    #7\n\t"
                    "mov    %0, r0\n\t"
                    : "=r" (rval)
                    : "r" (fd),
                      "r" (buf),
                      "r" (len),
                      "Ir" (__NR_write)
                    : "r0", "r1", "r2", "r7");
        return rval;
    }
    
    static inline void exit(int status)
    {
            asm volatile ("mov      r0, %0\n\t"
                    "mov    r7, %1\n\t"
                    "swi    #7\n\t"
                    : : "r" (status),
                      "Ir" (__NR_exit)
                    : "r0", "r7");
    }
    

    您必须添加自己的启动机器,由C&#39; C&#39;库,

    /* Called from assembler startup. */
    int main (int argc, char*argv[])
    {
        write(STDOUT, "Hello world\n", sizeof("Hello world\n"));
        return 0;
    }
    
    /* Wrapper for main return code. */
    void __attribute__ ((unused)) estart (int argc, char*argv[])
    {
        int rval = main(argc,argv);
        exit(rval);
    }
    
    /* Setup arguments for estart [like main()]. */
    void __attribute__ ((naked)) _start (void)
    {
        asm(" sub     lr, lr, lr\n"   /* Clear the link register. */
            " ldr     r0, [sp]\n"     /* Get argc... */
            " add     r1, sp, #4\n"   /* ... and argv ... */
            " b       estart\n"       /* Let's go! */
            );
    }
    

    如果这太令人生畏,因为您需要实现许多功能,那么您可以尝试获取各种库源并使用-fno-builtin重建它们,并确保库不与Ubuntu链接库是不兼容的。

    crosstool-ng这样的项目可以让你构建一个正确适合 armv5 系统的正确编译器(可能有更高级的代码生成)。这可能看起来很痛苦,但上述替代方案也不容易。