c-用于展开支持的内存利用率(在ARM体系结构上)



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

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

.text           0x00116824      0xee4 c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2libgcc.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.2libgcc.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.2libgcc.a(pr-support.o)
                0x00117958                __gnu_unwind_execute
                ...
                0x00117e08                _Unwind_GetTextRelBase

我试着找一些关于展开的信息,找到了1和2。然而,以下内容对我来说仍然不清楚:

  1. 我何时/为什么需要解除支持
  2. 我的代码的哪一部分导致了prsupport.o、unflerm.o和libunflex.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

这个答案的几个部分:

  • 展开库函数是从一些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工具的发行版。

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

-fno-exceptions

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

最新更新