- 论坛徽章:
- 3
|
=====================================================
4. the translation steps
pretend there's a program composed of obj.c and main.c.
the example is in the attachment, lies in the dir compile.
we can invoke gcc on commandline like the following:
#gcc main.c obj.c
then an executable program named a.out will be yield.
gcc hide the process how it be made.
in fact, the 2 source files are preprocessed, compiled, and assembled independently, each source
file yield an object file, then the 2 object files is linked.
obj.c
\
\ preprocesser. substitute the macro string, and do header files include, etc.
\ #cpp obj.c > obj.i
\ or
\ #gcc -E obj.c -o obj.i
\
\------> obj.i
\
\ compiler, to compile C source file to assembly source file.
\ the compiler is cc1. the compiler is wrapped by gcc,
\ we can manually invoke it on commandline:
\ (this command depend on platform, 4.4.3 is the gcc version on my system)
\ #/usr/lib/gcc/x86_64-linux-gnu/4.4.3/cc1 obj.c -o obj.s
\ or
\ #gcc -S obj.c -o obj.s
\
\------> obj.s
\
\ assembler, to assemble the assembly source file to binary object file.
\ #as obj.s -o obj.o
\ or
\ #gcc -c obj.s -o obj.o
\
\------> obj.o
main.c
\
\ #gcc -c main.c -o main.o
\
\------> main.o
-------------------------------------------------------------------------------------
then, we link these 2 object files:
#gcc main.o obj.o
the program named a.out is yield.
in fact we can manually invoke ld on commandline to complete the link step.
but many details, at this occasion, are very complex. these details should be cared by gcc
but not us.
why? because in fact the C library should be linked with our object files -- we used printf in
our program. and printf is a routine lies in the standard C library. we know, libraries on
our system lies in dir /lib or /usr/lib, so the standard C library is /usr/lib/libc.a(static library)
or /lib/libc.so.*(shared object, or dynamic linked library). in most cases, if we just invoke
gcc like the above command, the .so library is linked; and some cases the static .a library is
used, so, the standard C library just supplied itself by .a and .so form.
and, the crt1.o, crti.o, crtn.o should be linked with our object files too. -- now just never mind
what these crt*.o are...
not over yet.
in fact, you can see the details what's gcc do at the link step. just add a --verbose or -v option:
#gcc main.o obj.o --verbose
see it?
so, if you really want to invoke ld manually, you can use the following command[it work on my platform,
ubuntu 10.04 LTS, x86_64. your environment is the about the same with me, so you can try it]:
#ld main.o obj.o /usr/lib/crt*.o -lc --dynamic-linker /lib/ld-linux-x86-64.so.2 -o main
the above ld invocation will yield the executable program main.
1) main.o obj.o /usr/lib/crt*.o should be linked.
2) -lc: -l is a option means to link a library; c is the .so library libc.so.6, -lc means to link the
standard C library.
3) --dynamic-linker option specify the dynamic linker we need: /lib/ld-linux-x86-64.so.2
more complete command:
#ld main.o obj.o -dynamic-linker /lib/ld-linux-x86-64.so.2 /usr/lib/crt1.o /usr/lib/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3
-lgcc -lgcc_eh -lc /usr/lib/gcc/i686-linux-gnu/4.4.5/crtend.o /usr/lib/crtn.o -o main
1) -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3 specify the dir in addition to the default path
in which the ld search libraries.
2) you can ls these dirs in the above command.
tips: the above commands may be changed depend on different platform & system.
by the way, the ld's true colors is the program collect2.
so now you see why invoke ld manually on commandline is not a good idea.
-------------------------------------------------------------------------------------
a question:
why does compiler just translate C source language to assembly language?
why doesn't compiler translate C source language to object file directly?
a good question, isn't it?
let's shelve this question temporarily. |
|