Grub: Where exactly is my kernel?
Grub: Where exactly is my kernel?
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.
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.
- Combuster
- 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?
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.
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?
Oh, i guess it's this part in my linker.ldCombuster 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.
Code: Select all
SECTIONS
{
. = 1M;
Well, where? It's multiple files, multiple .o-files, which one is the 'last' one? What if the linker rearranges things?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.
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
- max
- 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?
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.
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?
I still think that the most correct type is one that tells that there isn't really an object there:max wrote:So in C, you just define it as an extern variable of any type and use its address.
Code: Select all
extern const void endKernel;
Re: Grub: Where exactly is my kernel?
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 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;
Re: Grub: Where exactly is my kernel?
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?
Not exactly. C99 says in 6.2.5 Types clause 1: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.
Later, clause 20: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).
Footnote 36: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)
Makes sense, right?Since object types do not include incomplete types, an array of incomplete type cannot be constructed.
Still later, footnote 109:
Makes sense, right?An incomplete type may only by used when the size of an object of that type is not needed. ...
So, while you can't declare
Code: Select all
void foo;
Code: Select all
extern void foo;
Re: Grub: Where exactly is my kernel?
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.alexfru wrote:Not exactly.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.
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?
"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 wrote: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.alexfru wrote:Not exactly.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.
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?
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?
All three declarationsKevin 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.
Code: Select all
extern void end;
extern char end;
extern char end[];