Page 1 of 3

ELF Relocation!

Posted: Fri Jul 06, 2007 3:00 am
by pcmattman
I'm rather pleased with myself, this afternoon (ie. 4 hours) I was able to completely implement ELF execution. At the moment it's pretty messy and rather hacked, but it all works well.

The screen shot shows a lot of excess text, which I've kept for debug purposes. The real text that should be printed is the last line of the display.

Image

I will be committing the changes to my CVS (and SVN) soon if you want to view the code.

Edit: hmmm, it doesn't seem to want to show the image... View here

Posted: Fri Jul 06, 2007 3:26 am
by AJ
Hi,

I guess you proboably have to directly reference the jpg file to get it displayed here.

Congrats on getting ELF up and running! I can currently relocate ELF and COFF and am looking at PE support too - the idea is that my second stage boot loader can be fairly universal. Seeing as I am putting various format support in there, I may as well add support to the kernel too...

I am thinking of not supporting flat binaries due to the danger with not knowing BSS size etc - I would prefer all executables to have a format.

Adam

Posted: Fri Jul 06, 2007 3:52 am
by pcmattman
I'm currently planning on rewriting my ELF code, just because I hacked it together to load a single file, and no special cases would work. It was also an ELF object file, not linked yet, so I have yet to figure that part out. Thankfully I have the ELF file format documentation in front of me so I'm set.

Posted: Fri Jul 06, 2007 5:11 am
by AJ
Hi,

I've done it the other way round - I can currently only relocate fully linked executables. As I am planning to use dynamic ELF linking for drivers, I really need to get round to that part though.

Adam

Posted: Fri Jul 06, 2007 6:05 pm
by pcmattman
Interesting, maybe we could swap code?

Edit: newer, much better code is now available on my CVS. I'm about to start work on loading and executing program files. I just have one small problem - how do I tell the difference?

Posted: Sat Jul 07, 2007 2:37 pm
by Kevin McGuire
pcmattman wrote:Interesting, maybe we could swap code?

Edit: newer, much better code is now available on my CVS. I'm about to start work on loading and executing program files. I just have one small problem - how do I tell the difference?
I downloaded the source from the CVS, and I am unable to get anything to compile correctly out of the box. I have errors and warnings flying all over my screen (after making some changes to the Makefile) to support compiling on a Linux host.

I give up at this moment. When someone is this hard to compile out of box there is no reason to continue trying..

Posted: Sat Jul 07, 2007 5:42 pm
by Alboin
Kevin McGuire wrote:
pcmattman wrote:Interesting, maybe we could swap code?

Edit: newer, much better code is now available on my CVS. I'm about to start work on loading and executing program files. I just have one small problem - how do I tell the difference?
I downloaded the source from the CVS, and I am unable to get anything to compile correctly out of the box. I have errors and warnings flying all over my screen (after making some changes to the Makefile) to support compiling on a Linux host.

I give up at this moment. When someone is this hard to compile out of box there is no reason to continue trying..
You'll discover that GCC isn't as portable as you'd like it to be. ;)

I still haven't been able to get my OS to compile correctly on Linux. (I originally wrote it on Windows.) It's partially why I've stopped working on it for the moment.

Posted: Sat Jul 07, 2007 8:20 pm
by pcmattman
Kevin McGuire wrote:
pcmattman wrote:Interesting, maybe we could swap code?

Edit: newer, much better code is now available on my CVS. I'm about to start work on loading and executing program files. I just have one small problem - how do I tell the difference?
I downloaded the source from the CVS, and I am unable to get anything to compile correctly out of the box. I have errors and warnings flying all over my screen (after making some changes to the Makefile) to support compiling on a Linux host.

I give up at this moment. When someone is this hard to compile out of box there is no reason to continue trying..
What errors, and what warnings? I compiled with GCC 4.2.0, an ELF cross-compiler (Cygwin-based) I compiled a while ago. I doubt any earlier version of GCC will work properly, especially with the template classes I use - I couldn't get them to work until I upgraded.

Posted: Sun Jul 08, 2007 4:51 am
by Kevin McGuire
It might help if you passed the compile flags to the compiler.
%.o : %.cc
@echo Compiling $<
@echo $(CXXFLAGS) -c $< -o $@ > comp.txt
$(CXX) $(CXXFLAGS) $(SRCS)


This does not work with GNU Make 3.81.
%.o : %.cc
@echo Compiling $<
@echo $(CXXFLAGS) -c $< -o $@ > comp.txt
@$(CXX) @comp.txt

Posted: Sun Jul 08, 2007 6:10 am
by Kevin McGuire
Here is a Makefile.linux for Linux which uses as for the assembler. However, it does not correctly produce a Multiboot Header. Anyone who has GCC should have GAS.

Code: Select all

# compiler and flags
CXX:=c++
CXXFLAGS:=-I ./include -nostdlib -fno-rtti -fno-exceptions
## DJGPP ELF-ENABLED LD ###
LD:=ld
LDFLAGS:=-T linker.ld -Map link.map -o
# assembler
NASM:=as
AS:=as
NASM_SRCS:=$(shell find -mindepth 1 -maxdepth 3 -name "*.s")
AS_SRCS:=$(shell find -mindepth 1 -maxdepth 3 -name "*.asm")
# source and objects, and final binary
SRCS:=$(shell find -mindepth 1 -maxdepth 3 -name "*.cc")
OBJS:=$(patsubst %.asm,%.o,$(AS_SRCS)) $(patsubst %.s,%.o,$(NASM_SRCS)) $(patsubst %.cc,%.o,$(SRCS))
FINALBIN:=kernel.bin

# clean up
clean:
	rm $(OBJS) *.bin

# buld the full kernel
all: $(FINALBIN)

# link command
$(FINALBIN) : $(OBJS)
	@echo Linking
	@echo $(OBJS)
	@$(LD) $(LDFLAGS) $(FINALBIN) *.o

# C++ source
# -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wredundant-decls -Winline -Wno-long-long -Wconversion
# the above = nightmare!
%.o : %.cc
	@echo Compiling $<
	@$(CXX) $(CXXFLAGS) -c $<

# assembly
%.o : %.asm irq.inc isr.inc
	@echo Assembling $<
	$(NASM) $< -o $@

%.o: %.s
	@echo Assembling $<
	@$(AS) -f elf -o $@ $<
With this in your kernel.cc the loader.asm can be compiled by as on Linux, and still produce a valid Multiboot Header.

Code: Select all

struct __attribute__ ((__packed__)) tmbhdr{
	unsigned long	magic;
	unsigned long	flags;
	unsigned long	checksum;
	unsigned long	hdr_addr;
	unsigned long	load_addr;
	unsigned long	load_end_addr;
	unsigned long	bss_end_addr;
	unsigned long	entry_addr;
	unsigned long	mode_type;
	unsigned long	width;
	unsigned long	height;
	unsigned long	depth;
	// http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Header-layout
};

#define MB_MAGIC	0x1BADB002
#define MB_FLAGS	((1<<1))
struct tmbhdr g_mbhdr = {
	MB_MAGIC,
	MB_FLAGS,
	0x0 - MB_MAGIC - MB_FLAGS,
	0x0,
	0x0,
	0x0,
	0x0,
	0x0
};
Since the Multiboot Header is produced as data inside the source file for GCC we have to place the .data section in front of the .text section to make it work.

Code: Select all

ENTRY (_loader)

SECTIONS 
{
	. = 0x00100000;
	.data ALIGN (0x1000) :
	{
		start_ctors = .;
		*(.ctor*)
		end_ctors = .;
		start_dtors = .;
		*(.dtor*)
		end_dtors = .;
		*(.data)
	}

	.text :
	{ 
		*(.text)
		*(.text.*)
	}

	.rodata ALIGN (0x1000) :
	{
		*(.rodata)
	}

	.bss : 
	{ 
		_sbss = .;
		*(COMMON)
		*(.bss)
		_ebss = .;
	}

	end = .; _end = .; __end = .;
}
Let me also give you the whole difference as during writting this I forgot about changes to irq.inc, to make it work with as apparently.
Index: linker.ld
===================================================================
--- linker.ld (revision 5)
+++ linker.ld (working copy)
@@ -3,18 +3,6 @@
SECTIONS
{
. = 0x00100000;
-
- .text :
- {
- *(.text)
- *(.text.*)
- }
-
- .rodata ALIGN (0x1000) :
- {
- *(.rodata)
- }
-
.data ALIGN (0x1000) :
{
start_ctors = .;
@@ -26,6 +14,17 @@
*(.data)
}

+ .text :
+ {
+ *(.text)
+ *(.text.*)
+ }
+
+ .rodata ALIGN (0x1000) :
+ {
+ *(.rodata)
+ }
+
.bss :
{
_sbss = .;
Index: irq.inc
===================================================================
--- irq.inc (revision 5)
+++ irq.inc (working copy)
@@ -20,113 +20,113 @@
# 32: IRQ0
irq0:
cli
- pushb $0
- pushb $32
+ push $0x0
+ push $32
jmp irq_common_stub

# 33: IRQ1
irq1:
cli
- pushb $0
- pushb $33
+ push $0
+ push $33
jmp irq_common_stub

# 34: IRQ2
irq2:
cli
- pushb $0
- pushb $34
+ push $0
+ push $34
jmp irq_common_stub

# 35: IRQ3
irq3:
cli
- pushb $0
- pushb $35
+ push $0
+ push $35
jmp irq_common_stub

# 36: IRQ4
irq4:
cli
- pushb $0
- pushb $36
+ push $0
+ push $36
jmp irq_common_stub

# 37: IRQ5
irq5:
cli
- pushb $0
- pushb $37
+ push $0
+ push $37
jmp irq_common_stub

# 38: IRQ6
irq6:
cli
- pushb $0
- pushb $38
+ push $0
+ push $38
jmp irq_common_stub

# 39: IRQ7
irq7:
cli
- pushb $0
- pushb $39
+ push $0
+ push $39
jmp irq_common_stub

# 40: IRQ8
irq8:
cli
- pushb $0
- pushb $40
+ push $0
+ push $40
jmp irq_common_stub

# 41: IRQ9
irq9:
cli
- pushb $0
- pushb $41
+ push $0
+ push $41
jmp irq_common_stub

# 42: IRQ10
irq10:
cli
- pushb $0
- pushb $42
+ push $0
+ push $42
jmp irq_common_stub

# 43: IRQ11
irq11:
cli
- pushb $0
- pushb $43
+ push $0
+ push $43
jmp irq_common_stub

# 44: IRQ12
irq12:
cli
- pushb $0
- pushb $44
+ push $0
+ push $44
jmp irq_common_stub

# 45: IRQ13
irq13:
cli
- pushb $0
- pushb $45
+ push $0
+ push $45
jmp irq_common_stub

# 46: IRQ14
irq14:
cli
- pushb $0
- pushb $46
+ push $0
+ push $46
jmp irq_common_stub

# 47: IRQ15
irq15:
cli
- pushb $0
- pushb $47
+ push $0
+ push $47
jmp irq_common_stub

# handles irq calls - two bytes already pushed - error code and interrupt number
Index: kernel.cc
===================================================================
--- kernel.cc (revision 5)
+++ kernel.cc (working copy)
@@ -26,6 +26,36 @@
#include <stddef.h>
#include <io.h>

+struct __attribute__ ((__packed__)) tmbhdr{
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long hdr_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+ unsigned long mode_type;
+ unsigned long width;
+ unsigned long height;
+ unsigned long depth;
+ // http://www.gnu.org/software/grub/manual ... der-layout
+};
+
+#define MB_MAGIC 0x1BADB002
+#define MB_FLAGS ((1<<1))
+struct tmbhdr g_mbhdr = {
+ MB_MAGIC,
+ MB_FLAGS,
+ 0x0 - MB_MAGIC - MB_FLAGS,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0
+};
+
+
// main() must be C so no name mangling occurs
extern "C" int main( multiboot_info_t* mb, unsigned int magic_number );

Posted: Sun Jul 08, 2007 6:25 am
by Kevin McGuire
A little something I noticed was that you apparently have no support for allocation of pages physical nor virtual. You do have a working heap implementation, which I assume you are using for all the allocations you need as you set it to the maximum memory size during booting.

Code: Select all

	// is there a heap?
	if( kheap == (MemBlock*) NULL )
	{
		// set it to the end of the image
		kheap = mblk = (MemBlock*) &end;
		
		// set it up properly
		mblk->used = 0;
		mblk->size = ( ( MultiBootHeader->mem_upper + MultiBootHeader->mem_lower ) * 1024 ) - sizeof( MemBlock ) - (uint_t) &end; // we allocate within the full memory available
		mblk->next = (MemBlock*) NULL;
	}

Posted: Sun Jul 08, 2007 5:10 pm
by pcmattman
Kevin McGuire wrote:A little something I noticed was that you apparently have no support for allocation of pages physical nor virtual.
Something I have yet to figure out how to do...

Posted: Sun Jul 08, 2007 5:55 pm
by pcmattman
Kevin McGuire wrote:It might help if you passed the compile flags to the compiler.
%.o : %.cc
@echo Compiling $<
@echo $(CXXFLAGS) -c $< -o $@ > comp.txt
$(CXX) $(CXXFLAGS) $(SRCS)


This does not work with GNU Make 3.81.
%.o : %.cc
@echo Compiling $<
@echo $(CXXFLAGS) -c $< -o $@ > comp.txt
@$(CXX) @comp.txt
I now know why printf() (but not kprintf()) was trying to drag puts() in with it :D...

I do assemble with GAS, and it does produce a multiboot header.

You're using the wrong makefile... Because of my switch to a Cygwin cross-compiler I created a new makefile, "Makefile_cygwin". It's full contents are shown here:

Code: Select all

# compiler and flags
CXX:=/usr/cross/bin/i586-elf-g++.exe
CXXFLAGS:=-I ./include -I ./lib -nostdlib -fno-rtti -fno-exceptions -O2

# linker and flags
LD:=/usr/cross/bin/i586-elf-ld.exe
LDFLAGS:=-T ./linker.ld -Map link.map -o

# project directories
PROJDIRS:=$(shell find ./ -type d -not -name "CVS")

# assembler
AS:=/usr/cross/bin/i586-elf-as.exe
AS_SRCS:=$(shell find $(PROJDIRS) -maxdepth 1 -name "*.asm" -type f)

# source and objects, and final binary
SRCS:=$(shell find $(PROJDIRS) -maxdepth 1 -name "*.cc" -type f)
OBJS:=$(patsubst %.asm,%.o,$(AS_SRCS)) $(patsubst %.cc,%.o,$(SRCS))

# final binary location
FINALBIN:=kernel.bin

# echo command location
ECHO:=echo

# dependiencies
DEPFILES:=$(patsubst %.cc,%.d,$(SRCS))

# tests the makefile
test:
	$(ECHO) $(DEPFILES)

# install
install: $(FINALBIN)
	@$(ECHO) $(SRCS) > srcs.txt
	cp $(FINALBIN) "Z:/boot/kernel.bin"

# clean up
clean:
	rm $(OBJS) *.bin

# buld the full kernel
all: $(FINALBIN)

# link command
$(FINALBIN) : $(OBJS)
	@$(ECHO) Linking
	@$(ECHO) $(OBJS) > objects.txt
	@$(LD) $(LDFLAGS) $(FINALBIN) @objects.txt
	@rm comp.txt objects.txt

# included files
-include $(DEPFILES)

# C++ source
%.o : %.cc
	@$(ECHO) Compiling $<
	@$(ECHO) $(CXXFLAGS) -MMD -MP -MT "$*.d" -c $< -o $@ > comp.txt
	@$(CXX) $(CXXFLAGS) @comp.txt

# assembly
%.o : %.asm
	@$(ECHO) Assembling $<
	@$(AS) $< -o $@
I probably should remove the earlier makefile...

Posted: Sun Jul 08, 2007 6:36 pm
by Kevin McGuire
pcmattman wrote:
Kevin McGuire wrote:A little something I noticed was that you apparently have no support for allocation of pages physical nor virtual.
Something I have yet to figure out how to do...
Well. Now, that it will compile. (not tried the existing Makefile you just specified).

I could write a really simple physical memory manager? I would like to work on something with SVN. I do not want to do anything terribly complicated.

Posted: Sun Jul 08, 2007 7:28 pm
by pcmattman
Kevin McGuire wrote:
pcmattman wrote:
Kevin McGuire wrote:A little something I noticed was that you apparently have no support for allocation of pages physical nor virtual.
Something I have yet to figure out how to do...
Well. Now, that it will compile. (not tried the existing Makefile you just specified).

I could write a really simple physical memory manager? I would like to work on something with SVN. I do not want to do anything terribly complicated.
What do you mean by physical memory manager? Do you mean the page allocator or actual paging?

SVN is giving me hell because of an apparently 'out of date' folder...