用于ARM架构的取消支持的内存利用率

11

我目前正在尝试使用C语言为SAM7X256微控制器开发软件。该设备运行contiki操作系统,我使用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

C++还是堆栈回溯打印? - auselen
@auselen,你是说unwind只在C++中使用吗? - maguirre
不,我没有。我的所有软件都是用C开发的,我也没有打印堆栈。 - maguirre
1
Mischief,你能展示一下你的include和链接字符串吗? - osgx
1
能否说明您编译代码时使用的标志? - Raj
显示剩余3条评论
2个回答

14

回答分为以下几部分:

  • Unwinding库函数被从异常“personality routines”(__aeabi_unwind_cpp_pr0等) 中拉出来的,这些函数在部分GCC库函数模块的异常表中被提到。

  • 您的映射文件显示bpapi.o(包含整数除法函数的模块)引入了此异常代码。我在最新的YAGARTO中没有看到这个,但我在_divdi3.o中发现了它,这是另一个整数除法辅助模块。通过编写执行64位除法的微不足道的main()函数,可以重现引入取消代码的效果。

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

  • 如果函数不能抛出或调用抛出函数,则如果它们根本有异常表,则只需要将其标记为CANTUNWIND的平凡表,以便不会引入取消库。您期望除法辅助程序属于此类,并且实际上在CodeSourcery的发行版中,_divdi3.o被标记为CANTUNWIND。

  • 因此,根本原因是YAGARTO的GCC库(libgcc.a)建立不当。不完全正确,因为它仍然可以工作,但它是代码膨胀,在嵌入式工具链中这是意外的。

您能对此做些什么吗?即使有/DISCARD/脚本,GNU链接器似乎没有简单的方法来忽略ARM异常部分——与文本部分的链接覆盖了它。但您可以添加异常personality routine的存根定义:

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

使用YAGARTO编译后仅为4K,相比没有存根的情况下的14K。但您可能还想调查替代的GNU工具发行版。


2
你的回答看起来非常有理有据,经过了深入的研究。虽然我还没有测试过,但是看起来你已经做到了。一旦我测试了一些这些函数的存根,我就会授予你答案。你能否教我如何钓鱼,并指引我学习以下内容:
  • 异常处理程序
  • 我可以存根哪些其他函数
  • 哪些函数可以和不能解开
- maguirre
你的第一步将是在ARM ABI中了解C++异常处理ABI(EHABI)。您可以在“ARM软件开发工具”下的infocenter.arm.com上找到它。 - Al Grant
1
简而言之,你可以为任何仅在.ARM.exidx部分中引用的异常库函数提供存根。但作为应用程序开发人员,你不需要了解这个细节层面。但如果你正在构建工具链和库,那么你应该知道这些。 - Al Grant
1
我遇到了类似的问题,但是我没有重建工具链或编辑较大项目中的每个main.c文件,我的解决方法是:在链接器行中添加 “-Wl,--wrap,__aeabi_unwind_cpp_pr0 -lgcc” 将此代码添加到项目代码的公共库中的某个位置: void __wrap___aeabi_unwind_cpp_pr0( ) { while(1) {} } - kert

1
GCC有一个选项可以消除异常处理。
-fno-exceptions

虽然我对yagarto不是很熟悉,但它可能有类似的选项。在GCC上,这个选项通过牺牲标准异常支持来消除这种开销。


这是我尝试的第一件事情之一(遇到了同样的问题) 在Yagarto的情况下,它不会删除巨大的展开内容。 - Otzen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接