clang links wrong ARM builtins in thumb mode - arm

I am trying to build Cortex-M0 (ARMv6, thumb) firmware with clang 13.0. Everything seems fine except for builtin functions like __udivsi3, __udivmoddi4 that are in ARM mode. Of course the CPU only supports thumb and delivers a fault when trying to execute them. I know that these functions are wrong because the CPU faults, the debugger displays them as ARM mode and their addresses in the .elf have Lsb cleared. I am linking to newlib provided by gcc (v6 flavor of libc_nano.a) and the libc functions are correct (ie. thumb mode). Functions from my .c files are also correctly built in thumb mode and the firmware runs just fine until it encounters integer division.
My compile options:
clang -o some_file.o -c -MD --target=armv6m-none-eabi -nostdlib
--sysroot="/path/to/newlib/arm-none-eabi" -fshort-enums -mcpu=cortex-m0
-mthumb -mfloat-abi=soft -g3 -I ../some/includes -Oz -std=gnu11
-Wall -pipe -ffunction-sections -fdata-sections some_file.c
My linking options:
clang -o my_project.elf --target=armv6m-none-eabi -nostdlib
-L"/path/to/newlib/arm-none-eabi/lib/." "/path/to/newlib/lib/gcc/arm-none-eabi/9.2.1/libgcc.a"
"/path/to/newlib/arm-none-eabi/lib/thumb/v6-m/nofp/libc_nano.a"
-mcpu=cortex-m0 -mthumb -mfloat-abi=soft -g3 -Wl,--gc-sections
-T my_linker_script.ld object_file1.o object_file2.o object_file3.o -lm
The same happens when I try --target=arm-none-eabi or -mtune=cortex-m0. I am using clang 13.0.0 (official binaries from github). I tried building on both Windows and Linux machines. Clang lists cortex-m0 as available for target arm-none-eabi. llc lists thumb in the list of targets (and all my own functions are correctly built in thumb mode).
What am I doing wrong?
Thanks for help

I traced it down to the wrong libgcc.a being linked. I did not provide the correct architecture/thumb flags when executing arm-none-eabi-gcc -print-libgcc-file-name and it supplied the default version of that library build in ARM mode.

Related

How to Cross-Compile from LLVM IR to Assembly for ARM Cortex M4?

I'm trying to cross-compile an llvm-ir file to assembly, or better generate an object file, for an ARM Cortex M4 microprocessor using llc compiler.
Which are the parameters that I have to specify in order to do so?
I have tried with this command
llc -mtriple=armv7m-eabi -mcpu=cortex-m4 file.ll -o file.s
It doesn't throw any error but the assembly code generated is still for an x86 machine.
In particular, trying to compiling with random parameters, e.g.
llc -mtriple=randomwords -mcpu=cortex-m4 file.ll -o file.s
It goes smooth, producing an assembly code for the x86 machine. It ignores what I specify.
I found a solution, or better a work around to this problem.
Instead of using directly llc, first I've obtained the binary code through this command
llvm-as file.ll -o file.bc
An than I used clang to crosscompile and obtain the object file for ARM Cortex M4 using this instruction
clang --target=arm-none-eabi -march=armv7e-m -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -nostdlib file.bc -c -o file.o
The -c is used to compile only.
It is also possible to obtain the assembly code by using the following command line
clang -S --target=arm-none-eabi -march=armv7e-m -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -nostdlib file.bc -o file.s
llc (not sure about prior to v9) seems to only care about the architecture.
I can cross compile and link with the following script (for a RPI running Linux):
#/bin/sh
llc-9 -march=arm -float-abi=hard -O3 -filetype obj $1.ll -o $1.o
~/devel/musl/musl-cross-make/output/bin/arm-linux-musleabihf-gcc -mfloat-abi=hard -static $1.o -o $1
llc --version will show the available architectures
Try the following for your case (or use a more specific architecture if it is in the list):
llc -march=arm -mcpu=cortex-m4 -filetype obj file.ll -o file.o

Cross Compile Raspberry with external libraries - copying of target folders

I am cross compiling C-Code from Mac OS (Host) for a Raspberry Pi B+, running Raspbian Jessie, (Target). In order to link external libraries ("WiringPi" and "pthread") during make I have used a somewhat lazy approach of copying the relevant folders containing headers and libraries from the target (i.e. /lib/, /usr/include/, /usr/lib/, /usr/local/lib/, /usr/local/include/) to the host machine in advance.
My Cross GCC Compiler call is then modified as:
arm-linux-gnueabihf-gcc -I"/Path/to/copy/of/target-folders/.../usr/local/include" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.o" -o "main.o" "../main.c"
The GCC Linker call is modified as:
arm-linux-gnueabihf-gcc --sysroot=/Path/to/copy/of/target-folders/ -o "BlinkLedCrossCompile" ./main.o -lWiringPi -lpthread
This uses the copied target folders as sysroot. And so far, it works without any problems.
My question is: Is this a valid approach? Can I expect any problems further on?

clang ARM neon support

I just cross-compiled the clang compiler for ARM on my x86 machine with instructions from here. I am trying to compile a c code containing NEON intrinsics with clang compiler. It is giving error, (which i do not encounter with arm-linux-gnueabi-gcc)
$ clang -march=armv7-a -mfpu=neon -mfloat-abi=soft -integrated-as test.c -o test
In file included from test.c:2:
/home/junaid/llvm/build/Release+Asserts/bin/../lib/clang/3.2/include/arm_neon.h:28:2: error:
"NEON support not enabled"
The line test.c:2 is #include arm_neon.h
It will be the -mfloat-abi=soft. I'm surprised that works for you with an arm-none-linux-gnueabi toolchain.
For Neon support you will want to be targetting either the softfp, or hard float ABI, with either -mfloat-abi=softfp or -mfloat-abi=hard

Segmentation fault during running for mkl's interface

I am running mkl_lab_solution.c which is an example for using MKL, I can compile it correctly, while I run it, I got Segmentation fault.My runtime is below:
OS is centos 6.3
gcc's version is 4.1.2
mkl is mkl_10.3.12.361
makefile is below
gcc -g -L/opt/intel/composer_xe_2011_sp1.12.361/mkl/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_lp64 -lmkl_intel_sp2dp -lmkl_intel_thread -lmkl_core -lpthread -L/opt/intel/composer_xe_2011_sp1.12.361/compiler/lib/intel64 -liomp5 -L/usr/lib64 -lstdc++ -I/opt/intel/composer_xe_2011_sp1.12.361/mkl/include -o test mkl-lab-solution.c
Since this works fine on my system, let me point you to possible errors.
First, you need to run . /path/to/intel/compilervars.sh intel64 such all environment variables are set, like MKLROOT.
Second, check on intel mkl link line advisor for the options on your system. So reading your compile command I guess: linux, gnu compiler, dynamic linked, 64 bit target architecture, 64 bit long pointer, multithreaded, intel omp library.
These settings give me:
linker options:
-L$(MKLROOT)/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm
compile options:
-DMKL_ILP64 -m64 -I$(MKLROOT)/include
For whatever reason the brackets around MKLROOT don't work on bash, so just remove them.
Next remember to put all compile options in front of linker options. The final command line should read like this:
gcc mkl-lab-solution.c -DMKL_ILP64 -m64 -I$MKLROOT/include -L$MKLROOT/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm
Since you get runtime errors, I suspect that you are linking the Intel MKL libraries with objects compiled for different interface layers.

intel_sse2 problems when linking to gsl with icc

My program links to both PETSc and gsl, and both libraries were compiled with icc. Here's the link command:
/usr/local/mpich2/bin/mpicc -Wall -Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -g3 -I/usr/local/gsl-icc-1.15/include/ -I/usr/local/gsl-icc-1.15/include/ -L/usr/local/gsl-icc-1.15/lib/ -lgsl -lgslcblas prog_name.o -L/usr/local/petsc-3.2-p6/lib -lpetsc -lX11 -lpthread -llapack -lblas -L/central/intel/Compiler-11.1.072/mkl/lib/em64t -L/central/intel/Compiler-11.1.072/lib/intel64 -L/central/intel/Compiler-11.1.072/tbb/intel64/cc3.4.3_libc2.3.4_kernel2.6.9/lib -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -ldl -lgcc_s -lifport -lifcore -limf -lsvml -lm -lipgo -lirc -lpthread -lirc_s -lm -lstdc++ -lstdc++ -ldl -lgcc_s -ldl -o prog_name
MPICH_CC is set to icc, so mpicc calls the intel compiler.
When I try to link to the gsl .so file, I get the following errors:
gsl-icc-1.15/lib/libgsl.so: undefined reference to `__intel_sse2_strcpy'
gsl-icc-1.15/lib/libgsl.so: undefined reference to `__intel_sse2_strchr'
gsl-icc-1.15/lib/libgsl.so: undefined reference to `__intel_sse2_strncpy'
What could be the cause of this error? Is gsl incompatible with the intel compiler?
What could be the cause of this error?
You didn't show us your link command, but my crystall ball tells me that you are trying to link libgsl.so with ld (or perhaps with gcc), instead of icc.
In general, one should never link anything directly with ld on UNIX. Always use appropriate compiler driver (icc in this case).
I also get the same error message when linking some code with gcc against a PETSc version that was compiled with icc. Even more, when using the newest Intel 12.x compiler for the final code, and compiling PETSc with Intel 11.x results in the same error message as Intel 12.x uses 11.x.
So check, that mpicc really use the Intel 11.1.072 compiler. Check for mpic++ -show and which icc.
Maybe the intel environment not set.
Try the following environment setting:
source /etc/Intel_Compiler/10.0/XXXX/iccvars_intel64.sh
source /etc/Intel_Compiler/10.0/XXXX/ifortvars_intel64.sh
make the folder to your Intel Compiler folder. Some version's environment setting is different, you can also try:
source /etc/Intel_Compiler/10.0/XXXX/iccvars.sh intel64
source /etc/Intel_Compiler/10.0/XXXX/ifortvars.sh intel64
Hope helpfully.

Resources