LLVM Discussion Forums

Llvm-link: symbol multiply defined

I am working on creating a single llvm ir file for the open source software ardupilot. They use a build system called waf, so I edited the wscript and changed g++ to clang++ and gcc to clang. I then added flags to emit ir llvm. This successfully goes through each file, creates the ir code and stores it in a .o file. I changed all the extensions to be .ll and then attempted to use llvm-link -S … to link the files into one ir file.

It is worth mentioning that ArduPilot consists of subprojects such as ArduCopter and ArduPlane etc. You can compile any of these projects individually for different systems such as a quadcopter or rc plane (where ArduCopter is for the quadcopter and ArduPlane is for fixed wing aircrafts). The project structure also has a bunch of libraries that are used by the main code for whatever you are compiling, be it ArduCopter or ArduPlane. (See below for a glimpse at the structure. Of particular note is ArduCopter and the libraries folder.)

I am personally working with ArduCopter. After running the build script, I get the ir files for the main ArduCopter code and the libraries.

However, when I use llvm-link -S folder_with_ir_files/*.ll -o file_name.ll, I get the following: “error: Linking globals named 'main': symbol multiply defined!
This is probably due to the fact that the libraries each have a main function leading to the symbol conflict.

If I try to resolve this issue by adding the flag --only-needed, all references to library functions get removed and instead simply a definition for the library class name appears. For example, references to a function selectHeightForFusion are removed and a define for AP_NavEKF3_PosVelFusion.cpp appears.

Ex. The function name is not found in the output ir file, but a reference to the class is.
define internal void @_GLOBAL__sub_I_AP_NavEKF3_PosVelFusion.cpp() #6 section ".text.startup" {

I instead tried using the flag --internalize to solve this problem. It seems to work where the references are now to the library functions themselves instead of the file, but it does not feel like the best way to go about solving this issue. (See below.)

Ex. These appear in the output ir file when searching for the function name.
call void @_ZN12NavEKF3_core21selectHeightForFusionEv(%class.NavEKF3_core.8709* %this1)
define internal void @_ZN12NavEKF3_core21selectHeightForFusionEv(%class.NavEKF3_core.8709* %this) #0 align 2 {

Ultimately, I wanted to get any feedback I could on the proper way to link multiple ir files in a project that uses libraries with multiple mains while not losing any ir code from the libraries.
It is also likely that I simply do not understand the process of linking these files and perhaps there is a reason for the references to selectHeightForFusion to be removed when using --only-needed.

Any guidance would be much appreciated.

I am working on creating a single llvm ir file for the open source software ardupilot.

Can you clarify what is the end-goal for this “single llvm IR” file?

Certainly. The end goal is to pass this file through SVF for data flow analysis. SVF can perform value flow and pointer analysis over an llvm ir file. We can dump the generated value flow graph as a dot file from SVF and then create python scripts to visualize how specific data is moved around in ArduCopter.