11

我目前正在尝试用 C 语言为 SAM7X256 微控制器开发软件。该设备正在运行 contiki OS,我正在使用 yagarto 工具链。

在研究地图文件时(试图找出 .text 区域增长如此之多的原因),我发现有几个 kb 的 .text 区域分配给展开支持(见下文)

.text           0x00116824      0xee4 c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2\libgcc.a(unwind-arm.o)
                0x00116c4c                _Unwind_VRS_Get
                ......   
                0x0011763c                __gnu_Unwind_Backtrace

.text           0x00117708      0x1b0 c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2\libgcc.a(libunwind.o)
                0x00117708                __restore_core_regs
                0x00117708                restore_core_regs
                ....
                0x00117894                _Unwind_Backtrace

.text           0x001178b8      0x558 c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2\libgcc.a(pr-support.o)
                0x00117958                __gnu_unwind_execute
                ...
                0x00117e08                _Unwind_GetTextRelBase

我试图寻找一些关于展开的信息并找到12。但是,我仍然不清楚以下内容:

  1. 何时/为什么我需要平仓支持?
  2. 我的代码的哪一部分导致 pr-support.o、unwind-arm.o 和 libunwind.o 被链接?
  3. 如果适用,我如何避免链接以下项目。

如果有必要,我会包含指向完整地图文件的链接

在此先感谢您的帮助

编辑 1:添加链接器命令

CC       = arm-none-eabi-gcc
CFLAGSNO = -I. -I$(CONTIKI)/core -I$(CONTIKI_CPU) -I$(CONTIKI_CPU)/loader \
       -I$(CONTIKI_CPU)/dbg-io \
           -I$(CONTIKI)/platform/$(TARGET) \
           ${addprefix -I,$(APPDIRS)} \
           -DWITH_UIP -DWITH_ASCII -DMCK=$(MCK) \
           -Wall $(ARCH_FLAGS) -g -D SUBTARGET=$(SUBTARGET)

CFLAGS  += $(CFLAGSNO) -O -DRUN_AS_SYSTEM -DROM_RUN  -ffunction-sections

LDFLAGS += -L $(CONTIKI_CPU) --verbose -T $(LINKERSCRIPT) -nostartfiles  -Wl,-Map,$(TARGET).map

$(CC) $(LDFLAGS) $(CFLAGS) -nostartfiles -o project.elf -lc Project.a
4

2 回答 2

13

这个答案的几个部分:

  • 展开库函数是从某些 GCC 库函数模块的异常表中提到的异常“个性例程”(__aeabi_unwind_cpp_pr0 等)中提取的。

  • 您的地图文件显示 bpapi.o(包含整数除法函数的模块)引入了此异常代码。我在最新的 YAGARTO 中没有看到这一点,但我在 _divdi3.o 中执行此操作,这是另一个整数除法辅助模块。我可以通过编写一个执行 64 位除法的简单 main() 来重现展开代码的效果。

  • C 代码具有(非平凡的)异常表的一般原因是,当您在应用程序中任意混合 C 和 C++ 代码时,可以“通过”C 代码抛出 C++ 异常。

  • 不能抛出或调用抛出函数的函数,如果它们根本有异常表,则应该只需要标记为 CANTUNWIND 的琐碎的函数,这样展开库就不会被拉入。你会期望除法助手在这个类别,实际上在 CodeSourcery 的发行版中,_divdi3.o 被标记为 CANTUNWIND。

  • 所以根本原因是YAGARTO的GCC库(libgcc.a)构建不当。并非完全不正确,因为它应该仍然可以工作,但这是您在嵌入式工具链中不会想到的代码膨胀。

你能对此做些什么吗?似乎没有简单的方法让 GNU 链接器忽略 ARM 异常部分,即使使用 /DISCARD/ 脚本也是如此——文本部分的链接会覆盖它。但是您可以做的是为异常个性例程添加一个存根定义:

void __aeabi_unwind_cpp_pr0(void) {}
int main(void) { return *(unsigned long long *)0x1000 / 3; }

与没有存根的 14K 相比,使用 YAGARTO 编译为 4K。但是您可能也想研究替代的 GNU 工具发行版。

于 2012-12-27T17:49:03.457 回答
1

GCC 有一个选项可以消除异常处理。

-fno-exceptions

虽然我不熟悉 yagarto 可以肯定地说,它可能有类似的选择。在 GCC 上,此选项以对标准异常的支持为代价消除了这种开销。

于 2014-04-19T17:41:45.967 回答