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