3

I have two source files (one is written in NASM assembly - try.asm, another in plain C - tryasmc.c). I have a C function func() in the .c file which I have to link to the extern func in the assembly file.

The try.asm file :

section .text
extern func

global main
main:
    push ebp
    mov ebp, esp

    call func

    pop ebp
    ret

The tryasmc.c file :

void func()
{
    // doesn't really do anything
}

The linker script (mylink.ld):

ENTRY(main)
OUTPUT_FORMAT(binary)

SECTIONS
{
    .text :
    {
        tryasm.o (.text)
        tryasmc.o (.text)
    }
}

I want to separately compile them and link them (via a linker script) to produce a flat binary file. I did the following:

  1. nasm -f elf32 -o tryasm.o try.asm (compiling the assembly code)
  2. gcc -c -g -m32 -o tryasmc.o tryasmc.c (compiling the C code)
  3. gcc -m32 tryasm.o tryasmc.o -o tryasm -T mylink.ld

I am getting the following error:

/usr/lib32/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x18): undefined reference to `__init_array_end'
/usr/lib32/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x23): undefined reference to `__init_array_start'
/usr/lib32/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x47): undefined reference to `__init_array_start'
/usr/bin/ld: tryasm: hidden symbol `__init_array_end' isn't defined
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

As I stated earlier, I want to produce flat binary file tryasm which will contain main as the entry point and func as a subroutine. How can I acieve that ? And why am I getting these errors ?

Note: I am using a 64 bit Linux (ubuntu-16) machine but compiling codes as 32 bit elf format using gcc and nasm.

Purpose: I am writing a little OS in assembly, so all I need is flat binary to load onto RAM.

ayandas
  • 2,070
  • 1
  • 13
  • 26
  • 3
    Compile the _C_ files with additional options `-ffreestanding -nostdlib` then link with `gcc -m32 -ffreestanding -nostdlib tryasm.o tryasmc.o -o tryasm -T mylink.ld` – Michael Petch Jan 16 '17 at 20:49
  • 1
    You are also going to need a number of other sections, like `.bss` and `.data`. – fuz Jan 16 '17 at 20:53
  • @fuz He's also going to want to set a VMA (Virtual Memory address) in his linker script. As it is it none is specified so it default to 0x00000000 (which is likely not where the code will be run in memory). Although the linker script doesn't have the other section you mentioned it will place any unprocessed section that are loadable after what is specified in the linker script followed by the sections that don't load(like .bss) in the order they were found. I personally like to specify them as I can tell the linker exactly where I want them placed. – Michael Petch Jan 16 '17 at 21:00
  • @MichaelPetch that `-ffreestanding -nostdlib` worked ! Thanks. What do they exactly do ? – ayandas Jan 16 '17 at 21:03
  • 1
    It says that none of the _C_ runtime startup code should be used and that none of the _C_ standard libraries are available. I also recommend adding this option `-lgcc` to the GCC line that links **after** all the `.o` files.. There are some routines that GCC needs under certain circumstances when generating code that are available in the libgcc support library. As well I suggest you consider building yourself a cross compiler (ie i686-elf-gcc) instead of using the native _GCC_ on your system. – Michael Petch Jan 16 '17 at 21:08
  • @AyanDas Have you tried reading the documentation to find out? You are not going to get far if you don't read documentation. – fuz Jan 16 '17 at 21:49
  • Thanks @MichaelPetch. – ayandas Jan 17 '17 at 09:01
  • @fuz thats exactly what I am trying to do. Thank you. – ayandas Jan 17 '17 at 09:02
  • @MichaelPetch would you mind identifying the extra code (from mem 0x10 onwards) generated when I disassembled the flat binary. Here is a screenshot https://s24.postimg.org/dqeu2gpjp/Screenshot_from_2017_01_17_17_01_45.png – ayandas Jan 17 '17 at 11:34
  • That appears to be an [.eh_frame section](http://stackoverflow.com/a/26302715/3857942) or something of that sort. You can eliminate it by adding `-fno-asynchronous-unwind-tables` to the lines where you use _GCC_ to compile. Although likely not an issue here you can get _GCC_ to omit build notes as well when linking. You can do that by adding this to the _GCC_ linking line `-Wl,--build-id=none` – Michael Petch Jan 17 '17 at 17:46
  • I should point out that the instructions aren't code but it is informational data in this case. _NDISASM_ attempted to take all the bytes and disassemble them because it can't tell where the code ends and where such data begins. – Michael Petch Jan 17 '17 at 18:34
  • I'd be curious, how are you loading your kernel into memory? – Michael Petch Jan 17 '17 at 18:54

0 Answers0