End of Kernel Linker Script

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
inixsoftware
Member
Member
Posts: 32
Joined: Fri Jan 31, 2014 8:21 am

End of Kernel Linker Script

Post by inixsoftware »

To determine the End-of-Kernel (using end defined in Linker Script), should you use &end or just end? On other posts, I have seen people argue both sides, so I am not exactly sure who is 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:

Re: End of Kernel Linker Script

Post by Combuster »

If you look at it you can have two options

Code: Select all

extern uint32_t end;
(...)
a = end;
b = &end;
With basic C you should already know the difference between these operations: one returns the location where a variable is stored, the other returns the contents of that variable. That means you have to choose according to what end really does in the linker script.

A linker script has however no idea what a variable is, but only what symbols are: names with a value. If you for instance have the typical construct in your linker script

Code: Select all

end = .
then the symbol end has the value that corresponds with that location, i.e. the end as the symbol equals the end of the kernel.

variables in C work by reserving space, and giving that space a name. The corresponding symbol gets the name of that variable, and the linker is asked to fill in the address where it is stored as that symbol's value. Using the variable then results in using that symbol's variable as an address and perform a memory access on it, whereas an reference operator will simply return the actual symbol as that is the address where that data is stored.

Therefore in this particular example, variable a, which implies a memory access, will return whatever data was stored directly after the kernel. variable b will hold the numeric address of that location, i.e. the location of the first bytes after the kernel. Hence answer b is correct for this particular set-up. There are of course methods to be found where you don't use the unary &-operator, but they all depend on how end gets defined.
"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 ]
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: End of Kernel Linker Script

Post by bluemoon »

Furthermore, from the above example, B works better on 64-bit system since you don't need to care about address size, and just use pointer directly.
you may even do:

Code: Select all

extern void end;
void* end_of_kernel = &end;
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: End of Kernel Linker Script

Post by neon »

I never quite understood the purpose of using this hack. What is so difficult about parsing your image headers and getting the end of the last segment in memory? Both will work however the latter won't tie the software component to a specific linker feature and thus more compatible to other tool chains.

I suppose it would not matter if you don't ever plan on switching linkers; however it is something to be considered for long term projects.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: End of Kernel Linker Script

Post by bluemoon »

neon wrote:I never quite understood the purpose of using this hack. What is so difficult about parsing your image headers and getting the end of the last segment in memory? Both will work however the latter won't tie the software component to a specific linker feature and thus more compatible to other tool chains.

I suppose it would not matter if you don't ever plan on switching linkers; however it is something to be considered for long term projects.
The problem is that some loader may not preserve the headers in the visible address space of the loaded kernel, unless you link it in a special way.

I'm not aware any linker, that support the linker script, that do not support emitting a variable.
In the worst case you could write a .c file with a variable named end and ask the linker to put it at the end.

If all that do not work, I would consider such linker crap and switch to other toolchain.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: End of Kernel Linker Script

Post by neon »

The problem is that some loader may not preserve the headers in the visible address space of the loaded kernel, unless you link it in a special way.
The kernel should be able to access its own section information in some standard form expected by the kernel image; this includes debug information, resources, and special section information specific to that kernel that the loader might not (and should not care to) know about.

I don't see any particular case where stripping the headers is a good thing provided that the loader does not provide an alternative means of access (as of this writing, Multiboot does not.)
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: End of Kernel Linker Script

Post by Owen »

neon wrote:
The problem is that some loader may not preserve the headers in the visible address space of the loaded kernel, unless you link it in a special way.
The kernel should be able to access its own section information in some standard form expected by the kernel image; this includes debug information, resources, and special section information specific to that kernel that the loader might not (and should not care to) know about.

I don't see any particular case where stripping the headers is a good thing provided that the loader does not provide an alternative means of access (as of this writing, Multiboot does not.)
An ELF header parser is a whole bunch of code wasting memory I don't want nor need?

Besides, my linker script is sufficiently complicated for a whole bunch of other reasons - static initialization, exception handling, matching up the vectors segment with the 0xFFFF0000 ARM HIVECS location
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: End of Kernel Linker Script

Post by neon »

Perhaps we just have different ideas in design structure. If the operating system is to support ELF, an associated ELF header parser implementation is a necessity anyways. The only real drawback is that it increases the complexity of kernel initialization.

I suppose it does not really matter anyways as we typically encourage the use of LD scripts for tasks as long as they are not tightly coupled with the source.
Last edited by neon on Sun Feb 02, 2014 6:06 pm, edited 1 time in total.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: End of Kernel Linker Script

Post by bluemoon »

For ELF specification, the loader is not required to retain headers information when loading objects (And there is no defined memory address to put such information).

To have the header accessible from kernel you then require to do non-trivial mechanism asking the linker to attach the headers into the kernel sections - ld support that by tweaking linker script, but I doubt if many other linkers support that too.

And I do not see this any simpler then putting an end on linker script.
neon wrote:The point here is that the script does simplify a lot of things -- but is not a necessity.
You are right, there are more than one way to do it.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: End of Kernel Linker Script

Post by neon »

Sorry, I updated my last post before you responded. We do typically encourage its use; and I agree using the linker script is far simpler.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: End of Kernel Linker Script

Post by Owen »

neon wrote:Perhaps we just have different ideas in design structure. If the operating system is to support ELF, an associated ELF header parser implementation is a necessity anyways. The only real drawback is that it increases the complexity of kernel initialization.

I suppose it does not really matter anyways as we typically encourage the use of LD scripts for tasks as long as they are not tightly coupled with the source.
You assume the binary loader is a part of the kernel. True for most monolithic kernels, but those of us developing microkernels are inclined towards it being a part of some library and/or service.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: End of Kernel Linker Script

Post by neon »

Good observation there. For a microkernel architecture it will create yet another chicken and egg scenario.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Post Reply