Page 1 of 1

Protected mode segment override problem

Posted: Tue Oct 13, 2009 5:43 pm
by tarrox
Hi guys,
I am implementing my syscall routines ready to use for programs. Because of the three different methods to call make syscalls (int, syscall, sysenter), i got an special page which abstracts the call for the functions (i dont call int/syscall/sysenter but call the page, just like linux does it). This works realy great when i call the address directly. But i want it to be position independent, so like linux i want to use a segment override with the gs register which points to a gdt entry with a base of the address of the syscall page.
But i tried what i could, looked everywhere but the call doesn't want work, in bochs and virtual box.
Different tries different problems:
1.
My first try was to test it from a nasm source:

Code: Select all

call [gs:0x0];
gs is set to 0x33 and the gdt entry is a normal user mode code segment with the difference of the base which is 0xFEC00000.
But the given code doesn't jump to the address 0xFEC00000 but 0x55525160.

If I instead use as the call:

Code: Select all

call 0x33:0x0 
It works perfectly when i name the segment directly. No problems o.O

2.
My next try was to make it somehow work in gcc inline assembler
for this purpose i have this code:

Code: Select all

asm volatile ("call *%gs:0x0;");
Which makes just the same error and jumps to 0x55525160.

So i thought that maybe my gs register is wrong and tested this here:

Code: Select all

asm volatile ("call *%cs:0xFEc00000;");
and this

Code: Select all

asm volatile ("call *%cs:0c0110000;");
C0110000 is a kernel page with the syscall page.

Both make the same error and jumps to 0x55525160.

3.
So i was thinking that maybe my call is wrong and searched for another possibility and found out about lcall
so my new test code was:

Code: Select all

asm volatile ("lcall *%gs:0x0;");
But here i get a rely wried GP. It says it got a fetch_raw_descriptor on the gdt where the index is bigger then the limit.
And if i change to the cs version it gives the exact same error o.O.

So now am i stuck... and sit here thinking: where the hell is the error? Am i using the call in a wrong way? Are the emulators wrong? Or does God just hate me?

I hope someone can help me.

MfG Tarrox

Re: Protected mode segment override problem

Posted: Wed Oct 14, 2009 3:24 am
by Combuster
tarrox wrote:My first try was to test it from a nasm source:

Code: Select all

call [gs:0x0];
gs is set to 0x33 and the gdt entry is a normal user mode code segment with the difference of the base which is 0xFEC00000.
But the given code doesn't jump to the address 0xFEC00000 but 0x55525160.
Did you notice that your "address" disassembles to push-push-push-push? Did you notice the memory operand in the opcode. jump to address specified in memory location gs:0. Go figure.

A far call/jump to a non-fixed location always requires that you set up an address in memory. So you should create a structure, put the segment and offset in there, and then use that as the memory operand of your far jump/call.

Also, reading the intel manuals could have answered the question, probably even faster.

Re: Protected mode segment override problem

Posted: Wed Oct 14, 2009 10:01 am
by Firestryke31
tarrox wrote: 1.
My first try was to test it from a nasm source:

Code: Select all

call [gs:0x0];
gs is set to 0x33 and the gdt entry is a normal user mode code segment with the difference of the base which is 0xFEC00000.
But the given code doesn't jump to the address 0xFEC00000 but 0x55525160.
This does not do what I think you think it does. It doesn't go to gs:0x0, it reads the address to call from gs:0x0.

Re: Protected mode segment override problem

Posted: Wed Oct 14, 2009 12:57 pm
by tarrox
Firestryke31 wrote:
tarrox wrote: 1.
My first try was to test it from a nasm source:

Code: Select all

call [gs:0x0];
gs is set to 0x33 and the gdt entry is a normal user mode code segment with the difference of the base which is 0xFEC00000.
But the given code doesn't jump to the address 0xFEC00000 but 0x55525160.
This does not do what I think you think it does. It doesn't go to gs:0x0, it reads the address to call from gs:0x0.
Yeah after reading Combuster Post i realized that my understanding of the segment override was very very wrong. Thats why i didn't find the answer for the problem. So thanks for the help it works great^^.