13

Consider the hello world C program:

hello.c:

#include "stdio.h"

int main()
{
        printf("Hello, World!\n");
}

If I call:

$ gcc -c hello.c -o hello.o

It will produce an ELF Relocatable File hello.o

If I then call:

$ gcc hello.o -o hello            [1]

It will link hello.o with ld and produce an ELF Executable File hello

However if I call ld directly [2] instead of [1]:

$ ld hello.o -o hello             [2]

I get these errors:

/usr/bin/ld.bfd.real: warning: cannot find entry symbol _start
test.c:(.text+0xa): undefined reference to `puts'

gcc must be passing other options to ld (to link the C library for example).

Is there anyway to determine exactly what the command-line gcc is passing through to ld in command [1] ?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319

2 Answers2

20

Yes, you can use gcc -v hello.o -o hello to get the link line. For your example on my ubuntu machine, I get this link line (edited to be multiline for readability):

/usr/lib/gcc/x86_64-linux-gnu/4.4.5/collect2
--build-id
--eh-frame-hdr
-m elf_x86_64
--hash-style=gnu
-dynamic-linker
/lib64/ld-linux-x86-64.so.2
-o hello
-z relro
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/crtbegin.o
-L/usr/lib/gcc/x86_64-linux-gnu/4.4.5
-L/usr/lib/gcc/x86_64-linux-gnu/4.4.5
-L/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib
-L/lib/../lib
-L/usr/lib/../lib
-L/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../.. -L/usr/lib/x86_64-linux-gnu
hello.o
-lgcc
--as-needed -lgcc_s --no-as-needed 
-lc
-lgcc
--as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crtn.o

Note that collect2 is just an alias for ld.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • 2
    It seems on my Ubuntu 12.10 64 box `collect2` is not a simple alias for `ld`. `collect2` is an executable- whereas `ld` is a sym link to `ld.bfd` which is a symlink to `hardened-ld` which is a perl script. No idea what is going on there. – Andrew Tomazos Jan 19 '13 at 20:09
  • 2
    Sorry, I don't mean literal alias. You'll find that if you run the same command with `ld` instead it will work the same, though. Docs: http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gccint/Collect2.html – Carl Norum Jan 19 '13 at 20:47
  • What is the difference between `collect2` and `ld`? Could not understand easily after reading the gccint. – Ciro Santilli OurBigBook.com May 16 '15 at 18:25
  • They are literally the same binary. – Carl Norum May 16 '15 at 20:29
2

For oneline lovers:

echo "int main(void) {}" | gcc -o /dev/null -v -x c - &> /dev/stdout| grep collect | tr -s " " "\012"

Replace -x c with -x c++ to get c++ flags.

Can be used also with clang, but in such case you should grep for /usr/bin/ld

Treviño
  • 2,999
  • 3
  • 28
  • 23