This is an archive of the discontinued LLVM Phabricator instance.

[AVR] Fixed broken linking using `avr-gcc`.
ClosedPublic

Authored by KOLANICH on Jun 10 2022, 8:08 AM.

Details

Summary

clang provides arguments to avr-gcc in a wrong order. This results in linking errors undefined reference to .... This patch fixes this.

Bug on GitHub: https://github.com/llvm/llvm-project/issues/56409

Diff Detail

Event Timeline

KOLANICH created this revision.Jun 10 2022, 8:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 10 2022, 8:08 AM
KOLANICH requested review of this revision.Jun 10 2022, 8:08 AM
KOLANICH updated this revision to Diff 435974.Jun 10 2022, 10:51 AM

Fixing tests

KOLANICH updated this revision to Diff 435978.Jun 10 2022, 10:56 AM

Removed unneeded changes introduced by clang-format

Could you please give more details about the error you got ?

  1. what OS did you use ?
  2. What avr-gcc version did you use? And what was its installation path ?
  3. What were your input files ? And what were the command options when you run clang ?
benshi001 added inline comments.Jun 11 2022, 2:23 AM
clang/lib/Driver/ToolChains/AVR.cpp
491

I think directly using AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); twice is fine, we need not define a lamnda function.

benshi001 added inline comments.Jun 11 2022, 2:24 AM
clang/lib/Driver/ToolChains/AVR.cpp
523

We need to add more tests to test this else branch.

KOLANICH added a comment.EditedJun 11 2022, 11:16 AM
  1. >what OS did you use ?

Kubuntu 21.10

  1. >What avr-gcc version did you use?

7.3.0-atmel3.6.1-arduino7, it is the latest one that Arduino IDE has updated. Its version number matches the one coming from Atmel Microchip website, but it has some patches by Arduino applied.

And what was its installation path ?

Not installed, just unpacked, it is portable.

What were your input files ?

The ones I have created. I'm not ready to share them they are in pretty dirty state now, but the issue is fundamental and should be reproducible on any project structured as a typical Arduino project and using its standard library and runtime.

And what were the command options when you run clang ?

I have modified the well-known set of CMake toolchain files, here is my fork: https://github.com/KOLANICH/Arduino-CMake-Toolchain/tree/clang

The failed command was

bash
/usr/lib/llvm-15/bin/clang++ --target=avr --sysroot=./arduino_ide/1.8.19/hardware/tools/avr -fno-rtti -mmcu=atmega2560 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -O3 -DNDEBUG -mmcu=atmega2560 -lm  -fuse-linker-plugin -v --ld-path="/usr/lib/llvm-15/bin/ld.lld" CMakeFiles/stepper_control.dir/src/main.cpp.obj -o stepper_control.elf  lib_arduino_lib_core.a  lib_arduino_lib_Stepper.a  lib_arduino_lib_core.a

(the paths have been edited, the prefix was replaced to not disclose projects location in the fs)

It results in

clang: warning: argument unused during compilation: '--ld-path=/usr/lib/llvm-15/bin/ld.lld' [-Wunused-command-line-argument]

It seems that lld cannot link for AVR target and it is an another big issue.

bash
"./arduino_ide/1.8.19/hardware/tools/avr/lib/gcc/avr/7.3.0/../../../../bin/avr-ld" -lm CMakeFiles/stepper_control.dir/src/main.cpp.obj lib_arduino_lib_core.a lib_arduino_lib_Stepper.a lib_arduino_lib_core.a -o stepper_control.elf --gc-sections -L./arduino_ide/1.8.19/hardware/tools/avr/lib/gcc/avr/7.3.0/../../../../avr/lib/avr6 -L./arduino_ide/1.8.19/hardware/tools/avr/lib/gcc/avr/7.3.0/avr6 -Tdata=0x800200 --start-group -l:crtatmega2560.o -lgcc -lm -lc -latmega2560 --end-group -mavr6

The actual command - it always calls avr-ld and I have no means to override it. If we put our object files to the group in the end, it links succesfully (if -flto is not enabled. Offtop: if it is enabled, the linker fails to link llvm bitcode, I have tried to link all the bitcode + native code into a joint object file, then compile it using llc, then link using avr-ld and got other undefined reference issues, it seems the optimizer eats some symbols, and using -O0 makes it run out of registers). To be honest, if I had means to override it I'd have just written a shell script instead of taking the burden of compiling clang from source.

./arduino_ide/1.8.19/hardware/tools/avr/lib/gcc/avr/7.3.0/../../../../avr/lib/avr6/crtatmega2560.o:(.init9+0x0): undefined reference to `main'

main is defined within lib_arduino_lib_core.a, which is compiled by the CMake scripts for each target, and it uses setup and loop that are defined in CMakeFiles/stepper_control.dir/src/main.cpp.obj, which is compiled from my code. A typical Arduino project is structured like this.

We need to add more tests to test this else branch.

It should have been already tested, we just changed the place where the user's files are placed into the command line.

I think directly using AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); twice is fine, we need not define a lamnda function.

I think it is more error-prone than having a lambda. I expect the optimizer to be smart enough to inline it.

  1. If you can not offer the source code, could please attach the obj files and the library files ? I am quite confused that the order affects.
  1. I am uncomfortable with the lamnda, I still think copying twice looks more clear.

Here is the test project. https://github.com/KOLANICH/barebones_arduino_mega_2560_clang_test
Feel free to use its contents in Clang tests.

KOLANICH updated this revision to Diff 441096.EditedJun 29 2022, 11:16 AM

Synced with the latest changes + addressed some review comments.

KOLANICH marked an inline comment as done.Jun 29 2022, 11:17 AM
KOLANICH edited the summary of this revision. (Show Details)Jul 6 2022, 12:50 PM
benshi001 accepted this revision.EditedJul 7 2022, 2:18 AM

Please give me your full name and an email for the author of commit message.

This revision is now accepted and ready to land.Jul 7 2022, 2:18 AM
This revision was automatically updated to reflect the committed changes.