My OS is ubuntu 14.04 32bit and my source program test.c is :
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("test.");
return;
}
I compile it with command :
gcc -S test.c
which output as a test.s file. I assemble it with command :
as -o test.o test.s
then I want to link it with c standard library statically. I searched for libc.a
file , located it at /usr/lib/i386-linux-gnu/libc.a
. so I tried to link it with command:
ld test.o /usr/lib/i386-linux-gnu/libc.a
but comes out with a lot of error message:
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048210
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x20): undefined reference to `_Unwind_GetIP'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x45): undefined reference to `_Unwind_GetGR'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x50): undefined reference to `_Unwind_GetCFA'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `__backtrace':
(.text+0xb1): undefined reference to `_Unwind_Backtrace'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o): In function `_IO_new_fclose':
(.text+0x1b1): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o):(.eh_frame+0x167): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o): In function `_IO_fflush':
(.text+0xd7): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o): In function `_IO_fputs':
(.text+0xf9): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o): In function `_IO_fwrite':
(.text+0x139): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o): In function `_IO_getdelim':
(.text+0x285): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o): In function `_IO_wfile_underflow':
(.text+0x5fc): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o):(.eh_frame+0x137): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(fileops.o): In function `_IO_new_file_underflow':
(.text+0x40b): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(fileops.o):(.eh_frame+0x1b3): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xbc6): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xc08): undefined reference to `__moddi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0x249d): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xcc9): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xd0b): undefined reference to `__moddi3'
...
...
My question is, why these error messages ? I'm trying to learn how the compiling system works, so instead of knowing how to solve this problem I 'm more desiring to know how it comes this way. It seems that the static C library depends on other libraries, why and what are those libraries ?
EDIT:
I'm doing this because I want to know how things work so I'd rather avoid the gcc
script.
You also need crt0 startup object files (in addition of static libc.a
), which notably are defining the _start
entry point (in your ELF executable) and contain ABI specific (prologue and epilog) code to call your main
(and finally process atexit(3) registered handlers and stdio flushing). The low-level libgcc is also needed. Details are complex and implementation specific. To understand them, compile your test code as
gcc -v -static test.c -o mytest
(avoid calling an executable test
because it would collide with /usr/bin/test
or with the builtin of your shell)
In practice, better at least link with gcc
If you are curious, take advantage that Linux is mostly free software and study the source code (e.g. of GCC, of the C standard library, of binutils, etc...). You might find musl-libc interesting.
I'd rather avoid the
gcc
script
Technically, gcc
is not a script but a driver program (see gcc/gcc.c in the source code of GCC). But it will run ld
which indeed runs some linker scripts. The actual compilation is done by cc1 which is started by the gcc
program.
You must also link the gcc
intrinsic library. The easiest way to do this is to use the gcc
front-end to compile and link with the -static
option:
gcc -static -o test test.c
If you insist on compiling from assembly, you can do this:
gcc -static -o test test.s
Static linking may not be supported on your system.
EDIT: giving gcc the -v
option will tell you what commands it executes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With