I'm programming my kernel (32 bits x86), and I am cursed with a problem I can't see how to solve.
It's the first time I am confronted with such an issue, usually, I program in user space, so, here it is:
This is my kernel entry function:
void _start(){ const char* welcome = "HEYYY IT'S A MEEEE , MAAARIOOO! "; init_video(); clear_screen(); video_write((char*) welcome, 0x0E, false); init_idt(); while(1); }
And the result:
the thing works.
If I check the section .rodata:
Contents of section .rodata:2000 30313233 34353637 38394142 43444546 0123456789ABCDEF2010 08000000 48455959 59204954 27532041 ....HEYYY IT'S A2020 204d4545 4545202c 204d4141 4152494f MEEEE , MAAARIO2030 4f4f2120 0000000a 00202000 20202020 OO! ..... . 2040 20002000
You can see that our "welcome" variable has been stored in 0x2014.
But... If I do this:
int stuff(long long s, long long a, long long b);void _start(){ const char* welcome = "HEYYY IT'S A MEEEE , MAAARIOOO! "; init_video(); clear_screen(); video_write((char*) welcome, 0x0E, false); init_idt(); while(1); } int stuff (long long s, long long b, long long c) { return 0; }
Our Italian plumber disappeared:
Our "welcome" variable is now stored at 0x3014, in the .rodata section:
3000 30313233 34353637 38394142 43444546 0123456789ABCDEF 3010 08000000 48455959 59204954 27532041 ....HEYYY IT'S A 3020 204d4545 4545202c 204d4141 4152494f MEEEE , MAAARIO 3030 4f4f2120 0000000a 00202000 20202020 OO! ..... . 3040 20002000 . .
Now, for the spooky part:
There's nothing at 0x3014, when I run the program.If I run GDB, and print "welcome", I get this:
(gdb) print /x welcome$1 = 0x3014(gdb) print welcome$2 = 0x3014 ""
This happens when I add a function with a certain number of arguments, even without using it.So , if I have to guess (correct me if I'm wrong), either this is a stack issue, or this is a compilation/linking issue?
Is it maybe due to the fact that I'm not using a cross-compiler?
Here's the relevant part of the Makefile for the compilation and linking:
EXEC = SaharaOSCC = gccCFLAGS = -fno-PIC -mno-red-zone -fno-stack-protector -std=c11 -m32 -g -ffreestanding -pedantic -WallBOOTLOADER_DIR = ./bootloaderBOOTLOADER = $(BOOTLOADER_DIR)/bootloader.binASM_DIR = ./kernel/asmKERNEL_ENTRY = $(BOOTLOADER_DIR)/kernel_entry/kernel_entry.oKERNEL_ENTRY_FILE = $(BOOTLOADER_DIR)/kernel_entry/kernel_entry.asmKERNEL = ./kernel.binKDEBUG = ./symbol-debug-kernelKERNEL_DIR = ./kernelKERNEL_SRC_DIR = $(KERNEL_DIR)/srcKERNEL_INC_DIR = $(KERNEL_DIR)/includesKERNEL_OBJ_DIR = $(KERNEL_DIR)/objDRIVERS_DIR = ./driversDRIVERS_OBJ_DIR = $(DRIVERS_DIR)/objASM_SRC = $(wildcard $(ASM_DIR)/*.asm)BOOTLOADER_SRC = $(wildcard $(BOOTLOADER_DIR)/assembly/*.asm)KERNEL_OBJ = $(wildcard $(KERNEL_OBJ)/*.o)KERNEL_SRC = $(wildcard $(KERNEL_SRC_DIR)/*.c)KERNEL_INC = $(wildcard $(KERNEL_INC_DIR)/*.h)DRIVERS_SRC = $(wildcard $(DRIVERS_DIR)/*/src/*.c)DRIVERS_INC = $(wildcard $(DRIVERS_DIR)/*/includes/*.h)OBJ_K = $(KERNEL_SRC:.c=.o)OBJ_D = $(DRIVERS_SRC:.c=.o)OBJ_ASM_K = $(ASM_SRC:.asm=.o)all: run$(EXEC): assembledebug: $(EXEC) $(KDEBUG) qemu-system-i386 -S -gdb tcp::9000 $<run: $(EXEC) qemu-system-i386 -d guest_errors $<disassemble: $(KERNEL) ndisasm -b 32 $? | catassemble: $(BOOTLOADER) $(KERNEL) cat $^ > $(EXEC) qemu-img resize $(EXEC) +100KOBJDUMP: $(KERNEL_ENTRY) $(OBJ_D) $(OBJ_K) $(OBJ_ASM_K) ld -melf_i386 -o $@ -Ttext 0x1000 $^ #Kernel build and drivers$(KERNEL): $(KERNEL_ENTRY) $(OBJ_D) $(OBJ_K) $(OBJ_ASM_K) ld -melf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary$(KDEBUG): $(KERNEL_ENTRY) $(OBJ_D) $(OBJ_K) $(OBJ_ASM_K) ld -melf_i386 -o $@ -Ttext 0x1000 $^ %.o: %.c $(KERNEL_INC) $(DRIVERS_INC) $(CC) $(CFLAGS) -c $< -o $@%.o: %.asm nasm -f elf32 -F dwarf -g $< -o $@#Bootloader buildKERNEL_ENTRY: $(KERNEL_ENTRY)BOOTLOADER: $(BOOTLOADER)$(KERNEL_ENTRY): nasm -f elf32 -F dwarf -g $(KERNEL_ENTRY_FILE) -o $@ $(BOOTLOADER): nasm $(BOOTLOADER_DIR)/assembly/boot.asm -i $(BOOTLOADER_DIR)/assembly -f bin -o $@