Home | History | Annotate | Download | only in x86-linux
      1 
      2 #include <stdio.h>
      3 #include <errno.h>
      4 #include <string.h>
      5 
      6 /* Stuff from Wine. */
      7 
      8 typedef  unsigned short  WORD;  /* I guess */
      9 typedef  unsigned char   BYTE;
     10 
     11 typedef struct _LDT_ENTRY {
     12     WORD        LimitLow;
     13     WORD        BaseLow;
     14     union {
     15         struct {
     16             BYTE        BaseMid;
     17             BYTE        Flags1;
     18                /*Declare as bytes to avoid alignment problems */
     19             BYTE        Flags2;
     20             BYTE        BaseHi;
     21         } Bytes;
     22         struct {
     23             unsigned    BaseMid         : 8;
     24             unsigned    Type            : 5;
     25             unsigned    Dpl             : 2;
     26             unsigned    Pres            : 1;
     27             unsigned    LimitHi         : 4;
     28             unsigned    Sys             : 1;
     29             unsigned    Reserved_0      : 1;
     30             unsigned    Default_Big     : 1;
     31             unsigned    Granularity     : 1;
     32             unsigned    BaseHi          : 8;
     33         } Bits;
     34     } HighWord;
     35 } LDT_ENTRY;
     36 
     37 inline static void *wine_ldt_get_base( const LDT_ENTRY *ent )
     38 {
     39     return (void *)(ent->BaseLow |
     40                     (unsigned long)ent->HighWord.Bits.BaseMid << 16 |
     41                     (unsigned long)ent->HighWord.Bits.BaseHi << 24);
     42 }
     43 inline static unsigned int wine_ldt_get_limit( const LDT_ENTRY *ent )
     44 {
     45     unsigned int limit = ent->LimitLow | (ent->HighWord.Bits.LimitHi << 16);
     46     if (ent->HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;
     47     return limit;
     48 }
     49 
     50 
     51 /* our copy of the ldt */
     52 LDT_ENTRY ldt_copy[8192];
     53 
     54 /* System call to set LDT entry.  */
     55 //extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
     56 extern int __modify_ldt (int, void *, size_t);
     57 
     58 void print_ldt ( void )
     59 {
     60    int res;
     61    res = __modify_ldt( 0, ldt_copy, 8192*sizeof(LDT_ENTRY) );
     62    printf("got %d bytes\n", res );
     63    perror("error is");
     64 }
     65 
     66 /* Structure passed on `modify_ldt' call.  */
     67 #define MODIFY_LDT_CONTENTS_DATA        0
     68 #define MODIFY_LDT_CONTENTS_STACK       1
     69 #define MODIFY_LDT_CONTENTS_CODE        2
     70 
     71 struct modify_ldt_ldt_s
     72 {
     73   unsigned int entry_number;
     74   unsigned long int base_addr;
     75   unsigned int limit;
     76   unsigned int seg_32bit:1;
     77   unsigned int contents:2;
     78   unsigned int read_exec_only:1;
     79   unsigned int limit_in_pages:1;
     80   unsigned int seg_not_present:1;
     81   unsigned int useable:1;
     82   unsigned int empty:25;
     83 };
     84 
     85 /* System call to set LDT entry.  */
     86 //extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
     87 
     88 void set_ldt1 ( void* base )
     89 {
     90   int stat;
     91   struct modify_ldt_ldt_s ldt_entry;
     92 
     93   /* stop valgrind yelping about initialised holes in this struct. */
     94   memset(&ldt_entry, 0, sizeof(ldt_entry));
     95 
     96   ldt_entry.entry_number = 1;
     97   ldt_entry.base_addr = (unsigned)base; //0x12345678;
     98   ldt_entry.limit = 10;
     99   ldt_entry.seg_32bit = 1;
    100   ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
    101   ldt_entry.read_exec_only = 0;
    102   ldt_entry.limit_in_pages = 0;
    103   ldt_entry.seg_not_present = 0;
    104   stat = __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
    105   printf("stat = %d\n", stat);
    106 }
    107 
    108 
    109 void ldt_seg_write ( int ldt_entno, unsigned offset, unsigned val )
    110 {
    111   asm volatile("movl %2, %%eax\n\t"
    112                "movl %1, %%edx\n\t"
    113 	       "movl %0, %%fs\n\t"
    114                "movl %%eax, %%fs:(%%edx)\t"
    115 	       :
    116                : "r" (7 /* LDT(TI), least privilege */ + (ldt_entno << 3)),
    117                  "r" (offset), "r" (val)
    118                : "eax", "edx", "cc" );
    119 }
    120 
    121 int main ( void )
    122 {
    123   int i;
    124   int arr[9];
    125 
    126   for (i = 0; i < 9; i++) arr[i] = 11*i;
    127 
    128   set_ldt1( &arr[4] );
    129   print_ldt();
    130 
    131   ldt_seg_write(1 /* ldt entry # */, 4 /* offset */, 4444);
    132 
    133   for (i = 0; i < 9; i++) printf("%d ", arr[i]);
    134   printf("\n");
    135 
    136   return 0;
    137 }
    138 
    139