问题 展开支持的内存利用率(在ARM体系结构上)


我目前正在努力为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

我试图寻找有关展开和发现的一些信息 1 和 2。但是我仍然不清楚以下内容:

  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

4059
2017-12-25 05:50


起源

C ++或堆栈回溯打印? - auselen
@auselen,你是说只在c ++中使用unwind吗? - maguirre
不,我问你是否使用c ++或一些实用程序来打印堆栈。 - auselen
恶作剧,你能展示你的 includes和链接字符串? - osgx
如果您可以指定用于编译代码的标志,那就太棒了。 - Raj


答案:


这个答案的几个部分:

  • 展开库函数是从一些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; }

使用YAGARTO编译为4K,相比之下没有存根的14K。但您也可能想要研究其他GNU工具分发。


13
2017-12-27 17:49



你的答案似乎非常合理和研究。我没有测试,但它看起来像你有。一旦我测试了其中一些功能,我会立即给你答案。你会教一个男人如何捕鱼并指出我可以学习的方向: - 异常个性例程 - 我可以用什么其他功能 - 什么功能可以和不能解开 - maguirre
您的第一步是ARM ABI中的C ++异常处理ABI(EHABI)。您可以在“ARM软件开发工具”下的infocenter.arm.com上找到它。 - Al Grant
简而言之,您可以存根任何仅从.ARM.exidx部分引用的异常库函数。但实际上,作为一名应用程序开发人员,您不应该知道这种详细程度。但是,如果您正在构建工具链和库,那么您应该这样做。 - Al Grant
我遇到了类似的问题,我的解决方法没有重建工具链并在一个更大的项目中编辑每一个main.c是这样的:链接器行添加“-Wl, - wrap,__ aeabi_unwind_cpp_pr0 -lgcc”在公共库中的某处添加它项目代码:void __wrap ___ aeabi_unwind_cpp_pr0(){while(1){}} - kert


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

-fno-exceptions

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


1
2018-04-19 17:41



这是我尝试的第一件事(有同样的问题)。在Yagarto的情况下,它不会删除巨大的放松东西。 - Otzen