Unable to link AVR object files with lld? (unrecognized relocation R_AVR_LO8_LDI_GS etc)

I built llvm with clang and lld with AVR as one of the target architectures and I’m trying to use them to build an AVR executable.

llc is working well, making object files from llvm or files.

I can link these just fine using gnu ld with this command:

Carls-MacBook-Air:AVR2 carlpeto$ "/Users/carlpeto/compilers/extracted/bin/avr-ld" -L"/Users/carlpeto/compilers/extracted/lib/avr-libc/lib/avr5" -L"/Users/carlpeto/compilers/extracted/lib/avr-libgcc/avr5" -L"/Users/carlpeto/compilers/extracted/lib/avr-binutils/avr/lib/ldscripts" -Tdata 0x800100 -Tavr5.xn --gc-sections "/Users/carlpeto/compilers/extracted/lib/avr-libc/lib/avr5/crtatmega328p.o" -o main.elf main.o reference.o uSwift/Runtime/missing_runtime_show_warning.o -L AVR -lAVR -L uSwift -lSwift --start-group -lgcc -lm -lc -latmega328p --end-group
Carls-MacBook-Air:AVR2 carlpeto$

No error message and the elf file is well structured and runs.

But if I take the above command and just replace avr-ld with my version of lld, it fails to link with a bunch of errors about relocations...

Carls-MacBook-Air:AVR2 carlpeto$ ~/compilers/llvm-project/llvm/build/bin/ld.lld -L"/Users/carlpeto/compilers/extracted/lib/avr-libc/lib/avr5" -L"/Users/carlpeto/compilers/extracted/lib/avr-libgcc/avr5" -L"/Users/carlpeto/compilers/extracted/lib/avr-binutils/avr/lib/ldscripts" -Tdata 0x800100 -Tavr5.xn --gc-sections "/Users/carlpeto/compilers/extracted/lib/avr-libc/lib/avr5/crtatmega328p.o" -o main.elf main.o reference.o uSwift/Runtime/missing_runtime_show_warning.o -L AVR -lAVR -L uSwift -lSwift --start-group -lgcc -lm -lc -latmega328p --end-group
ld.lld: warning: cannot find entry symbol _start; defaulting to 0x0
ld.lld: error: vfprintf.c:(function vfprintf: .text.avr-libc+0x4): unrecognized relocation R_AVR_LO8_LDI_GS
ld.lld: error: snprintf.c:(function snprintf: .text.avr-libc+0x4): unrecognized relocation R_AVR_LO8_LDI_GS
ld.lld: error: serial.c:(function _setupSerial: .text._setupSerial+0xC): relocation R_AVR_7_PCREL out of range: 68 is not in [-64, 63]
ld.lld: error: util.c:(function _stringAddWord: .text._stringAddWord+0x14): relocation R_AVR_7_PCREL out of range: 92 is not in [-64, 63]
ld.lld: error: util.c:(function _stringCompare: .text._stringCompare+0x2): relocation R_AVR_7_PCREL out of range: 74 is not in [-64, 63]
ld.lld: error: serial.c:(function __vector_24: .text.__vector_24+0x90): relocation R_AVR_7_PCREL out of range: -78 is not in [-64, 63]
ld.lld: error: malloc.c:(function malloc: .text.avr-libc+0x36): relocation R_AVR_7_PCREL out of range: 120 is not in [-64, 63]
ld.lld: error: /Users/carlpeto/compilers/extracted/lib/avr-libc/lib/avr5/libc.a(ultoa_invert.o):(function __ultoa_invert: .text.avr-libc+0x6): relocation R_AVR_7_PCREL out of range: 86 is not in [-64, 63]
ld.lld: error: util.c:(function __vector_6: .text.__vector_6+0x40): relocation R_AVR_7_PCREL out of range: 82 is not in [-64, 63]
ld.lld: error: util.c:(function __vector_11: .text.__vector_11+0x2C): relocation R_AVR_7_PCREL out of range: 96 is not in [-64, 63]
ld.lld: error: util.c:(function _stringCompare: .text._stringCompare+0x8): relocation R_AVR_7_PCREL out of range: 68 is not in [-64, 63]
ld.lld: error: serial.c:(function __vector_24: .text.__vector_24+0xB0): relocation R_AVR_7_PCREL out of range: 124 is not in [-64, 63]
ld.lld: error: snprintf.c:(function snprintf: .text.avr-libc+0x6): unrecognized relocation R_AVR_HI8_LDI_GS
ld.lld: error: vfprintf.c:(function vfprintf: .text.avr-libc+0x6): unrecognized relocation R_AVR_HI8_LDI_GS
ld.lld: error: util.c:(function __vector_6: .text.__vector_6+0x48): relocation R_AVR_7_PCREL out of range: 74 is not in [-64, 63]
ld.lld: error: util.c:(function __vector_9: .text.__vector_9+0x2C): relocation R_AVR_7_PCREL out of range: 74 is not in [-64, 63]
ld.lld: error: util.c:(function _stringCompare: .text._stringCompare+0xC): relocation R_AVR_7_PCREL out of range: 64 is not in [-64, 63]
ld.lld: error: malloc.c:(function malloc: .text.avr-libc+0x40): relocation R_AVR_7_PCREL out of range: 100 is not in [-64, 63]
ld.lld: error: vfprintf.c:(function vfprintf: .text.avr-libc+0x64): relocation R_AVR_7_PCREL out of range: 70 is not in [-64, 63]
ld.lld: error: serial.c:(function __vector_24: .text.__vector_24+0x13C): relocation R_AVR_7_PCREL out of range: 84 is not in [-64, 63]
ld.lld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
Carls-MacBook-Air:AVR2 carlpeto$

Does anyone have any ideas what I’ve done wrong?

The AVR port is incomplete. Some relocations are not handled.

Ok that makes sense.

I’m happy to try and add the relocations. I’m pretty comfortable with hacking llvm and with AVR assembly and the AVR back end in llvm.

One thing I don’t understand. R_AVR_7_PCREL Is saying out of range.

Is that because the implementation is there but is buggy?

I thought about “branch relaxing code” issues, which is something I’ve heard of but never quite understood. However that’s a compile thing I think. Not a linker thing. The code links fine using the standard gnu linker so perhaps that’s a dead end?

Secondly, are there any good resources, blogs, etc. That I can use to help learn how the linker works? Or is it just read the source code for lld and come back here if I get stuck?

Final question, when it comes time to submit a patch, I’ve never really done it properly before. I used to had them to the maintainer Dylan. Who did the work of formal submission. Is there some good getting started guides for how to use Phabricator etc. Do I raise a bug on there then submit a patch there somehow?

Thanks for any help people can give!

Ok that makes sense.

I’m happy to try and add the relocations. I’m pretty comfortable with hacking llvm and with AVR assembly and the AVR back end in llvm.

One thing I don’t understand. R_AVR_7_PCREL Is saying out of range.

Is that because the implementation is there but is buggy?

Unlikely a bug.

For such long branches, there are usually two approaches

* compiler: avoid short range branches if likely overflow
* assembler: if a branch instruction can be converted to a wider range form
* linker: range extension thunk mechanism

I know barely nothing about AVR... I guess the first two are more
possible and the LLVM backend hasn't implemented them.

I thought about “branch relaxing code” issues, which is something I’ve heard of but never quite understood. However that’s a compile thing I think. Not a linker thing. The code links fine using the standard gnu linker so perhaps that’s a dead end?

Secondly, are there any good resources, blogs, etc. That I can use to help learn how the linker works? Or is it just read the source code for lld and come back here if I get stuck?

There are some LLD talks giving high-level overview. You may debug
Finding the review threads of various patches introducing some new
features is useful. You may also debug lld/test/ELF tests. For newer
tests, we've been spent more time writing the tests and adding comments.

Final question, when it comes time to submit a patch, I’ve never really done it properly before. I used to had them to the maintainer Dylan. Who did the work of formal submission. Is there some good getting started guides for how to use Phabricator etc. Do I raise a bug on there then submit a patch there somehow?

You can `git log -- avr-reloc.s` :slight_smile:

In 2019 I added ppc32 support and largely improved RISC-V. I hope
ppc32-*.s and riscv-*.s are well organized and representative for
targets we don't devote too much time:)