【问题标题】:how can I prevent arm-none-eabi compiler generating main symbol如何防止 arm-none-eabi 编译器生成主符号
【发布时间】:2015-04-28 08:26:56
【问题描述】:

我正在使用arm-none-eabi 编译源文件。 编译生成elf文件后。我使用 nm 命令得到以下符号

00021da8 T ISR_Init
         U main
         U malloc
010008b0 D MASTER_AHB_MAP

我正在使用 gdb 进行调试,但我对未定义的 main 符号有疑问。 gdb 生成以下错误:

Function "main" not defined.

当我将入口点更改为 main 时,它工作正常。 我正在开发裸机程序,所以我没有在程序的任何地方定义main

我将我的程序与以下库链接

(GNU_ARM_TOOL)/lib/gcc/arm-none-eabi/4.8.4/armv7-ar/thumb/fpu
(GNU_ARM_TOOL)/arm-none-eabi/lib/armv7-ar/thumb/fpu

据我了解,main 符号是从上述库之一生成的。我的问题是如何避免编译器生成未定义符号main,或者至少删除最终elf 文件中未定义的main 符号以避免gdb 错误。

【问题讨论】:

  • 运行用于链接程序的命令和 -v 选项。您应该看到引入了一些启动代码(有时称为 crt0.o)。这就是对 main() 的引用的来源。

标签: gdb cross-compiling debug-symbols


【解决方案1】:

为避免 gcc 生成对 main 的引用,请将您的程序与 -nostdlib gcc option 链接:

-nostdlib:链接时不要使用标准的系统启动文件或库。没有启动文件,只有您指定的库被传递给链接器,并且指定系统库链接的选项(例如 -static-libgcc 或 -shared-libgcc)被忽略。 编译器可以生成对 memcmp、memset、memcpy 和 memmove 的调用。这些条目通常由 libc 中的条目解析。指定此选项时,应通过其他机制提供这些入口点。

-nostdlib 和 -nodefaultlibs 绕过的标准库之一是 libgcc.a,这是一个内部子例程库,GCC 使用它来克服特定机器的缺点或某些语言的特殊需求。 (有关 libgcc.a 的更多讨论,请参阅与 GCC 输出的接口。)在大多数情况下,即使您想避免使用其他标准库,也需要 libgcc.a。换句话说,当您指定 -nostdlib 或 -nodefaultlibs 时,您通常也应该指定 -lgcc。这可确保您没有对内部 GCC 库子例程的未解析引用。

为避免 gcc 生成对 memcmpmemsetmemcpy 等的调用,请使用 gcc 的 -ffreestanding 选项进行编译。或者使用“函数属性”语法,例如:

/* defined in the linker script gcc.ld */
extern int __etext, __data_start__, __data_end__, __bss_start__, __bss_end__;

/* make gcc not translate the data copy loop into a memcpy() call
 *
 * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
 * Note that just passing optimize("freestanding", "no-builtin")
 * as a function attribute here doesn't work on
 * gcc-arm-embedded 2014 (gcc 4.9.3) */
__attribute__((optimize("freestanding", "no-builtin",
                        "no-tree-loop-distribute-patterns")))
void Reset_Handler()
{
        int *src, *dst;
        for (src = &__etext, dst = &__data_start__;
                        dst != &__data_end__;
                        src++, dst++)
                *dst = *src;
        for (dst = &__bss_start__; dst < &__bss_end__; dst++)
            *dst = 0;

        main();
}

【讨论】:

  • 对不起,我使用 -nostdlib 选项编译,但我仍然使用 nm 命令获取符号 U main。是因为我链接到上面的那两个库。这个选项也可用于as 命令
  • 这意味着您正在链接到一个明确调用main 的库(可能是C 标准库或供应商启动代码)。 as 没有等效选项,因为 -nostdlib 仅控制链接。建议:盯着你的 Makefile 中的链接命令。是否有-lc 或任何可能调用main 的可疑对象?
  • 是的,我已经与调用 main 的库链接,它位于 (GNU_ARM_TOOL)/lib/gcc/arm-none-eabi/4.8.4/armv7-ar/thumb/fpupath 中。在这条路径中有 crti.o , crtn.o , libgcc.a crtbegin.o crtend libgcov.a 。你的意思是避免生成main 符号我不应该链接到那些库???。我正在寻找避免生成main 并链接到同时生成main 的库的方法
  • “我正在寻找方法来避免生成 main 并链接到同时生成 main 的库”-> 您正在与链接器和启动代码作斗争,但没有任何收获。不要这样做。如果您不需要它,请不要链接到调用main 的启动代码,或者链接到启动代码并给它一个`符号。
  • 如果你知道如何在你的裸机平台上进行硬件初始化并且认为你不需要启动代码,只需添加像我上面的Restart_Handler()这样的代码来初始化.data.bss 段。这适用于 C。
猜你喜欢
  • 2013-12-16
  • 1970-01-01
  • 2019-06-19
  • 2014-02-08
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2017-03-24
  • 2016-05-01
相关资源
最近更新 更多