Recent site activity

Welcome‎ > ‎

gcc: relocation truncated

posted 25 Nov 2009 14:46 by Chris Shucksmith   [ updated 18 Jul 2011 05:30 ]
I've been struggling with this message "relocation truncated to fit: R_ARM_THM_CALL" during a build with GCC binutils for arm-elf:

$ make

arm-elf-gcc -I. -Iinc -ISTM32_USB/inc -ISTM32F10x_StdPeriph/inc -ICMSIS/Core/CM3 -I/usr/include -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb src/main.c
arm-elf-as -ahls -mapcs-32  -o startup_stm32f10x_ld.o CMSIS/Core/CM3/startup_stm32f10x_ld.s > startup_stm32f10x_ld.lst
arm-elf-ld -v -Tstm_h103_linker -nostartfiles -o main.out startup_stm32f10x_ld.o main.o misc.o hw_config.o usb_init.o usb_istr.o usb_int.o usb_desc.o usb_mem.o usb_endp.o usb_prop.o usb_sil.o usb_core.o usb_pwr.o usb_regs.o stm32f10x_rcc.o stm32f10x_flash.o stm32f10x_gpio.o stm32f10x_usart.o
startup_stm32f10x_ld.o:(.text.Reset_Handler+0x26): relocation truncated to fit: R_ARM_THM_CALL against symbol `main' defined in .text section in main.o
make: *** [main.out] Error 1
GNU ld (GNU Binutils) 2.18 + coff-avr-patch (20050630)

Took me a long while to figure this one out!

In 
CMSIS/Core/CM3/startup_stm32f10x_ld.s  there is an assembler routine doing initialisation then calling the C main function. The code was set to output to a section not defined in my linker script (stm_h103_linker). It seems the default behaviour is to append the object code at the end of the last defined segment, which was an address in RAM starting at 2gb, far away from the rest of the code, starting at 0x0 in the .text section. This caused the error above when the linker tried to substitute the address of main into the following code:

/* Call the application's entry point.*/
  bl main
  bx lr

To figure this out I in-lined the "long-call veneer" i.e.. assembly to call a full 32bit address, rather than the bx thumb instruction above which is limited to calling +/- 4mb.

/* Call the application's entry point.*/
  ldr r0, =main
  bx r0
  bx  lr

This fudge allowed the linking to complete. I then went through the listing main.lst and noticed the bogus address. Interestingly, I think the resulting binary would initially work on the target hardware, only to fail badly at runtime after a reboot, as init code in RAM would be lost.

The following CrossWorks support post was helpful http://rowley.zendesk.com/forums/51134/entries/46203 as was the discussion on the binutils developers list http://sourceware.org/ml/binutils/2009-02/msg00224.html

Lessons learned? Know the hardware memory map, really understand what the toolchain is doing and watch out for undeclared sections!