#include<stdio.h>
int main(int argc, char *argv[])
{
printf("Hello, World !");
return 0;
}
gcc -E main.c -o main.i
gcc -S main.i -o main.s
as main.s -o main.o
gcc -c -o main.o main.c
Namely, crti.o & crtn.o (they define function prologs & epilogs, respectively), crt1.o (contains _start symbol for bootstrapping the initial execution of the program), libc.so path or -lc flag for libc and then finally set the name of the dynamic linker, to generate a dynamically linked ELF executable:
On x86_64:
ld -I /lib64/ld-linux-x86-64.so.2 -o main main.o /usr/lib/crti.o /usr/lib/crtn.o /usr/lib/crt1.o -lc
Or to specify path to libc.so
ld -I /lib64/ld-linux-x86-64.so.2 -o main main.o /usr/lib/crti.o /usr/lib/crtn.o /usr/lib/crt1.o /usr/lib/libc.so
#include<stdio.h>
const char x[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
int main(int argc, char *argv[])
{
char hello[] = "Hello, World !";
puts(hello);
__asm__("mov $60, %rax; mov $0, %rdi; syscall;");
}
gcc -c -o main.o main.c
ld -e main -o main main.o -lc