How to use cross-compiler on Brian Tutorial

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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:How to use cross-compiler on Brian Tutorial

Post by Solar »

jason7007 wrote: How can I output these messages to a file...
{command} > {filename}

writes the stdout to filename.

{command} 2> {filename}

writes the stderr to filename.

{command} > {filename1} 2> {filename2}

writes stdout to filename1 and stderr to filename2.

{command} > filename 2>&1

writes stdout and stderr to filename. Note: As the buffering policy on stdout and stderr differ, messages might be out of sync.

(Are you really sure you want to start OS development? ;) )
Every good solution is obvious once you've found it.
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

Solar,
Do you mean like this?

i386-elf-ld -T link.ld -o kernel.bin start.o main.o scrn.o gdt.o idt.o isrs.o irq.o timer.o kb.o 2 > myfile.txt

Yes, I am very devoted in os development. In many aspect I have advance knowledge , but in some like Unix/Linux or even batch filing in Dos I am very amateur.

Thank you for your patience.
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

Solar, I got it, thanks.

Here is the error output:

start.o: In function `mboot':
start.asm:(.text+0x1c): undefined reference to `code'
start.asm:(.text+0x20): undefined reference to `bss'
start.asm:(.text+0x24): undefined reference to `end'
start.o: In function `stublet':
start.asm:(.text+0x2d): undefined reference to `_main'
start.o: In function `_gdt_flush':
start.asm:(.text+0x39): undefined reference to `_gp'
start.o: In function `_idt_load':
start.asm:(.text+0x5b): undefined reference to `_idtp'
start.o: In function `isr_common_stub':
start.asm:(.text+0x1af): undefined reference to `_fault_handler'
start.o: In function `irq_common_stub':
start.asm:(.text+0x27f): undefined reference to `_irq_handler'
gdt.o: In function `gdt_install':
gdt.c:(.text+0xf7): undefined reference to `gdt_flush'
idt.o: In function `idt_install':
idt.c:(.text+0x5f): undefined reference to `idt_load'
isrs.o: In function `isrs_install':
isrs.c:(.text+0xb): undefined reference to `isr0'
isrs.c:(.text+0x1e): undefined reference to `isr1'
...
isrs.c:(.text+0x272): undefined reference to `isr30'
isrs.c:(.text+0x285): undefined reference to `isr31'
irq.o: In function `irq_install':
irq.c:(.text+0xbb): undefined reference to `irq0'
irq.c:(.text+0xce): undefined reference to `irq1'
...
irq.c:(.text+0x1ed): undefined reference to `irq15'

Thank you for your patience.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:How to use cross-compiler on Brian Tutorial

Post by Candy »

Solar wrote: (Are you really sure you want to start OS development? ;) )
OS development fitness has pretty much nothing to do with unix aptness. It might be an advantage, but you can do quite a lot of OSdev without touching unix.
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

I just need a help to compile the tutorial of Bran kernel development source code using my cross-compiler. If the cross-compiler can compile it without error then I will have confidence in using it. I can really appreciate your help.


Thanks for your patience.
Candamir

Re:How to use cross-compiler on Brian Tutorial

Post by Candamir »

I think I ought to be able to give you a hint to most of the errors:
Leading underscores is where the game won't play. In all ASM files, you must remove all leading underscores from method names visible in C. I'm pretty sure about this, so please do as described here and then try to build your kernel again.

About the first three warnings I'm not that sure, but I think it has to do something with the a.out kludge and as now your format is ELF, you don't need it anymore. Again, we will use BareBones from the FAQ as our starting point.

This file will be your new start.asm:

Code: Select all

global loader           ; making entry point visible to linker
extern main             ; main is defined elsewhere

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM

; reserve initial kernel stack space
STACKSIZE equ 0x4000          ; that's 16k.

loader:
   mov esp, stack+STACKSIZE           ; set up the stack
   
   call  main                        ; call kernel proper
               hlt                    ; halt machine should kernel return

; ===========================================
; Here you insert all the GDT, IDT, ISRs and IRQ code from your previous start.asm
; ===========================================

section .bss
align 32
stack:
   resb STACKSIZE      ; reserve 16k stack on a quadword boundary
Where you see the comment with '=' signs, do what you're told there. Then, the only thing you have to do is to modify your linker script when it comes to the entry point: ENTRY(loader) instead of ENTRY(start). You could also modify the method name from loader to start, that's your choice.

Note: I removed the 'push eax' and the 'push ebx' operations because in bkerndev, no multiboot information is used. Jason, you can add these lines just before the 'call main' line later on, when you want to retrieve information from the Bootloader, but right now, I think you should try to just compile and run everything and then start adding features.

OK, now it should work. Please tell me if anything's wrong.

Candamir

PS: I hope this really helped you so that you now can start with the fun part of osdeving...
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

After following your instructions here is the error message.

Code: Select all

i386-elf-ld: warning: cannot find entry symbol loader; defaulting to 00100000
gdt.o: In function `gdt_install':
gdt.c:(.text+0xf7): undefined reference to `gdt_flush'
idt.o: In function `idt_install':
idt.c:(.text+0x5f): undefined reference to `idt_load'
isrs.o: In function `isrs_install':
isrs.c:(.text+0xb): undefined reference to `isr0'
isrs.c:(.text+0x1e): undefined reference to `isr1'
isrs.c:(.text+0x34): undefined reference to `isr2'
...
isrs.c:(.text+0x272): undefined reference to `isr30'
isrs.c:(.text+0x285): undefined reference to `isr31'
irq.o: In function `irq_install':
irq.c:(.text+0xbb): undefined reference to `irq0'
irq.c:(.text+0xce): undefined reference to `irq1'
...
irq.c:(.text+0x1ed): undefined reference to `irq15'
Thank you for your patience.
Candamir

Re:How to use cross-compiler on Brian Tutorial

Post by Candamir »

Let me see... It seems like as your ASM-to-C references have been resolved, but not the C-to-ASM references...

Could you please post all your start.asm and your linker script? That'll help me.

Candamir
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

I am attaching the "start.asm" because it is too long to be pasted here.


The linker script is this:
OUTPUT_FORMAT("elf32-i386")
ENTRY(loader)
SECTIONS
{
. = 0x00100000;

.text :
{
*(.text)
}

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

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

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

Thank you so much.
Candamir

Re:How to use cross-compiler on Brian Tutorial

Post by Candamir »

Ok, here we go. First, you now have two stacks. Just at the very end of your file, delete everything between 'iret' and '; ======================' That's what I can do for you now.

For the moment, it's ok if you just do what I told you in the above section and try to compile. But this time, please redirect the output from your build process to a file and also attach it in your post, along with your new start.asm. Oh, and please also send me a copy of your gdt.c or idt.c or isrs.c or irq.c, whichever you like will do (but don't attach all of these four, just one of them). You might have to put them into a zip or tar file in order to have them in one single archive.

Candamir

BTW: Your linker script is OK :D
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,
The output of linker is blank, does this mean it is okay? I redirected it to myfile.txt, but when I open this file it is blank.
Also, it is kinda weird this form because when I am attaching the files they are not showing this time.

Here is the gdt.c

/* bkerndev - Bran's Kernel Development Tutorial
* By: Brandon F. ([email protected])
* Desc: Global Descriptor Table management
*
* Notes: No warranty expressed or implied. Use at own risk. */
#include <system.h>

/* Defines a GDT entry */
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));

struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));

/* Our GDT, with 3 entries, and finally our special GDT pointer */
struct gdt_entry gdt[3];
struct gdt_ptr gp;

/* This is in start.asm. We use this to properly reload
* the new segment registers */
extern void gdt_flush();

/* Setup a descriptor in the Global Descriptor Table */
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
/* Setup the descriptor base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;

/* Setup the descriptor limits */
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);

/* Finally, set up the granularity and access flags */
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}

/* Should be called by main. This will setup the special GDT
* pointer, set up the first 3 entries in our GDT, and then
* finally call gdt_flush() in our assembler file in order
* to tell the processor where the new GDT is and update the
* new segment registers */
void gdt_install()
{
/* Setup the GDT pointer and limit */
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
gp.base = &gdt;

/* Our NULL descriptor */
gdt_set_gate(0, 0, 0, 0, 0);

/* The second entry is our Code Segment. The base address
* is 0, the limit is 4GBytes, it uses 4KByte granularity,
* uses 32-bit opcodes, and is a Code Segment descriptor.
* Please check the table above in the tutorial in order
* to see exactly what each value means */
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);

/* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment */
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);

/* Flush out the old GDT and install the new changes! */
gdt_flush();
}

Thanks.
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

Here the new start.asm in two messages because it is too long.

Part 1:

global loader ; making entry point visible to linker
extern main ; main is defined elsewhere

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required

section .text
align 4
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM

; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that's 16k.

loader:
mov esp, stack+STACKSIZE ; set up the stack

call main ; call kernel proper
hlt ; halt machine should kernel return

; ===========================================
; Here you insert all the GDT, IDT, ISRs and IRQ code from your previous start.asm
; This will set up our new segment registers. We need to do
; something special in order to set CS. We do what is called a
; far jump. A jump that includes a segment as well as an offset.
; This is declared in C as 'extern void gdt_flush();'
global gdt_flush
extern gp
gdt_flush:
lgdt [gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret

; Loads the IDT defined in '_idtp' into the processor.
; This is declared in C as 'extern void idt_load();'
global idt_load
extern idtp
idt_load:
lidt [idtp]
ret
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

Here is Part 2:

; In just a few pages in this tutorial, we will add our Interrupt
; Service Routines (ISRs) right here!
global isr0
global isr1
...
global isr31

; 0: Divide By Zero Exception
isr0:
cli
push byte 0
push byte 0
jmp isr_common_stub

; 1: Debug Exception
isr1:
cli
push byte 0
push byte 1
jmp isr_common_stub

...

; 8: Double Fault Exception (With Error Code!)
isr8:
cli
push byte 8
jmp isr_common_stub

...

; 10: Bad TSS Exception (With Error Code!)
isr10:
cli
push byte 10
jmp isr_common_stub

...

; 14: Page Fault Exception (With Error Code!)
isr14:
cli
push byte 14
jmp isr_common_stub

...
<edit by pype: ISR 15..31 points to the 'not installed' stub/>
jason7007

Re:How to use cross-compiler on Brian Tutorial

Post by jason7007 »

Hi,

Here is the last part of start.asm:
; We call a C function in here. We need to let the assembler know
; that '_fault_handler' exists in another file
extern fault_handler

; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, fault_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret

global irq0
global irq1
...
global irq15

; 32: IRQ0
irq0:
cli
push byte 0
push byte 32
jmp irq_common_stub

; 33: IRQ1
irq1:
cli
push byte 0
push byte 33
jmp irq_common_stub

...

; 47: IRQ15
irq15:
cli
push byte 0
push byte 47
jmp irq_common_stub

extern irq_handler

irq_common_stub:
pusha
push ds
push es
push fs
push gs

mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp

push eax
mov eax, irq_handler
call eax
pop eax

pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret


; ===========================================

section .bss
align 32
stack:
resb STACKSIZE ; reserve 16k stack on a quadword boundary
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:How to use cross-compiler on Brian Tutorial

Post by Pype.Clicker »

Hmm ..

could you put all these sources into a zipfile that you attach next time rather than filling 4 posts with source code? (so much code on a forum is a bit hard to read and distracts us from your actual question).

if i understand correctly
The output of linker is blank, does this mean it is okay? I redirected it to myfile.txt, but when I open this file it is blank.
Also, it is kinda weird this form because when I am attaching the files they are not showing this time.
I suggest you use "objdump -h {output file}" to see if everything is in place in the file generated by the linker. You may also request it a "symbol map" (e.g. myGdt ... 0x001234 myIdt...0x005678, etc.) with the "-M{mapfile}" option.
It's normal for the linker (or the compiler, or the assembler, etc) to be quiet on success: think of what nightmare Linux Kernel Compilation could be otherwise ;)
Post Reply