Going from C Bare Bones to C++ Bare Bones

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
opengeek
Posts: 5
Joined: Mon Oct 25, 2010 3:02 pm

Going from C Bare Bones to C++ Bare Bones

Post by opengeek »

I have some questions about the process.

When you finish the C Bare Bones kernel (http://wiki.osdev.org/Bare_bones) you have 3 files:

linker.ld -> which is the script that tells linker how to link different object code sections

loader.s -> written in gas (in my case) which passes the control from bootloader to kernel main function initializin kernel stack and other things.

kernel.c -> kernel main function

Then I'm following the C++ Bare Bones Kernel Tutorial (http://wiki.osdev.org/C%2B%2B_Bare_Bones)

I need to override my linker.ld from de C with the C++ (without forgeting the ENRTY (loader) ) one that defines extra rules to link constructor and destructor sections of the ELF and GNU soft linking. Untill here everything is fine.

Then the wiki talks about constructors and destructors and that in C++ you must call a constructor before you use an object and the destructor when you don't need the object any more, and after that you give some sample code.
I have some questions about de C/C++ code, i write it inline:

extern start_ctors, end_ctors, start_dtors, end_dtors;
//my compiler says me that all variables declared in extern have no type

void loader(void)
{
//- call all the static constructors in the list.
//I do not understand where and why this list exists if we need an object I will construt it when we need it
for(unsigned long *constructor(&start_ctors); constructor < &end_ctors; ++constructor)
((void (*) (void)) (*constructor)) ();

//- call kernel proper
main();
//I supose here we have to pass the struct mb_header *header, unsigned magic parameters, but I need the *header //and magic but I don't no from where I get them, I need to use a multiboot.h file or something?

//- call all the static destructors in the list.
//I do not understand where and why this list exists if I don't need an object I will destroy it.
for(unsigned long *destructor(&start_dtors); destructor < &end_dtors; ++destructor)
((void (*) (void)) (*destructor)) ();
}

Thank you for solving my n00b doubts.
User avatar
KotuxGuy
Member
Member
Posts: 96
Joined: Wed Nov 25, 2009 1:28 pm
Location: Somewhere within 10ft of my favorite chubby penguin!

Re: Going from C Bare Bones to C++ Bare Bones

Post by KotuxGuy »

Try putting your code in code tags(look under "Post a reply"). That makes it easier for us to see your code.
Also, try adding a few crucial spaces between your source code lines. That would help, too.
Give a man Linux, you feed the nearest optician ( Been staring at the PC too long again? ).
Give a man OS X, you feed the nearest NVidia outlet ( I need more GPU power!! )
Give a man Windows, you feed the entire Tylenol company ( Self explanatory :D )
HitmanYesman
Member
Member
Posts: 47
Joined: Fri Apr 23, 2010 8:27 am

Re: Going from C Bare Bones to C++ Bare Bones

Post by HitmanYesman »

You can't extern variables without defining their type first. So for example you could do:

Code: Select all

extern unsigned int start_ctors, end_ctors, start_dtors, end_dtors;
Well, as for objects. I think you need to read up more on C++. But here's how it is simply. The linker combines all the constructors into one section and all the deconstructors in a different section. You have to call these sections. But you must also define their place in the linker script, since you are using a custom one.

And if you followed the Bare Bones tutorial right, it boots off of GrUB to a loader.s file passing the parameters with it by pushing them onto the stack. Then, the kmain function takes the parameters.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Going from C Bare Bones to C++ Bare Bones

Post by qw »

HitmanYesman wrote:The linker combines all the constructors into one section and all the deconstructors in a different section. You have to call these sections. But you must also define their place in the linker script, since you are using a custom one.
Actually, GCC puts pointers to the constructors in one section called ".ctors" and pointers to the destructors in one section called ".dtors".

So you could treat "start_ctors" and "start_dtors" as arrays of pointers to functions:

Code: Select all

extern void (*start_ctors[])(void);
But beware, some linker scripts put a null value or the number of pointers in start_ctors[0].

In a hosted environment, the constructors in the array are called by a function named "__main". I believe it is in crt0.o or perhaps in libgcc.a, I'm not sure.
User avatar
gravaera
Member
Member
Posts: 737
Joined: Tue Jun 02, 2009 4:35 pm
Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.

Re: Going from C Bare Bones to C++ Bare Bones

Post by gravaera »

Hi:
Hobbes wrote:But beware, some linker scripts put a null value or the number of pointers in start_ctors[0].
DJGPP does that: no modern enough version of GCC should. It's easy enough to write a compiler abstraction layer anyway.

--All the best,
gravaera.
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Going from C Bare Bones to C++ Bare Bones

Post by Solar »

In a hosted environment (i.e., userspace programming), global / static objects are constructed before main() is entered.

This - as well as other housekeeping things, like setting up a stack, putting argc and argv on that stack etc. - is done by the "C runtime environment" (crt0.o on Unix machines), a small piece of code that is added to all executables by the compiler automatically. (The real entry point into a userspace executable is signified by the symbol _start, not main(). That's the entry function of crt0.o.)

In a freestanding environment (i.e., kernel programming), you don't have a crt0.o, and anyways you are using a custom linker script (among other reasons, so you can define which function is called as entry, and to avoid complaints about crt0.o missing - because a cross-compiler doesn't have one by default).

Thus, it falls upon you to do those things usually done by the runtime. Sooner or later you will write your version of crt0.o, but that will be for userspace applications, since the kernel init phase is different.

It actually gets less confusing if you do it in Assembler, IMHO. Having the stack set up, global / static objects constructed and the parameters (magic number, Multiboot data structure pointer) on the stack already before you enter C++ source.
Last edited by Solar on Wed Oct 27, 2010 6:22 am, edited 1 time in total.
Every good solution is obvious once you've found it.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Going from C Bare Bones to C++ Bare Bones

Post by qw »

gravaera wrote:DJGPP does that: no modern enough version of GCC should. It's easy enough to write a compiler abstraction layer anyway.
So does MinGW.
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: Going from C Bare Bones to C++ Bare Bones

Post by Combuster »

And who is in control of the linker script? :wink:

Edit: 5000 posts! :D
"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
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Going from C Bare Bones to C++ Bare Bones

Post by qw »

Combuster wrote:And who is in control of the linker script? :wink:
The forces of darkness. Who else?
Combuster wrote:Edit: 5000 posts! :D
Wow! Congratulations!
Post Reply