OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 8:24 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Calling an elf object file from Assembly
PostPosted: Thu Apr 25, 2019 2:07 pm 
Offline

Joined: Thu Apr 25, 2019 2:02 pm
Posts: 11
I'm trying to call an ELF from assembly

1)I created an assembly file with a simple print code and assembled it into an ELF .o file

2)I linked this file using ld to the my bootsect.asm file(with offset of 0x1000)

ld -o kernel.tmp - Ttext 0x1000 kernel_entry.o

objcopy - O binary kernel.tmp kernel.bin

then I combine bootsect.bin and kernel.bin to get my final image. I also tried - T NUL with ld

3)bootsect.asm uses BIOS interrupts to load the elf to memory(to 0x1000) and I call 0x1000

but the print function doesn't execute.

I'm following this tutorial : https://github.com/cfenollosa/os-tutori ... -barebones

kernel_entry.asm :
Code:
print msg ; this pseudo not my actual print code


bootsect.asm :
Code:
[org 0x7c00]
KERNEL_OFFSET equ 0x1000 ; The same one we used when linking the kernel

    mov [BOOT_DRIVE], dl ; Remember that the BIOS sets us the boot drive in 'dl' on boot
    mov bp, 0x9000
    mov sp, bp

    mov bx, MSG_REAL_MODE
    call print
    call print_nl

    call load_kernel ; read the kernel from disk
    call switch_to_pm ; disable interrupts, load GDT,  etc. Finally jumps to 'BEGIN_PM'
    jmp $ ; Never executed

%include "../05-bootsector-functions-strings/boot_sect_print.asm"
%include "../05-bootsector-functions-strings/boot_sect_print_hex.asm"
%include "../07-bootsector-disk/boot_sect_disk.asm"
%include "../09-32bit-gdt/32bit-gdt.asm"
%include "../08-32bit-print/32bit-print.asm"
%include "../10-32bit-enter/32bit-switch.asm"

[bits 16]
load_kernel:
    mov bx, MSG_LOAD_KERNEL
    call print
    call print_nl

    mov bx, KERNEL_OFFSET ; Read from disk and store in 0x1000
    mov dh, 2
    mov dl, [BOOT_DRIVE]
    call disk_load
    ret

[bits 32]
BEGIN_PM:
    mov ebx, MSG_PROT_MODE
    call print_string_pm
    call KERNEL_OFFSET ; Give control to the kernel
    jmp $ ; Stay here when the kernel returns control to us (if ever)


BOOT_DRIVE db 0 ; It is a good idea to store it in memory because 'dl' may get overwritten
MSG_REAL_MODE db "Started in 16-bit Real Mode", 0
MSG_PROT_MODE db "Landed in 32-bit Protected Mode", 0
MSG_LOAD_KERNEL db "Loading kernel into memory", 0

; padding
times 510 - ($-$$) db 0
dw 0xaa55


disk_load label is here https://github.com/cfenollosa/os-tutori ... t_disk.asm

Thanks


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Thu Apr 25, 2019 2:17 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
The entry point is not necessarily the first thing linked in. I'd drop the objcopy step and use the ELF file directly.

ELF files start with an ELF header (which isn't executable). The ELF header contains the entry point address. If you have loaded the file to the correct address, you should be able to just load the entry point address out of the header and jump there. The entry point address is 24 bytes into the file, and is one machine word in size. So, assuming ELF32, you could replace the final call instruction with
Code:
call dword [KERNEL_OFFSET + 24]

Does that work for you?

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Thu Apr 25, 2019 11:38 pm 
Offline

Joined: Thu Apr 25, 2019 2:02 pm
Posts: 11
No sir it didn't work. Thank you for taking your time to help.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 1:26 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
The most educational way to solve this problem would be to single-step through the code in a debugger (e.g. Bochs, SimNow or qemu + gdb). Inspect the registers and memory at each stage. Pay particular attention to the location and contents of your GDT, and the destination of function calls. It should then become fairly obvious where the error is.

Debugging techniques like this, practised on trivial code, will serve you well in the future when you meet more challenging problems.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 2:07 am 
Offline

Joined: Thu Apr 25, 2019 2:02 pm
Posts: 11
I used objdump to examine kernel.o and noticed somehow kernel_entry.asm is not being put in there.

I removed the kernel_entry.asm completely and added an inline assembly in kernel.c to what kernel_entry.asm did and now everything is working fine.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 1:03 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,

Optimizer wrote:
I used objdump to examine kernel.o and noticed somehow kernel_entry.asm is not being put in there.

I removed the kernel_entry.asm completely and added an inline assembly in kernel.c to what kernel_entry.asm did and now everything is working fine.
If I were you, I wouldn't let this go, because it's a symptom of a bug in your build environment which will cause more troubles in the future.

Other than that, I agree with the others: iansjack is right you should use a debugger, and nullplan is also right that you should interpret the unmodified ELF object.

For the latter, I can offer example code how to parse and ELF.
* In Assembly, for BIOS machines (uses protected mode, fasm syntax)
* In C, for UEFI machines
Note that my code expects the ELF to be linked at -2M. If you want to load any arbitrary ELF kernel, then you must load (or copy) the kernel's segments to the specified locations (using program header's p_vaddr fields).

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 2:45 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Given that he's using MinGW the default is probably the generation of i386pe instead of ELF which would have to be considered. I'd like to see his complete kernel_entry.asm code though.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 4:03 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,

MichaelPetch wrote:
Given that he's using MinGW the default is probably the generation of i386pe instead of ELF which would have to be considered. I'd like to see his complete kernel_entry.asm code though.
What makes you think he's generating PE instead of ELF? He did not mentioned MinGW, but the subject of this topic is "Calling an elf object file from Assembly" and the OP starts with the sentence "I'm trying to call an ELF from assembly". The objdump output would tell if it's ELF or unintentionally PE. So yeah, I agree we need more info on what he is doing, kernel_entry.asm included.

To the OP:
Just in case if it's PE what you meant, not ELF, then the steps are the same:
1. parse the header, get the segment's offsets and sizes (text, data, bss)
2. load (or copy) them into place
3. and transfer control to the entry point.
The only difference is you'll have to use different structs.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 11:03 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
I learned what he was using when I looked at an os-image.bin file he generated and placed in his Github project. Build information was present in the last section (including compiler). His makefile was the first indication he was using a GCC on Windows.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 11:53 pm 
Offline

Joined: Thu Apr 25, 2019 2:02 pm
Posts: 11
bzt wrote:
Hi,

MichaelPetch wrote:
Given that he's using MinGW the default is probably the generation of i386pe instead of ELF which would have to be considered. I'd like to see his complete kernel_entry.asm code though.
What makes you think he's generating PE instead of ELF? He did not mentioned MinGW, but the subject of this topic is "Calling an elf object file from Assembly" and the OP starts with the sentence "I'm trying to call an ELF from assembly". The objdump output would tell if it's ELF or unintentionally PE. So yeah, I agree we need more info on what he is doing, kernel_entry.asm included.

To the OP:
Just in case if it's PE what you meant, not ELF, then the steps are the same:
1. parse the header, get the segment's offsets and sizes (text, data, bss)
2. load (or copy) them into place
3. and transfer control to the entry point.
The only difference is you'll have to use different structs.

Cheers,
bzt


Yeah definitely shouldn't let this go. I will continue my os after fixing this.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Fri Apr 26, 2019 11:55 pm 
Offline

Joined: Thu Apr 25, 2019 2:02 pm
Posts: 11
MichaelPetch wrote:
I learned what he was using when I looked at an os-image.bin file he generated and placed in his Github project. Build information was present in the last section (including compiler). His makefile was the first indication he was using a GCC on Windows.


You're right I'm using mingw but I will soon switch to linux.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Sat Apr 27, 2019 5:09 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
MichaelPetch wrote:
I learned what he was using when I looked at an os-image.bin file he generated and placed in his Github project. Build information was present in the last section (including compiler). His makefile was the first indication he was using a GCC on Windows.
I see. Then accidentally creating PEs could be an issue indeed, you made a good point!

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Sun May 19, 2019 2:59 pm 
Offline

Joined: Sat Dec 29, 2018 3:09 am
Posts: 10
Must have been an optimization issue, in my experience when the compiler optimizes a block of code out (even when I'm calling it), converting the block to inline assembly typically prevents the optimization.


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Mon May 20, 2019 7:19 am 
Offline
Member
Member
User avatar

Joined: Tue Mar 06, 2007 11:17 am
Posts: 1225
bigboyav wrote:
Must have been an optimization issue, in my experience when the compiler optimizes a block of code out (even when I'm calling it), converting the block to inline assembly typically prevents the optimization.
In GCC, __asm__ __volatile__ leaves the assembly block untouched. A typical example is linux/arch/i386/lib/strstr.c:

strstr.c
Code:
#include <linux/string.h>

char * strstr(const char * cs,const char * ct)
{
int   d0, d1;
register char * __res;
__asm__ __volatile__(
   "movl %6,%%edi\n\t"
   "repne\n\t"
   "scasb\n\t"
   "notl %%ecx\n\t"
   "decl %%ecx\n\t"   /* NOTE! This also sets Z if searchstring='' */
   "movl %%ecx,%%edx\n"
   "1:\tmovl %6,%%edi\n\t"
   "movl %%esi,%%eax\n\t"
   "movl %%edx,%%ecx\n\t"
   "repe\n\t"
   "cmpsb\n\t"
   "je 2f\n\t"      /* also works for empty string, see above */
   "xchgl %%eax,%%esi\n\t"
   "incl %%esi\n\t"
   "cmpb $0,-1(%%eax)\n\t"
   "jne 1b\n\t"
   "xorl %%eax,%%eax\n\t"
   "2:"
   :"=a" (__res), "=&c" (d0), "=&S" (d1)
   :"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
   :"dx", "di");
return __res;
}


_________________
Live PC 1: Image Live PC 2: Image

YouTube:
http://youtube.com/@AltComp126/streams
http://youtube.com/@proyectos/streams

http://master.dl.sourceforge.net/projec ... 7z?viasf=1


Top
 Profile  
 
 Post subject: Re: Calling an elf object file from Assembly
PostPosted: Mon May 20, 2019 8:41 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
~ wrote:
A typical example is linux/arch/i386/lib/strstr.c:
Typical example (even from older Linux kernel) with a bug. To demonstrate try this code:
Code:
#include <stdio.h>

char * strstr(const char * cs,const char * ct)
{
int   d0, d1;
register char * __res;
__asm__ __volatile__(
   "movl %6,%%edi\n\t"
   "repne\n\t"
   "scasb\n\t"
   "notl %%ecx\n\t"
   "decl %%ecx\n\t"   /* NOTE! This also sets Z if searchstring='' */
   "movl %%ecx,%%edx\n"
   "1:\tmovl %6,%%edi\n\t"
   "movl %%esi,%%eax\n\t"
   "movl %%edx,%%ecx\n\t"
   "repe\n\t"
   "cmpsb\n\t"
   "je 2f\n\t"      /* also works for empty string, see above */
   "xchgl %%eax,%%esi\n\t"
   "incl %%esi\n\t"
   "cmpb $0,-1(%%eax)\n\t"
   "jne 1b\n\t"
   "xorl %%eax,%%eax\n\t"
   "2:"
   :"=a" (__res), "=&c" (d0), "=&S" (d1)
   :"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
   :"dx", "di");
return __res;
}

int main()
{
    char string[]="Hello There";
    char search[]="here";
    return (strstr(string, search) ? 1 : 0);
}


This should return 1 since the string "here" is in the string to search. Compile and run without optimizations:
Code:
gcc test.c -O0 -m32 -Wall
./a.out; echo $?
1
Good to go! Not quite, build with optimizations on:
Code:
gcc test.c -O3 -m32 -Wall
./a.out; echo $?
0
So why did optimizations on cause this to fail? It is a subtle bug in the inline assembly. Passing pointers to memory through registers as is done with the constraints "=&c" (d0), "=&S" (d1) doesn't actually tell the compiler that what those pointers point at is actually going to be read or written. In this case the code generator produced code that never put the strings search and string on the stack as the optimizer never realized that the data in the character arrays were being accessed. We only told the compiler we were using the pointers (not what they point at). To get around this you can add a memory clobber to the inline assembly to ensure all the data in the arrays are saved (and then restored if need be) before the inline assembly is executed. Adding a memory clobber can be done with this modification:
Code:
:"dx", "di", "memory");
. This is discussed in the GCC inline assembly documentation along with an alternate solution (example shows a proper repne scasb) in the section 6.47.2.6 Clobbers and Scratch Registers


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 51 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group