Page 1 of 2
determining the kernel size
Posted: Wed Jun 27, 2007 7:11 pm
by Bughunter
Hello,
I've been told at #osdev (at FreeNode) that it's possible to put a symbol at the end of the linker script and at the start, and then subtracting those to get the size of the kernel.
My questions are:
1. How can I do that?
2. How can I use that symbol from the linker script in C code?
Thanks in advance
Posted: Thu Jun 28, 2007 12:28 am
by Combuster
1:
You can define symbols anywhere in your linker script.
There is an example here
2:
You can import the symbol by using
and then use it wherever you want.
Posted: Thu Jun 28, 2007 3:24 am
by Bughunter
So by modifying the example, would this be a correct way to determine the kernel size?
Code: Select all
ENTRY (_loader)
SECTIONS{
kernel_start = .;
. = 0x00100000;
.text :{
*(.text)
}
.rodata ALIGN (0x1000) : {
*(.rodata)
}
.data ALIGN (0x1000) : {
*(.data)
}
.bss : {
_sbss = .;
*(COMMON)
*(.bss)
_ebss = .;
}
kernel_size = . - kernel_start;
}
Posted: Thu Jun 28, 2007 4:50 am
by Bughunter
Hmm why do I need to use a "&" in front of my variable name in my C code like below? If I'd let it out, it tries to dereference the symbol.
Code: Select all
extern unsigned long kernel_size;
kprintf("Kernel size: 0x%x\n", &kernel_size);
Oh and how could I get the size of the kernel exactly? I mean when I put the symbol "kernel_size" in the linker script after the BSS section, I get the size of the kernel in memory (which actually is what I wanted), not on disk. But when I put the "kernel_size" symbol before the BSS section, I don't get the correct file size either.
Posted: Thu Jun 28, 2007 7:52 am
by t0xic
Try doing the subtraction in your C code, not in your linker script.
--Michael
Posted: Thu Jun 28, 2007 2:31 pm
by Bughunter
Why would that make a difference?
Anyways, it _does_ make a difference. By subtracting it inside the linker script I measured a kernel size of 0x8000 bytes, and by doing it inside the code I measured a kernel size of 0x2000 bytes.
In code, it subtracts the addresses of the symbols, and in the linker script it subtracts the virtual address assigned to the symbol, is this what happens?
Posted: Thu Jun 28, 2007 6:34 pm
by t0xic
As far as my limited knowledge of linker scripts goes, I believe you are correct. The linker script is aligning the positions of the variables to your script.
Try something like this in C if you already haven't
Code: Select all
extern long start;
extern long end;
long size = end - start;
Other than that, try "end - (put base address here, i.e 0x00100000")"
Hope that helps,
--Michael
Posted: Fri Jun 29, 2007 5:24 am
by Bughunter
I now have this C code:
Code: Select all
/* <TODO> display the size of the kernel */
extern unsigned long kernel_end;
extern unsigned long kernel_start;
kprintf("Kernel start: 0x%x\n", &kernel_start);
kprintf("Kernel end: 0x%x\n", &kernel_end);
kprintf("Kernel size: 0x%x bytes\n", (&kernel_end - &kernel_start));
The linker script I now have is an attachment, please check it too.
This code gives the following output:
Kernel start: 0xc0100000
Kernel end: 0xc0108000
Kernel size: 0x2000
Maybe it's my knowledge of C, but I can't really understand why the result of the subtraction is 0x2000 instead of 0x8000.
EDIT: Good news:
When doing it like this:
uintptr_t end = (uintptr_t)&kernel_end;
uintptr_t start = (uintptr_t)&kernel_start;
uintptr_t size = end-start;
It works! But why? Why do I first need to assign new variables the value, and then subtract those?
Sizes
Posted: Fri Jun 29, 2007 6:19 am
by Mark139
The result is out by 4 - is that a clue?
It's C doing pointer maths. So the answer print is saying 0x2000 words (because the pointers a 4 byte words).
Posted: Fri Jun 29, 2007 7:11 am
by Bughunter
Indeed, I noticed that later
Posted: Fri Jun 29, 2007 5:46 pm
by AndrewAPrice
A more difficult way:
Place everything into one huge C++ class. Then call sizeof(kernel_class);
Posted: Fri Jun 29, 2007 6:09 pm
by Kevin McGuire
MessiahAndrw wrote:A more difficult way:
Place everything into one huge C++ class. Then call sizeof(kernel_class);
Should work, unless you have virtual functions in classes so that you forget about the
VTABLE data which would not be considered when doing the
sizeof in C/C++.
Posted: Sun Jul 01, 2007 10:42 am
by carbonBased
bughunter wrote:Hmm why do I need to use a "&" in front of my variable name in my C code like below? If I'd let it out, it tries to dereference the symbol.
Since your first question wasn't directly addressed (although has probably been discovered already) -- it's because the linker script merely defines symbols (and not variables with values, as is often thought). They have no size. By taking the value of a linker symbol, you're actually getting the bytes after the location of the symbol.
However, since it's a located symbol, taking the address of the symbol yields the value you're looking for.
--Jeff
Posted: Fri Jul 06, 2007 6:08 am
by Bughunter
My kernel now reports its size is 0x9000 bytes, while when I manually sum up the sizes of all sections (by doing 'objdump -h') I get a size of 0x7487.
Where do the other 0x1B79 bytes come from? Padding? Maybe I don't know ELF good enough. Can anyone shed some light on this?
Posted: Fri Jul 06, 2007 6:12 pm
by pcmattman
Look at the file size in your dev OS, not via objdump.