Link error when compiling gcc atomic operation in 32-bit mode - gcc

I have the following program:
~/test> cat test.cc
int main()
{
int i = 3;
int j = __sync_add_and_fetch(&i, 1);
return 0;
}
I'm compiling this program using GCC 4.2.2 on Linux running on a multi-cpu 64-bit Intel machine:
~/test> uname --all
Linux doom 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
When I compile the program in 64-bit mode, it compiles and links fine:
~/test> /share/tools/gcc-4.2.2/bin/g++ test.cc
~/test>
When I compile it in 32-bit mode, I get the following error:
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccEVHGkB.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test>
Although I will never actually run on a 32-bit processor, I do need a 32-bit executable so I can link with some 32-bit libraries.
My 2 questions are:
Why do I get a link error when I compile in 32-bit mode?
Is there some way to get the program to compile and link, while still being able to link with a 32-bit library?

The answer from Dan Udey was close, close enough in fact to allow me to find the real solution.
According to the man page "-mcpu" is a deprecated synonym for "-mtune" and just means "optimize for a particular CPU (but still run on older CPUs, albeit less optimal)". I tried this, and it did not solve the issue.
However, "-march=" means "generate code for a particular CPU (and don't run on older CPUs)". When I tried this it solved the problem: specifying a CPU of i486 or better got rid of the link error.
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccYnYLj6.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i386 test.cc
/tmp/ccOr3ww8.o(.text+0x22): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i486 test.cc
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=pentium test.cc

From the GCC page on Atomic Builtins:
Not all operations are supported by
all target processors. If a particular
operation cannot be implemented on the
target processor, a warning will be
generated and a call an external
function will be generated. The
external function will carry the same
name as the builtin, with an
additional suffix `_n' where n is the
size of the data type.
Judging from your compiler output, which refers to __sync_add_and_fetch_4, this is what's happening. For some reason, GCC is not generating the external function properly.
This is likely why you're only getting an error in 32-bit mode - when compiling for 64-bit mode, it compiles for your processor more closely. When compiling for 32-bit, it may well be using a generic arch (i386, for example) which does not natively support those features. Try specifying a specific architecture for your chip family (Xeon, Core 2, etc.) via -mcpu and see if that works.
If not, you'll have to figure out why GCC isn't including the appropriate function that it should be generating.

Related

compiling multithreading C example with riscv gnu cross compiler

I'm using homebrew-riscv toolchain on mac machine.
I want to compile a simple multithreading program that is written using pthread library in C using riscv gnu cross compiler. So that, I've used the below command:
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 pthreadExample.c -o pthreadExample -lpthread
And I've got the following warning and error:
warning: implicit declaration of function 'pthread_create' [-Wimplicit-function-declaration]
32 | pthread_create(&tid, NULL, myThreadFun, (void *)&tid);
| ^~~~~~~~~~~~~~
pthreadExample.c:34:5: warning: implicit declaration of function 'pthread_exit' [-Wimplicit-function-declaration]
34 | pthread_exit(NULL);
| ^~~~~~~~~~~~
/opt/homebrew/Cellar/riscv-gnu-toolchain/master/lib/gcc/riscv64-unknown-elf/11.1.0/../../../../riscv64-unknown-elf/bin/ld: cannot find -lpthread
collect2: error: ld returned 1 exit status
Does anyone have any ideas for solving this error? Or should I use another option instead of -lpthread for compiling?
Thanks in advance
you are using the bare metal cross compiler, what you need is:
riscv64-unknown-linux-gnu-gcc
additionally, you are using the -march=rv32i flag, but you are using the 64 bit version of the compiler, that doesn't seem correct to me. If the target machine is a 32 bit one, then perhaps you should use the riscv32-unknown-linux-gnu-gcc

GCC 7.1.1 RISCV compilation (link) failures, incompatible ABI

I'm having difficulty doing basic compilation & link for RISCV on the latest GCC for RISCV on a windows 7-64bit platform.
Tools installed: 7.1.1-2-20170912-2255 gotten from https://github.com/gnu-mcu-eclipse/riscv-none-gcc/releases/
Platform: Windows 7, 64 bit, no cygwin
Program:
#include <stdint.h>
int32_t iBlahblah;
int main (void)
{
while(1)
iBlahblah++;
return 0;
}
Command line:
"c:\Program Files\GNU MCU Eclipse\RISC-V Embedded GCC\7.1.1-2-20170912-2255\bin\riscv64-unknown-elf-gcc.exe" -c hello.c -o hello -march=rv32imac -mabi=ilp32 -Os
"c:\Program Files\GNU MCU Eclipse\RISC-V Embedded GCC\7.1.1-2-20170912-2255\bin\riscv64-unknown-elf-gcc.exe" -o hello.elf -march=rv32imac -mabi=ilp32 -Os -Wl,-Map=hello.lst hello.o
Output:
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: hello.o: ABI is incompatible with that of the selected emulation: target emulation `elf64-littleriscv' does not match `elf32-littleriscv'
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: failed to merge target specific data of file hello.o
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/lib/rv32imac/ilp32\libg.a(lib_a-exit.o): In function `.L0 ': exit.c:(.text.exit+0x1e): undefined reference to `_exit'
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: hello.elf(.text): relocation "iBlahblah+0x0 (type R_RISCV_HI20)" goes out of range
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: hello.o: file class ELFCLASS64 incompatible with ELFCLASS32
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: final link failed: File in wrong format
collect2.exe: error: ld returned 1 exit status
The big question is how do I resolve the "ABI is incompatible with that of the selected emulation"? We can ignore the other issues regarding relocation, exit, etc. because my larger build environment takes care of that (it builds for many platforms, just not RISCV at the moment).
riscv64-unknown-elf-gcc.exe -c hello.c -o hello -march=rv32imac -mabi=ilp32 -Os
This part is wrong. Your gcc tolchain docs says https://gnu-mcu-eclipse.github.io/toolchain/riscv/
riscv64-unknown-elf-gcc vs riscv32-unknown-elf-gcc
With lots of architectures and systems supported, GCC recommends prefixing the binaries with a unique tuple:
<arch>-<vendor>-<os>-<libc/abi>-
The current RISC-V prefixes for the bare metal toolchains are riscv64-unknown-elf- and riscv32-unknown-elf-.
Well, don’t be confused by this unfortunate names. The 64 or 32 attached to the architecture ... It does not mean either that the compiler produces 64-bits or 32-bits RISC-V binaries. Actually, the compilers produce both 32/64-bits binaries, based on -march and -mabi. The only difference are defaults, when the compiler are invoked without the -march and -mabi explicitly set on the command line.
Try to use riscv32-unknown-elf-gcc.exe for compiling programs for 32-bit riscv platform (with arch & abi having r32 & 32 parts in their names), it should use correct 32-bit CRT files.
There is some support for multilib, when riscv64 will search for 32-bit libs (https://gnu-mcu-eclipse.github.io/toolchain/riscv/#multiple-libraries, https://gnu-mcu-eclipse.github.io/blog/2017/09/13/riscv-none-gcc-v7-1-1-2-20170912-released/, https://gcc.gnu.org/onlinedocs/gccint/Target-Fragment.html MULTILIB_OPTIONS), but something was wrong. Please, post gcc -v .... -o your_program.bin results for riscv32 compiler, riscv64 compiler and several march/mabi combinations.

OpenMP not available on mac with gcc 4.9

The OpenMP website says: "GCC 4.9 supports OpenMP 4.0 for C/C++".
I'm using gcc 4.9.1 from brew, yet I see this error when I try to compile liblinear: omp.h file not found.
Specifically:
Compiling liblinear version 1.93
Source code page:
http://www.csie.ntu.edu.tw/~cjlin/liblinear/
external/liblinear-1.93_multicore/matlab/train.cpp:7:10: fatal error: 'omp.h' file not found
#include <omp.h>
^
1 error generated.
mex: compile of ' "external/liblinear-1.93_multicore/matlab/train.cpp"' failed.
Here's the matlab code used to compile liblinear, which contains a file that contains #include <omp.h>:
% Compile liblinear
if ~exist('liblinear_train')
fprintf('Compiling liblinear version 1.93\n');
fprintf('Source code page:\n');
fprintf(' http://www.csie.ntu.edu.tw/~cjlin/liblinear/\n');
mex -outdir bin ...
COMPFLAGS="$COMPFLAGS -fopenmp" -largeArrayDims ...
external/liblinear-1.93_multicore/matlab/train.cpp ...
external/liblinear-1.93_multicore/matlab/linear_model_matlab.cpp ...
external/liblinear-1.93_multicore/linear.cpp ...
external/liblinear-1.93_multicore/tron.cpp ...
"external/liblinear-1.93_multicore/blas/*.c" ...
-output liblinear_train;
end`
UPDATE
I changed the gcc version in mexopts.sh (side note: I copied it from /Applications/MATLAB_R2013a_Student.app/bin/mexopts.sh to ~/.matlab/R2013a). Specifically, I changed CC=xcrun -sdk macosx10.9 clang to CC='gcc-4.9'.
I think Matlab does indeed use this compiler, because when I run this code:
if ~exist('anigauss')
fprintf('Compiling the anisotropic gauss filtering of:\n');
fprintf(' J. Geusebroek, A. Smeulders, and J. van de Weijer\n');
fprintf(' Fast anisotropic gauss filtering\n');
fprintf(' IEEE Transactions on Image Processing, 2003\n');
fprintf('Source code/Project page:\n');
fprintf(' http://staff.science.uva.nl/~mark/downloads.html#anigauss\n\n');
mex -Dchar16_t=uint16_T -outdir bin ...
selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c ...
selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss.c ...
-output anigauss
end
Matlab prints:
dyld: Library not loaded: /usr/local/opt/mpfr2/lib/libmpfr.1.dylib
Referenced from: /usr/local/Cellar/gcc49/4.9.1/libexec/gcc/x86_64-apple-darwin14.0.0/4.9.1/cc1
Reason: Incompatible library version: cc1 requires version 4.0.0 or later, but libmpfr.1.dylib provides version 3.0.0
gcc-4.9: internal compiler error: Trace/BPT trap: 5 (program cc1)
/Applications/MATLAB_R2013a_Student.app/bin/mex: line 1343: 77128 Abort trap: 6 gcc-4.9 -c -I/Applications/MATLAB_R2013a_Student.app/extern/include -I/Applications/MATLAB_R2013a_Student.app/simulink/include -DMATLAB_MEX_FILE -fno-common -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -mmacosx-version-min=10.9 -fexceptions -Dchar16_t=uint16_T -DMX_COMPAT_32 -O2 -DNDEBUG "selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c" -o bin/anigauss_mex.o
mex: compile of ' "selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c"' failed.
Yet when I try to compile liblinear, I get the very same error message as usual.
COMPFLAGS="$COMPFLAGS /openmp" -largeArrayDims ...
^^^^^^^
This was probably written for Microsoft Visual C/C++ or for Intel C/C++ Compiler on Windows. Unix systems, including OS X, traditionally use - to denote command line flags.
To enable OpenMP support in GCC you should change /openmp to -fopenmp in the compiler flags COMPFLAGS.
It appears that in addition to passing the wrong OpenMP flag, mex is using the wrong compiler. Compare the error outputs from GCC and Clang:
GCC
foo.c:1:25: fatal error: nonexistent.h: No such file or directory
#include <nonexistent.h>
^
compilation terminated.
Clang
foo.c:1:10: fatal error: 'nonexistent.h' file not found
#include <nonexistent.h>
^
1 error generated.
Clang, or at least the version that Apple ships with Xcode, does not support OpenMP. Consult the MATLAB documentation of the mex command on how to select a different compiler. Basically, you have to execute:
mex -setup
If MATLAB detects several usable compilers, it should present you with the ability to pick one of them. Unfortunately, according to this table, MATLAB might not support GCC on OS X (at least it is not listed in the table).

Should gcc builtins always be resolved during the compilation step, or the linker step?

In running gcc 3.4.3 on a Solaris 5.11 box I see that builtin functions are left undefined during compilation, but are resolved against libgcc.a when the Solaris linker links against libgcc.a.
On gcc 4.5.2 on another Solaris box, the same builtin functions are resolved during compilation of the .o, and the linker isn't concerned about them.
A boiled down example file compiled on gcc 3.4.3:
# cat ctzll.c
int func(unsigned long long x)
{
return __builtin_ctzll(x);
}
# cat main.c
int main(void)
{
return func(0xc0ffee);
}
First compile ctzll.c, and check the symbols:
# nm ctzll.o
U __ctzdi2
0000000000000000 T func
Now compile main.c, and link the objects:
# gcc -m64 main.c -c
# gcc -m64 ctzll.o main.o -v
Reading specs from /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/specs
Configured with: /build/i386/components/gcc3/gcc-3.4.3/configure --prefix=/usr/sfw --mandir=/usr/sfw/share/man --infodir=/usr/sfw/share/info --without-gnu-ld --with-ld=/usr/bin/ld --enable-languages=c,c++,f77,objc --enable-shared --with-gnu-as --with-as=/usr/gnu/bin/as
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-20050802)
/usr/sfw/libexec/gcc/i386-pc-solaris2.11/3.4.3/collect2 -V -Y P,/lib/64:/usr/lib/64:/usr/sfw/lib/64 -R /lib/64:/usr/lib/64:/usr/sfw/lib/64 -Qy /usr/lib/amd64/crt1.o /usr/lib/amd64/crti.o /usr/lib/amd64/values-Xa.o /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtbegin.o -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64 -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/../../../amd64 -L/lib/amd64 -L/usr/lib/amd64 ctzll.o main.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtend.o /usr/lib/amd64/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.2276
# nm a.out | grep ctz
0000000000400fd0 T __ctzdi2
So, if I understand correctly, the Solaris linker resolved __ctzdi2 (the internal representation of __builtin_ctzll).
Now, compile with gcc 4.5.2 on the other Solaris machine:
#gcc -m64 ctzll.c -c
# nm ctzll.o
0000000000000000 T func
The symbol has been resolved fine in the object file, and it has been inlined into the .o assembly as:
8: 48 0f bc 45 f8 bsf -0x8(%rbp),%rax
Is the 3.4.3 compiler behaving correctly? I'd have expected the actual compilation to handle the builtins, like 4.5.2, by referencing the 64 bit version of libgcc.a. The lack of uniformity across the compilers is causing upstream problems in my project as the builtin remains undefined and the linker isn't resolving the symbols as I'm not linking against the OS specific 64 bit libraries (libgcc.a). I'm not sure if the 3.4.3 compiler is misconfigured causing the .o files to have undefined builtin functions caught by linking, or if the newer compilers are just smarter and I need to add the 64 bit libraries to the linker to handler the older compiler.
The 3.4.3 seems to show a valid libgcc.a which contains the definition of _ctzdi2:
# gcc -m64 -print-libgcc-file-name
/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a
# nm /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a | grep ctzdi2
0000000000000000 T __ctzdi2
_ctzdi2.o:
The whole point of libgcc.a is to implement builtin operations that gcc can't emit code for (which includes not only __builtin_ functions, but also things like 'long long' math operations on some 32-bit platforms).
Obviously the newer gcc got smarter about emitting code.

Linker (ld) crashes on Mac OS X when compiling with debuginfo, but works fine without

I'm working on a snow leopard machine (10.6.5) and I'm hunting a bug in our C++ application. However, I can't build our app with g++ -O0 -g, because the linker crashes:
g++-4.0 -arch i386 -arch x86_64 ... -dynamic -bundle -o SOMELIB.dylib <SOME OBJECTS>...
collect2: ld terminated with signal 11 [Segmentation fault]
collect2: ld terminated with signal 11 [Segmentation fault]
I guess the two crashes are because there are two "-arch" flags.
I managed to get a core file, which said the crash occurs in
(gdb) bt
#0 0x000000010001a2eb in Linker::synthesizeDebugNotes ()
#1 0x0000000100024cc5 in Linker::collectDebugInfo ()
#2 0x0000000100028198 in Linker::link ()
#3 0x000000010002a9eb in main ()
With this hint, I removed '-g' from the compiler flags, and everything builds fine. Moreover, most of our stuff builds fine with '-g', but just two of the big modules (.dylibs) don't, so I'm left with no debuginfo for those. And, ironically, the bug lurks just there, in one of these dylibs.
The bug is most likely due to an uninitialized memory use, as it manifests rarely, and running the app under valgrind reveals that there are a few uninitialized memory refences, but because of the missing debuginfo, it just says it happens inside module XXX (the dylib I can't compile with "-g")
So, I tried to download the ld utility from Apple's open source website, but I found (just like that guy) that it won't build because of a missing dependency to a Mac-specific version of libunwind, which Apple won't give away. Thus I can't recompile the linker.
So the next question is - what should I do now? I really wanted to avoid contacting Mac support...
ld version is "ld64 97.17", XCode is 3.2.5, gcc is 4.0.1.
I really need some directions...

Resources