OSDev.org

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

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: [Solved] Invalid Magic number if global constructors called
PostPosted: Mon Jun 04, 2018 1:46 am 
Offline

Joined: Mon Jun 04, 2018 1:34 am
Posts: 5
I've tried looking for solutions all over, but haven't come up with anything, so I decided to ask here.
The system boots fine if I don't call the _init & _fini functions, but if I call them (I've got the proper files linked, and the constructors themselves seem to work/be called) the magic number becomes 0xFFFFFFFF. As far as i looked, the assembly code doesn't seem to be touching either of the (eax and ebx) registers.

crti.s
Code:
.section .init
.global _init
.type _init, @function
_init:
   push %ebp
   movl %esp, %ebp

.section .fini
.global _fini
.type _fini, @function
_fini:
   push %ebp
   movl %esp, %ebp



crtn.s
Code:
.section .init
   popl %ebp
   ret

.section .fini
   popl %ebp
   ret



boot.s
Code:
.set MAGIC,    0x1BADB002
.set FLAGS,    (1<<0) | (1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)

.section .multiboot
   .align 4
   .long MAGIC
   .long FLAGS
   .long CHECKSUM

.section .bss
   .align 16
   stack_bottom: #16kb stack
      .skip 16384
   stack_top:

.section .text
   .global _start
   .type _start, @function

_start:
   
   mov $stack_top, %esp
   
   call _init

   pushl %eax
   pushl %ebx
   call kernel_main #push magic & multiboot struct and call main

   call _fini

   cli
hang:
   hlt
   jmp hang

.size _start, . - _start



obligatory "not my first language, so sorry for bad english"


Last edited by RicardoLuis0 on Mon Jun 04, 2018 5:26 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 2:20 am 
Offline
Member
Member

Joined: Tue Mar 04, 2014 5:27 am
Posts: 1108
Your _init and _fini look odd. I don't know if that's the actual code or how you posted it. I'd expect them to be complete subroutines, e.g.:

Code:
_whatever:
push ebp
mov ebp, esp
pop ebp
ret


or simply:
Code:
_whatever:
ret


Your _init seems to be continuing execution into _fini and that one... who knows.


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 2:26 am 
Offline

Joined: Mon Jun 04, 2018 1:34 am
Posts: 5
I've got the code from here: https://wiki.osdev.org/Calling_Global_Constructors
it seems that gcc joins the two together with crtbegin.o,the constructors, and crtend.o between crti.s and crtn.s
i've got it somewhat working by calling _init in my kernel_main, but i'm pretty sure that's not how it's supposed to be done


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 2:34 am 
Offline
Member
Member

Joined: Tue Mar 04, 2014 5:27 am
Posts: 1108
RicardoLuis0 wrote:
I've got the code from here: https://wiki.osdev.org/Calling_Global_Constructors
it seems that gcc joins the two together with crtbegin.o,the constructors, and crtend.o between crti.s and crtn.s
i've got it somewhat working by calling _init in my kernel_main, but i'm pretty sure that's not how it's supposed to be done


Ah, there's some compiler magic... Anyhow, what's in the binary? If you disassemble it, does the code around these init/fini things look right?


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 2:46 am 
Offline

Joined: Mon Jun 04, 2018 1:34 am
Posts: 5
I haven't ever done disassembly before, which tools does it use?
Also, how I call it in the kernel:
Code:
extern void _init(void);
void kernel_main(multiboot_info_t* mbt,unsigned int magic){
   _init();

When I call it like that it works, but it's not how the tutorial says it should be called from.

If it matters, i'm using QEMU to run, and https://github.com/lordmilko/i686-elf-tools to build


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 5:32 am 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2646
Location: Devon, UK
Hi,

Use objdump with the -d flag on your compiled kernel to get the disassembly. You will find that at the bottom of the dumped file, you get a very useful disassembly with offsets displayed.

Cheers,
Adam


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 11:31 am 
Offline

Joined: Mon Jun 04, 2018 1:34 am
Posts: 5
here's the disassembly: https://drive.google.com/open?id=1fB6QY ... PQ7uI_r6QL
i don't really know all that much about assembly, but it seems that the code to call the constructors that was added by the compiler uses the (eax and ebx) registers and that's why they're changing.


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 4:32 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
When you call `_init` it may in turn call global constructors and static initialization code which may alter the registers. Effectively EAX and EBX are being clobbered by initialization. In theory you should be able to push EAX and EBX on the stack before the call to `_init`. After `_init` is called the values should remain unmodified on the stack. Then you just call your kernel_main function from that point. Code could look like:
Code:
_start:
   
   mov $stack_top, %esp
   
   pushl %eax
   pushl %ebx
   call _init

   call kernel_main #push magic & multiboot struct and call main

   call _fini

   cli


Top
 Profile  
 
 Post subject: Re: Invalid Magic number if global constructors are called
PostPosted: Mon Jun 04, 2018 5:25 pm 
Offline

Joined: Mon Jun 04, 2018 1:34 am
Posts: 5
MichaelPetch wrote:
When you call `_init` it may in turn call global constructors and static initialization code which may alter the registers. Effectively EAX and EBX are being clobbered by initialization. In theory you should be able to push EAX and EBX on the stack before the call to `_init`. After `_init` is called the values should remain unmodified on the stack. Then you just call your kernel_main function from that point.


Thanks, that worked!


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] 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