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!

+3


source to share


3 answers


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

      

+4


source


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

      

+1


source


Very simple: in the program there is no main()

... that way, no matter what you do, the C-program launch mechanism is not delayed.

0


source







All Articles