Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory utilization for unwind support (on ARM architecture)

Tags:

c

gcc

embedded

ld

arm

I am currently working trying to develop software for a SAM7X256 microcontroller in C. The device is running contiki OS and I am using the yagarto toolchain.

While studying the map file (to try to figure out why the .text region had grown so much) I discovered that several kb of the .text region where assigned to unwind support (see below)

.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

I have tried finding looking for some information on unwinding and found 1 and 2. However the following is still unclear to me:

  1. When/why do I need unwinding support?
  2. What part of my code is causing pr-support.o, unwind-arm.o and libunwind.o to be linked?
  3. If applicable, how do I avoid linking the items below.

In case it is necessary I am including a link to the complete map file

Thanks in advance for your help

Edit 1: Adding Linker commands

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
like image 687
maguirre Avatar asked Dec 25 '12 05:12

maguirre


2 Answers

Several parts to this answer:

  • the unwinding library functions are pulled in from exception "personality routines" (__aeabi_unwind_cpp_pr0 etc.) that are mentioned in exception tables in some of the GCC library function modules.

  • your map file shows that bpapi.o (a module which contains integer division functions) pulls in this exception code. I don't see this in the latest YAGARTO, but I do it in _divdi3.o which is another integer division helper module. I can reproduce the effect of the unwinding code being pulled in by writing a trivial main() that does a 64-bit division.

  • the general reason for C code having (non-trivial) exception tables is so that C++ exceptions can be thrown "through" the C code when you arbitrarily mix C and C++ code in your application.

  • functions which can't throw or call throwing functions, should, if they have exception tables at all, only need trivial ones marked as CANTUNWIND, so that the unwinding library isn't pulled in. You'd expect division helpers to be in this category and in fact in CodeSourcery's distribution, _divdi3.o is marked CANTUNWIND.

  • so the root cause is that YAGARTO's GCC library (libgcc.a) is built inappropriately. Not quite incorrectly, as it should still work, but it's code bloat that you wouldn't expect in an embedded toolchain.

Can you do anything about this? There seems to be no simple way to get the GNU linker to ignore ARM exception sections, even with a /DISCARD/ script - the link to the text section overrides that. But what you can do is add a stub definition for the exception personality routine:

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

compiles to 4K using YAGARTO, compared to 14K without the stub. But you might want to investigate alternative GNU tools distributions too.

like image 88
Al Grant Avatar answered Sep 29 '22 06:09

Al Grant


GCC has an option that eliminates exception handling.

-fno-exceptions

While I'm not familiar with yagarto to say for sure, it may have a similar option. On GCC, this option eliminates this overhead at the expense of support for standard exceptions.

like image 22
Marc Signer Avatar answered Sep 29 '22 06:09

Marc Signer