3

I write a program including two files main.c and comp.c

main.c

#include <stdio.h>
extern int secure_func(int, int);
void main()
{
    printf("hello, world\n");
    int result = secure_func(1, 1);
}

comp.c

int secure_func(int text, int key)
{
    return text * key * key;
}

First, I directly use gcc to build program and run executable, that is fine.

gcc -o main main.c comp.c
./main
hello, world

Then I try to use toolchain to build program step by step like this

gcc -c -o comp.o comp.c
gcc -c -o main.o main.c
ld -o main main.o comp.o -lc --entry main

ld generate a file main. But if I try to run it, it show error

bash: ./main: No such file or directory

The executable has X permission.

List Info

>    ~/test/segtest2$ ls -l
>    total 24
>    -rw-rw-r-- 1 kail kail   88 Sep 28 21:20 comp.c
>    -rw-rw-r-- 1 kail kail   37 Sep 28 21:20 comp.h
>    -rw-rw-r-- 1 kail kail 1248 Sep 28 21:22 comp.o
>    -rwxrwxr-x 1 kail kail 3241 Sep 28 21:22 main
>    -rwxrwxr-- 1 kail kail  137 Sep 28 21:20 main.c
>    -rw-rw-r-- 1 kail kail 1568 Sep 28 21:21 main.o

Do I lost anything? Any suggestion will be appreciated. Thanks!

KyL
  • 987
  • 12
  • 24

3 Answers3

2

The argument --entry=main you pass to ld is not doing what you think it does. The entry point of a program is where the program starts. This is not main though, it's a function called _start defined in an object file crt0.o found somewhere on your system. To manually link a C program, invoke ld like this:

ld -o main main.o comp.o /path/to/crt0.o -lc

Do not supply --entry unless you know what it does.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • What should I do if I want to fully control the steps of building? Could I define the path of `crt0.o` or define `_start` by myself? I use `gcc -v` to see the log of building. But no `ld` in output. – KyL Sep 28 '15 at 13:46
  • @KyL The object file `crt0.o` is part of the **C** **r**untime **e**nvironment. If you want to use the libc, your program should start up from that file, otherwise various things might not work (e.g. `malloc` or `stdio`) as the corresponding initialization is not being performed. The code in `crt0.o` basically sets up a stack, counts the arguments to your program, then calls into the libc to initialize it, then calls `main` and finally `exit`. You can skip it, but then you need to manually set up all of this stuff. – fuz Sep 28 '15 at 13:49
  • @KyL you can manually supply that path, but after looking again, I think that there are even more object files linked into the final binary by the C compiler. I do not recommend you to manually do this unless you work completely without the libc (manually writing startup code, too), as the exact steps the C compiler takes to link your binary are not stable and may change without notice. – fuz Sep 28 '15 at 13:52
1

I see something similar when I try to run:

-bash: ./main: /lib/ld64.so.1: bad ELF interpreter: No such file or directory

So you're probably not calling ld correctly. Rather than using ld, use gcc instead to invoke it, as it takes care of details you'd otherwise have to worry about with ld.

gcc -c -o comp.o comp.c
gcc -c -o main.o main.c
gcc -o main main.o comp.o
dbush
  • 205,898
  • 23
  • 218
  • 273
1

Let's see how gcc works in verbose mode.

gcc -v -o main main.o comp.o

gcc links objects using following command

/usr/lib/gcc/x86_64-linux-gnu/4.4.3/collect2 --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main -z relro /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../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 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../.. main.o comp.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.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crtn.o

If you replace /usr/lib/gcc/x86_64-linux-gnu/4.4.3/collect2 with ld then the linking process completes successfully.

ld --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main -z relro /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../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 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../.. main.o comp.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.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crtn.o

Refer this answer for further information

Community
  • 1
  • 1
Gangadhar
  • 10,248
  • 3
  • 31
  • 50
  • could i get the intermediate linker script if i use gcc to build program ? – KyL Sep 29 '15 at 07:45
  • As like ld, gcc also supports linker script options with -T. – Gangadhar Sep 29 '15 at 07:55
  • My meaning is if i use gcc or ld to build program without -T option, I guess gcc will generate default link script to deal with object files. Could I get this generated script? – KyL Sep 29 '15 at 08:57
  • If you do not specify -T option gcc or ld uses internal linker scripts. You can get linker script if you execute above commands with **--verbose** option. – Gangadhar Sep 29 '15 at 09:37
  • 1
    thank you. it works. i get script by gcc -Wl,--verbose – KyL Sep 30 '15 at 05:25