Page 1 of 1

Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 10:57 am
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.

Re: Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 11:42 am
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.

Re: Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 11:52 am
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

Re: Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 1:00 pm
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;

Re: Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 2:32 pm
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.

Re: Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 4:15 pm
by max
Word! Thats the best approach.

Re: Grub: Where exactly is my kernel?

Posted: Wed Jul 15, 2015 11:34 pm
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++.

Re: Grub: Where exactly is my kernel?

Posted: Thu Jul 16, 2015 2:49 am
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.

Re: Grub: Where exactly is my kernel?

Posted: Thu Jul 16, 2015 4:18 am
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.

Re: Grub: Where exactly is my kernel?

Posted: Thu Jul 16, 2015 7:13 am
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.

Re: Grub: Where exactly is my kernel?

Posted: Thu Jul 16, 2015 11:05 pm
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 &).

Re: Grub: Where exactly is my kernel?

Posted: Fri Jul 17, 2015 3:01 am
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.

Re: Grub: Where exactly is my kernel?

Posted: Sat Jul 18, 2015 2:17 am
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.