C++ kernel placement constructor

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
hubris
Member
Member
Posts: 28
Joined: Sun May 24, 2015 12:38 am
Location: Brisbane, Australia

C++ kernel placement constructor

Post by hubris »

Hi all, like others I have been lurking in the shadows, learning enough to at least have interesting problems. I have been reading the many articles and tutorials on this and the other 'standard' sites and now I am at the physical page management stage.
My problem is this:

Code: Select all

class Table
{
protected:
	ui32_v		m_size;
	ui32_v		m_count;
	ui32_v		m_total;
	page_v*		m_table;

	inline
	Table		(ui32_v address,ui32_v total,ui32_v size)
	:m_size		(size)
	,m_count	(0)
	,m_total	(total)
	,m_table	(0)
	{
		m_size = size;
		m_total = total;

		m_count = m_total / size;
		if	(m_count * size < total)
		{
			m_count++;
		}

		Vga	vga;
		vga.setPos(0,10);
//		vga << "t-ctor total=" << total << " size=" << size << " count=" << m_count;
		vga << "t-ctor total=" << m_total << " size=" << m_size << " count=" << m_count;

		m_table = new((void*)address) page_v[(std::size_t)m_count];
	}

public:

	inline
	ui32_v		count()
	{
		return m_count;
	}

	inline
	ui32_v		size()
	{
		return m_size;
	}
};

class SpanTable : public Table
{
public:

	inline
	SpanTable	(ui32_v address,ui32_v total,ui32_v size)
	:Table		(address,total,size)
	{
		Vga	vga;
		vga.setPos(0,11);
		vga << "st-ctor total=" << total << " size=" << size << " count=" << (total / size);
	}
};
I am using a new placement allocator to position the SpanTable instance that I create using

Code: Select all

spanTable01 = new((void*)0x60000000) SpanTable(0x70000000,0xF0000000,4096);
I get a message indicating that the Table ctor and then the SpanTable ctor are called. I can see that the values are passed correctly via the stack, and yet if I do this after construction

Code: Select all

spanTable01->size()
The result is always zero, and this is true for all of the other Table members. I have checked and I can see that the SpanTable instance is correctly located at the placement address, no exception or interrupt thrown, and yet the values are still zero.
I am not expecting someone to debug this for me, but I am looking for any scenarios where this is possible so I can trace the problem. At this point I am out of ideas because nothing goes boom, and yet every thing in the Table class is zero.
I have chosen to build in C++, a rod for my own back but I felt there was little point in simply copying other solutions, perhaps not the best choice but I am persistent.
The only though I had was that the void* operator new(size_t,void*) method which I wrote was not calling the ctor but then the appropriate messages are displayed on the screen.
So in summary, the SpanTable and Table ctors are called, the stack arguments and local variables are correct but all of the member variables are zero. Note if I set the values of the member variables in the ctor, e.g. m_count = 12, this will display in the ctor correctly but if I attempt to display this value once the ctor has returned the value is once again zero.
So I am thinking this has something to do with the layout of the inherited class (Table) in memory, I thought the SpanTable address would begin with the Table vtab and members (although there are no virtuals in this code).
So suggestions anyone?
Techel
Member
Member
Posts: 215
Joined: Fri Jan 30, 2015 4:57 pm
Location: Germany
Contact:

Re: C++ kernel placement constructor

Post by Techel »

Are you sure your placement new operator returns the value given to it and that you handle that returned pointer correctly? Seems you are accessing other memory than your object. If you're using an emulator, use a ram image with random content and check weather it still remains zero. Or test on real hw.
Hellbender
Member
Member
Posts: 63
Joined: Fri May 01, 2015 2:23 am
Libera.chat IRC: Hellbender

Re: C++ kernel placement constructor

Post by Hellbender »

What's the value of "this" in the constructor and in the "size()" method that returns the wrong value?
Hellbender OS at github.
hubris
Member
Member
Posts: 28
Joined: Sun May 24, 2015 12:38 am
Location: Brisbane, Australia

Re: C++ kernel placement constructor

Post by hubris »

Thank both for suggestions. You can ignore the arguments to the ctor, they are not currently used until I solve this problem, So to answer the first and second by saying I have used your seggestion placed a print in each ctor and method, in each case the 'this' value is the value I have used in the new placement operator. So no extra clues unfortunately. I have also since read up on class memory layout, no joy there either. Additionally I have tried some very ugly code *((ui32_v*) spanTable01) = 99887766, no vtab so I expected the first 4 bytes to be the the m_size member, which I then printed and it was still zero.
So still thinking about how this can occur without some form of explicit failure, onwards through the fog.
Hellbender
Member
Member
Posts: 63
Joined: Fri May 01, 2015 2:23 am
Libera.chat IRC: Hellbender

Re: C++ kernel placement constructor

Post by Hellbender »

If you are running Bochs, put break points in the constructor (just before m_size = .., and in size() member. I use the following macro for Bochs break points:

Code: Select all

extern unsigned long __force_order;
#define BREAK asm volatile("xchg %%bx, %%bx" : "=m"(__force_order));
When running Bochs in debug mode (e.g. bochsdbg.exe), it will stop at those points. You can then examine the assembler instructions, and memory layout ("info tab" if you are using virtual memory). If your "m_size =" assignment writes to the same address as your "return m_size", there must be some code in between that zeroes the memory, either by remapping pages, memsetting, or something else..

--
- Tuomas
Hellbender OS at github.
hubris
Member
Member
Posts: 28
Joined: Sun May 24, 2015 12:38 am
Location: Brisbane, Australia

Re: C++ kernel placement constructor

Post by hubris »

The fog clears, I have gradually lowered the placement address until 0x00600000 it all started working, fortune favours the bloody minded. I have been using QEMU for development, still working my way upto BOCHS. My hypothesis is that although my code is correct, and I have used QEMU out-of-the-box, I suspect that QEMU is supplying me with limited memory, at least below where I thought it was. Reading the various pages I have seen that you can read and write to non-existent memory, write have no effect, and reads can be what ever was left in the data bus. So I think QEMU is leaving zeroes in the data bus and that is what I have been reading back.
I will have to spend a little more time on QEMU to verify if this is correct, in the mean time, thank you all for your guidance.
Hellbender
Member
Member
Posts: 63
Joined: Fri May 01, 2015 2:23 am
Libera.chat IRC: Hellbender

Re: C++ kernel placement constructor

Post by Hellbender »

I've noticed that Bochs catches way more errors than QEmu. For example, QEmu doesn't trap when exceeding segment limits.. Debugging features in Bochs are invaluable, it'll quickly save you the time you invest in getting it running. It's really a must have if you are serious. Really. Don't wait, go for it now. I mean like right now. =)
Hellbender OS at github.
Post Reply