Page 1 of 1

Segments

Posted: Sun Jun 17, 2012 6:09 am
by RajivKumarSrivastav
<Split from a necro thread>
JAAman


i have similar problem. can any one pls help to find the answer.
i want code segment base = 0x6000 and limit as 0x6F00 with Granularity G bit as 0.

Code: Select all

// GDT(kgdt) setup written in .c source file
0x0    // NULL selector
0x00C09B0060006F00 // CODE selector
0x00CF93000000FFFF  // DATA
0x00C0970000000000  // stack

// To install GDT 
void GDTInstall() {
     desc gdtp;
     gdtp.limit = (sizeof (gdt_entry) * MAX_GDT_ENTRIES) - 1;
     gdtp.base = (uint32)kgdt;
    InstallGdt((uint32)&gdtp);
}

// asm.s file
InstallGdt:
        mov 4(%esp), %eax
        lgdt (%eax)
        mov $DATA_SEL, %ax  // load 0x10
        mov %ax, %ds
        mov %ax, %es
        mov %ax, %fs
        mov %ax, %gs
        mov $STACK_SEL, %ax  // load 0x18
        mov %ax, %ss

// below 3 lines are byte code like : ljmp $CODE_SEL, $0x0
        .byte  0xEA
        .long  done
        .word  CODE_SEL
done:
        ret
test:
       // some code 
I could see through DUMP file that address of label 'done' is 0x5fa2 which is less than limit of CODE segment GDT limit.
i built this source into BINARY file using GCC compiler. Here CS Register is loaded with CS segment selector and jump happens to label 'done'.
But the probelm is , then instead of returning to GDTInstall function , ecexution continue at label 'test' .
But then Is there any problem with GCC compiler? When FAR JUMP is converted to "ljump 0x08:0x5fa2", then why does not address is calculated as 0x6000(base)+0x5fa2(offset) ? Why base address is ignored ?
Thanks,

Re: Segments

Posted: Mon Jun 18, 2012 1:51 am
by Gigasoft
If CS.base was 0 before, obviously the location you return to will not be the same as the one that called InstallGdt. Furthermore, GCC always assumes that CS, DS, ES and SS refer to the same memory, so you can't have it work with CS at 0x6000 and DS at 0.

Re: Segments

Posted: Mon Jun 18, 2012 12:55 pm
by Combuster
Gigasoft wrote:Furthermore, GCC always assumes that CS, DS, ES and SS refer to the same memory, so you can't have it work with CS at 0x6000 and DS at 0.
Actually, you can. GCC doesn't generate data references using CS, nor stores immediates in the .code section, so the code can be completely separated from the rest of the binary - you can, for instance enforce W^X with segmentation that way. GCC does mix references to SS and DS, and occasionally ES so those selectors do indeed need to point to the same memory.

Re: Segments

Posted: Fri Jun 22, 2012 6:06 am
by RajivKumarSrivastav
Thanks for the reply. I found the solution.
Actually i had built the BINARY with .text segment to start with 0x6000. When i built with 0x0, then it works.
The reason is for FAR JUMP, SS:OFFSET should result in a valid IP which we want to execute. So,
1- if i already build BIN with .text segment at 0x6000, then GDT base should be 0x0.
2- If i already build BIN with .text segment at 0x0, then GDT base can be 0x6000.