The meaning relocatable(Gu ld -Ur).

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.
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

The meaning relocatable(Gu ld -Ur).

Post by TylerH »

When I link with the -Ur flag, it makes my kernel relocatable. But what does relocatable mean in this use? Does it mean my kernel is a PIE and can be loaded anywhere, but unmovable, or does it mean it can be loaded anywhere then remapped into (for example) 0xC0000000?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: The meaning relocatable(Gu ld -Ur).

Post by gerryg400 »

When I link with the -Ur flag, it makes my kernel relocatable. But what does relocatable mean in this use?
In this sense it means that the kernel is not fully linked. It will (most likely) not run correctly. To complete the link and make it work, you have to run ld again without the -Ur or -r flag. It would theoretically be possible to have a very smart loader that could complete the link, but Grub cannot do that.
If a trainstation is where trains stop, what is a workstation ?
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by TylerH »

Odd... It's always worked before. Albeit to work is only to print a to 0xb8000.

How is it that kernels can be loaded at x address, then mapped to a different virtual address. Would that not confuse the kernel of where it's data (among just about everything else) is?

Edit:
My final call to ld: ld -melf_i386 -nostdlib --oformat elf32-i386 -T link.ld -Ur --warn-unresolved-symbols $+ -o $@
My ld script:

Code: Select all

ENTRY(trampoline)
SECTIONS {
	.text 0x100000 : {
		code = .;_code = .;
		boot/boot.o(.text)
		*(.text)
		. = ALIGN(_pagesize);
		code_end = .;_code_end = .;
	}
	.data ALIGN(_pagesize) : {
		data = .;_data = .;
		*(.data)
		*(.rodata)
		. = ALIGN(_pagesize);
		data_end = .;_data_end = .;
	}
	.bss ALIGN(_pagesize) : {
		bss = .;_bss = .;
		*(.bss)
		. = ALIGN(_pagesize);
		bss_end = .;_bss_end = .;
	}
}
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by Owen »

The kernel is linked to its final destination address, and the early boot code is made explicitly aware of the fact that its address information is "wrong". Alternatively, you can engage in some big linker tricks, which also work.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: The meaning relocatable(Gu ld -Ur).

Post by gerryg400 »

You must remove the -Ur. It may work, or appear to work but it will eventually fail.
How is it that kernels can be loaded at x address, then mapped to a different virtual addres
One way is like this ...

Code: Select all

.text 0xc0000000 : 
     AT ( 0x100000 ) ALIGN (0x1000)
     { *(.text) }

    etc.
This causes the code to be loaded by Grub at 0x100000. However, after you set up paging, the code can be re-mapped to 0xc0000000 and run there. There are a few tricks needed. You need to make sure that the start-up code is position independent because it will start at 0x100000 and then switch to 0xc0000000, and you'll have to apply an offset to access data until you set the paging bit.
If a trainstation is where trains stop, what is a workstation ?
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by TylerH »

Code: Select all

ENTRY(trampoline)
SECTIONS {
    .init 0x1000000 : AT(0x1000000) {
        init = .;_init = .;
		boot/boot.o(.text)
		boot/boot.o(.data)
        init_end = .;_init_end = .;
    }
	.text 0xc0000000 : {
		code = .;_code = .;
		*(EXCLUDE_FILE (boot/boot.o).text)
		. = ALIGN(pagesize);
		code_end = .;_code_end = .;
	}
	.data ALIGN(pagesize) : {
		data = .;_data = .;
		*(EXCLUDE_FILE (boot/boot.o).data .rodata)
		. = ALIGN(pagesize);
		data_end = .;_data_end = .;
	}
	.bss ALIGN(pagesize) : {
		bss = .;_bss = .;
		*(EXCLUDE_FILE (boot/boot.o).bss)
		. = ALIGN(pagesize);
		bss_end = .;_bss_end = .;
	}
}
How do I close the huge gap between .init and .text?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: The meaning relocatable(Gu ld -Ur).

Post by gerryg400 »

Something like this .... (sorry unchecked because I am away from my dev machine)

Code: Select all

ENTRY(trampoline)
SECTIONS {
    .init 0xc0000000 : AT(0x100000) {
        init = .;_init = .;
      boot/boot.o(.text)
      boot/boot.o(.data)
        init_end = .;_init_end = .;
    }
   .text ALIGN(pagesize) : {
      code = .;_code = .;
      *(EXCLUDE_FILE (boot/boot.o).text)
      . = ALIGN(pagesize);
      code_end = .;_code_end = .;
   }
   .data ALIGN(pagesize) : {
      data = .;_data = .;
      *(EXCLUDE_FILE (boot/boot.o).data .rodata)
      . = ALIGN(pagesize);
      data_end = .;_data_end = .;
   }
   .bss ALIGN(pagesize) : {
      bss = .;_bss = .;
      *(EXCLUDE_FILE (boot/boot.o).bss)
      . = ALIGN(pagesize);
      bss_end = .;_bss_end = .;
   }
}
Note as I said before, that the code in boot.S that executes and sets up the mappings before the paging bit is set must be position independent because it will need to execute at 0x100000 even though LD thought it would execute at 0xc0000000. Also if you access any global variables before the remapping is done and the paging bit is set, you will have to subtract 0xbff00000 from the address. That's because LD will fixup the addresses to be in the 0xc0000000 range. I have some sample code somewhere that does this. I can try to find it if no-one can point you to some.

BTW, I think you have a typo you said

Code: Select all

    .init 0x1000000 : AT(0x1000000) {
but I think you meant

Code: Select all

    .init 0x100000 : AT(0x100000) {
If a trainstation is where trains stop, what is a workstation ?
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by TylerH »

No, the point was to have .init have vma=lma(0x100000), then for the others to have a contiguous lma with .init, but with the real vma. All the code and data in .init is for setting up paging.

After the kernel is setup it can just unmap and mark the phys memory used by .init free.

My problem is that grub loads .init at 0x10000 and the tries to load .text at 0xc0000000. I want .text loaded at the next page aligned addr after .init, but with a vma of 0xc0000000.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: The meaning relocatable(Gu ld -Ur).

Post by gerryg400 »

Well try ..

Code: Select all

ENTRY(trampoline)
SECTIONS {
    .init 0x100000 : AT(0x100000) {
        init = .;_init = .;
      boot/boot.o(.text)
      boot/boot.o(.data)
        init_end = .;_init_end = .;
    }
   .text 0xc0000000 : AT(0x104000) {
      code = .;_code = .;
      *(EXCLUDE_FILE (boot/boot.o).text)
      . = ALIGN(pagesize);
      code_end = .;_code_end = .;
   }
   .data ALIGN(pagesize) : {
      data = .;_data = .;
      *(EXCLUDE_FILE (boot/boot.o).data .rodata)
      . = ALIGN(pagesize);
      data_end = .;_data_end = .;
   }
   .bss ALIGN(pagesize) : {
      bss = .;_bss = .;
      *(EXCLUDE_FILE (boot/boot.o).bss)
      . = ALIGN(pagesize);
      bss_end = .;_bss_end = .;
   }
}
No guarantees though.

P.S. Don't forget to FIX YOUR TYPO. ( 1M = 0x100000 not 0x1000000 )
If a trainstation is where trains stop, what is a workstation ?
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by Owen »

I'll quote the relevant bit of my ARM ldscript, which is built the same way:

Code: Select all

    . += 0xFFFF0000
    .text : AT(ADDR(.text) - 0xFFFF0000) {
        *(.ivt)
        *(.text*)
        *(.rodata*)
     }
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by TylerH »

I'm loading at 16mb on purpose, isn't there important stuff in the area between 1mb and 16mb?
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:

Re: The meaning relocatable(Gu ld -Ur).

Post by Combuster »

memory that's actually present? :wink:
"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 ]
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: The meaning relocatable(Gu ld -Ur).

Post by gerryg400 »

In you 2nd post you said

Code: Select all

SECTIONS {
   .text 0x100000 : {
      code = .;_code = .;
In your 3rd post you said

Code: Select all

SECTIONS {
    .init 0x1000000 : AT(0x1000000) {
        init = .;_init = .;
In your 4th post you said

Code: Select all

grub loads .init at 0x10000
At least 2 of those 3 different addresses must be typos.
If a trainstation is where trains stop, what is a workstation ?
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: The meaning relocatable(Gu ld -Ur).

Post by TylerH »

That's gerryf400 for pointing that out. I'll make it 1mb.

But something just occurred to me. Why am I adding all this extra complexity to my kernel, when it'd be simple to just run it in the low x mbs? Is there any practical reason to choose the higher half over the lower half? It leaves the same amount for apps to use later on, either way.

Is higher half just a tradition, or is there a rationale to it? The only meaningful reason(IMHO) in the wiki is for 64bit oses, mine is 32bit.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: The meaning relocatable(Gu ld -Ur).

Post by gerryg400 »

I think the main advantage of the higher half kernel is that that you can change the memory map of your O/S and you have more chance of keeping the applications that have been written for your O/S binary compatible.

Let's say you decide on a memory map where user-space goes from 0 to 0xbfff ffff and the kernel from 0xc000 0000 to 0xffff ffff. And let's say the apps built for your O/S have an entry point at 0x401000. If you one day re-design your kernel so that it need more memory you could change the kernel to begin at 0xb000 0000 and your apps wouldn't need to be rebuilt. It's not so easy to guarantee that with a lower-half kernel.
If a trainstation is where trains stop, what is a workstation ?
Post Reply