[Solved] Invalid Magic number if global constructors called

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
RicardoLuis0
Posts: 5
Joined: Mon Jun 04, 2018 1:34 am

[Solved] Invalid Magic number if global constructors called

Post 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"
Last edited by RicardoLuis0 on Mon Jun 04, 2018 5:26 pm, edited 1 time in total.
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Invalid Magic number if global constructors are called

Post 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.
RicardoLuis0
Posts: 5
Joined: Mon Jun 04, 2018 1:34 am

Re: Invalid Magic number if global constructors are called

Post 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
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Invalid Magic number if global constructors are called

Post 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?
RicardoLuis0
Posts: 5
Joined: Mon Jun 04, 2018 1:34 am

Re: Invalid Magic number if global constructors are called

Post 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
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Invalid Magic number if global constructors are called

Post 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
RicardoLuis0
Posts: 5
Joined: Mon Jun 04, 2018 1:34 am

Re: Invalid Magic number if global constructors are called

Post 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.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Invalid Magic number if global constructors are called

Post 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
RicardoLuis0
Posts: 5
Joined: Mon Jun 04, 2018 1:34 am

Re: Invalid Magic number if global constructors are called

Post 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!
Post Reply