Higher Half kernel linker problems

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
vhg119
Member
Member
Posts: 71
Joined: Fri Aug 24, 2007 5:56 pm
Location: CA, USA

Higher Half kernel linker problems

Post by vhg119 »

I'm having some trouble getting my linker script to work right.

Everything is working correctly except for the fact that after the jump to the higherHalf label, it's not actually running at the higher half. I know this because Bochs reports that my EIP is at location "EIP=000001fa" when I kill bochs.

This is my kernel entry point (start.s):

Code: Select all

# This is the Kernel entry point
# At this point, GDT should be set up and we should be in protected mode

.section .start
.text
.global kernel_start
.code32
kernel_start:
	# Set up Segment Registers
	movw $0x0010, %ax
	movw %ax, %ds
	movw %ax, %es
	movw %ax, %fs
	movw %ax, %gs
	movw %ax, %ss
	
	call k_install_paging

	# Set up kernel stack (2MB at HigherHalf)
	movl $0x801FFFFF, %ebp
	movl $0x801FFFFF, %esp

	jmp HigherHalf

.text
HigherHalf:
	call k_main

hang:
	jmp hang

# Include the ISR and IRQ stubs
.include "boot/interrupts.inc"

This is my linker script:

Code: Select all

ENTRY( kernel_start )

OUTPUT_FORMAT( binary )

SECTIONS
{
        . = 0x0;
       
        .start 0x0 : AT(0x0)
        {
                *(.start)
                . = ALIGN( 4096 );
        }

        .text 0x80000000 + SIZEOF( .start ) : AT( ADDR( .start ) + SIZEOF( .start ) )
        {
                *(.text)
		*(.rodata*)
       		*(.gnu.linkonce.r.*)
        }
       
        .data ADDR( .text ) + SIZEOF( .text ) : AT( LOADADDR( .text ) + SIZEOF( .text ) )
        {
                *(.data)
        }
       
        .bss ALIGN( ADDR( .data ) + SIZEOF( .data ), 4096 ): AT( LOADADDR( .data ) + SIZEOF( .data ) )
        {
                *(.bss .bss.*)
                *(COMMON)
        }	
}
Here's what bochs reports:

Code: Select all

00092426000i[CPU0 ] protected mode
00092426000i[CPU0 ] CS.d_b = 32 bit
00092426000i[CPU0 ] SS.d_b = 32 bit
00092426000i[CPU0 ] | EAX=00000000  EBX=00000000  ECX=0000002e  EDX=00000f56
00092426000i[CPU0 ] | ESP=801fffef  EBP=801ffff7  ESI=00002000  EDI=00002000
00092426000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df IF tf SF zf AF pf cf
00092426000i[CPU0 ] | SEG selector     base    limit G D
00092426000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00092426000i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00092426000i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00092426000i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00092426000i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00092426000i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00092426000i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00092426000i[CPU0 ] | EIP=000001fa (000001fa)
00092426000i[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x00000000
00092426000i[CPU0 ] | CR3=0x00091000 CR4=0x00000000
00092426000i[CPU0 ] >> jmp .+0xfffffffe (0x000001fa) : EBFE
00092426000i[     ] restoring default signal behavior

User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

I'm not an expert on this but:

1) HigherHalf: still seems to be in the .start section, I think?
2) Nothing to do with the problem, but if later down the line you would like to use v86 mode for anything (VESA, for example), avoid putting code at 0x00 as you will overwrite the real mode IVT.

Cheers,
Adam
vhg119
Member
Member
Posts: 71
Joined: Fri Aug 24, 2007 5:56 pm
Location: CA, USA

Post by vhg119 »

Ok.. I think I know what my problem is (one of my problems). I do not know how to link a program to run at a starting address other than 0x0.

Say I have a program I wrote in assembly. I compile and link this program as a binary object file. Then I want to load it at 0x3000. And then I want my kernel to call it at 0x3000.

How would I setup my linker script to get this working right?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

I'd first have tried:

Code: Select all

.start 0x3000 : AT(0x0)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

I think you are having a problem with the assembler. I have tried unsuccessfully to get the output from the assembler to get relocated but it has never worked. Of course this is with FASM but maybe you are having the same problem. Try calling k_main directly instead of jumping to HigherHalf first. Your linker script looks fine to me. Maybe you should try creating a map file to figure out exactly where everything is linked at. Add -Map kernel.map to the end of your ld command.
vhg119
Member
Member
Posts: 71
Joined: Fri Aug 24, 2007 5:56 pm
Location: CA, USA

Post by vhg119 »

frank wrote:I think you are having a problem with the assembler. I have tried unsuccessfully to get the output from the assembler to get relocated but it has never worked. Of course this is with FASM but maybe you are having the same problem. Try calling k_main directly instead of jumping to HigherHalf first. Your linker script looks fine to me. Maybe you should try creating a map file to figure out exactly where everything is linked at. Add -Map kernel.map to the end of your ld command.
Thanks for the reply Frank. Calling k_main directly works fine. It all runs fine... except, it's not running at the address I'd expect it to be running at- which is suppose to be > 0x80000000.

At the end of k_main is an infinite loop so I know it shouldn't be returning from it. Also, interrupts are firing fine. It looks to me like LD's not linking it correctly.

Before you ask...
No, I'm not issuing any command line parameters for LD that would override the linker script.
Yes, I'm sure that I'm linking it using the linker script.

Maybe you're right. Maybe I'm assembling it incorrectly.

I'm just doing

Code: Select all

as start.s -o start.o
Should I be using special parameters to affect the output object file?

I've attached my whole project if anyone wants to take a look and help me out with anything at all.

The files you probably want to pay attention to are:
boot/boot.s - bootloader
boot/start.s - kernel asm stub
kernel/main.c - calls the rest of the initialization code (gdt/idt/tss...)

There's also a .bochsrc included... If you read the Makefile you'll notice that i use a loopback device to write my kernel and read it back.

Don't mind the name.. this is just all for academic purposes.

Thanks for any help guys.
Attachments
vinux-0.0.13-hh.tar.gz
my crappy proof of concept os...
(17.61 KiB) Downloaded 19 times
vhg119
Member
Member
Posts: 71
Joined: Fri Aug 24, 2007 5:56 pm
Location: CA, USA

Post by vhg119 »

I got it working!

Since my '.start' section calls k_install_paging, I had to have paging.o relocated to the same section.

So my .start output section looks like this now.

Code: Select all

.start 0x0: AT(0x0)
        {
                *(.start)
		paging.o
                . = ALIGN( 4096 );
        }
And now it all works!

Thanks for the help guys. oh.. and I found my answer, of course, by RTM.

I read every word of http://www.gnu.org/software/binutils/ma ... html#SEC23
Post Reply