Page 1 of 1

Calling C++ Constructors

Posted: Wed Jun 04, 2008 2:31 am
by AJ
Hi,

I am looking at the C PlusPlus page, having just updated to GCC 4.3.0, specifically the 'Constructors' part, stating that global object constructors are found in the elf section 'ctors*', which is what I have always used. I used a construction function something along the following lines:

Code: Select all

void Construct()
{
	/*	construct global/static objects	*/
	void (**constructor)() = &start_ctors;
	void (**lastctor)() = &end_ctors;
	kprintf("Calling %#08x to %#08x\n", constructor, lastctor);
	if((constructor)>=(lastctor)) return;
	
	do
	{
		kprintf("Constructor (at %#08x) calling EIP %#08x\n", constructor, *constructor);
		(*constructor)();		
	}while((*++constructor)<(*lastctor));	
}
OK - I know it's messy, but I've just been playing around with it a lot. As you can see, I have added some debug output and I like my hex numbers padded :)

When compiling with G++ 4.3.0, the whole lot seems to be misaligned by a byte - in other words, I have to add one byte to 'start_ctors' in order to get things running. The value of the additional byte is zero. I am aware that GCC sometimes sets the first integer in the constructor list as the number of constructors present, but think that if it does this the integer should be a full 4 bytes?

Is there any reason why it should be exhibiting this new behaviour (my previous compiler was g++ 4.2.2 i586 elf - all that has changed is the version), or has something gone wrong with my linking?

Cheers,
Adam

Posted: Wed Jun 04, 2008 2:45 am
by JamesM
Hi,

Mine works on GCC 4.3.0 - we didn't have to make any changes so I suppose it's to do with your linking.

This is ours - it looks slightly different to yours...

Code: Select all

/// Calls the constructors for all global objects.
/// Call this before using any global objects.
void initialiseConstructors()
{
  // Constructor list is defined in the linker script.
  // The .ctors section is just an array of function pointers.
  // iterate through, calling each in turn.
  uintptr_t *iterator = reinterpret_cast<uintptr_t*>(&start_ctors);
  while (iterator < reinterpret_cast<uintptr_t*>(&end_ctors))
  {
    void (*fp)(void) = reinterpret_cast<void (*)(void)>(*iterator);
    fp();
    iterator++;
  }
}
Hope this helps,

James

Posted: Wed Jun 04, 2008 2:52 am
by AJ
OK, thanks - I'll dig deeper and see what I've done wrong. Your code certainly looks a better style to mine, even after you remove my debug rubbish!

I have been making a few stupid mistakes in my code recently, but the only change I can think I have made is the GCC update. I either need to get more sleep or have a break from my code for a few days and come back to it with fresh eyes :?

Cheers,
Adam

Posted: Wed Jun 04, 2008 4:05 am
by AJ
Right - adjusting the location of the ctors and dtors lists in the link script solved the issue, but I'm still not happy - no idea why updating my toolchain should have caused the problem. This is especially the case because LD is part of binutils, of which I am still using the same version. There was obviously something slightly wrong that was just waiting to show itself with a slight compile-time change.

I hate it when I just have to cross my fingers and hope the problem doesn't arise again. Oh well :roll:

Cheers,
Adam

Posted: Wed Jun 04, 2008 7:23 pm
by kmcguire
AJ wrote:I hate it when I just have to cross my fingers and hope the problem doesn't arise again. Oh well :roll:
You could always check the length of the section to make sure it is a multiple, and if not it would signify there is a problem and you could try the work around by adding one.