Hi,
I have an issue with kernel space c++ objects that are global i.e. declared at the top of the file.
When I access a method inside the object, a call to another method causes a page fault.
The pagefault error code is 0 and CR2 is something that it shouldnt be which is definately not mapped, which is probably why the page fault happens.
The strange thing is that if the object is delacred inside a function (even as static) then it works great.
reating the object dynamically using new also works fine.
I followed the gudie here https://wiki.osdev.org/C%2B%2B#Introduction
The fact that its only global objects is some kind of hint but im not sure what exactly it could be
Can anyone point me in the right direction on what im missing?
Thanks
Page fault when accessing global c++ object method
-
- Posts: 22
- Joined: Sun Apr 28, 2019 7:39 am
Re: Page fault when accessing global c++ object method
An object declared in a function will be stored on the stack. Thus its memory will most likely be mapped.
An object declared globally will be stored somewhere else (BSS or DATA section). Check where that object is in your binary image (make sure it exists) and see where it is loaded.
An object declared globally will be stored somewhere else (BSS or DATA section). Check where that object is in your binary image (make sure it exists) and see where it is loaded.
Last edited by kzinti on Fri Jul 17, 2020 11:02 am, edited 1 time in total.
-
- Posts: 22
- Joined: Sun Apr 28, 2019 7:39 am
Re: Page fault when accessing global c++ object method
I've identity mapped the entire kernel space according to the multiboot structure so it shouldnt't be a probme.
I also checked with qemu using tbl command and the page is mapped to the same address in physical memory
The problem is that one method calls another, which then causes the page fault.
The first method that is caused sits very close to the method that causes the page fault - they are in the same page.
I also checked with qemu using tbl command and the page is mapped to the same address in physical memory
The problem is that one method calls another, which then causes the page fault.
The first method that is caused sits very close to the method that causes the page fault - they are in the same page.
Re: Page fault when accessing global c++ object method
Where/when/did you call the constructor for that global object? Perhaps you are crashing when trying to call a virtual function...
Using a C++ object that is not properly initialized is undefined behaviour.
Using a C++ object that is not properly initialized is undefined behaviour.
-
- Posts: 22
- Joined: Sun Apr 28, 2019 7:39 am
Re: Page fault when accessing global c++ object method
Ah how stupid of me the particular object that was causing the problem is declared as virtual.
Thanks for giving me a nudge in the right direction
The object is declared as a global so if I understand correctly the constructor should be called before my kernel main?
I can see that when its declared globally the constructor doesn't get called
I guess im missing something...
Thanks for giving me a nudge in the right direction
The object is declared as a global so if I understand correctly the constructor should be called before my kernel main?
I can see that when its declared globally the constructor doesn't get called
I guess im missing something...
Re: Page fault when accessing global c++ object method
Normally, ELF constructors are run by the ELF loader (if you are using ELF, that is). However, in case of a kernel, that doesn't happen. The bootloader usually dumps your binary into memory, and then maybe clears BSS, and then that's your lot, then it jumps to your start symbol. If you do require constructors to run, you have to call them yourself. I'm going to continue guessing you use ELF, as I have no idea how exactly this works for PE. You can run all constructors just by running this code:
Since I literally just came up with this code, you might want to check it for bugs. All these symbols should be declared by the linker. If you ever switch to a higher-half memory model, you can only run this code after the switching on paging. As for the constructors themselves, those are emitted by the compiler.
Code: Select all
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
static void dummy(void) {}
extern void _init(void) __attribute((weak, alias("dummy")));
void run_constructors(void) {
for (void (**it)(void) = __init_array_start; (uintptr_t)it < (uintptr_t)__init_array_end; it++)
(*it)();
_init();
}
Carpe diem!
-
- Posts: 22
- Joined: Sun Apr 28, 2019 7:39 am
Re: Page fault when accessing global c++ object method
Thanks its now working...that was pretty painless. BTW...can I add the below code to the wiki? Is it editable by anyone?
I had to use nullplans answer with some stuff on the wiki. It explains a bit in https://wiki.osdev.org/index.php?title= ... ldid=14651 how to do it
Add this to your linker
Then somewhere in your main you can call
I had to use nullplans answer with some stuff on the wiki. It explains a bit in https://wiki.osdev.org/index.php?title= ... ldid=14651 how to do it
Add this to your linker
Code: Select all
.rodata ALIGN(0x1000) :
{
start_ctors = .;
*(SORT(.ctors*)) /* Note the "SORT" */
end_ctors = .;
start_dtors = .;
*(SORT(.dtors*))
end_dtors = .;
*(.rodata*)
*(.gnu.linkonce.r*)
}
Code: Select all
extern void (*start_ctors)(void) __attribute__((weak));
extern void (*end_ctors)(void) __attribute__((weak));
// Constructor list is defined in the linker script.
// The .ctors section is just an array of function pointers.
// iterate through, calling each in turn.
uintptr_t *iterator = reinterpret_cast<uintptr_t*>(&start_ctors);
while (iterator < reinterpret_cast<uintptr_t*>(&end_ctors))
{
void (*fp)(void) = reinterpret_cast<void (*)(void)>(*iterator);
fp();
iterator++;
}