File: seg_override.c

package info (click to toggle)
valgrind 1%3A3.6.0~svn11254%2Bnmu1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 36,460 kB
  • ctags: 39,734
  • sloc: ansic: 339,440; sh: 15,713; xml: 15,183; cpp: 6,982; asm: 6,630; perl: 5,105; makefile: 3,576; exp: 678; haskell: 250
file content (138 lines) | stat: -rw-r--r-- 3,666 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

#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;
}