.ctors section empty?
Posted: Fri Aug 17, 2012 6:22 am
Hello,
I've been following this forums for a week, reading the wiki and other tutorials on how to start working on an OS. I've followed all tutorials so far (compiling a cross compiler, starting with a c++ bare bone, ...) and I've got simple print screen stuff working, both in qemu and VMware.
However I am unable to bring the compiler to create the .ctors table for global objects. It seems to me that the table is empty, although I have one global object. From the looks of it, both start_ctors and end_ctors point to the same address and the content of said address is always 0. From what I've heard about that table, it should simply be a nullterminated array of function pointers, shouldn't it?
kmain.cpp
linker.ld
globals.cpp
makefile:
loader.s:
I have tried the loader.s content from the tutorial, but it didn't work either (I assume that it executed the loop zero times, but I couldn't verify this, hence I wrote c++ code and added calls to screen::write).
build output:
I don't really know how to tackle this problem. Can you tell me what I can do in order to find what I did wrong?
I really hope I haven't overlooked something stupid, but I've spent half a day googling for this problem, without success so far.
I've been following this forums for a week, reading the wiki and other tutorials on how to start working on an OS. I've followed all tutorials so far (compiling a cross compiler, starting with a c++ bare bone, ...) and I've got simple print screen stuff working, both in qemu and VMware.
However I am unable to bring the compiler to create the .ctors table for global objects. It seems to me that the table is empty, although I have one global object. From the looks of it, both start_ctors and end_ctors point to the same address and the content of said address is always 0. From what I've heard about that table, it should simply be a nullterminated array of function pointers, shouldn't it?
kmain.cpp
Code: Select all
#include <stdint.h>
#include "boot/multiboot.hpp"
#include "devices/screen.hpp"
#include "kernel.h"
#include "runtime/globals.h"
extern "C" uint32_t magic;
extern "C" multiboot_info *mbd;
Kernel kernel;
extern "C" void kmain(void)
{
screen::clear();
if ( magic != 0x2BADB002 )
{
screen::write("There's been an error with the boot sequence: Magic number's dont match");
}
__ctors();
//asm volatile ("int $3");
__dtors();
}
Code: Select all
ENTRY (start)
SECTIONS
{
. = 0x00100000;
.text ALIGN (0x1000) :
{
*(.text)
*(.gnu.linkonce.t*)
}
.rodata ALIGN (0x1000) :
{
start_ctors = .;
*(SORT(.ctors.*)) /* Note the "SORT" */
end_ctors = .;
start_dtors = .;
*(SORT(.dtors.*))
end_dtors = .;
*(.rodata*)
*(.gnu.linkonce.r*)
}
.data ALIGN (0x1000) :
{
*(.data)
*(.gnu.linkonce.d*)
}
.bss :
{
sbss = .;
*(COMMON)
*(.bss)
*(.gnu.linkonce.b*)
ebss = .;
}
/DISCARD/ :
{
*(.comment)
*(.eh_frame) /* discard this, unless you are implementing runtime support for C++ exceptions. */
}
}
Code: Select all
extern "C"
{
extern uint32_t *start_ctors;
extern uint32_t *end_ctors;
void __ctors()
{
screen::writeLine("Constructing global objects...");
screen::write("lower: ");
screen::writeHex(start_ctors);
screen::writeLine();
screen::write("upper: ");
screen::writeHex(end_ctors);
auto it = reinterpret_cast<void(**)(void)>(&start_ctors);
while(*it != nullptr)
{
(*it)();
++it;
}
}
}
Code: Select all
OBJECTS=kernel/boot/loader.o \
kernel/kmain.o \
kernel/kernel.o \
kernel/runtime/pure_virt_call.o \
kernel/runtime/globals.o \
kernel/gdt/gdt_flush.o \
kernel/gdt/gdt.o \
kernel/idt/idt.o \
kernel/idt/interrupts.o \
kernel/idt/idt_flush.o \
kernel/devices/io.o \
kernel/devices/screen.o \
TOOLSET=/usr/local/cross/bin
INCLUDES=-I./stdlib -I./
CC=$(TOOLSET)/i586-elf-g++
CFLAGS=-c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles \
-nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector \
-ffreestanding \
-std=c++11 \
$(INCLUDES)
AS=$(TOOLSET)/i586-elf-as
ASFLAGS=
LD=$(TOOLSET)/i586-elf-ld
LDFLAGS=-Tlinker.ld -v
all: kernel.img
.cpp.o:
$(CC) $(CFLAGS) -o $@ $<
.s.o:
$(AS) $(ASFLAGS) -o $@ $<
kernel.img: kernel.bin
./patch_floppy_image.sh
./build_qemu_image.sh
kernel.bin: $(OBJECTS)
$(LD) $(LDFLAGS) -o kernel.bin $(OBJECTS)
clean:
-rm kernel.bin $(OBJECTS)
Code: Select all
.global start # making entry point visible to linker
# setting up the Multiboot header - see GRUB docs for details
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum required
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
# reserve initial kernel stack space
.set STACKSIZE, 0x4000 # that is, 16k.
.lcomm stack, STACKSIZE # reserve 16k stack on a doubleword boundary
.comm mbd, 4 # we will use this in kmain
.comm magic, 4 # we will use this in kmain
start:
mov $(stack + STACKSIZE), %esp # set up the stack
movl %eax, magic # Multiboot magic number
movl %ebx, mbd # Multiboot data structure
call kmain # call kernel proper
cli
hang:
hlt # halt machine should kernel return
jmp hang
build output:
Code: Select all
/usr/local/cross/bin/i586-elf-as -o kernel/boot/loader.o kernel/boot/loader.s
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/kmain.o kernel/kmain.cpp
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/kernel.o kernel/kernel.cpp
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/runtime/pure_virt_call.o kernel/runtime/pure_virt_call.cpp
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/runtime/globals.o kernel/runtime/globals.cpp
/usr/local/cross/bin/i586-elf-as -o kernel/gdt/gdt_flush.o kernel/gdt/gdt_flush.s
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/gdt/gdt.o kernel/gdt/gdt.cpp
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/idt/idt.o kernel/idt/idt.cpp
/usr/local/cross/bin/i586-elf-as -o kernel/idt/interrupts.o kernel/idt/interrupts.s
/usr/local/cross/bin/i586-elf-as -o kernel/idt/idt_flush.o kernel/idt/idt_flush.s
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/devices/io.o kernel/devices/io.cpp
/usr/local/cross/bin/i586-elf-g++ -c -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -ffreestanding -std=c++11 -I./stdlib -I./ -o kernel/devices/screen.o kernel/devices/screen.cpp
/usr/local/cross/bin/i586-elf-ld -Tlinker.ld -v -o kernel.bin kernel/boot/loader.o kernel/kmain.o kernel/kernel.o kernel/runtime/pure_virt_call.o kernel/runtime/globals.o kernel/gdt/gdt_flush.o kernel/gdt/gdt.o kernel/idt/idt.o kernel/idt/interrupts.o kernel/idt/idt_flush.o kernel/devices/io.o kernel/devices/screen.o
GNU ld (GNU Binutils) 2.22
I really hope I haven't overlooked something stupid, but I've spent half a day googling for this problem, without success so far.