Function-static variable placed after kernel (GCC, C++)

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
User avatar
rJah
Posts: 20
Joined: Tue Jun 26, 2007 12:36 pm

Function-static variable placed after kernel (GCC, C++)

Post 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
This is not a productive area of discussion
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Function-static variable placed after kernel (GCC, C++)

Post by xenos »

It would probably be helpful to see your linker script, and where you place your sections in memory.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
rJah
Posts: 20
Joined: Tue Jun 26, 2007 12:36 pm

Re: Function-static variable placed after kernel (GCC, C++)

Post 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 = .;
}

This is not a productive area of discussion
User avatar
rJah
Posts: 20
Joined: Tue Jun 26, 2007 12:36 pm

Re: Function-static variable placed after kernel (GCC, C++)

Post 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?
This is not a productive area of discussion
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Function-static variable placed after kernel (GCC, C++)

Post by qw »

Try insert *(COMMON) inside your .bss section.
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: Function-static variable placed after kernel (GCC, C++)

Post 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.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
rJah
Posts: 20
Joined: Tue Jun 26, 2007 12:36 pm

Re: Function-static variable placed after kernel (GCC, C++)

Post 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
This is not a productive area of discussion
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Function-static variable placed after kernel (GCC, C++)

Post 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.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: Function-static variable placed after kernel (GCC, C++)

Post 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).
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
rJah
Posts: 20
Joined: Tue Jun 26, 2007 12:36 pm

Re: Function-static variable placed after kernel (GCC, C++)

Post 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
This is not a productive area of discussion
Post Reply