gnu ld: symbol remains undefined, even when it is defined - gcc

Trying to link a program which (for unknown reasons) generates a reference to "xmemdup".
I found the source code for xmemdup.c, and compiled it, and included the .o file in the link, but ld still claims it is undefined.
$ gcc -Wall -g -O2 -pipe -DBINDIR=\"/usr/bin\" -c -o rsh.o rsh.c
This worked, generating rsh.o
$ ll rsh.o ../publib-0.40/alloc/xmemdup.o
-rw-r--r-- 1 perryh perryh 2344 Dec 29 22:25 ../publib-0.40/alloc/xmemdup.o
-rw-r--r-- 1 perryh perryh 68656 Dec 30 00:47 rsh.o
Proves that the .o files I am about to pass to the linker do exist. BTW xmemdup.o is an object file, not a library, so it should get included unconditionally even if it were not needed to resolve a reference.
$ gcc -Wall -g -O2 -pipe -DBINDIR=\"/usr/bin\" -o rsh rsh.o ../publib-0.40/alloc/xmemdup.o
/usr/bin/ld: symbol lookup error: /usr/bin/ld: undefined symbol: xmemdup
collect2: error: ld returned 127 exit status
and yet the linker can't see the definition of xmemdup in xmemdup.o

Related

ld cannot find shared library even with -L specified

I'm trying to compile a C file against a shared library at a specific location (/home/user/cuda_sync_analyzer-install/lib/libInsertTimingInstr.so), but ld cannot seem to find it -
$ gcc -g -I/home/user/tools/cuda_sync_analyzer/src/InsertTimingInstr \
-L/home/user/cuda_sync_analyzer-install/lib/ \
callback.c -o callback -lInsertTimingInstr.so
/usr/bin/ld: cannot find -lInsertTimingInstr.so
collect2: error: ld returned 1 exit status
I also tried
$ gcc -g -I/home/user/tools/cuda_sync_analyzer/src/InsertTimingInstr \
-L/home/user/cuda_sync_analyzer-install/lib/ \
-lInsertTimingInstr.so callback.c -o callback
/usr/bin/ld: cannot find -lInsertTimingInstr.so
collect2: error: ld returned 1 exit status
as well as setting LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH=/home/user/cuda_sync_analyzer-install/lib/
$ gcc -g -I/home/user/tools/cuda_sync_analyzer/src/InsertTimingInstr \
callback.c -o callback -lInsertTimingInstr.so
/usr/bin/ld: cannot find -lInsertTimingInstr.so
collect2: error: ld returned 1 exit status
The file libInsertTimingInstr.so is present in the directory -
$ ls -l /home/user/cuda_sync_analyzer-install/lib/ | grep Timing
-rw-r--r-- 1 user user 51992 Mar 18 18:04 libInsertTimingInstr.so
but ld cannot seem to find it
This command line: gcc ... -lInsertTimingInstr.so ... asks the linker to link against libInsertTimingInstr.so.a or libInsertTimingInstr.so.so, neither of which exists.
You want: gcc ... -lInsertTimingInstr ... (i.e. drop the lib prefix and the .so suffix).
Alternatively, you could do this: gcc ... /home/user/cuda_sync_analyzer-install/lib/libInsertTimingInstr.so ...

gcc compile error ld cannot find -l Permission denied

When I execute:
gcc D:\project\c\test\collection -Wall -o test main.c -lfoo
it reports the error:
D:\project\c\test\collection>gcc D:\project\c\test\collection -Wall -o test main.c -lfoo
d:/gcc-9.2.0-no-debug/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
cannot find D:\project\c\test\collection: Permission denied
d:/gcc-9.2.0-no-debug/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
cannot find -lfoo
collect2.exe: error: ld returned 1 exit status
I followed the steps found here: gcc example
My OS is Windows 10 and I use cmd with administrator role.
UPDATE 1
I execute:
gcc -L D:\project\c\test\collection -Wall -o test main.c -lfoo
and get the error:
gcc -L D:\project\c\test\collection -Wall -o test main.c -lfoo
d:/gcc-9.2.0-no-debug/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lfoo
collect2.exe: error: ld returned 1 exit status
My collection directory has libfoo.so file:
2019/12/28 11:19 <DIR> .
2019/12/28 11:19 <DIR> ..
2019/12/28 10:55 3,262 a.exe
2019/12/28 10:38 87 foo.c
2019/12/28 10:37 80 foo.h
2019/12/28 10:38 838 foo.o
2019/12/28 10:38 47,372 libfoo.so
2019/12/28 10:38 134 main.c
UPDATE 2
I change to execute:
gcc -L / -Wall -o test main.c
and get the error:
//libfoo.dll.a: Unrecognized file: File truncated,collect2.exe: error: ld returned 1 exit status
gcc D:\project\c\test\collection -Wall -o test main.c -lfoo
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Files that aren't part of an option (like -o test or -lfoo) are generally considered to be input files for compiling or linking.
There's a good chance that's meant to be a library location for locating the foo library, simply because the tutorial you're following has almost the exact same line:
gcc -L/home/username/foo -Wall -o test main.c -lfoo
If that's the case, then you're missing the -L to tell it this should be added to the library search path, so something like this should fix it:
gcc -L D:\project\c\test\collection -Wall -o test main.c -lfoo
In any case, since you appear to have all your files in a single directory (source, libs, etc), you don't need to adjust the search path. Or, if you do, you can just used -L. to specify the current directory, something like:
gcc -Wall -o test main.c -L. -lfoo

How to specify the path to lib in gcc

I have the problem about linking libraries.
"見つかりません" means "Not found"
edit LD_LIBRARY_PATH
$ LD_LIBRARY_PATH="/home/myname/.local/boost/lib" g++ main.cc -lboost_serialization
/home/myname/.linuxbrew/bin/ld: -lboost_serialization が見つかりません
collect2: error: ld returned 1 exit status
edit LIBRARY_PATH
$ LIBRARY_PATH="/home/myname/.local/boost/lib" g++ main.cc -lboost_serialization
/home/myname/.linuxbrew/bin/ld: -lboost_serialization が見つかりません
collect2: error: ld returned 1 exit status
adding the -L option (successfully compiled)
$ g++ main.cc -lboost_serialization -L "/home/myname/.local/boost/lib"
$
Indeed I have successfully compiled my program with the -L option.
But I want to compile without this (like 1 or 2, not 3).
In this case, what do I have to check or modify in my environmental variables?
note: my gcc is 5.3.0 (Homebrew gcc 5.3.0).

Making relocatable object with gcc causes "cannot find -lgcc_s" error

I'm trying to make a relocatable object file with gcc. I use solution from this post. The solution works fine with ld:
$ ld -r a.o b.o -o c.o
However when I try to use it with gcc, the following error happens:
$ gcc -r a.o b.o -o c.o
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
Using the -Wl,-r and -Wl,--relocatable options gives the same result.
Is there any way to link relocatable object file with gcc or I'm forced to use ld for doing this?
To solve this problem, the -nostdlib option must also be passed to gcc:
$ gcc -r -nostdlib a.o b.o -o c.o
I don't know it for sure, but it seems without this option gcc tries to link standard libraries into output relocatable object.

GCC 4.5 vs 4.4 linking with dependencies

I am observing a difference when trying to do the same operation on GCC 4.4 and GCC 4.5. Because the code I am doing this with is proprietary, I am unable to provide it, but I am observing a similar failure with this simple test case.
What I am basically trying to do is have one shared library (libb) depend on another shared library (liba). When loading libb, I assume that liba should be loaded as well - even though libb is not necessarily using the symbols in liba.
What I am observing is when I compile with GCC 4.4, I observe that the liba is loaded, but if I compile with GCC 4.5, libb is not loaded.
I have a small test case that consists of two files, a.c and b.c . The contents of the files:
//a.c
int a(){
return 0;
}
//b.c
int b(){
return 0;
}
//c.c
#include <stdio.h>
int a();
int b();
int main()
{
printf("%d\n", a()+b());
return 0;
}
//test.sh
$CC -o liba.so a.c -shared
$CC -o libb.so b.c -shared -L. -la -Wl,-rpath-link .
$CC c.c -L. -lb -Wl,-rpath-link .
LD_LIBRARY_PATH=. ./a.out
This is my output with different versions of GCC
$ CC=gcc-4.4 ./test.sh
1
$ CC=gcc-4.5 ./test.sh
/tmp/cceJhAqy.o: In function `main':
c.c:(.text+0xf): undefined reference to `a'
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
$ CC=gcc-4.6 ./test.sh
/tmp/ccoovR0x.o: In function `main':
c.c:(.text+0xf): undefined reference to `a'
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
$
Can anyone explain what is happening? Another extra bit of information is that ldd on libb.so does show liba.so on GCC 4.4 but not on GCC 4.5.
EDIT
I changed test.sh to the following:
$CC -shared -o liba.so a.c
$CC -L. -Wl,--no-as-needed -Wl,--copy-dt-needed-entries -la -shared -o libb.so b.c -Wl,-rpath-link .
$CC -L. c.c -lb -Wl,-rpath-link .
LD_LIBRARY_PATH=. ./a.out
This gave the following output with GCC 4.5:
/usr/bin/ld: /tmp/cc5IJ8Ks.o: undefined reference to symbol 'a'
/usr/bin/ld: note: 'a' is defined in DSO ./liba.so so try adding it to the linker command line
./liba.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
There seems to have been changes in how DT_NEEDED libraries are treated during linking by ld. Here's the relevant part of current man ld:
With --copy-dt-needed-entries dynamic libraries mentioned on the command
line will be recursively searched, following their DT_NEEDED tags to other libraries, in order to resolve symbols required by the output binary. With the
default setting however the searching of dynamic libraries that follow it will stop with the dynamic library itself. No DT_NEEDED links will be traversed
to resolve symbols.
(part of the --copy-dt-needed-entries section).
Some time between GCC 4.4 and GCC 4.5 (apparently, see some reference here - can't find anything really authoritative), the default was changed from the recursive search, to no recursive search (as you are seeing with the newer GCCs).
In any case, you can (and should) fix it by specifying liba in your final link step:
$CC c.c -L. -lb -la -Wl,-rpath-link .
You can check that this linker setting is indeed (at least part of) the issue by running with your newer compilers and this command line:
$CC c.c -L. -Wl,--copy-dt-needed-entries -lb -Wl,--no-copy-dt-needed-entries \
-Wl,-rpath-link .

Resources