Page 1 of 1
Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 6:21 am
by rJah
Hi, everybody!
If this is old news, or the there is something on the wiki (though I haven't seen it yet) I would very much appreciate the link.
I'm porting the latest iteration of my kernel to C++.
I followed
http://wiki.osdev.org/C%2B%2B and all was well. Then I made a Video class to handle video output and all was well. DTs, ISRs, IRQs done. After that I wrote my PMM which allocates a frame bitmap after the kernel (I use the linker script to insert a symbol at the end) and zero it out. i call pmmInit and again all is well. Then I decided it would be great if the Video class was a singleton, because that would be really cool
So I checked out some articles and came up with a Video singleton like this
Code: Select all
class Video
{
public:
//! Video memory start at 0xb8000.
const uint32_t videoMemStart;
//! The tab width in spaces.
const uint32_t tabWidth;
public:
//! @brief Returns the one and only instance of the object.
inline static Video& instance()
{
static Video video;
video.print("!!!!! 0x").putUnsigned((uint32_t)&video, true).newLine();
return video;
}
/* implementation */
protected:
//! Default constructor.
explicit Video();
//! Default destructor.
~Video();
private:
explicit Video(Video const&);
Video& operator=(Video const&);
};
Now the static video object is located after my kernel in RAM and when I zero out my frame bitmap I trash the whole thing and my output starts at (0, 0) again.
AFAIK static variables are placed in the bss section. Is this also true for static variables which are not arithmetic types or pointers?
Is there anything else I'm missing?
I'm stuck, so any info is welcome.
rJah
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 6:26 am
by xenos
It would probably be helpful to see your linker script, and where you place your sections in memory.
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 6:30 am
by rJah
This is my linker script, the kernel is loaded at 1 MB.
Code: Select all
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
start = phys;
.text phys : AT(phys) {
code = .;
*(.text)
. = ALIGN(4096);
*(.rodata*)
. = ALIGN(4096);
}
.data ALIGN(4096) :
{
start_ctors = .;
*(.ctor*)
end_ctors = .;
start_dtors = .;
*(.dtor*)
end_dtors = .;
*(.data)
. = ALIGN(4096);
}
.bss ALIGN(4096) :
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 6:54 am
by rJah
Ok, I've tries static integers and objects, and all variables are placed after the kernel if they are declared static inside a member function.
If they are declared static in a global function, they are where they're supposed to be.
Could it be that there is another section I don't specify in my linker script, but ld automatically adds it AFTER adding the end symbol?
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 8:16 am
by qw
Try insert *(COMMON) inside your .bss section.
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 8:39 am
by Creature
I think you may be a victim of the "Oh noes, GCC adds symbols to random sections that are fairly obscure"-problem. I also use Singletons in my C++ kernel and sometimes classes require special linker script sections. For example:
Code: Select all
.gnu.linkonce.d._vt.Q28CryptoPPt18StringSi...
The sections you might want to include are:
Code: Select all
*(.gnu.linkonce.t*)
*(.gnu.linkonce.r*)
*(.gnu.linkonce.d*)
*(.gnu.linkonce.b*)
Respectively for text, rodata, data and bss. Not sure if this is your problem, but it's probably a good idea to include them anyways, otherwise GCC might put them at random places and you will sooner or later (when your kernel becomes big) experience a GRUB (if that's what you're using) that won't be able to load your kernel anymore.
Let me know if that helps.
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 9:01 am
by rJah
Hobbes wrote:Try insert *(COMMON) inside your .bss section.
Tried it, didnt work. Thanks anyway.
Creature wrote:
The sections you might want to include are:
Code: Select all
*(.gnu.linkonce.t*)
*(.gnu.linkonce.r*)
*(.gnu.linkonce.d*)
*(.gnu.linkonce.b*)
Respectively for text, rodata, data and bss. Not sure if this is your problem, but it's probably a good idea to include them anyways, otherwise GCC might put them at random places and you will sooner or later (when your kernel becomes big) experience a GRUB (if that's what you're using) that won't be able to load your kernel anymore.
Let me know if that helps.
Sure does! Thank you!
I did see the sections when I did an objdump of the kernel binary, but I didn't figure I have to add them to the lnker script. Lucky I noticed the problem now, otherwise it would have been a big pain down the road I imagine.
Just to be sure: the .t* and .r* sections belong in .text, the .t.d in .data and the .t.b in .bss (in the linker script), right?
Thanks again
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 9:14 am
by xenos
Creature wrote:I think you may be a victim of the "Oh noes, GCC adds symbols to random sections that are fairly obscure"-problem. I also use Singletons in my C++ kernel and sometimes classes require special linker script sections.
I wonder why I have not encountered this problem yet*, since I'm also writing a C++ kernel. I once stumbled across these sections, but I didn't really know what to do with them. Probably I should have a closer look at my object files... Thanks for this hint!
* Perhaps it's because I don't use global objects at all. Instead, I just reserve space, and use "placement new" to call the constructors explicitly at the desired time.
rJah wrote:Just to be sure: the .t* and .r* sections belong in .text, the .t.d in .data and the .t.b in .bss (in the linker script), right?
Yes, exactly.
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 9:19 am
by Creature
rJah wrote:Just to be sure: the .t* and .r* sections belong in .text, the .t.d in .data and the .t.b in .bss (in the linker script), right?
Well I place linkonce.t in text, linkonce.r in rodata, linkonce.d in data and linkonce.b in bss,
like so. I've wondered a few times if there may be suffixes that require them to be placed somewhere else, but then again, I haven't found a lot of information yet about it. I've also included some information on the C++ Bare Bones page about the linkonce sections (it's been around for a while now and never really got into the wiki).
XenOS wrote:Creature wrote:I think you may be a victim of the "Oh noes, GCC adds symbols to random sections that are fairly obscure"-problem. I also use Singletons in my C++ kernel and sometimes classes require special linker script sections.
I wonder why I have not encountered this problem yet*, since I'm also writing a C++ kernel. I once stumbled across these sections, but I didn't really know what to do with them. Probably I should have a closer look at my object files... Thanks for this hint!
* Perhaps it's because I don't use global objects at all. Instead, I just reserve space, and use "placement new" to call the constructors explicitly at the desired time.
The problem tends to pop up at absolutely random times. I remember placing a harmless statement such as int i = 5; somewhere long ago which suddenly resulted in GRUB not being able to load my kernel anymore (the kernel's executable magically increased by 50 kB and when I removed the statement, it went down again and everything was fine).
Re: Function-static variable placed after kernel (GCC, C++)
Posted: Tue Apr 27, 2010 10:51 am
by rJah
I've also included some information on the C++ Bare Bones page about the linkonce sections
Good to have it all in one place, would have saved me some trouble
I also saw the eh_frame in your linker script, and wanted to ask you about it, but you already added it to the wiki