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