Mixing build programming and C on linux
There are only two files, main.c
and kernel.asm
, and I tried to create a program with them using NASM and GCC. the content looks like this:
main.c
#include <stdio.h>
void Print_String() {
printf("Hello World!\n");
}
kernle.asm
extern Print_String
[section .text]
global _start
_start:
call Print_String
Compilation and link:
nasm -f elf -o kernel.o kernel.asm
gcc -c -o main.o main.c
ld -s -lc -o final kernel.o main.o
Then I run the file final
with the command:, ./final
but the result is depressing:
bash: ./final: No such file or directory
However the current directory has a file final
, for the command ls
it displays:
final kernel.asm kernel.o main.c main.o
So why can't it find the file final
? Something is wrong? Any help is appreciated!
source to share
It is not that he cannot find it as such. The error message is somewhat misleading. The dynamic linker cannot resolve its dependencies and hence your program image is not loaded (nor executed)
The problem is that you are dynamically linking to libc without any other attributes to make dynamic linking really work. Thus, you are left with a binary image that cannot be loaded.
You may find it easier to statically reference libc. This can be done as follows:
ld -Bstatic -o final kernel.o main.o -lc
Note that you need to move the -lc bit after the main.o code module that uses it.
If you try this, you end up with a whole bunch of unresolved characters. This is because you will also need to communicate with libgcc and libgcc_eh.
The following got me pretty close (apologies while working on a 64 bit system here):
ld -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/32/ -melf_i386 -Bstatic -lc -o final kernel.o main.o -lc -lgcc -lgcc_eh
It failed for me with
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/32//libgcc_eh.a(unwind-dw2-fde-glibc.o): In function `_Unwind_Find_FDE':
(.text+0x193b): undefined reference to `dl_iterate_phdr'
It doesn't make much sense. You may have more luck tying 32-bit to 32-bit system.
Update
Sorry for speeding. I thought about it again, and of course a dynamic linking job can be done. The downside is specifying a dynamic linker:
In my case it was:
ld -dynamic-linker /lib32/ld-linux.so.2 -melf_i386 -o final kernel.o main.o -lc
So the following should work for you:
ld -dynamic-linker /lib/ld-linux.so.2 -o final kernel.o main.o -lc
Refresh again
In response to markzar's comment - you must do syscall for a clean exit. This causes you to do something similar to exit (0) in C:
mov eax,1 ; Syscall #1
mov ebx,0 ; Return code 0 = success
int 80H
source to share
Try it. First, modify kernel.asm as follows:
extern Print_String
[section .text]
global main
main:
call Print_String
Then use the following commands to create an executable (instead of a linker).
nasm -f elf -o kernel.o kernel.asm
gcc -c -o main.o main.c
gcc -o final kernel.o main.o
source to share