Code: Select all
#define _CRTALLOC(x) __declspec(allocate(x))
#pragma section(".CRT$XIA",long,read)
#pragma section(".CRT$XIZ",long,read)
#pragma section(".CRT$XCA",long,read)
#pragma section(".CRT$XCZ",long,read)
#pragma section(".CRT$XPA",long,read)
#pragma section(".CRT$XPZ",long,read)
#pragma section(".CRT$XTA",long,read)
#pragma section(".CRT$XTZ",long,read)
typedef void (*_PVFV)(void);
typedef int (*_PIFV)(void);
extern "C" _CRTALLOC(".CRT$XIA") _PIFV __xi_a[] = { 0 }; // C initializers (first)
extern "C" _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[] = { 0 }; // C initializers (last)
extern "C" _CRTALLOC(".CRT$XCA") _PVFV __xc_a[] = { 0 }; // C++ initializers (first)
extern "C" _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[] = { 0 }; // C++ initializers (last)
extern "C" _CRTALLOC(".CRT$XPA") _PVFV __xp_a[] = { 0 }; // C pre-terminators (first)
extern "C" _CRTALLOC(".CRT$XPZ") _PVFV __xp_z[] = { 0 }; // C pre-terminators (last)
extern "C" _CRTALLOC(".CRT$XTA") _PVFV __xt_a[] = { 0 }; // C terminators (first)
extern "C" _CRTALLOC(".CRT$XTZ") _PVFV __xt_z[] = { 0 }; // C terminators (last)
#pragma comment(linker, "/merge:.CRT=.rdata")
extern "C" int crt_call_c(_PIFV * a, _PIFV * b)
{
while (a != b)
{
if (*a)
{
int r = (**a)();
if (r) return r;
}
++a;
}
return 0;
}
extern "C" void crt_call(_PVFV * a, _PVFV * b)
{
while (a != b)
{
if (*a)
{
(**a)();
}
++a;
}
}
static _PVFV ExitList[32];
static unsigned MaxExitListEntries;
static unsigned CurrentExitListIndex;
static void _crt_init_atexit_tables(void)
{
MaxExitListEntries = 32;
CurrentExitListIndex = 0;
}
static void _crt_clean_atexit_tables(void)
{
MaxExitListEntries = 0;
CurrentExitListIndex = 0;
}
extern "C" int
__cdecl atexit(_PVFV Func)
{
if (CurrentExitListIndex < MaxExitListEntries)
{
ExitList[CurrentExitListIndex++] = Func;
return 0;
}
return -1;
}
void _cdecl crt_init()
{
_crt_init_atexit_tables();
crt_call_c(__xi_a, __xi_z);
crt_call(__xc_a, __xc_z);
}
void _cdecl crt_done()
{
_crt_clean_atexit_tables();
crt_call(__xp_a, __xp_z);
crt_call(__xt_a, __xt_z);
}
int __cdecl _purecall_handler()
{
for (;;);
}
In my Multiboot.cpp file I declare init/done functions and call them like this:
Code: Select all
extern void _cdecl crt_init();
extern void _cdecl crt_done();
void Start(uint32 eax, uint32 ebx)
{
crt_init();
Kernel(eax, ebx);
crt_done();
}
NOPROLOGUE void MultibootEntry(void)
{
__asm {
align 4
multiboot_header:
dd(MULTIBOOT_HEADER_MAGIC);
dd(MULTIBOOT_HEADER_FLAGS);
dd(CHECKSUM);
dd(HEADER_ADDRESS);
dd(KERNEL_LOAD_ADDRESS);
dd(00);
dd(00);
dd(HEADER_ADDRESS + 0x20);
kernel_entry:
cli
mov esp, KERNEL_STACK;
mov ebp, esp
push 0;
popf;
push ebx;
push eax;
call Start;
halt:
jmp halt;
}
}
Code: Select all
SECTION HEADER #6
.CRT$XCA name
0 physical address
0 virtual address
4 size of raw data
E50 file pointer to raw data (00000E50 to 00000E53)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40300040 flags
Initialized Data
4 byte align
Read Only
SECTION HEADER #7
.CRT$XCZ name
0 physical address
0 virtual address
4 size of raw data
E54 file pointer to raw data (00000E54 to 00000E57)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40300040 flags
Initialized Data
4 byte align
Read Only
Just to show an example, this works fine:
Code: Select all
struct S
{
int a = 10;
};
static S s{}; //I expected that atleast C initializers need to be called but I guess not since it works even without calling crt_init
Code: Select all
struct S
{
S() : a() {}
int a = 10;
};
static S s{};