Mercurial > mplayer.hg
comparison loader/ldt_keeper.c @ 7386:174e2a58b4cd
avifile sync - 95% cosmetics 5% bug
author | arpi |
---|---|
date | Fri, 13 Sep 2002 19:43:17 +0000 |
parents | 02576893af2a |
children | 9d3e1476ecd0 |
comparison
equal
deleted
inserted
replaced
7385:e2fcdd7608b1 | 7386:174e2a58b4cd |
---|---|
2 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 2 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
3 * This file MUST be in main library because LDT must | 3 * This file MUST be in main library because LDT must |
4 * be modified before program creates first thread | 4 * be modified before program creates first thread |
5 * - avifile includes this file from C++ code | 5 * - avifile includes this file from C++ code |
6 * and initializes it at the start of player! | 6 * and initializes it at the start of player! |
7 * it might sound like a hack and it really is - but | |
8 * as aviplay is deconding video with more than just one | |
9 * thread currently it's necessary to do it this way | |
10 * this might change in the future | |
7 */ | 11 */ |
8 | 12 |
13 /* applied some modification to make make our xine friend more happy */ | |
9 #include "ldt_keeper.h" | 14 #include "ldt_keeper.h" |
10 | 15 |
11 #include <string.h> | 16 #include <string.h> |
12 #include <stdlib.h> | 17 #include <stdlib.h> |
13 #include <errno.h> | 18 #include <errno.h> |
17 #include <stdio.h> | 22 #include <stdio.h> |
18 #include <unistd.h> | 23 #include <unistd.h> |
19 #ifdef __linux__ | 24 #ifdef __linux__ |
20 #include <asm/unistd.h> | 25 #include <asm/unistd.h> |
21 #include <asm/ldt.h> | 26 #include <asm/ldt.h> |
27 /* prototype it here, so we won't depend on kernel headers */ | |
28 #ifdef __cplusplus | |
29 extern "C" { | |
30 #endif | |
31 int modify_ldt(int func, void *ptr, unsigned long bytecount); | |
32 #ifdef __cplusplus | |
33 } | |
34 #endif | |
22 #else | 35 #else |
23 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) | 36 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) |
24 #include <machine/segments.h> | 37 #include <machine/segments.h> |
25 #include <machine/sysarch.h> | 38 #include <machine/sysarch.h> |
26 #endif | 39 #endif |
31 | 44 |
32 /* solaris x86: add missing prototype for sysi86() */ | 45 /* solaris x86: add missing prototype for sysi86() */ |
33 #ifdef __cplusplus | 46 #ifdef __cplusplus |
34 extern "C" { | 47 extern "C" { |
35 #endif | 48 #endif |
36 extern int sysi86(int, void*); | 49 int sysi86(int, void*); |
37 #ifdef __cplusplus | 50 #ifdef __cplusplus |
38 } | 51 } |
39 #endif | 52 #endif |
40 | 53 |
41 #ifndef NUMSYSLDTS /* SunOS 2.5.1 does not define NUMSYSLDTS */ | 54 #ifndef NUMSYSLDTS /* SunOS 2.5.1 does not define NUMSYSLDTS */ |
67 | 80 |
68 | 81 |
69 /* user level (privilege level: 3) ldt (1<<2) segment selector */ | 82 /* user level (privilege level: 3) ldt (1<<2) segment selector */ |
70 #define LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3) | 83 #define LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3) |
71 | 84 |
85 /* i got this value from wine sources, it's the first free LDT entry */ | |
72 #ifndef TEB_SEL_IDX | 86 #ifndef TEB_SEL_IDX |
73 #define TEB_SEL_IDX 1 | 87 #define TEB_SEL_IDX 17 |
74 #endif | 88 #endif |
89 | |
75 #define TEB_SEL LDT_SEL(TEB_SEL_IDX) | 90 #define TEB_SEL LDT_SEL(TEB_SEL_IDX) |
76 | 91 |
77 /** | |
78 * | |
79 * This should be performed before we create first thread. See remarks | |
80 * for write_ldt(), linux/kernel/ldt.c. | |
81 * | |
82 */ | |
83 | |
84 void* fs_seg = NULL; | |
85 static char* prev_struct = NULL; | |
86 /** | 92 /** |
87 * here is a small logical problem with Restore for multithreaded programs - | 93 * here is a small logical problem with Restore for multithreaded programs - |
88 * in C++ we use static class for this... | 94 * in C++ we use static class for this... |
89 */ | 95 */ |
90 | 96 |
96 __asm__ __volatile__( | 102 __asm__ __volatile__( |
97 "movl %0,%%eax; movw %%ax, %%fs" : : "i" (TEB_SEL) | 103 "movl %0,%%eax; movw %%ax, %%fs" : : "i" (TEB_SEL) |
98 ); | 104 ); |
99 } | 105 } |
100 | 106 |
107 /* we don't need this - use modify_ldt instead */ | |
108 #if 0 | |
101 #ifdef __linux__ | 109 #ifdef __linux__ |
102 /* XXX: why is this routine from libc redefined here? */ | 110 /* XXX: why is this routine from libc redefined here? */ |
103 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */ | 111 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */ |
104 static int LDT_Modify( int func, struct modify_ldt_ldt_s *ptr, | 112 static int LDT_Modify( int func, struct modify_ldt_ldt_s *ptr, |
105 unsigned long count ) | 113 unsigned long count ) |
128 if (res >= 0) return res; | 136 if (res >= 0) return res; |
129 errno = -res; | 137 errno = -res; |
130 return -1; | 138 return -1; |
131 } | 139 } |
132 #endif | 140 #endif |
141 #endif | |
133 | 142 |
134 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) | 143 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) |
135 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content ) | 144 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content ) |
136 { | 145 { |
137 *buffer++ = ((content->base_addr & 0x0000ffff) << 16) | | 146 *buffer++ = ((content->base_addr & 0x0000ffff) << 16) | |
145 ((content->limit_in_pages != 0) << 23) | | 154 ((content->limit_in_pages != 0) << 23) | |
146 0xf000; | 155 0xf000; |
147 } | 156 } |
148 #endif | 157 #endif |
149 | 158 |
150 void Setup_LDT_Keeper(void) | 159 //void* fs_seg=0; |
160 | |
161 ldt_fs_t* Setup_LDT_Keeper(void) | |
151 { | 162 { |
152 struct modify_ldt_ldt_s array; | 163 struct modify_ldt_ldt_s array; |
153 int fd; | |
154 int ret; | 164 int ret; |
155 | 165 ldt_fs_t* ldt_fs = (ldt_fs_t*) malloc(sizeof(ldt_fs_t)); |
156 if (fs_seg) | 166 |
157 return; | 167 if (!ldt_fs) |
158 | 168 return NULL; |
159 prev_struct = 0; | 169 |
160 fd = open("/dev/zero", O_RDWR); | 170 ldt_fs->fd = open("/dev/zero", O_RDWR); |
161 if(fd<0){ | 171 if(ldt_fs->fd<0){ |
162 perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " ); | 172 perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: "); |
163 return; | 173 return NULL; |
164 } | 174 } |
165 fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, | 175 // fs_seg= |
166 fd, 0); | 176 ldt_fs->fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, |
167 if(fs_seg==(void*)-1) | 177 ldt_fs->fd, 0); |
178 if (ldt_fs->fs_seg == (void*)-1) | |
168 { | 179 { |
169 perror("ERROR: Couldn't allocate memory for fs segment"); | 180 perror("ERROR: Couldn't allocate memory for fs segment"); |
170 return; | 181 close(ldt_fs->fd); |
171 } | 182 free(ldt_fs); |
172 // printf("fs seg %p\n", fs_seg); | 183 return NULL; |
173 *(void**)((char*)fs_seg+0x18) = fs_seg; | 184 } |
174 array.base_addr=(int)fs_seg; | 185 *(void**)((char*)ldt_fs->fs_seg+0x18) = ldt_fs->fs_seg; |
186 array.base_addr=(int)ldt_fs->fs_seg; | |
175 array.entry_number=TEB_SEL_IDX; | 187 array.entry_number=TEB_SEL_IDX; |
176 array.limit=array.base_addr+getpagesize()-1; | 188 array.limit=array.base_addr+getpagesize()-1; |
177 array.seg_32bit=1; | 189 array.seg_32bit=1; |
178 array.read_exec_only=0; | 190 array.read_exec_only=0; |
179 array.seg_not_present=0; | 191 array.seg_not_present=0; |
180 array.contents=MODIFY_LDT_CONTENTS_DATA; | 192 array.contents=MODIFY_LDT_CONTENTS_DATA; |
181 array.limit_in_pages=0; | 193 array.limit_in_pages=0; |
182 #ifdef __linux__ | 194 #ifdef __linux__ |
183 ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s)); | 195 //ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s)); |
196 ret=modify_ldt(0x1, &array, sizeof(struct modify_ldt_ldt_s)); | |
184 if(ret<0) | 197 if(ret<0) |
185 { | 198 { |
186 perror("install_fs"); | 199 perror("install_fs"); |
187 printf("Couldn't install fs segment, expect segfault\n"); | 200 printf("Couldn't install fs segment, expect segfault\n"); |
188 } | 201 } |
198 { | 211 { |
199 perror("install_fs"); | 212 perror("install_fs"); |
200 printf("Couldn't install fs segment, expect segfault\n"); | 213 printf("Couldn't install fs segment, expect segfault\n"); |
201 printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n"); | 214 printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n"); |
202 } | 215 } |
203 printf("Set_LDT\n"); | |
204 } | 216 } |
205 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ | 217 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ |
206 | 218 |
207 #if defined(__svr4__) | 219 #if defined(__svr4__) |
208 { | 220 { |
221 } | 233 } |
222 #endif | 234 #endif |
223 | 235 |
224 Setup_FS_Segment(); | 236 Setup_FS_Segment(); |
225 | 237 |
226 prev_struct = (char*)malloc(sizeof(char) * 8); | 238 ldt_fs->prev_struct = (char*)malloc(sizeof(char) * 8); |
227 *(void**)array.base_addr = prev_struct; | 239 *(void**)array.base_addr = ldt_fs->prev_struct; |
228 close(fd); | 240 |
229 } | 241 return ldt_fs; |
230 | 242 } |
231 void Restore_LDT_Keeper(void) | 243 |
232 { | 244 void Restore_LDT_Keeper(ldt_fs_t* ldt_fs) |
233 if (fs_seg == 0) | 245 { |
246 if (ldt_fs == NULL || ldt_fs->fs_seg == 0) | |
234 return; | 247 return; |
235 if (prev_struct) | 248 if (ldt_fs->prev_struct) |
236 free(prev_struct); | 249 free(ldt_fs->prev_struct); |
237 munmap((char*)fs_seg, getpagesize()); | 250 munmap((char*)ldt_fs->fs_seg, getpagesize()); |
238 fs_seg = 0; | 251 ldt_fs->fs_seg = 0; |
239 } | 252 close(ldt_fs->fd); |
253 free(ldt_fs); | |
254 } |