AT&T syntax

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.
DruG5t0r3

AT&T syntax

Post by DruG5t0r3 »

I'm moving my code to AT&T...(arghhh) and there is a few things I might need help for...

first thing is I'm trying to do a far call to a ring 3 code segment from ring 0.

Something like call 0x08:offset in intel syntax.

What would it be in AT&T?
Guest

Re:AT&T syntax

Post by Guest »

I believe something along the lines of:

Code: Select all

lcall $0x08, $offset
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

Okay...I'm just about to run crazy here...

I'm trying to ljmp to some ring 3 code from ring 0 code.
with something like this

__asm__ ("ljmp $0x1b, $ring_3_code");

0x1b is actually 0x18 + 3 for the RPL, Is that right?

I get a General Protection Fault, it doesn't actually even jmp to that code.

If I change this value from 0x1b to 0x08 which is my ring 0 code segment. Well everything is fine.
Simon

Re:AT&T syntax

Post by Simon »

If 0x18 is your user mode code segment then yes,you need to add 3. It might be that you can't switch priviledge levels without using a TSS or 'iret'ing to the code,that's the only explanation I can think of as those are the only ways to load SS at the same time.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

I do have a TSS, but there is no SS and ESP for ring 3 code in it right? Only for privilege levels < 3.

I thought that the only time you'd need the TSS for is when you switched form level 3 code to anything lower.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

Help anyone? I'm really stuck on this one.

Thanks.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

Here is my source code, keep in mind i'm simply trying to switch to ring 3 code

Code: Select all

void gdt_set_gate(int num, unsigned long base, unsigned long limit, 
unsigned char access, unsigned char gran)
{
   memset(&gdt[num], 0, sizeof(struct gdtr));

   gdt[num].base_low = (base & 0xFFFF);
   gdt[num].base_middle = (base >> 16) & 0xFF;
   gdt[num].base_high = (base >> 24) & 0xFF;
 
   gdt[num].limit_low = (limit & 0xFFFF);
   gdt[num].gran = ((limit >> 16) & 0x0F);

   gdt[num].gran |= (gran & 0xF0);
       gdt[num].access = access;
}

// Main gdt.c function called from kernel.c
// Will install all the global descriptor tables and the Task-State Segment.
void gdt_install()
{
   unsigned short tss_val;

       gdt_set_gate(NULL_SEG, 0, 0, 0, 0);

       // Code Descriptor, 4gb limit, 0 base
       gdt_set_gate(CODE0_SEG, 0, 0xFFFFFFFF, 0x9A, 0xCF);

       // Same thing for data segment.
       gdt_set_gate(DATA0_SEG, 0, 0xFFFFFFFF, 0x92, 0xCF);
   
   // base ring 3 code segment
   gdt_set_gate(CODE3_SEG, 0, 0xFFFFFFFF, 0xFA, 0xCF);

   // base ring 3 data segment
   gdt_set_gate(DATA3_SEG, 0, 0xFFFFFFFF, 0xF2, 0xCF);

   // Main TSS Descriptor
   gdt_set_gate(TSS_SEG, (unsigned long)&kernel_tss, 0x67, 0xE9, 0x80);
Now this is my "test code"

Code: Select all

void ring3_code() {
   for(;;);
}

void switch_to() {

   __asm__ __volatile__ ("ljmp $0x1b,$ring3_code");
}
If I change 0x1b to 0x08 which is my code 0 ring segment , NOOo problem. But with the above, General Protection Fault. Hellpp
AR

Re:AT&T syntax

Post by AR »

Without a TSS the system will explode when it tries to load SS0 when an interrupt occurs in Ring 3. The obvious problem there is that your task is C code and therefore probably disassembles as:

Code: Select all

push %ebp
mov %esp, %ebp

1:
jmp 1b

pop %ebp
ret
The push at the start attempts to write to the stack which is still Ring0 (DPL < CPL) which will throw a GPF. If this is actually the case then you will need to load the Ring3 stack before switching or write the task in assembly.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

nah, it GP faults when executing the jmp, it doesnt actually jmp.

and the IF flag is cleared anyway
AR

Re:AT&T syntax

Post by AR »

The only other thing that comes to mind is that you aren't allowed to jump/call DPL/RPL > CPL, I don't think this is the case (I don't have the docs with me) but you may want to try using IRET to switch anyway.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

I have tried the IRET equivalent and it does the same error.

I have found something in the Intel Manual Though...and it reads
Execution cannot be transferred by a call or a jump to a less-privilged (nummerically higher privilege level) code segment, regardless of whether the target segment is a conforming or nonconforming code segment. Attempting such an execution will result in a general-protection exception.
Interesting...sounds like you can't jmp from more priviledged segment to a less one. I thought it was possible, at least logicaly possible, but, as always, the specs aren't always what you think they should be.

So in the end, what would be the only way to switch over? Through a call gate?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:AT&T syntax

Post by Brendan »

Hi,
DruG5t0r3 wrote:So in the end, what would be the only way to switch over? Through a call gate?
Pretend to do a return from an interrupt (IRET) or a return from a call gate (RETF).

Why didn't "IRET" work?


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

Exact same error

Code: Select all

void ring3_code() {
   for(;;);
}

void switch_to() {

   __asm__ __volatile__ ("pushfl; \
            pushl $0x1b; \
            pushl %0; \
            iret"::"r"((unsigned int)ring3_code));
}
But if I change the $0x1b value to 0x08, again it works.
As I said, with $0x1b, it doesn't actually even jump, it GP faults while executing the iret.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:AT&T syntax

Post by Brendan »

Hi,
DruG5t0r3 wrote: Exact same error

Code: Select all

   __asm__ __volatile__ ("pushfl; \
            pushl $0x1b; \
            pushl %0; \
            iret"::"r"((unsigned int)ring3_code));
A slightly different error, with the same exception!

For an interrupt, the CPU pops EIP, then CS, then EFLAGS, so for your code what does it pop for EFLAGS?


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
DruG5t0r3

Re:AT&T syntax

Post by DruG5t0r3 »

"pushfl"

Doesn't that push the EFLAGS?
Post Reply