#include <stdio.h>
#include <errno.h>
#include <string.h>
/* Stuff from Wine. */
typedef unsigned short WORD; /* I guess */
typedef unsigned char BYTE;
typedef struct _LDT_ENTRY {
WORD LimitLow;
WORD BaseLow;
union {
struct {
BYTE BaseMid;
BYTE Flags1;
/*Declare as bytes to avoid alignment problems */
BYTE Flags2;
BYTE BaseHi;
} Bytes;
struct {
unsigned BaseMid : 8;
unsigned Type : 5;
unsigned Dpl : 2;
unsigned Pres : 1;
unsigned LimitHi : 4;
unsigned Sys : 1;
unsigned Reserved_0 : 1;
unsigned Default_Big : 1;
unsigned Granularity : 1;
unsigned BaseHi : 8;
} Bits;
} HighWord;
} LDT_ENTRY;
inline static void *wine_ldt_get_base( const LDT_ENTRY *ent )
{
return (void *)(ent->BaseLow |
(unsigned long)ent->HighWord.Bits.BaseMid << 16 |
(unsigned long)ent->HighWord.Bits.BaseHi << 24);
}
inline static unsigned int wine_ldt_get_limit( const LDT_ENTRY *ent )
{
unsigned int limit = ent->LimitLow | (ent->HighWord.Bits.LimitHi << 16);
if (ent->HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;
return limit;
}
/* our copy of the ldt */
LDT_ENTRY ldt_copy[8192];
/* System call to set LDT entry. */
//extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
extern int __modify_ldt (int, void *, size_t);
void print_ldt ( void )
{
int res;
res = __modify_ldt( 0, ldt_copy, 8192*sizeof(LDT_ENTRY) );
printf("got %d bytes\n", res );
perror("error is");
}
/* Structure passed on `modify_ldt' call. */
#define MODIFY_LDT_CONTENTS_DATA 0
#define MODIFY_LDT_CONTENTS_STACK 1
#define MODIFY_LDT_CONTENTS_CODE 2
struct modify_ldt_ldt_s
{
unsigned int entry_number;
unsigned long int base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
unsigned int empty:25;
};
/* System call to set LDT entry. */
//extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
void set_ldt1 ( void* base )
{
int stat;
struct modify_ldt_ldt_s ldt_entry;
/* stop valgrind yelping about initialised holes in this struct. */
memset(&ldt_entry, 0, sizeof(ldt_entry));
ldt_entry.entry_number = 1;
ldt_entry.base_addr = (unsigned)base; //0x12345678;
ldt_entry.limit = 10;
ldt_entry.seg_32bit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
ldt_entry.read_exec_only = 0;
ldt_entry.limit_in_pages = 0;
ldt_entry.seg_not_present = 0;
stat = __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
printf("stat = %d\n", stat);
}
void ldt_seg_write ( int ldt_entno, unsigned offset, unsigned val )
{
asm volatile("movl %2, %%eax\n\t"
"movl %1, %%edx\n\t"
"movl %0, %%fs\n\t"
"movl %%eax, %%fs:(%%edx)\t"
:
: "r" (7 /* LDT(TI), least privilege */ + (ldt_entno << 3)),
"r" (offset), "r" (val)
: "eax", "edx", "cc" );
}
int main ( void )
{
int i;
int arr[9];
for (i = 0; i < 9; i++) arr[i] = 11*i;
set_ldt1( &arr[4] );
print_ldt();
ldt_seg_write(1 /* ldt entry # */, 4 /* offset */, 4444);
for (i = 0; i < 9; i++) printf("%d ", arr[i]);
printf("\n");
return 0;
}