determining the kernel size

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.
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

determining the kernel size

Post 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 :)
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:

Post 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

Code: Select all

extern int symbol_name;
and then use it wherever you want.
"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
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post 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;
}
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post 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.
User avatar
t0xic
Member
Member
Posts: 216
Joined: Sat May 05, 2007 3:16 pm
Location: VA
Contact:

Post by t0xic »

Try doing the subtraction in your C code, not in your linker script.

--Michael
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post 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?
User avatar
t0xic
Member
Member
Posts: 216
Joined: Sat May 05, 2007 3:16 pm
Location: VA
Contact:

Post 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
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post 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?
Attachments
kernel.ld
Linker script
(501 Bytes) Downloaded 144 times
Mark139
Member
Member
Posts: 39
Joined: Mon Jan 15, 2007 2:32 pm

Sizes

Post 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).
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post by Bughunter »

Indeed, I noticed that later :)
User avatar
AndrewAPrice
Member
Member
Posts: 2309
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Post by AndrewAPrice »

A more difficult way:

Place everything into one huge C++ class. Then call sizeof(kernel_class);
My OS is Perception.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post 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++.
User avatar
carbonBased
Member
Member
Posts: 382
Joined: Sat Nov 20, 2004 12:00 am
Location: Wellesley, Ontario, Canada
Contact:

Post 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
User avatar
Bughunter
Member
Member
Posts: 94
Joined: Mon Dec 18, 2006 5:49 am
Location: Netherlands
Contact:

Post 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?
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Look at the file size in your dev OS, not via objdump.
Post Reply