AVR relocation truncations workaround

From Wikistix

While attempting to build targets for Atmel ATmega2560 (Arduino) on NetBSD, I tripped over the following interesting link errors:

/usr/pkg/bin/avr-g++ -mmcu=atmega2560 -I. -DF_CPU=16000000 -DARDUINO=105 -I/home/stix/src/arduino-1.0.5/hardware/arduino/cores/arduino -I/home/stix/src/arduino-1.0.5/libraries/LiquidCrystal -I/home/stix/src/arduino-1.0.5/libraries/Wire -I/home/stix/src/arduino-1.0.5/libraries/utility/twi  -I../libraries/DS1307RTC -I../libraries/OneWire -I../libraries/Time -I/home/stix/src/arduino-1.0.5/libraries/LiquidCrystal/utility/ -I/home/stix/src/arduino-1.0.5/libraries/Wire/utility/ -I/home/stix/src/arduino-1.0.5/libraries/utility/twi/utility/ -I../libraries/DS1307RTC/utility/ -I../libraries/OneWire/utility/ -I../libraries/Time/utility/ -I/home/stix/src/arduino-1.0.5/hardware/arduino/variants/mega -Os -mno-short-calls -o applet/thermo.elf applet/thermo.cpp -L. applet/core.a -Wl,--gc-sections -lm -lc
/usr/pkg/lib/gcc/avr/4.5.3/../../../../avr/lib/avr6/libm.a(pow.o):../../../libm/fplib/pow.S:214:(.text.avr-libc.fplib+0x94): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in /usr/pkg/lib/gcc/avr/4.5.3/avr6/libgcc.a(_mul_sf.o)
/usr/pkg/lib/gcc/avr/4.5.3/../../../../avr/lib/avr6/libm.a(inverse.o):../../../libm/fplib/inverse.S:50:(.text.avr-libc.fplib+0xc): relocation truncated to fit: R_AVR_13_PCREL against symbol `__divsf3' defined in .text section in /usr/pkg/lib/gcc/avr/4.5.3/avr6/libgcc.a(_div_sf.o)
/usr/pkg/lib/gcc/avr/4.5.3/../../../../avr/lib/avr6/libm.a(log.o):../../../libm/fplib/log.S:96:(.text.avr-libc.fplib+0x46): relocation truncated to fit: R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in /usr/pkg/lib/gcc/avr/4.5.3/avr6/libgcc.a(_addsub_sf.o)
/usr/pkg/lib/gcc/avr/4.5.3/../../../../avr/lib/avr6/libm.a(log.o):../../../libm/fplib/log.S:100:(.text.avr-libc.fplib+0x4e): relocation truncated to fit: R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in /usr/pkg/lib/gcc/avr/4.5.3/avr6/libgcc.a(_addsub_sf.o)
/usr/pkg/lib/gcc/avr/4.5.3/../../../../avr/lib/avr6/libm.a(log.o):../../../libm/fplib/log.S:116:(.text.avr-libc.fplib+0x6a): relocation truncated to fit: R_AVR_13_PCREL against symbol `__floatsisf' defined in .text section in /usr/pkg/lib/gcc/avr/4.5.3/avr6/libgcc.a(_si_to_sf.o)
/usr/pkg/lib/gcc/avr/4.5.3/../../../../avr/lib/avr6/libm.a(modf.o):../../../libm/fplib/modf.S:90:(.text.avr-libc.fplib+0x3e): relocation truncated to fit: R_AVR_13_PCREL against symbol `__subsf3' defined in .text section in /usr/pkg/lib/gcc/avr/4.5.3/avr6/libgcc.a(_addsub_sf.o)
collect2: ld returned 1 exit status

libm uses RCALL and RJMP which use a space and execution time efficient instruction format. However, it is limited to a 13-bit signed PC-relative offset - ±4KiB. Normally these symbols should be resolved to the ones present in libm, however, in the above output, ld is resolving them to the duplicate symbols present in libgcc.

This is a known bug (libavr and gcc) that seems to not have received much love. A workaround is to force the library order passed to the linker, passing libm before libgcc. The avr-g++ command line becomes:

/usr/pkg/bin/avr-g++ -mmcu=atmega2560 -I. -DF_CPU=16000000 -DARDUINO=105 -I/home/stix/src/arduino-1.0.5/hardware/arduino/cores/arduino -I/home/stix/src/arduino-1.0.5/libraries/LiquidCrystal -I/home/stix/src/arduino-1.0.5/libraries/Wire -I/home/stix/src/arduino-1.0.5/libraries/utility/twi  -I../libraries/DS1307RTC -I../libraries/OneWire -I../libraries/Time -I/home/stix/src/arduino-1.0.5/libraries/LiquidCrystal/utility/ -I/home/stix/src/arduino-1.0.5/libraries/Wire/utility/ -I/home/stix/src/arduino-1.0.5/libraries/utility/twi/utility/ -I../libraries/DS1307RTC/utility/ -I../libraries/OneWire/utility/ -I../libraries/Time/utility/ -I/home/stix/src/arduino-1.0.5/hardware/arduino/variants/mega -Os -mno-short-calls -o applet/thermo.elf applet/thermo.cpp -L. applet/core.a -nodefaultlibs -Wl,--gc-sections -lm -lgcc -lc -lgcc

That is, pass -nodefaultlibs to prevent libgcc and libc being automatically added, and append -lm -lgcc -lc -lgcc. The second -lgcc is required to resolve symbols in libgcc referenced by libc.

See Also