Grub: Where exactly is my kernel?

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
tkausl
Posts: 17
Joined: Tue Jul 14, 2015 9:54 pm

Grub: Where exactly is my kernel?

Post by tkausl »

Hello,

i am doing my first steps in kernel-development. I use grub to load my kernel and i have a little problem here. I read the memory-map from grub (which gets passed to my kernel in ebx) and i found a chunk of memory (of type 1) starting at address 1048576 (dec, no hex-output yet) with size ~254MB (which seems correct). I was curious where my kernel may be and printed out &kernel_main to see, where the main-function actually is and i got 1049632 which is somewhere in the chunk of usable memory i found. The thing is, i don't want to overwrite my kernel-code in memory, would be bad, wouldn't it? So my question, how can i get the exact memory-address and size of my kernel, does grub give me this information? I checked the multiboot-specification but i can't find anything useful there.
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: Grub: Where exactly is my kernel?

Post by Combuster »

It's the exact opposite way around: A multiboot-compliant kernel instructs GRUB exactly where to be loaded. This can be done using the ELF headers, or it can be the a.out kludge. Regardless of the way, the location of the kernel is already known at link time.

You know the start address because its hardcoded. You can get the end location by defining a label or symbol for it, and google says you should be ashamed for not looking at all the existing examples.
"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 ]
tkausl
Posts: 17
Joined: Tue Jul 14, 2015 9:54 pm

Re: Grub: Where exactly is my kernel?

Post by tkausl »

Combuster wrote:It's the exact opposite way around: A multiboot-compliant kernel instructs GRUB exactly where to be loaded. This can be done using the ELF headers, or it can be the a.out kludge. Regardless of the way, the location of the kernel is already known at link time.
Oh, i guess it's this part in my linker.ld

Code: Select all

SECTIONS
{
	. = 1M;
Combuster wrote:You can get the end location by defining a label or symbol for it, and google says you should be ashamed for not looking at all the existing examples.
Well, where? It's multiple files, multiple .o-files, which one is the 'last' one? What if the linker rearranges things?
Which examples? I've read through a lot of examples in the osdev-wiki but i apologize if i've missed something :(

Edit: I just found this Thread: http://f.osdev.org/viewtopic.php?f=1&t=174
Now i just need to find a way to use the label in c
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: Grub: Where exactly is my kernel?

Post by max »

When you write "kernelEnd = .;" in your linker script, it tells the linker that it should place that symbol at that location. You can't write a value to that location, but you can obtain it's address.

So in C, you just define it as an extern variable of any type and use its address. The linker will link that together then.

Code: Select all

extern void* endKernel;
addr_t endKernelAddress = &endKernel;
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: Grub: Where exactly is my kernel?

Post by Kevin »

max wrote:So in C, you just define it as an extern variable of any type and use its address.
I still think that the most correct type is one that tells that there isn't really an object there:

Code: Select all

extern const void endKernel;
The advantage is that you can't accidentally read the value of this one. If you do anything with it other than taking the address, the compiler will complain.
Developer of tyndur - community OS of Lowlevel (German)
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: Grub: Where exactly is my kernel?

Post by max »

Word! Thats the best approach.
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Grub: Where exactly is my kernel?

Post by alexfru »

Kevin wrote: I still think that the most correct type is one that tells that there isn't really an object there:

Code: Select all

extern const void endKernel;
While it looks like this isn't prohibited in C, some compilers (e.g. Open Watcom C/C++) will complain on such dubious declarations. Further, this is actually prohibited in C++.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: Grub: Where exactly is my kernel?

Post by Kevin »

Not sure what's dubious about it? void is an incomplete type like any other. A C compiler that complains about it is plain broken.
Developer of tyndur - community OS of Lowlevel (German)
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Grub: Where exactly is my kernel?

Post by alexfru »

Kevin wrote:Not sure what's dubious about it? void is an incomplete type like any other. A C compiler that complains about it is plain broken.
Not exactly. C99 says in 6.2.5 Types clause 1:
Types are partitioned into object types(types that fully describe objects), function types
(types that describe functions), and incomplete types (types that describe objects but lack
information needed to determine their sizes).
Later, clause 20:
Any number of derived types can be constructed from the object, function, and
incomplete types, as follows:
— An array type describes a contiguously allocated nonempty set of objects with a
particular member object type, called the element type. 36)
Footnote 36:
Since object types do not include incomplete types, an array of incomplete type cannot be constructed.
Makes sense, right?

Still later, footnote 109:
An incomplete type may only by used when the size of an object of that type is not needed. ...
Makes sense, right?

So, while you can't declare

Code: Select all

void foo;
and it makes no sense, there's nothing preventing you from declaring (you don't need the size, sizeof(void))

Code: Select all

extern void foo;
How come you can't ever have a variable of type void, but you can declare that there somewhere is, but just not here. For that reason "extern void foo;" is dubious. It doesn't have to allowed, but it is.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: Grub: Where exactly is my kernel?

Post by Kevin »

alexfru wrote:
Kevin wrote:Not sure what's dubious about it? void is an incomplete type like any other. A C compiler that complains about it is plain broken.
Not exactly.
I don't understand. The next thing you do is quoting from the standard that it is in fact just an incomplete type. It behaves the same as e.g. a struct that hasn't been defined yet.

I'll readily admit that there aren't many cases where extern void makes sense. However, symbols defined in a linker script can be such cases.

Feel free to suggest a different type for kernelEnd that makes more sense logically. So far extern void is the most accurate one that I could find.
Developer of tyndur - community OS of Lowlevel (German)
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Grub: Where exactly is my kernel?

Post by alexfru »

Kevin wrote:
alexfru wrote:
Kevin wrote:Not sure what's dubious about it? void is an incomplete type like any other. A C compiler that complains about it is plain broken.
Not exactly.
I don't understand. The next thing you do is quoting from the standard that it is in fact just an incomplete type. It behaves the same as e.g. a struct that hasn't been defined yet.

I'll readily admit that there aren't many cases where extern void makes sense. However, symbols defined in a linker script can be such cases.

Feel free to suggest a different type for kernelEnd that makes more sense logically. So far extern void is the most accurate one that I could find.
"extern char end;" is good. "extern char end[];" is fine as well. Actually, "extern char end[];" has a couple of small advantages over "extern char end;". You can't assign to the array by mistake. You need to index or dereference end with [] or *, which requires more typing. The array converts to a pointer everywhere ("sizeof end", where it wouldn't convert, won't compile), which is what you actually need from the symbol, again, less typing (no need for &).
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: Grub: Where exactly is my kernel?

Post by Kevin »

Both forms would imply that there is a byte at that address that I may read and write, which is not true. I might accept an array of 0 elements as an accurate description, but that isn't allowed by C.
Developer of tyndur - community OS of Lowlevel (German)
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Grub: Where exactly is my kernel?

Post by alexfru »

Kevin wrote:Both forms would imply that there is a byte at that address that I may read and write, which is not true. I might accept an array of 0 elements as an accurate description, but that isn't allowed by C.
All three declarations

Code: Select all

extern void end;
extern char end;
extern char end[];
lie to the compiler. :) So, either you live with one of these (so long as the compiler and the linker are OK with it) or you avoid them altogether.
Post Reply