Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error when trying to link with static c standard library

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.

like image 863
social_loser Avatar asked Nov 03 '16 08:11

social_loser


2 Answers

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.

like image 184
Basile Starynkevitch Avatar answered Nov 08 '22 09:11

Basile Starynkevitch


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.

like image 3
chqrlie Avatar answered Nov 08 '22 09:11

chqrlie