gcc link error depending on the input file argument position - gcc

Environment
$ lsb_release -a
Description: Ubuntu 20.04.2 LTS
$gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Problem
link error happens depending on the position of input file.
NG
$gcc -lsndfile -o snd-003 snd-003.c
/usr/bin/ld: /tmp/ccMmdgxh.o: in function `main':
snd-003.c:(.text+0x5c): undefined reference to `sf_open'
/usr/bin/ld: snd-003.c:(.text+0x88): undefined reference to `sf_readf_short'
/usr/bin/ld: snd-003.c:(.text+0xc4): undefined reference to `sf_close'
collect2: error: ld returned 1 exit status
OK
If you change the argument position of input file, then link error does not happen.
$gcc snd-003.c -lsndfile -o snd-003
Other info
snd-003.c is uploaded below (just FYI).
https://file.io/PA4K22CzXwsi
this problem happens on other gcc version
gcc 8.4.0
gcc 7.5.0
this error happens on other libraries too (e.x. libssl).
there is no this problem on other machines.
deiban 10.9 (gcc 8.3.0)
debian 8.3 (gcc 4.9.2)
similar problem reported long time ago, but it's not solved.
strange g++ linking behavior depending on arguments order
Question
Does anyone have some clue on what's wrong with this ? gcc ? environment ?
I want to know the root cause of this behavior.
Any comments are really appreciated.

I guess this is the expected behavior (https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html):
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again. See the -( option for a way to force the linker to search archives multiple times.

Related

Darwin `ld` stubbornly won't find symbol that's defined in object file, while `lld` does

When using macOS's built in ld, I get the following error:
ld -arch x86_64 -platform_version macos 11.0 12.2.1 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -lSystem -lc++ -o /Users/blashyrk/Documents/source/nim/asserttrigger /Users/blashyrk/.cache/nim/asserttrigger_d/asserttrigger.o
Undefined symbols for architecture x86_64:
"_nlvmEHPersonality", referenced from:
Dwarf Exception Unwind Info (__eh_frame) in asserttrigger.o
ld: symbol(s) not found for architecture x86_64
However, that symbol is a function that's defined inside that very same object file.
Using objdump on the object file, I can confirm that the function is indeed there:
objdump -t ~/.cache/nim/asserttrigger_d/asserttrigger.o | grep nlvmEH
00000000000063b0 l F __TEXT,__text _nlvmEHPersonality
And just to make sure I wasn't crazy, I decided to see for myself with Ghidra (please see attached image).
So my question is, what makes macOS's ld not find this symbol? When using LLVM's lld it works, so the symbol is defined properly.
Am I, perhaps, missing a flag? Is ld expecting the EH personality function to be a part of some external object/library?
Here's also a link to the object file, if someone wants to try it out on their end: https://www46.zippyshare.com/v/0UFxM7zD/file.html
The program (if you manage to link it successfully) should run and exit with no output.
I've gotten it to work by changing the linkage type of nlvmEHPersonality from internal to external.
For some reason, ld64 cant't find it with internal linkage even though lld can.

What does "ld: mach-o string pool extends beyond end of file" mean?

I am currently trying to make and install a specialist suite of software (https://github.com/scottransom/presto), and am encountering this error:
gfortran -g -fPIC -o /path-to/presto/bin/psrorbit powerplot.o xyline.o psrorbit.o -L/usr/local/Cellar/cfitsio/3.450/lib -lcfitsio -lcurl -L/path-to/presto/lib -lpresto -L/usr/local/lib -lfftw3f -L/usr/local/lib/pgplot -lcpgplot -lpgplot -L/opt/X11/lib -lX11 -L/opt/X11/lib -lpng16 -lm
ld: mach-o string pool extends beyond end of file in /usr/local/lib/libcpgplot.dylib file '/usr/local/lib/libcpgplot.dylib' for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [psrorbit] Error 1
I don't think it's a problem related to PRESTO per se, as several searches (see this, this, and this) point to something fundamental, perhaps with Xcode. I currently have version 11.3, and I also installed the command line tools. So again, what does the error itself mean? Any help would be useful!
According to my reading of the source code for Apple's version of ld, this error means that the symbol table in an object prematurely ends when the file does.
There appear to be quite a few sanity checks performed on object files when linking. Likely, your copy of /usr/local/lib/libcpgplot.dylib is corrupt.

fglut/libfglut.a(freeglut_state.o): undefined reference to symbol 'XGetWindowAttributes'

I am compiling a C++ program using make, this is the error i'm getting.
/usr/bin/ld: fglut/libfglut.a(freeglut_state.o): undefined reference to symbol 'XGetWindowAttributes'
//usr/lib/i386-linux-gnu/libX11.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Makefile:55: recipe for target 'morphlines' failed
make: *** [morphlines] Error 1
I'm beginner
/usr/bin/ld: fglut/libfglut.a(freeglut_state.o):
This tells me you link libfglut statically (*.a is just an archive of object files). When you do this, you must link all dependencies as well, because with the object files from the static library actually compiled into your program, your program will depend on them.
Either link libfglut dynamically (this is the default with the GNU toolchain), so your program will depend on libfglut.so which will itself depend on libX11.so -- or add -lX11 after -lfglut on the command line of your final linking step. You might need -Wl,-Bdynamic before -lX11 to switch the linker back to dynamic linking.
If this doesn't directly solve your problem, I suggest you edit your question to include the relevant parts of the Makefile you're using.

Can't find libstdc++?

I built gcc 4.9.0 from source, and was also planning on building clang 3.4.2, however something seems to have gone awry with regards to libstdc++, as the clang build baled pretty quickly with the linker complaining about various undefined references from std.
Indeed, I then tried compiling and linking the trivial program:
#include <iostream>
int main() {
std::cout << 42;
}
and again hit linker errors:
/tmp/ccrptgVW.o:temp.cpp:function main: error: undefined reference to 'std::cout'
/tmp/ccrptgVW.o:temp.cpp:function main: error: undefined reference to 'std::ostream::operator<<(int)'
/tmp/ccrptgVW.o:temp.cpp:function __static_initialization_and_destruction_0(int, int): error: undefined reference to 'std::ios_base::Init::Init()'
/tmp/ccrptgVW.o:temp.cpp:function __static_initialization_and_destruction_0(int, int): error: undefined reference to 'std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
(full gcc -v output), both with my freshly-minted gcc 4.9.0 and my Ubuntu's stock gcc 4.6.3.
libstdc++.so exists, in /usr/local/lib64:
ls /usr/local/lib64/libstd*
/usr/local/lib64/libstdc++.a
/usr/local/lib64/libstdc++.so
/usr/local/lib64/libstdc++.so.6.0.20
/usr/local/lib64/libstdc++.la
/usr/local/lib64/libstdc++.so.6
/usr/local/lib64/libstdc++.so.6.0.20-gdb.py
and this directory appears in LIBRARY_PATH and as an -L argument to collect2 in the verbose gcc output.
How do I restore sanity to my system and have the linker find the shared library?
As turns out from your comment, you compiled with gcc rather than g++.
Do not take it as an error, as the compilation went fine! What's showing up is a linker error. Indeed, gcc will tell ld to link against the C standard library rather than the C++ standard one.
To solve, either go for g++ directly or pass -lstdc++.

Building GLFW with MinGW64 gcc -- entry-symbol warnings & linker errors

This is on a fairly fresh vanilla Win7 64-bit installation with the latest MinGW64, in a clean (freshly extracted) GLFW 2.7.5 source directory calling their make win32-msys command.
[A] Building the libs
#1 -- Warning at gcc -c -I. -I.. -Wall -mwin32 -O2 -o win32_init.o win32_init.c:
win32_init.c: In function '_glfwPlatformTerminate':
win32_init.c:353:27: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
#2 -- Warning at gcc -c -I. -I.. -Wall -mwin32 -O2 -mdll -DGLFW_BUILD_DLL -D_GLFW_NO_DLOAD_GDI32 -D_GLFW_NO_DLOAD_WINMM -o win32_init_dll.o win32_init.c:
win32_init.c: In function '_glfwPlatformTerminate':
win32_init.c:353:27: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
But the relevant output files do get created in .\lib\win32: glfw.dll, libglfwdll.a and libglfw.a. However I worry those might be corrupted, since it's impossible for me to link to them via gcc later on -- same problem as the last one in this post described further down.
[B] Building the examples
#3 -- Warning at triangle.exe, pong3d.exe, splitview.exe, mipmaps.exe, gears.exe, boing.exe, wave.exe, heightmap.exe:
c:/mingw64/x86_64-w64-mingw32/bin/ld.exe: warning: cannot find entry symbol _mainCRTStartup; defaulting to 0000000000401000
Not so however for listmodes.exe, mthello.exe, mtbench.exe and particles.exe which build fine. Indeed those 4 are the only ones running properly here afterwards, the others just exit immediately without outputs or errors (naturally, since there is no valid entry point for them).
[C] Building the tests
Warning at accuracy.exe, dynamic.exe:
c:/mingw64/x86_64-w64-mingw32/bin/ld.exe: warning: cannot find entry symbol _mainCRTStartup; defaulting to 0000000000401000
No such problem for defaults.exe. For dynamic.exe it then proceeds with the following errors:
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x1c): undefined reference to `__imp_glfwGetVersion'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x62): undefined reference to `__imp_glfwInit'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0xcf): undefined reference to `__imp_glfwOpenWindow'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x10b): undefined reference to `__imp_glfwSetWindowTitle'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x118): undefined reference to `__imp_glfwSetWindowSizeCallback'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x123): undefined reference to `__imp_glfwSwapInterval'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x14a): undefined reference to `__imp_glfwGetWindowParam'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x151): undefined reference to `__imp_glfwSwapBuffers'
C:\Users\roxor\AppData\Local\Temp\cc8hsorn.o:dynamic.c:(.text.startup+0x174): undefined reference to `__imp_glfwTerminate'
collect2: ld returned 1 exit status
make[1]: *** [dynamic.exe] Error 1
make[1]: Leaving directory `/c/glfw64/tests'
make: *** [win32-msys] Error 2
Now this latter one is the test program for loading the DLL. You might think that's simply missing the necessary libs (.a and .dll) in the correct places, but do note at this very point I DID have all the necessary includes and libs (from an earlier GLFW make that was exactly the same as the above, same versions, same warnings, same output files) in the correct places:
libglfwdll.a in \MinGW64\x86_64-w64-mingw32\lib (next to libglu32.a, libopengl32.a)
glfw.h in \MinGW64\x86_64-w64-mingw32\include\GL (next to gl.h, glaux.h, glu.h)
glfw.dll in \windows and \windows\system32 (next to opengl32.dll, glu32.dll)
Problem A is harmless but I've added an additional cast to remove the warning. Problems B and C are due to two bugs in GLFW. They have now been fixed, in part thanks to this thread. Thanks for posting it to the GLFW bug tracker and so bringing them to my attention. The fixes will be included in the 2.7.6 release. Until then, you can grab trunk from the GLFW Subversion repository.
Problem C was tricky enough to solve that someone may find a summary useful.
Proper linking for 32-bit requires a .def file with __stdcall decorated symbols, but this file cannot be used for 64-bit. The solution was to have GCC generate the correct .def file for the given architecture.
This is done by linking the DLL twice. First it's linked as exporting __stdcall decorated symbols (the default) and generating the .def file (using -Wl,--output-def,file.def) and then it's linked again without decorations (using --kill-at) to produce the final DLL. This generated .def file can then be used as usual with dlltool to generate the import library.
The most useful resource I found whilst researching this was Stdcall and DLL tools of MSVC and MinGW, which among other things outlines this method.
I got the same error too.
Solved by change the file glfw-2.7.5\tests\Makefile.win32.mingw:12 from
SOLIB = ../lib/win32/libglfwdll.a
to
SOLIB = ../lib/win32/glfw.dll
I ran into the exact same problem and while researching the errors and warning I found a fix for the 'cannot find entry symbol error' warning:
In examples/Makefile.win32.msys and tests/Makefile.win32.msys change the line
WINDOWS = -mwindows -e _mainCRTStartup
to
WINDOWS = -mwindows
Kabie's fix helps with the dynamic linking error
I'm not 100% sure this is a correct solution as I don't completely understand the reason for the alternate entry point name in the first place but at least the tests seem to work and the examples run.

Resources