odd C++ issue using G++

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
kllrnohj
Posts: 5
Joined: Thu Oct 02, 2008 4:14 pm

odd C++ issue using G++

Post by kllrnohj »

I followed the C++ bare bones tutorial, but I am having some weird problems. I can't call functions, and the placement of functions in the source can break things. Not sure how to describe it, so I'll post what I have.

linker.ld (same as the bare bones)

Code: Select all

ENTRY (loader)

SECTIONS{
    . = 0x00100000;

    .text :{
        *(.text)
    }

    .rodata ALIGN (0x1000) : {
        *(.rodata)
    }

	.data ALIGN (0x1000) : {
	   start_ctors = .;
	   *(.ctor*)
	   end_ctors = .;
	   start_dtors = .;
	   *(.dtor*)
	   end_dtors = .;
	   *(.data)
	}

    .bss : {
        sbss = .;
        *(COMMON)
        *(.bss)
        ebss = .;
    }
}
loader.asm (same as bare bones using NASM)

Code: Select all

global loader           ; making entry point visible to linker
extern _main            ; kmain is defined elsewhere

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM

; reserve initial kernel stack space
STACKSIZE equ 0x4000                  ; that's 16k.

extern start_ctors, end_ctors, start_dtors, end_dtors

_loader:
   mov esp, stack+STACKSIZE        ; set up the stack
   push eax                        ; Multiboot magic number
   push ebx                        ; Multiboot info structure

static_ctors_loop:
   mov ebx, start_ctors
   jmp .test
.body:
   call [ebx]
   add ebx,4
.test:
   cmp ebx, end_ctors
   jb .body

   call _main                      ; call kernel proper

static_dtors_loop:
   mov ebx, start_dtors
   jmp .test
.body:
   call [ebx]
   add ebx,4
.test:
   cmp ebx, end_dtors
   jb .body

   hlt                             ; halt machine should kernel return

section .bss
align 32
stack:
   resb STACKSIZE                     ; reserve 16k stack on a quadword boundary
kernel.cpp

Code: Select all

/*
 * kernel.cpp
 *
 *  Created on: Oct 2, 2008
 *      Author: kllrnohj
 */

#include "include/multiboot.h"

extern "C" void _main (multiboot_info_t* mbd, unsigned int magic);
void cls();

/*
uncomment to also break the code
void BREAK_EVERYTHING() {}
*/

void _main (multiboot_info_t* mbd, unsigned int magic)
{
//	cls();  <- BREAKS!
	*((int*)0xb8000)=0x07690748;
	for(;;);
}

void cls()
{

}
Now, the first thing I tried was reading through the C++ section of the wiki, and even though none of the sections sounded like it would cause the problem I am having, I still have the following anyway

cppruntime.cpp

Code: Select all

/*
 * cppruntime.cpp
 *
 *  Created on: Oct 2, 2008
 *      Author: kllrnohj
 */

namespace __cxxabiv1
{
	/* guard variables */

	/* The ABI requires a 64-bit type.  */
	__extension__ typedef int __guard __attribute__((mode (__DI__)));

	extern "C" int __cxa_guard_acquire (__guard *);
	extern "C" void __cxa_guard_release (__guard *);
	extern "C" void __cxa_guard_abort (__guard *);

	extern "C" int __cxa_guard_acquire (__guard *g)
	{
		return !*(char *)(g);
	}

	extern "C" void __cxa_guard_release (__guard *g)
	{
		*(char *)g = 1;
	}

	extern "C" void __cxa_guard_abort (__guard *)
	{
	}
}

extern "C" void __cxa_pure_virtual()
{
    // print error message
}

extern "C"
        {
        int __cxa_atexit(void (*f)(void *), void *p, void *d);
        void __cxa_finalize(void *d);
        };

void *__dso_handle; /*only the address of this symbol is taken by gcc*/

struct object
{
        void (*f)(void*);
        void *p;
        void *d;
} object[32] = {0};
unsigned int iObject = 0;

int __cxa_atexit(void (*f)(void *), void *p, void *d)
{
        if (iObject >= 32) return -1;
        object[iObject].f = f;
        object[iObject].p = p;
        object[iObject].d = d;
        ++iObject;
        return 0;
}

/* This currently destroys all objects */
void __cxa_finalize(void *d)
{
        unsigned int i = iObject;
        for (; i > 0; --i)
        {
                --iObject;
                object[iObject].f(object[iObject].p);
        }
}
I am using a makefile (partially auto-generated by eclipse) to compile

NASM is invoked as
nasm -f elf -o"$@" "$<"

G++ is invoked as
g++ -O0 -Wall -c -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-rtti -fno-builtin -fno-exceptions -fomit-frame-pointer -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"

LD is invoked as
ld -T ../src/linker.ld -o"kernel.bin" $(OBJS) $(USER_OBJS) $(LIBS)

Platform is Ubuntu 8.04.
G++ version is 4.2.3
LD version is 2.18.0.20080103
NASM version is 0.99.06-20071101

I have used this same platform to successfully make a kernel in C, so the toolchain has previously worked fine. I am using Sun xVM VirtualBox and GRUB .97 with the VBE patch (I'm not setting a VBE mode yet, but I have tested that and it does work)

Now, when I say that it breaks, basically the "Hi" that should be printed never is. Either one of the commented out sections will cause the break.

And the build output is as follows
Building file: ../src/kernel.cpp
Invoking: GCC C++ Compiler
g++ -O0 -Wall -c -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-rtti -fno-builtin -fno-exceptions -fomit-frame-pointer -MMD -MP -MF"src/kernel.d" -MT"src/kernel.d" -o"src/kernel.o" "../src/kernel.cpp"
../src/kernel.cpp:13: warning: unused parameter ‘mbd’
../src/kernel.cpp:13: warning: unused parameter ‘magic’
Finished building: ../src/kernel.cpp

Building file: ../src/loader.asm
Invoking: GCC Assembler
nasm -f elf -o"src/loader.o" "../src/loader.asm"
Finished building: ../src/loader.asm

Building file: ../src/cppruntime/cppruntime.cpp
Invoking: GCC C++ Compiler
g++ -O0 -Wall -c -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-rtti -fno-builtin -fno-exceptions -fomit-frame-pointer -MMD -MP -MF"src/cppruntime/cppruntime.d" -MT"src/cppruntime/cppruntime.d" -o"src/cppruntime/cppruntime.o" "../src/cppruntime/cppruntime.cpp"
../src/cppruntime/cppruntime.cpp:52: warning: missing braces around initializer for ‘object’
../src/cppruntime/cppruntime.cpp:52: warning: missing initializer for member ‘object::p’
../src/cppruntime/cppruntime.cpp:52: warning: missing initializer for member ‘object::d’
../src/cppruntime/cppruntime.cpp:66: warning: unused parameter ‘d’
Finished building: ../src/cppruntime/cppruntime.cpp

Building target: kernel.bin
Invoking: GCC C++ Linker
ld -T ../src/linker.ld -o"kernel.bin" ./src/kernel.o ./src/loader.o ./src/cppruntime/cppruntime.o
ld: warning: cannot find entry symbol loader; defaulting to 0000000000100000
Finished building target: kernel.bin

make --no-print-directory post-build
cp kernel.bin ../iso/boot/ && mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o grub.iso ../iso
I: -input-charset not specified, using utf-8 (detected in locale settings)
Size of boot image is 4 sectors -> No emulation
Total translation table size: 2048
Total rockridge attributes bytes: 922
Total directory bytes: 4576
Path table size(bytes): 34
Max brk space used 0
233 extents written (0 MB)
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: odd C++ issue using G++

Post by pcmattman »

Code: Select all

ENTRY(loader)
and then...

Code: Select all

_loader:
That explains the ld error. It still doesn't explain the main problem though :?

You could try changing

Code: Select all

void _main (multiboot_info_t* mbd, unsigned int magic)
{
to

Code: Select all

extern "C" void _main (multiboot_info_t* mbd, unsigned int magic)
{
But I highly doubt that would change anything as the prototype has the extern "C" anyway.
kllrnohj
Posts: 5
Joined: Thu Oct 02, 2008 4:14 pm

Re: odd C++ issue using G++

Post by kllrnohj »

pcmattman wrote:

Code: Select all

ENTRY(loader)
and then...

Code: Select all

_loader:
That explains the ld error. It still doesn't explain the main problem though :?
Actually that seems to have fixed the issue - awesome. I hate to admit that I didn't even notice the LD warning, which is rather embarrassing, but I'm just glad it seems to be working now. Thanks again. (although on that note the Wiki probably should be updated then - as I said, that came from the bare bones C++ wiki entry)
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: odd C++ issue using G++

Post by pcmattman »

Fixed up the page ;)
Post Reply