Page 1 of 1

[Solved] Invalid Magic number if global constructors called

Posted: Mon Jun 04, 2018 1:46 am
by RicardoLuis0
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: Select all

.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: Select all

.section .init
	popl %ebp
	ret

.section .fini
	popl %ebp
	ret

boot.s

Code: Select all

.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"

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 2:20 am
by alexfru
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: Select all

_whatever:
push ebp
mov ebp, esp
pop ebp
ret
or simply:

Code: Select all

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

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 2:26 am
by RicardoLuis0
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

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 2:34 am
by alexfru
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?

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 2:46 am
by RicardoLuis0
I haven't ever done disassembly before, which tools does it use?
Also, how I call it in the kernel:

Code: Select all

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

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 5:32 am
by AJ
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

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 11:31 am
by RicardoLuis0
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.

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 4:32 pm
by MichaelPetch
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: Select all

_start:
   
   mov $stack_top, %esp
   
   pushl %eax
   pushl %ebx
   call _init

   call kernel_main #push magic & multiboot struct and call main

   call _fini

   cli

Re: Invalid Magic number if global constructors are called

Posted: Mon Jun 04, 2018 5:25 pm
by RicardoLuis0
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!