G++ 4 bug?

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.
User avatar
arabasso
Member
Member
Posts: 27
Joined: Thu Jul 10, 2008 9:41 am

G++ 4 bug?

Post by arabasso »

I'm writing a kernel in C++, and compiling with ELF Cross Compiler g++ 4.5. Seems a bug in g++ or ld, but they simply do not create the "dtors" section. To initialize and finalize the global objects, I'm using the following code:

Code: Select all

class Test
{
    public:
        Test()
        {
            mem = reinterpret_cast<unsigned short *>(0xB8000);

            * mem++ = 0x4041;
        }

        ~Test()
        {
            * mem++ = 0x4042;
        }
    private:
        unsigned short * mem;
};

Test test;

extern "C" unsigned long start_ctors, end_ctors, start_dtors, end_dtors;

extern "C" init(unsigned long magic, unsigned long addr)
{
    for(unsigned long * constructor(& start_ctors); constructor < & end_ctors; ++constructor)
        ((void (*) (void)) (*constructor)) ();

    // Kernel main

    for(unsigned long * destructor(& start_dtors); destructor < & end_dtors; ++destructor)
        ((void (*) (void)) (* destructor)) ();
}
Global constructors are initialized normally, but destructors... nothing happens (the above code should print "AB" on the screen, but strangely only "A" is printed). I seem to be a bug in g++ 4, because the g++ 3.4.6 creates the "dtors" section normally.

Follow my linker script and the output of the readelf:

Code: Select all

ENTRY(start)
SECTIONS
{
	.text 0x100000 :
	{
		code = .; _code = .; __code = .;
		*(.text*)
		*(.gnu.linkonce.t*)

		. = ALIGN(0x1000);
	}

	.rodata :
	{
		*(.rodata*)
		*(.rdata*)
		*(.gnu.linkonce.r*)

		. = ALIGN(0x1000);
	}

	.data :
	{
		data = .; _data = .; __data = .;
		*(.data*)
		*(.gnu.linkonce.d*)

		. = ALIGN(0x1000);
	}

	.ctors :
	{
		start_ctors = .; _start_ctors = .; __start_ctors = .;
		*(.ctor*)
		end_ctors = .; _end_ctors = .; __end_ctors = .;

		. = ALIGN(0x1000);
	}

	.dtors :
	{
		start_dtors = .; _start_dtors = .; __start_dtors = .;
		*(.dtor*)
		end_dtors = .; _end_dtors = .; __end_dtors = .;*/
	}

	.bss :
	{
		bss = .; _bss = .; __bss = .;

		*(.bss*)
		*(.gnu.linkonce.b*)

		. = ALIGN(0x1000);
	}

	end = .; _end = .; __end = .;
}

Code: Select all

There are 6 section headers, starting at offset 0x4024:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .text             PROGBITS        00100000 001000 001000 00  AX  0   0  4

  [ 2] .data             PROGBITS        00101000 002000 001000 00  WA  0   0  4

  [ 3] .ctors            PROGBITS        00102000 003000 001000 00  WA  0   0  4

  [ 4] .bss              NOBITS          00103000 004000 009000 00  WA  0   0 32

  [ 5] .shstrtab         STRTAB          00000000 004000 000023 00      0   0  1

Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
What happened with the dtors section, "evaporated"?
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: G++ 4 bug?

Post by Creature »

Might it have something to do with the fact that you've page-aligned all sections, except the .dtors section? (not being sarcastic, just throwing in suggestions). I don't use destructors in my C++ myself (only constructors, because I have no use for destructors whatsoever, if anything would need to be done upon shutdown, I will call shutdown functions instead of relying on possible inner dependencies).
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
arabasso
Member
Member
Posts: 27
Joined: Thu Jul 10, 2008 9:41 am

Re: G++ 4 bug?

Post by arabasso »

I must have deleted the page alignment in time to post the message but nevertheless the g++ 4 does not create the "dtors" section. The problem is not only that, local static objects are also problems with g++ 4 (I'm using the ABI implementation in the osdev wiki). The constructors are executed, but not their destructors. If I run the function __cxa_finalize(0), the processor sends triple fault and restarts (implementation __cxa_atexit does not work).

I did a test here with the mingw gcc 3.4.5, and it usually creates a global dtor section, and for the local static objects, only the atexit function it is necessary (no dso, guard, etc.). Here's the code works perfectly in the g++ 3.4.5:

Code: Select all

#define ATEXIT_MAX_DESTRUCTORS			128

struct AtExit
{
	void (* func)(void *);
	void * obj;
};

static int atExitIndex = 0;
static AtExit atExitDestructors[ATEXIT_MAX_DESTRUCTORS];

extern "C" unsigned long start_ctors, end_ctors, start_dtors, end_dtors;

extern "C" void init(unsigned long magic, unsigned long addr)
{
	for(unsigned long * constructor(& start_ctors); constructor < & end_ctors; ++constructor)
		((void (*) (void)) (*constructor)) ();

	// Executes the kernel


	for (int i = 0; i < atExitIndex; i++)
		atExitDestructors[i].func(atExitDestructors[i].obj);

	for(unsigned long * destructor(& start_dtors); destructor < & end_dtors; ++destructor)
		((void (*) (void)) (* destructor)) ();
}

extern "C" void atexit(void (* f)(void *), void * obj)
{
	if (atExitIndex < ATEXIT_MAX_DESTRUCTORS)
	{
		atExitDestructors[atExitIndex].func = f;
		atExitDestructors[atExitIndex].obj  = obj;

		atExitIndex++;
	}
}
Also, sewed one has nothing to do with each other. If I use the destructors or not, this is MY CHOICE, not the compiler. After making several tests I conclude: there are numerous problems in the GCC 4. Not only that, another strange thing is with respect to code optimization. If I turn on the optimization flags of the G++ 4 (-O,-O2,-Os, no flag), the kernel collapses, and the processor sends an ISR 1, 6, 13 (each time a different error!?).

Using gcc 3.4.5, I can sets -O3 that the kernel runs normally (I can sets any flag,-Os,-O2, and everything works correctly). Another extremely annoying thing is that GCC 4 increases the size of the binaries (I have a SDL game where if I use gcc 3.4 to compile, the game is only 180KB. If I use GCC 4, the game jumps to more of 460kb, even using strip symbols and -O2 optimization flag).

I know this will generate discussion, but to comment on possible errors. I believe it would help to improve this great opensource software...
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: G++ 4 bug?

Post by Creature »

arabasso wrote:Also, sewed one has nothing to do with each other. If I use the destructors or not, this is MY CHOICE, not the compiler.
You are absolutely right and you should be able to use what you want.
arabasso wrote:Using gcc 3.4.5, I can sets -O3 that the kernel runs normally (I can sets any flag,-Os,-O2, and everything works correctly). Another extremely annoying thing is that GCC 4 increases the size of the binaries (I have a SDL game where if I use gcc 3.4 to compile, the game is only 180KB. If I use GCC 4, the game jumps to more of 460kb, even using strip symbols and -O2 optimization flag).
The answer that many will give you here is: GCC 4's optimization is probably different from GCC 3, and thus optimization messing your kernel up will be because of your code being "broken" (since usually the definition for "proper C/C++ code" is "code that works under any circumstance, regardless of the optimization level". Annoying or not, I know how optimizations tend to mess everything up (still have quite some problems myself which I still need to fix) and I've had some C++ problems as well. Can't help you with the destructor problem however, as I've never really used them myself. If I weren't in a busy exam period right now, I'd give it a try myself.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
fronty
Member
Member
Posts: 188
Joined: Mon Jan 14, 2008 5:53 am
Location: Helsinki

Re: G++ 4 bug?

Post by fronty »

Code: Select all

crayon% uname -a
FreeBSD dev.localdomain 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:02:08 UTC 2009     [email protected]:/usr/obj/usr/src/sys/GENERIC  amd64
g++45 -v
Using built-in specs.
Target: x86_64-portbld-freebsd8.0
Configured with: ./../gcc-4.5-20090924/configure --disable-nls --with-system-zlib --with-libiconv-prefix=/usr/local --with-gmp=/usr/local --program-suffix=45 --libdir=/usr/local/lib/gcc45 --libexecdir=/usr/local/libexec/gcc45 --with-gxx-include-dir=/usr/local/lib/gcc45/include/c++/ --disable-libgcj --prefix=/usr/local --mandir=/usr/local/man --infodir=/usr/local/info/gcc45 --build=x86_64-portbld-freebsd8.0
Thread model: posix
gcc version 4.5.0 20090924 (experimental) (GCC)
crayon% cat main.cc
#include <iostream>

class foo {
public:
        foo(int val) : i(val) { }
        ~foo() {
            std::cout << "destroyed: i = " << i << std::endl;
        }

private:
        int i;
};

int
main(void)
{
        foo bar(10);
        return 0;
}
crayon% g++45 main.cc
crayon% ./a.out
destroyed: i = 10
objdump -h a.out | grep dtors
 19 .dtors        00000010  0000000000500dc0  0000000000500dc0  00000dc0  2**3
At least my g++ 4.5.0 creates .dtors section.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: G++ 4 bug?

Post by Solar »

arabasso wrote:After making several tests I conclude: there are numerous problems in the GCC 4.
When compiling your code.

I'm willing to bet 100 Euro that the problem is not in GCC 4.5 source.
Every good solution is obvious once you've found it.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: G++ 4 bug?

Post by gerryg400 »

I'm not so sure Solar, 4.5.0 is quite new and I've had some small problems with it that I don't understand. The native versions get a lot of user testing, cross-compiling bugs might take longer to appear. I find that increase in the size of the binaries a bit strange too.

Are you using the latest (or recommended binutils) ?

Why not try 4.3.5 ?
If a trainstation is where trains stop, what is a workstation ?
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: G++ 4 bug?

Post by pcmattman »

I've seen the same behaviour in my own kernel on GCC 4.4.1. You get a .ctors section but no .dtors. I don't use the .dtors section at all so I ignored it :)

Question - what are the flags you're passing the compiler?
User avatar
arabasso
Member
Member
Posts: 27
Joined: Thu Jul 10, 2008 9:41 am

Re: G++ 4 bug?

Post by arabasso »

Nothing special:

g++ -c init.cpp -o init.o
ld -Tlink.ld -o kernel.ko init.o

Tested on g++ 4.3, 4.4 and 4.5 - binutils 2.20

Code: Select all

There are 7 section headers, starting at offset 0x2034:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .text             PROGBITS        00100000 001000 001000 00  AX  0   0  4

  [ 2] .ctors            PROGBITS        00101000 002000 000004 00  WA  0   0  4

  [ 3] .bss              NOBITS          00101004 002004 000ffc 00  WA  0   0  4

  [ 4] .shstrtab         STRTAB          00000000 002004 00002d 00      0   0  1

  [ 5] .symtab           SYMTAB          00000000 00214c 000320 10      6  13  4

  [ 6] .strtab           STRTAB          00000000 00246c 000285 00      0   0  1

Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: G++ 4 bug?

Post by Solar »

That readelf output of yours... is that kernel.ko, or init.o?

If it's kernel.ko, check if there's a .dtors section in init.o...
Every good solution is obvious once you've found it.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: G++ 4 bug?

Post by Owen »

gerryg400 wrote:I'm not so sure Solar, 4.5.0 is quite new and I've had some small problems with it that I don't understand. The native versions get a lot of user testing, cross-compiling bugs might take longer to appear. I find that increase in the size of the binaries a bit strange too.

Are you using the latest (or recommended binutils) ?

Why not try 4.3.5 ?
I have had no issues with GCC 4.5 - even when testing some of the newest features like ASM goto. As for the binary size increase - I'm betting that GCC is just using some space-intensive optimizations (e.g. I don't know if GCC 3.4 knew how align loops, which will surely increase your code size as your binary gets padded with long nops). If you want to compare code size, compare -Os against -Os

As for your code not working at O3 - 99% chance thats a bug of your creation.

As for GCC not creating a destructors section - said section is not part of the IA64 C++ ABI and so compiler and compiler version dependent. G++ 3 and 4 use a different ABI.
User avatar
arabasso
Member
Member
Posts: 27
Joined: Thu Jul 10, 2008 9:41 am

Re: G++ 4 bug?

Post by arabasso »

I managed to solve what is happening with G++ 4, is not a problem, it's just a different way. Actually, the G++ 4 does not create the dtors section, nor puts data about destructors in some section. It Apparently only makes use of the routine "atexit" for everything, for both global objects and local static objects. That's what I noted here at least, correct me if I'm wrong.

About optimization flags, I can not say with certainty that there are no errors in my code, but I believe that is not the case. Depending on the optimization, the compiler attempts to improve the code and ends up ruining it.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: G++ 4 bug?

Post by JamesM »

arabasso wrote:Depending on the optimization, the compiler attempts to improve the code and ends up ruining it.
This usually occurs when your code breaks some of the assumptions the compiler makes about it. If the compiler reasons incorrectly, it will produce incorrect code.

The usual example of this is forgetting "volatile", but there are others.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: G++ 4 bug?

Post by gerryg400 »

Or not getting your inline asm constraints correct.
If a trainstation is where trains stop, what is a workstation ?
User avatar
arabasso
Member
Member
Posts: 27
Joined: Thu Jul 10, 2008 9:41 am

Re: G++ 4 bug?

Post by arabasso »

This really happens, when gcc tries to optimize inline assembly or files .S, "it more spoils" that optimizes the code.
Post Reply