Providing C++ Runtime support for Kernel
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Providing C++ Runtime support for Kernel
looking at the mangled symbols will just give you the function pointers to the constructors, but isn't the .ctor and .dtor list giving more informations ? don't they tell which constructor should be invoked together with the memory address that will receive the object ?
Re:Providing C++ Runtime support for Kernel
Well, I'm not an asm guru
I thought, or though I could be mistaken, that It was just a case adding the code to call the static / global ctors and dtors, as the code is omitted when compilling for a free standing environment. The only time we would have to allocate memory for the objects would be for dynamic objects, which would then need new and delete support code added.
Could some one explain the information that is in the .ctor and .dtor sections here?
The section headers.
Assembler for .ctor and .dtor sections.
What is this code doing?
I create the list in my linker script.
So in my C support code, I just walk __CTOR_LIST__ calling the constructors as I go along. The first value in the list is the number of constructors.
I'm trying to get all this all sorted out, so I can write some tutorials on how to write a kernel in C++
I thought, or though I could be mistaken, that It was just a case adding the code to call the static / global ctors and dtors, as the code is omitted when compilling for a free standing environment. The only time we would have to allocate memory for the objects would be for dynamic objects, which would then need new and delete support code added.
Could some one explain the information that is in the .ctor and .dtor sections here?
The section headers.
Code: Select all
objdump -h example1.o
example1.o: file format coff-go32
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000003b0 00000000 00000000 00000104 2**4
CONTENTS, ALLOC, LOAD, RELOC, CODE
1 .data 00000000 000003b0 000003b0 00000000 2**4
ALLOC, LOAD, DATA
2 .bss 00000220 000003b0 000003b0 00000000 2**2
ALLOC
3 .ctors 00000004 000005d0 000005d0 000004b4 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
4 .dtors 00000004 000005d4 000005d4 000004b8 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
5 .comment 00000010 000005d8 000005d8 000004bc 2**2
CONTENTS, DEBUGGING
What is this code doing?
Code: Select all
objdump -D example1.o
<snip>
Disassembly of section .data:
Disassembly of section .ctors:
000005d0 <.ctors>:
5d0: 70 03 jo 5d5 <.dtors+0x1>
...
Disassembly of section .dtors:
000005d4 <.dtors>:
5d4: 8a 03 mov (%ebx),%al
...
Code: Select all
<snip>
.data : {
__CTOR_LIST__ = .; LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) *(.ctors) LONG(0) __CTOR_END__ = .; __DTOR_LIST__ = .; LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) *(.dtors) LONG(0) __DTOR_END__ = .;
data = .; _data = .; __data = .;
*(.data)
. = ALIGN(4096);
}
</snip>
Code: Select all
void __do_global_init()
{
extern void (*_CTOR_LIST__)() ;
void (**constructor)() = &_CTOR_LIST__ ;
int total = *(int *)constructor ;
constructor++ ;
unsigned int i ;
for(i=0; i<=total; i++, constructor++)
{
(*constructor)() ;
}
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Providing C++ Runtime support for Kernel
with 4 bytes each, it is unlikely that your .ctor section actually hold code
Re:Providing C++ Runtime support for Kernel
When I call __do_global_init() it does successfully call all the global / static objects constructors.
Could the 4 bytes be 2 pointers, one to the ctor, one to the dtor? this example only had one global object.
Could the 4 bytes be 2 pointers, one to the ctor, one to the dtor? this example only had one global object.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Providing C++ Runtime support for Kernel
yep. that's probably what they are ... what i miss here is how they know *what* object is to be set up ... i mean, if instead of 1 object i do have 3 of them, how much entries in .dtor will there have ? and what will they point to ? some custom function call like
for every instanciated object ?
Code: Select all
__build_classXYZ_object(&XYZ_instance_target);
Re:Providing C++ Runtime support for Kernel
sections with 3 global objects of type OStream.
This is a list of all the mangled symbol names in example1.o
class OStream contains the following methods
The global objects are called cout, cout2, and cout3.
If you look though the symbols, you can pick out most of the functions. I'm sure the .ctor section holds a pointer to each constructor, which has a standard prefix to show that it is a gloab / static constructor.
Any ideas?
Code: Select all
objdump -h example1.o
example1.o: file format coff-go32
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000420 00000000 00000000 00000104 2**4
CONTENTS, ALLOC, LOAD, RELOC, CODE
1 .data 00000000 00000420 00000420 00000000 2**4
ALLOC, LOAD, DATA
2 .bss 00000660 00000420 00000420 00000000 2**2
ALLOC
3 .ctors 00000004 00000a80 00000a80 00000524 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
4 .dtors 00000004 00000a84 00000a84 00000528 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
5 .comment 00000010 00000a88 00000a88 0000052c 2**2
CONTENTS, DEBUGGING
Code: Select all
__Z41__static_initialization_and_destruction_0ii
__ZSt4endl
__GLOBAL__I__ZNSt7OStreamC2Ev
__GLOBAL__D__ZNSt7OStreamC2Ev
__ZNSt7OStreamC2Ev
__ZNSt7OStream5clearEv
__ZNSt7OStreamC1Ev
__ZNSt7OStreamD2Ev
__ZNSt7OStreamD1Ev
__ZNSt7OStreamlsEPc
__ZNSt7OStreamlsEc
__ZNSt7OStream5flushEv
__ZSt4cout
__ZSt5cout2
__ZSt5cout3
__ZN1XC2Ev
__ZN1XC1Ev
__ZN1XD2Ev
__ZN1XD1Ev
__ZN1YC2Ev
__ZN1YC1Ev
__ZN1YD2Ev
__ZN1YD1Ev
Code: Select all
OStream() ;
~OStream() ;
OStream& operator << (char * string) ;
OStream& operator << (const char manipulator) ;
void flush() ;
void clear() ;
If you look though the symbols, you can pick out most of the functions. I'm sure the .ctor section holds a pointer to each constructor, which has a standard prefix to show that it is a gloab / static constructor.
Any ideas?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Providing C++ Runtime support for Kernel
what you could do is look at the value stored in the 2x4 bytes of .ctors and .dtors and see which symbol it matches (if any), then trying to disassemble from this address ...
Re:Providing C++ Runtime support for Kernel
ok, this is what I did.
compiled using gxx -c x.cpp -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
Then I used objdump -D x.o, to display assembler contents of all sections.
Now would I be wrong in thinking that the 5e in the .ctor section is a pointer to the first instruction in __GLOBAL__I_x ?(which I assume is the initialisation code), and in turn that the 78 in the .dtor section points to the first instruction in __GLOBAL__D_x?
So if I look at some object code produced by other compilers, I should be able to see if it would be possible to write a tool which parses object files, looking for their version of __GLOBAL__I and then add's the .ctor and .dtor sections. Thus providing a more portable solution to using C++ in the Kernel.... or am I wrong somewhere?
Code: Select all
class X
{
public:
X() {};
~X() {};
};
X x ;
int main(void){}
Then I used objdump -D x.o, to display assembler contents of all sections.
Code: Select all
00000000 <_main>:
(some asm code)
00000018 <__Z41__static_initialization_and_destruction_0ii>:
(some asm code)
0000005e <__GLOBAL__I_x>:
5e: 55 push %ebp
(some asm code)
00000078 <__GLOBAL__D_x>:
78: 55 push %ebp
(some asm code)
Disassembly of section .ctors:
000000c4 <.ctors>:
c4: 5e pop %esi
c5: 00 00 add %al,(%eax)
...
Disassembly of section .dtors:
000000c8 <.dtors>:
c8: 78 00 js ca <.dtors+0x2>
...
So if I look at some object code produced by other compilers, I should be able to see if it would be possible to write a tool which parses object files, looking for their version of __GLOBAL__I and then add's the .ctor and .dtor sections. Thus providing a more portable solution to using C++ in the Kernel.... or am I wrong somewhere?
Re:Providing C++ Runtime support for Kernel
Instead of playing with the disassembly and guessing what goes on, why not just look up the libc startup code provided with your compiler? You can then copy it and paste it into your own libc, and it will work.
Re:Providing C++ Runtime support for Kernel
Yup, I've already looked at that source, and done something very similar. I've already it got it working with my compiler, because my compiler uses the .ctor and .dtor sections.
I'm just seeing if there is a way of doing it no matter what compiler you use.
Hence my idea for a tool which could add the sections.
I'm just seeing if there is a way of doing it no matter what compiler you use.
Hence my idea for a tool which could add the sections.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Providing C++ Runtime support for Kernel
Here's what i found so far:
the .ctor section actually holds one pointer to __GLOBAL_I_x, and the .dtor section holds one pointer to __GLOBAL_D_x. both these function call __static_initialisation_and_destruction(int,int) which has a list of instruction that actually call the initializer for every object (calling the right constructors with the address of the object to be initialized)
what is surprising is that when you have several static objects in the same file, there is still only one .ctors entry ... i think this is because the compiler is smart enough and collect all the global initialisation he sees from example.cpp into the same __static_initialisation_and_destruction code. The reason why .ctors can contain several entries is likely to be that there could be other __static_init ... from other object files.
Thus, imho, calling the pointers located in .ctors section before calling main() and calling the pointers in .dtors after main() returns is safe.
to tim : reverse engineering is sometimes easier to do than browsing Stallmans & co sources
the .ctor section actually holds one pointer to __GLOBAL_I_x, and the .dtor section holds one pointer to __GLOBAL_D_x. both these function call __static_initialisation_and_destruction(int,int) which has a list of instruction that actually call the initializer for every object (calling the right constructors with the address of the object to be initialized)
what is surprising is that when you have several static objects in the same file, there is still only one .ctors entry ... i think this is because the compiler is smart enough and collect all the global initialisation he sees from example.cpp into the same __static_initialisation_and_destruction code. The reason why .ctors can contain several entries is likely to be that there could be other __static_init ... from other object files.
Thus, imho, calling the pointers located in .ctors section before calling main() and calling the pointers in .dtors after main() returns is safe.
to tim : reverse engineering is sometimes easier to do than browsing Stallmans & co sources
Re:Providing C++ Runtime support for Kernel
Agree completely!Pype.Clicker wrote:to tim : reverse engineering is sometimes easier to do than browsing Stallmans & co sources
Re:Providing C++ Runtime support for Kernel
ok everyone, I've been busy writing my C++ Kernel, and I've just finished my first draft of parts 1 and 2 of my tutorials, and I've finished the code for parts 3-7.
Could you check it out and give me some constructive criticism. This is my first attempt at writing a tutorial.
http://www.invalidsoftware.net/os/
thanxs in advance.
Could you check it out and give me some constructive criticism. This is my first attempt at writing a tutorial.
http://www.invalidsoftware.net/os/
thanxs in advance.
Re:Providing C++ Runtime support for Kernel
you mis-typed somthing for the page title...you typed in
Writting
still reading...
Writting
still reading...
Re:Providing C++ Runtime support for Kernel
Hi,
Excellent stuff, I cannot wait for the rest of the tutorial parts.
Two prblems though, Video.h dosen't exist, you declare your class in Kernel.h, but in video.cpp and kernel.cpp you have #include "video.h" other than that, excellent work.
Excellent stuff, I cannot wait for the rest of the tutorial parts.
Two prblems though, Video.h dosen't exist, you declare your class in Kernel.h, but in video.cpp and kernel.cpp you have #include "video.h" other than that, excellent work.