C++ Kernel: Undefined reference to __cxa_atexit

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
Yargh
Member
Member
Posts: 56
Joined: Sat Jun 12, 2010 9:04 pm
Location: Somewhere else.

C++ Kernel: Undefined reference to __cxa_atexit

Post by Yargh »

I've recently been developing a C++ kernel, which requires me to use a global object. I have defined __cxa_atexit, __dso_handle, and __cxa_pure_virtual in a file called icxxabi.c (basically copied the wiki source for it):

Code: Select all


#ifdef _cplusplus
extern "C" {
#endif

#include "type.h"
#include "icxxabi.h"

void __cxa_pure_virtual() {
    // Do Nothing
}

atexitFuncEntry_t __atexitFuncs[ATEXIT_FUNC_MAX];
uarch_t __atexitFuncCount = 0;

void *__dso_handle = 0;

int __cxa_atexit(void (*f)(void *), void *objptr, void *dso){
    if(__atexitFuncCount >= ATEXIT_FUNC_MAX){
        return -1;
    }
    __atexitFuncs[__atexitFuncCount].destructorFunc = f;
    __atexitFuncs[__atexitFuncCount].objPtr = objptr;
    __atexitFuncs[__atexitFuncCount].dsoHandle = dso;
    __atexitFuncCount++;
    return 0;
}

void __cxa_finalize(void *f){
    signed i = __atexitFuncCount;
    if(!f){
        while(i--){
            if(__atexitFuncs[i].destructorFunc){
                (*__atexitFuncs[i].destructorFunc)(__atexitFuncs[i].objPtr);
            }
        }
        return;
    }

    for(; i >= 0; i--){
        if(__atexitFuncs[i].destructorFunc == f){
            (*__atexitFuncs[i].destructorFunc)(__atexitFuncs[i].objPtr);
            __atexitFuncs[i].destructorFunc = 0;
        }
    }
}


#ifdef _cplusplus
};
#endif
I've also made the required header:

Code: Select all

#ifndef ICXXABI_H_
#define ICXXABI_H_
#define ATEXIT_FUNC_MAX 128
#ifdef _cplusplus
extern "C" {
#endif

typedef unsigned uarch_t;

struct atexitFuncEntry_t {
    void (*destructorFunc) (void *);
    void *objPtr;
    void *dsoHandle;

};

extern void *__dso_handle;

int __cxa_atexit(void (*f)(void *), void *objptr, void *dso);
void __cxa_finalize(void *f);

void __cxa_pure_virtual();




#ifdef _cplusplus
};
#endif

#endif//ICXXABI_H_
I've included that in the preinit.cpp file which calls the main function of the kernel and does a __cxa_finalize(0) after it:

Code: Select all

#include "icxxabi.h"
#include "kernel.h"
#include "type.h"

extern unsigned long ctorStart, ctorEnd; // Start and end of constructors
extern unsigned long dtorStart, dtorEnd; // Start and end of destructors

extern "C" void kernelPreinit(mbootHeader_t mbootHeader, u32int mbootMagic){
	// Loop and call all the constructors
	for(unsigned long *ctor(&ctorStart); ctor < &ctorEnd; ctor++){
		((void (*) (void)) (*ctor))();
	}

	// Call the kernel main function
	kernelMain((u32int)mbootMagic, mbootHeader);

	// Loop and call all the destructors -- Not used after GCC 3.2, but shouldn't hurt anything
	for(unsigned long *dtor(&dtorStart); dtor < &dtorEnd; dtor++){
		((void (*) (void)) (*dtor))();
    }

    // Call __cxa_finalize to call all the destructors for after GCC 3.2
    __cxa_finalize(0);

}
Yet for some reason, I still get this error even though I have __cxa_atexit defined:

Code: Select all

kernel.o: In function `__static_initialization_and_destruction_0(int, int)':
kernel.cpp:(.text+0x233): undefined reference to `__cxa_atexit'
I have icxxabi.o being linked before kernel.o and preinit.o, so I do not see why I am still getting this error.

Also,

Code: Select all

$ i586-elf-gcc -v
Using built-in specs.
COLLECT_GCC=i586-elf-gcc
COLLECT_LTO_WRAPPER=/usr/local/cross/libexec/gcc/i586-elf/4.5.2/lto-wrapper.exe
Target: i586-elf
Configured with: ../gcc-4.5.2/configure --target=i586-elf --prefix=/usr/local/cr
oss --disable-nls --enable-languages=c,c++ --without-headers
Thread model: single
gcc version 4.5.2 (GCC) 
Wait... What?
Yargh
Member
Member
Posts: 56
Joined: Sat Jun 12, 2010 9:04 pm
Location: Somewhere else.

Re: C++ Kernel: Undefined reference to __cxa_atexit

Post by Yargh »

Thanks, by removing the #ifdef _cplusplus 's around the extern "C" in icxxabi.c and .h it fixed it (nm showed that __cxa_atexit and __cxa_finalize had horribly mangled names)
Wait... What?
Post Reply