OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Apr 17, 2024 9:04 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Bug in C++ bare bones ctor/dtor examples?
PostPosted: Sun Jan 30, 2011 9:06 pm 
Offline
Member
Member

Joined: Tue Apr 13, 2010 8:00 pm
Posts: 285
http://gcc.gnu.org/onlinedocs/gccint/Initialization.html says that the list starts and ends with a non-function-pointer value. The examples don't skip them.

It seems unlikely to me that there would be a bug in a bare bones, since (I assume) they're the most view articles. Is the GCC documentation wrong?


Top
 Profile  
 
 Post subject: Re: Bug in C++ bare bones ctor/dtor examples?
PostPosted: Mon Jan 31, 2011 12:40 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
As far as I can tell, it's an implementation detail. I define crtbegin.asm/crtend.asm as just a bunch of labels, which is something that not all linkers of all time might have liked. It would explain why there would be a necessity for leading and trailing "garbage". I couldn't be bothered however to locate the source for the crtbegin/crtend linux uses to see what's actually being put there.

In any case, barebones doesn't need it, I don't need it, you may find no reason to need it either.

_________________
"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 ]


Top
 Profile  
 
 Post subject: Re: Bug in C++ bare bones ctor/dtor examples?
PostPosted: Mon Jan 31, 2011 3:04 am 
Offline
Member
Member
User avatar

Joined: Thu Aug 11, 2005 11:00 pm
Posts: 1110
Location: Tartu, Estonia
I guess one can easily test whether gcc produces this "garbage" by having a look at the contents of the ctor/dtor lists. No matter whether it is necessary for one kernel or not for another - if it is present, one must be careful not to call something that is not a constructor. According to the gcc docs,

gcc wrote:
Each list always begins with an ignored function pointer (which may hold 0, −1, or a count of the function pointers after it, depending on the environment). This is followed by a series of zero or more function pointers to constructors (or destructors), followed by a function pointer containing zero.


I don't use global C++ objects in my kernel, so it would take me some time to write some simple test code, but I remember that I once worked on an OS named Trion, which actually relied on the first entry of the ctor/dtor list being the number of ctors/dtors, as you can see from this code:

Code:
// Walk and call the constructors in the ctor_list
void ExecuteConstructors(void)
{
   // Get a copy of the contructor list
   void (**constructor)(void) = &ctorStart;

   // The constructor list first contains an integer
   // containing the number of ctors, and then the
   // actual list begins...
   int total = *(int *)constructor;
   constructor++ ;

   while(total--)
   {
      (*constructor)() ;
      constructor++ ;
   }
}

void ExecuteDestructors(void)
{
   void (**deconstructor)(void) = &dtorStart;

   int total = *(int *)deconstructor ;
   deconstructor++ ;

   while(total--)
   {
      (*deconstructor)() ;
      deconstructor++ ;
   }
}


So it seems that there is indeed a bug in the barebones tutorial. However, I wonder why nobody has noticed it yet... Calling some invalid address right at the beginning of any kernel code should almost inevitably lead to a triple fault.

_________________
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS


Last edited by xenos on Mon Jan 31, 2011 4:25 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Bug in C++ bare bones ctor/dtor examples?
PostPosted: Mon Jan 31, 2011 3:27 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
The "garbage" comes from a combination of crtbegin.o/crtend.o and your system's linker script, and is therefore only present if you add it there.

Barebones is not wrong.

Edit: The stock crosscompiler does not have this behaviour either.

_________________
"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 ]


Top
 Profile  
 
 Post subject: Re: Bug in C++ bare bones ctor/dtor examples?
PostPosted: Mon Jan 31, 2011 5:23 am 
Offline
Member
Member
User avatar

Joined: Thu Aug 11, 2005 11:00 pm
Posts: 1110
Location: Tartu, Estonia
It took me quite a while how this "garbage" gets into the Trion kernel, which does not refer to crtbegin.o/crtend.o at all. I just had a look at the Trion kernel binary and I found the following contents (translated to asm code):
Code:
ctorStart:
   dd 0x02
   dd 0x103bf0
   dd 0x105fa0
   dd 0x00
ctorEnd:
dtorStart:
   dd 0x01
   dd 0x105fc0
   dd 0x00
dtorEnd:

So indeed the ctor/dtor list are preceded by their lengths, and followed by a zery dword. But in this case it is not surprising because these values are generated in the linker script!
Code:
SECTIONS {
  .text 0x00100000 :{
    textStart = .;
    *(.text)
    *(.text.*)
      *(.stub)
    *(.rodata*)
    *(.gnu.linkonce.t.*)
      *(.gnu.linkonce.r.*)
      *(.gcc_except_table)
      *(.eh_frame)
  }
  textEnd = .;

  .data :{
    ctorStart = .;
      LONG((ctorEnd - ctorStart) / 4 - 2)
      *(.ctors)
      LONG(0) ctorEnd = .;

    dtorStart = .;
      LONG((dtorEnd - dtorStart) / 4 - 2)
      *(.dtors)
      LONG(0) dtorEnd = .;

    *(.data*)
    *(.gnu.linkonce.d.*)
  }
  dataEnd = .;

  .bss :{
    *(.common)
    *(.bss*)
    *(.gnu.linkonce.b.*)
  }
  bssEnd = .;
}


I also had a look at crtbegin.o and crtend.o and both of them contain a single dword in the .ctors and .dtors sections - so I suppose that this is where the "garbage" comes from when these files are linked into the output binary. Another look at crtstuff.c and libgcc2.c from the gcc sources revealed that they actually rely on the presence of the "garbage" when they traverse the ctor/dtor lists.

However, as Combuster correctly explained, the "garbage" is not included by default by a plain cross compiler and (in general) not needed in an OS kernel, so the barebones example is correct.

_________________
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS


Top
 Profile  
 
 Post subject: Re: Bug in C++ bare bones ctor/dtor examples?
PostPosted: Mon Jan 31, 2011 3:52 pm 
Offline
Member
Member

Joined: Tue Apr 13, 2010 8:00 pm
Posts: 285
Okay. That clears it up.

I wasn't concerned by the fact it wasn't there, I was just concerned that if it was there, it would screw stuff up, obviously. I didn't know this "feature" isn't enabled by default for cross compilers. But, since it's not there, there's no reason to care.

Thanks.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 16 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group