Page 1 of 1

Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 8:16 am
by ExeTwezz
Hi,

A few days ago I bought a laptop (Windows 8, Intel Pentium N3530, 64-bit), also I have another laptop (Windows 8 and 64-bit too, but on Intel Core i5), and an old computer (Ubuntu 12.04 32-bit, AMD Athlon 64 3000+ as BIOS says when booting).

I'm using VirtualBox on laptops to run Linux Mint 17 64-bit, and I'm writing a 32-bit operating system, so I compile it using Clang or GCC with -m32 flag and NASM with -elf32.

More to the point. The problem is that my OS runs differently on computer&laptop and new laptop. On computer and laptop it runs successfully, but on the new laptop it stops after page fault. I use the same compiler (Clang) on these three machines, also tried cross-compiler (i686-elf-*), but on the new laptop the OS stops with strange page fault. After debugging with printing messages, I concluded that the page fault is caused after returning from some function.

I think that the problem is not in the code, but in compiling and/or linking. So, my Makefile on the new laptop:

Code: Select all

# This Makefile compiles files in "src" directory.

CROSS = i686-elf-

CC = $(CROSS)gcc
CC = clang # I know... But the result is the same as without this string.
CFLAGS = -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib

ASOURCES = $(wildcard src/*.asm)
AOBJECTS = $(ASOURCES:.asm=.o)
CSOURCES = $(wildcard src/*.c)
COBJECTS = $(CSOURCES:.c=.o)
ASOURCES2 = $(wildcard src/*/*.asm)
AOBJECTS2 = $(ASOURCES2:.asm=.o)
CSOURCES2 = $(wildcard src/*/*.c)
COBJECTS2 = $(CSOURCES2:.c=.o)
OBJECTS = $(AOBJECTS) $(AOBJECTS2) $(COBJECTS) $(COBJECTS2)
OUTPUT = ../bin/kernel.bin

ALLOBJECTS1 = $(wildcard src/*.o)
ALLOBJECTS2 = $(wildcard src/*/*.o)
ALLOBJECTS = $(ALLOBJECTS1) $(ALLOBJECTS2)

ASM = nasm
AFLAGS = -f elf32

LN = $(CROSS)ld
LFLAGS = -T linker.ld -o $(OUTPUT) $(OBJECTS)

all: build

build: $(OBJECTS)
	$(LN) $(LFLAGS)
	@../disk.sh ../

%.o: %.asm
	$(ASM) $(AFLAGS) $< -o $@

%.o: %.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -rf $(ALLOBJECTS) $(OUTPUT)
I run the OS on Qemu this way:

Code: Select all

$ qemu-system-i386 -boot cd -cdrom disk/ouros.iso -m 64

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 8:26 am
by sortie
I don't see where you actually link the kernel, and you forgot to pass -c when producing .o files. Does instructions like http://wiki.osdev.org/Bare_Bones work?

Btw: Discard your makefile and type the commands manually. Then paste them here. I don't want to decode your makefile, I don't care about it, I want to know the commands.

Use a cross-compiler. Don't use clang naively, that's as bad as using gcc naively. (Do CC="clang -targer i686-elf" or whatever is appropriate with clang). There is no need to pass -m32 to your cross-compiler.

-nostdlib is only relevant when linking, not when compiling. Don't put it in cflags. :)

Edit: Ah. I see it. You called your linker LN. Don't do that. LN is used as a variable that points to the correct ln(1), which creates hard links and symbolic links. Call it LD instead, and rename LFLAGS to LDFLAGS. Don't link with ld, link with your compiler, and pass -nostdlib and link with libgcc. As in bare bones.

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 8:30 am
by ExeTwezz
sortie wrote:I don't see where you actually link the kernel, and you forgot to pass -c when producing .o files. Does instructions like http://wiki.osdev.org/Bare_Bones work?

Btw: Discard your makefile and type the commands manually. Then paste them here. I don't want to decode your makefile, I don't care about it, I want to know the commands.

Use a cross-compiler. Don't use clang naively, that's as bad as using gcc naively. (Do CC="clang -targer i686-elf" or whatever is appropriate with clang). There is no need to pass -m32 to your cross-compiler.
Maybe you didn't see it.

-c

Code: Select all

CFLAGS = -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib
Linking

Code: Select all

LN = $(CROSS)ld
LFLAGS = -T linker.ld -o $(OUTPUT) $(OBJECTS)
<...>
build: $(OBJECTS)
   $(LN) $(LFLAGS)

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 8:32 am
by sortie
Yep, I didn't because you called it LN instead of LD. (Race condition, see my edit of my original post). That's why you should post the commands instead of the Makefile, especially if you diverge from Makefile conventions. :) Make usually writes the commands to stdout so they are easy to copy.

I suspect it could be your use of wildcards, perhaps the object files are linked in the wrong order?

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 8:50 am
by ExeTwezz
So the first is output of the old Makefile (command $ make):

Code: Select all

nasm -f elf32 src/kernel_ll.asm -o src/kernel_ll.o
nasm -f elf32 src/start.asm -o src/start.o
nasm -f elf32 src/idt/isrs.asm -o src/idt/isrs.o
nasm -f elf32 src/memory/paging_ll.asm -o src/memory/paging_ll.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/kernel.c -o src/kernel.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/basic/string.c -o src/basic/string.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/handlers/handlers.c -o src/handlers/handlers.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/handlers/keyboard.c -o src/handlers/keyboard.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/handlers/timer.c -o src/handlers/timer.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/idt/idt.c -o src/idt/idt.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/io/inoutb.c -o src/io/inoutb.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/io/screen.c -o src/io/screen.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/memory/kmalloc.c -o src/memory/kmalloc.o
src/memory/kmalloc.c:20:13: warning: 'print_tag' defined but not used [-Wunused-function]
 static void print_tag (tag_t *tag)
             ^
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/memory/memory.c -o src/memory/memory.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/memory/mm.c -o src/memory/mm.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ -nostdlib src/memory/paging.c -o src/memory/paging.o
i686-elf-ld -T linker.ld -o ../bin/kernel.bin src/kernel_ll.o src/start.o src/idt/isrs.o src/memory/paging_ll.o src/kernel.o src/basic/string.o src/handlers/handlers.o src/handlers/keyboard.o src/handlers/timer.o src/idt/idt.o src/io/inoutb.o src/io/screen.o src/memory/kmalloc.o src/memory/memory.o src/memory/mm.o src/memory/paging.o
Creating isofiles
Creating directories
Copying the files
Creating a CD-ROM from isofiles
xorriso 1.3.2 : RockRidge filesystem manipulator, libburnia project.

Drive current: -outdev 'stdio:../disk/ouros.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary: 0 sessions, 0 data blocks, 0 data, 9267m free
Added to ISO image: directory '/'='/tmp/grub.o0TjVx'
xorriso : UPDATE : 281 files added in 1 seconds
Added to ISO image: directory '/'='/home/yuri/Документы/Projects/Basic_OS/disk/isofiles'
xorriso : UPDATE : 285 files added in 1 seconds
xorriso : NOTE : Copying to System Area: 512 bytes from file '/usr/lib/grub/i386-pc/boot_hybrid.img'
xorriso : UPDATE :  47.76% done
ISO image produced: 2546 sectors
Written to medium : 2546 sectors at LBA 0
Writing to 'stdio:../disk/ouros.iso' completed successfully.

I just saw somewhere that the $(LN) is used, so I used it too.
OK, I've just edited Makefile and changed the linker to i686-elf-gcc (not in $(LD), but in `build:'):

Code: Select all

# This Makefile compiles files in "src" directory.

CROSS = i686-elf-

CC = $(CROSS)gcc
CFLAGS = -Wall -m32 -c -ffreestanding -Iinclude/

ASOURCES = $(wildcard src/*.asm)
AOBJECTS = $(ASOURCES:.asm=.o)
CSOURCES = $(wildcard src/*.c)
COBJECTS = $(CSOURCES:.c=.o)
ASOURCES2 = $(wildcard src/*/*.asm)
AOBJECTS2 = $(ASOURCES2:.asm=.o)
CSOURCES2 = $(wildcard src/*/*.c)
COBJECTS2 = $(CSOURCES2:.c=.o)
OBJECTS = $(AOBJECTS) $(AOBJECTS2) $(COBJECTS) $(COBJECTS2)
OUTPUT = ../bin/kernel.bin

ALLOBJECTS1 = $(wildcard src/*.o)
ALLOBJECTS2 = $(wildcard src/*/*.o)
ALLOBJECTS = $(ALLOBJECTS1) $(ALLOBJECTS2)

ASM = nasm
AFLAGS = -f elf32

LD = $(CROSS)ld
LDFLAGS = -T linker.ld -o $(OUTPUT) $(OBJECTS)

all: build

build: $(OBJECTS)
	i686-elf-gcc $(OBJECTS) -nostdlib -o $(OUTPUT)
	@../disk.sh ../

%.o: %.asm
	$(ASM) $(AFLAGS) $< -o $@

%.o: %.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -rf $(ALLOBJECTS) $(OUTPUT)
I don't know how to use i686-elf-gcc as a linker, so I just wrote the command that you can see in the above code.
The output of `make' is (object files are compiled successfully):

Code: Select all

i686-elf-gcc src/kernel_ll.o src/start.o src/idt/isrs.o src/memory/paging_ll.o src/kernel.o src/basic/string.o src/handlers/handlers.o src/handlers/keyboard.o src/handlers/timer.o src/idt/idt.o src/io/inoutb.o src/io/screen.o src/memory/kmalloc.o src/memory/memory.o src/memory/mm.o src/memory/paging.o -nostdlib -o ../bin/kernel.bin
/home/yuri/cross/lib/gcc/i686-elf/4.9.1/../../../../i686-elf/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080
src/kernel_ll.o: In function `kernel_ll':
src/kernel_ll.asm:(.text+0x7): undefined reference to `bss_end'
src/start.o: In function `header':
src/start.asm:(.text+0x18): undefined reference to `code_start'
src/start.asm:(.text+0x1c): undefined reference to `bss_start'
src/start.asm:(.text+0x20): undefined reference to `bss_end'
collect2: error: ld returned 1 exit status
make: *** [build] Ошибка 1   // Error 1

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 8:56 am
by ExeTwezz
I've just googled and understood that I can just change $(LD) to $(CROSS)gcc and add -nostdlib to $(LDFLAGS).

Code: Select all

# This Makefile compiles files in "src" directory.

CROSS = i686-elf-

CC = $(CROSS)gcc
CFLAGS = -Wall -m32 -c -ffreestanding -Iinclude/

ASOURCES = $(wildcard src/*.asm)
AOBJECTS = $(ASOURCES:.asm=.o)
CSOURCES = $(wildcard src/*.c)
COBJECTS = $(CSOURCES:.c=.o)
ASOURCES2 = $(wildcard src/*/*.asm)
AOBJECTS2 = $(ASOURCES2:.asm=.o)
CSOURCES2 = $(wildcard src/*/*.c)
COBJECTS2 = $(CSOURCES2:.c=.o)
OBJECTS = $(AOBJECTS) $(AOBJECTS2) $(COBJECTS) $(COBJECTS2)
OUTPUT = ../bin/kernel.bin

ALLOBJECTS1 = $(wildcard src/*.o)
ALLOBJECTS2 = $(wildcard src/*/*.o)
ALLOBJECTS = $(ALLOBJECTS1) $(ALLOBJECTS2)

ASM = nasm
AFLAGS = -f elf32

LD = $(CROSS)gcc
LDFLAGS = -T linker.ld -o $(OUTPUT) $(OBJECTS) -nostdlib

all: build

build: $(OBJECTS)
	$(LD) $(LDFLAGS)
	@../disk.sh ../

%.o: %.asm
	$(ASM) $(AFLAGS) $< -o $@

%.o: %.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -rf $(ALLOBJECTS) $(OUTPUT)
But the result is the same as if $(LD) was $(CROSS)ld. Btw, the output:

Code: Select all

nasm -f elf32 src/kernel_ll.asm -o src/kernel_ll.o
nasm -f elf32 src/start.asm -o src/start.o
nasm -f elf32 src/idt/isrs.asm -o src/idt/isrs.o
nasm -f elf32 src/memory/paging_ll.asm -o src/memory/paging_ll.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/kernel.c -o src/kernel.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/basic/string.c -o src/basic/string.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/handlers/handlers.c -o src/handlers/handlers.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/handlers/keyboard.c -o src/handlers/keyboard.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/handlers/timer.c -o src/handlers/timer.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/idt/idt.c -o src/idt/idt.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/io/inoutb.c -o src/io/inoutb.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/io/screen.c -o src/io/screen.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/memory/kmalloc.c -o src/memory/kmalloc.o
src/memory/kmalloc.c:20:13: warning: 'print_tag' defined but not used [-Wunused-function]
 static void print_tag (tag_t *tag)
             ^
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/memory/memory.c -o src/memory/memory.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/memory/mm.c -o src/memory/mm.o
i686-elf-gcc -Wall -m32 -c -ffreestanding -Iinclude/ src/memory/paging.c -o src/memory/paging.o
i686-elf-gcc -T linker.ld -o ../bin/kernel.bin src/kernel_ll.o src/start.o src/idt/isrs.o src/memory/paging_ll.o src/kernel.o src/basic/string.o src/handlers/handlers.o src/handlers/keyboard.o src/handlers/timer.o src/idt/idt.o src/io/inoutb.o src/io/screen.o src/memory/kmalloc.o src/memory/memory.o src/memory/mm.o src/memory/paging.o -nostdlib
Creating isofiles
Creating directories
Copying the files
Creating a CD-ROM from isofiles
xorriso 1.3.2 : RockRidge filesystem manipulator, libburnia project.

Drive current: -outdev 'stdio:../disk/ouros.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary: 0 sessions, 0 data blocks, 0 data, 9248m free
Added to ISO image: directory '/'='/tmp/grub.TBXToh'
xorriso : UPDATE : 281 files added in 1 seconds
Added to ISO image: directory '/'='/home/yuri/Документы/Projects/Basic_OS/disk/isofiles'
xorriso : UPDATE : 285 files added in 1 seconds
xorriso : NOTE : Copying to System Area: 512 bytes from file '/usr/lib/grub/i386-pc/boot_hybrid.img'
xorriso : UPDATE :  21.37% done
ISO image produced: 2546 sectors
Written to medium : 2546 sectors at LBA 0
Writing to 'stdio:../disk/ouros.iso' completed successfully.


Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 10:55 am
by sortie
Is start.o meant to come first?

Don't pass -m32 when using i686-elf, there is no need. You are not passing -ffreestanding when linking. You are not linking with libgcc.

If you do that, then you follow all the recommended build steps. If it still doesn't work, then the bug is somewhere else. If so, you should upload your source code to something like github so we can see it.

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 11:10 am
by ExeTwezz
sortie wrote:Is start.o meant to come first?

Don't pass -m32 when using i686-elf, there is no need. You are not passing -ffreestanding when linking. You are not linking with libgcc.

If you do that, then you follow all the recommended build steps. If it still doesn't work, then the bug is somewhere else. If so, you should upload your source code to something like github so we can see it.
No, it can be anywhere, since output is elf32, and linker marks the entry `entry' as the entry point of elf, so GRUB loads the elf and jumps to `entry'.

OK, I added `-ffreestanding' and `-lgcc' to $(LDFLAGS), but the result is the same.

The latest source code is here: https://yadi.sk/d/xXgzoTlicbZAF.

Re: Strange behaviour on another machine.

Posted: Sun Nov 09, 2014 1:55 pm
by ExeTwezz
Hi,

After doing some strange things with my repo, I concluded that the error is not in Makefile or whatever, and not in the source code, actually, nowhere. I've copied my new Makefile to the "previous state" of repo with the same source code (only the difference was Makefile as says git status), and everything was cool. So, I've just merged new Makefile with the "previous state" repo.

Anyway, thank you. I've learned some things.

Update: Oh, I feel stupid. The error was in the code, more precisely, in the sequence of structures (the field `next' was undefined after creating a new structure, and I was using the `next' field when it's undefined). I think it's strange that I didn't saw this on other structures.