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