I can override some linker symbol on command line i.e
arm-none-eabi-gcc -Wl,--defsym=exit=0 -Wl,--defsym=atexit=0
-mthumb -march=armv7 -T board.ld test.c -0 test
But how can I override this with linker file i.e (how can provide -Wl,--defsym=exit=0 -Wl,--defsym=atexit=0 through linker script file)
Related
The man for gold states:
-L DIR, --library-path DIR
Add directory to search path
--rpath-link DIR
Add DIR to link time shared library search path
The man for bfd ld makes it sort of sound like -rpath-link is used for recursively included sos.
ld.lld doesn't even list it as an argument.
Could somebody clarify this situation for me?
Here is a demo, for GNU ld, of the difference between -L and -rpath-link -
and for good measure, the difference between -rpath-link and -rpath.
foo.c
#include <stdio.h>
void foo(void)
{
puts(__func__);
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
foobar.c
extern void foo(void);
extern void bar(void);
void foobar(void)
{
foo();
bar();
}
main.c
extern void foobar(void);
int main(void)
{
foobar();
return 0;
}
Make two shared libraries, libfoo.so and libbar.so:
$ gcc -c -Wall -fPIC foo.c bar.c
$ gcc -shared -o libfoo.so foo.o
$ gcc -shared -o libbar.so bar.o
Make a third shared library, libfoobar.so that depends on the first two;
$ gcc -c -Wall -fPIC foobar.c
$ gcc -shared -o libfoobar.so foobar.o -lfoo -lbar
/usr/bin/ld: cannot find -lfoo
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
Oops. The linker doesn't know where to look to resolve -lfoo or -lbar.
The -L option fixes that.
$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar
The -Ldir option tells the linker that dir is one of the directories to
search for libraries that resolve the -lname options it is given. It searches
the -L directories first, in their commandline order; then it searches its
configured default directories, in their configured order.
Now make a program that depends on libfoobar.so:
$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
Oops again. The linker detects the dynamic dependencies requested by libfoobar.so
but can't satisfy them. Let's resist its advice - try using -rpath or -rpath-link -
for a bit and see what we can do with -L and -l:
$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar
So far so good. But:
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
at runtime, the loader can't find libfoobar.so.
What about the linker's advice then? With -rpath-link, we can do:
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)
and that linkage also succeeds. ($(pwd) means "Print Working Directory" and just "copies" the current path.)
The -rpath-link=dir option tells the linker that when it encounters an input file that
requests dynamic dependencies - like libfoobar.so - it should search directory dir to
resolve them. So we don't need to specify those dependencies with -lfoo -lbar and don't
even need to know what they are. What they are is information already written in the
dynamic section of libfoobar.so:-
$ readelf -d libfoobar.so
Dynamic section at offset 0xdf8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...
...
We just need to know a directory where they can be found, whatever they are.
But does that give us a runnable prog?
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
No. Same as story as before. That's because -rpath-link=dir gives the linker the information
that the loader would need to resolve some of the dynamic dependencies of prog
at runtime - assuming it remained true at runtime - but it doesn't write that information into the dynamic section of prog.
It just lets the linkage succeed, without our needing to spell out all the recursive dynamic
dependencies of the linkage with -l options.
At runtime, libfoo.so, libbar.so - and indeed libfoobar.so -
might well not be where they are now - $(pwd) - but the loader might be able to locate them
by other means: through the ldconfig cache or a setting
of the LD_LIBRARY_PATH environment variable, e.g:
$ export LD_LIBRARY_PATH=.; ./prog
foo
bar
rpath=dir provides the linker with the same information as rpath-link=dir
and instructs the linker to bake that information into the dynamic section of
the output file. Let's try that:
$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar
All good. Because now, prog contains the information that $(pwd) is a runtime search
path for shared libraries that it depends on, as we can see:
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
That search path will be tried after the directories listed in LD_LIBRARY_PATH, if any are set, and before the system defaults - the ldconfig-ed directories, plus /lib and /usr/lib.
The --rpath-link option is used by bfd ld to add to the search path used for finding DT_NEEDED shared libraries when doing link-time symbol resolution. It's basically telling the linker what to use as the runtime search path when attempting to mimic what the dynamic linker would do when resolving symbols (as set by --rpath options or the LD_LIBRARY_PATH environment variable).
Gold does not follow DT_NEEDED entries when resolving symbols in shared libraries, so the --rpath-link option is ignored. This was a deliberate design decision; indirect dependencies do not need to be present or in their runtime locations during the link process.
I have static library lib.a and in all tutorials using:
gcc -o main main.o -L. -lib
But I cant, I have errors:
/usr/bin/ld: cannot find -lib
collect2: error: ld returned 1 exit status
I need to use:
gcc -o main main.o -L. -lib.a
Why? What should I do to repair it ?
From the documentation of gcc -l:
-llibrary:
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
...
The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories.
So you cannot use -l with a library named 'lib.a'. Use 'lib.a' without the -l to include it. Of course, you cannot use -L then to set the directories to be searched for this particular library.
Do you have the error with this line ?
gcc -o main main.o -L. -llib
As MicroVirus found in the documentation, you will have to rename your library in liblib.a to use my previous line or just pass your library to gcc like a simple file.
While I was trying to solve a linker problem with g++, I found that trying to compile link a simple one-file program in one command was failing, due to undefined symbols.
g++ -lEGL -lGLESv2 -o test test.cpp
However, if I compiled test.cpp separately, and then linked as a second step, everything works OK.
g++ -c test.cpp
g++ -o test test.o -lGL -lGLESv2
What's the difference between the first command and the others, and why would one way fail and the other way work? I'm guessing it's something to do with the order of linking, but I get the feeling that this is a little buggy.
When you compile and link in one go, as per:
g++ -lEGL -lGLESv2 -o test test.cpp
g++ obeys as if you did:
g++ -c -o deleteme.o test.cpp
g++ -lEGL -lGLESv2 -o test deleteme.o
rm deleteme.o
(If you run the command with the -v (verbose) option and scrutinize the
goobledegook carefully, you'll be able to spot the distinct invocations
of the compiler, assembler, and linker, with temporary files passed between).
So now do you see what's wrong? It's library search order. In the linkage:
g++ -lEGL -lGLESv2 -o test deleteme.o
You are telling the linker to search libEGL and libGLESv2 for unresolved symbols
before reading the object file, deleteme.o that requires symbols from them, so those symbols
will go unresolved. In your second linkage:
g++ -o test test.o -lGL -lGLESv2
You've got the linkage order right. There's nothing buggy here. From man ld
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.
I have got the object-file from source code using MinGW.
But on linking:
ld -o test.exe test.o
I get errors, for example the following:
undefined reference to printf
First, why are you using ld directly?
The following is an excerpt from the "GCC and Make" tutorial found at http://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html.
Compile and Link Separately
The above command compile the source file into object file and link with other object files (system library) into executable in one step. You may separate compile and link in two steps as follows:
// Compile-only with -c option
> g++ -c -Wall -g Hello.cpp
// Link object file(s) into an executable
> g++ -g -o Hello.exe Hello.o
Note g++ (you can substitute gcc if you are using C and not C++) is used both for compiling and linking. ld is not used at all.
The benefit of using g++ or gcc to link is that it will link with default libraries, such as the one you need to link with for printf, automatically.
To link with other libraries, you specify the library name with the -l parameter, as in -lmylib.
We can view commands ran by compiler via command
c99 -v test.o
We'll get some text. All after string which contains "COLLECT_CGG_OPTIONS" will be arguments of ld.
But size of executable file is much more then size of file got by previous way.
I had some problems linking the static library stxxl into a shared library as outlined in my question Linking a static library into Boost Python (shared library) - Import Error
The command I was using was
g++ -Wall -pthread -march=i686 -I/home/zenna/Downloads/stxxl-1.3.0/include -include stxxl/bits/defines.h -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -I /home/zenna/local/include/ -I /usr/include/python2.6/ -fPIC -c partition.cpp -o obj/Partition_wrap.o
and to link:
g++ -shared -lboost_python -L/home/zenna/local/lib/ -L/home/zenna/Downloads/stxxl-1.3.0/lib/bk/ -Wall -pthread -L/home/zenna/Downloads/stxxl-1.3.0/lib -lstxxl -o lib/fast_parts.so obj/Partition_wrap.o
Using nm I found the missing symbols was in the final output shared object library, but had type "U" for undefined.
I then changed the linking command to not only use -lstxxl but also add the entire archive file as another input to the linker
such that the new command was (difference at end)
++ -shared -lboost_python -L/home/zenna/local/lib/ -L/home/zenna/Downloads/stxxl-1.3.0/lib/bk/ -Wall -pthread -L/home/zenna/Downloads/stxxl-1.3.0/lib -lstxxl -o lib/fast_parts.so obj/Partition_wrap.o obj/libstxxl.a
This fixed the problem as far as I can tell.
My question is then what is the difference between using the -l flag and adding the archive as an input and why did former method result in undefined symbols?
I think the problem in your case was that you specified -lstxxl before the object files. When you put libstxxl.a at the end, the symbols from it are read again and the undefined symbols are resolved. You could try moving it before obj/Partition_wrap.o and check if it will result in undefined symbols.
From man ld
ld -o /lib/crt0.o hello.o -lc
This tells ld to produce a file called output as the result of linking the file "/lib/crt0.o" with "hello.o" and the library "libc.a",
which will come from the standard search directories. (See the discussion of the -l option below.)
Some of the command-line options to ld may be specified at any point in the command line. However, options which refer to files, such
as -l or -T, cause the file to be read at the point at which the option appears in the command line, relative to the object files and
other file options.
Non-option arguments are object files or archives which are to be linked together. They may follow, precede, or be mixed in with
command-line options, except that an object file argument may not be placed between an option and its argument.
-l namespec
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.
Although it's not mentioned very clear there doesn't seem to be any difference between the 2 ways of giving the linker the files to link.