Mercurial > mplayer.hg
annotate loader/ldt_keeper.c @ 23951:993062afb229
Make the printoption function take the default values from the variable
names related to the flag name, with the possibility to override it if the
variable name is not the same as the flag name. This simplifies printing of
the help message and reduces the possibility of future errors.
author | ivo |
---|---|
date | Tue, 31 Jul 2007 15:10:10 +0000 |
parents | 363c84953547 |
children | b70f5ac9c001 |
rev | line source |
---|---|
2067 | 1 /** |
2 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
3 * This file MUST be in main library because LDT must | |
4 * be modified before program creates first thread | |
5 * - avifile includes this file from C++ code | |
6 * and initializes it at the start of player! | |
7386 | 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 | |
2067 | 11 */ |
12 | |
7386 | 13 /* applied some modification to make make our xine friend more happy */ |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
14537
diff
changeset
|
14 |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
14537
diff
changeset
|
15 /* |
18783 | 16 * Modified for use with MPlayer, detailed changelog at |
17 * http://svn.mplayerhq.hu/mplayer/trunk/ | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
14537
diff
changeset
|
18 * $Id$ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
14537
diff
changeset
|
19 */ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
14537
diff
changeset
|
20 |
2139 | 21 #include "ldt_keeper.h" |
22 | |
2067 | 23 #include <string.h> |
24 #include <stdlib.h> | |
25 #include <errno.h> | |
26 #include <fcntl.h> | |
27 #include <sys/mman.h> | |
28 #include <sys/types.h> | |
29 #include <stdio.h> | |
30 #include <unistd.h> | |
21187
d9cedf7b8069
added mmap_anon to osdep lib. Used in loader for now
nplourde
parents:
18878
diff
changeset
|
31 #include "osdep/mmap_anon.h" |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
32 #include "mp_msg.h" |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
33 #include "help_mp.h" |
2067 | 34 #ifdef __linux__ |
35 #include <asm/unistd.h> | |
36 #include <asm/ldt.h> | |
8213 | 37 // 2.5.xx+ calls this user_desc: |
38 #include <linux/version.h> | |
39 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,47) | |
40 #define modify_ldt_ldt_s user_desc | |
41 #endif | |
7386 | 42 /* prototype it here, so we won't depend on kernel headers */ |
43 #ifdef __cplusplus | |
44 extern "C" { | |
45 #endif | |
13351
698fe63084d3
declare modify_ldt with syscall3 macro for older glibcs patch by Mikulas Patocka <mikulas at artax.karlin.mff.cuni.cz>
faust3
parents:
10821
diff
changeset
|
46 /// declare modify_ldt with the _syscall3 macro for older glibcs |
13361 | 47 #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)) |
13351
698fe63084d3
declare modify_ldt with syscall3 macro for older glibcs patch by Mikulas Patocka <mikulas at artax.karlin.mff.cuni.cz>
faust3
parents:
10821
diff
changeset
|
48 _syscall3( int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount ); |
698fe63084d3
declare modify_ldt with syscall3 macro for older glibcs patch by Mikulas Patocka <mikulas at artax.karlin.mff.cuni.cz>
faust3
parents:
10821
diff
changeset
|
49 #else |
7386 | 50 int modify_ldt(int func, void *ptr, unsigned long bytecount); |
13351
698fe63084d3
declare modify_ldt with syscall3 macro for older glibcs patch by Mikulas Patocka <mikulas at artax.karlin.mff.cuni.cz>
faust3
parents:
10821
diff
changeset
|
51 #endif |
7386 | 52 #ifdef __cplusplus |
53 } | |
54 #endif | |
2067 | 55 #else |
15566 | 56 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) |
5872 | 57 #include <machine/segments.h> |
2067 | 58 #include <machine/sysarch.h> |
59 #endif | |
60 | |
61 #ifdef __svr4__ | |
62 #include <sys/segment.h> | |
63 #include <sys/sysi86.h> | |
64 | |
22715
363c84953547
check that definition of prototype of sysi86(int, void*) doesn't conflict; fixed compilation in opensolaris
nicodvb
parents:
21290
diff
changeset
|
65 /* solaris x86: add missing prototype for sysi86(), but only when sysi86(int, void*) is known to be valid */ |
363c84953547
check that definition of prototype of sysi86(int, void*) doesn't conflict; fixed compilation in opensolaris
nicodvb
parents:
21290
diff
changeset
|
66 #ifdef HAVE_SYSI86_iv |
2067 | 67 #ifdef __cplusplus |
68 extern "C" { | |
69 #endif | |
7386 | 70 int sysi86(int, void*); |
2067 | 71 #ifdef __cplusplus |
72 } | |
73 #endif | |
18362
29b2221982b3
Add a check for sysi86() on Solaris systems, solving a build failure on Solaris
diego
parents:
17605
diff
changeset
|
74 #endif |
2067 | 75 |
2139 | 76 #ifndef NUMSYSLDTS /* SunOS 2.5.1 does not define NUMSYSLDTS */ |
77 #define NUMSYSLDTS 6 /* Let's hope the SunOS 5.8 value is OK */ | |
2067 | 78 #endif |
79 | |
80 #define TEB_SEL_IDX NUMSYSLDTS | |
81 #endif | |
82 | |
83 #define LDT_ENTRIES 8192 | |
84 #define LDT_ENTRY_SIZE 8 | |
85 #pragma pack(4) | |
86 struct modify_ldt_ldt_s { | |
87 unsigned int entry_number; | |
88 unsigned long base_addr; | |
89 unsigned int limit; | |
90 unsigned int seg_32bit:1; | |
91 unsigned int contents:2; | |
92 unsigned int read_exec_only:1; | |
93 unsigned int limit_in_pages:1; | |
94 unsigned int seg_not_present:1; | |
95 unsigned int useable:1; | |
96 }; | |
97 | |
98 #define MODIFY_LDT_CONTENTS_DATA 0 | |
99 #define MODIFY_LDT_CONTENTS_STACK 1 | |
100 #define MODIFY_LDT_CONTENTS_CODE 2 | |
101 #endif | |
102 | |
103 | |
104 /* user level (privilege level: 3) ldt (1<<2) segment selector */ | |
105 #define LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3) | |
106 | |
7386 | 107 /* i got this value from wine sources, it's the first free LDT entry */ |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
108 #if (defined(__APPLE__) || defined(__FreeBSD__)) && defined(LDT_AUTO_ALLOC) |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
109 #define TEB_SEL_IDX LDT_AUTO_ALLOC |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
110 #define USE_LDT_AA |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
111 #endif |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
112 |
2067 | 113 #ifndef TEB_SEL_IDX |
7386 | 114 #define TEB_SEL_IDX 17 |
2067 | 115 #endif |
7386 | 116 |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
117 static unsigned int fs_ldt = TEB_SEL_IDX; |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
118 |
2067 | 119 |
120 /** | |
121 * here is a small logical problem with Restore for multithreaded programs - | |
122 * in C++ we use static class for this... | |
123 */ | |
124 | |
125 #ifdef __cplusplus | |
126 extern "C" | |
127 #endif | |
128 void Setup_FS_Segment(void) | |
129 { | |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
130 unsigned int ldt_desc = LDT_SEL(fs_ldt); |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
131 |
2067 | 132 __asm__ __volatile__( |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
133 "movl %0,%%eax; movw %%ax, %%fs" : : "r" (ldt_desc) |
14212
540903a59fc0
add missing registers in clobber list, fixes bug #169
reimar
parents:
13361
diff
changeset
|
134 :"eax" |
2067 | 135 ); |
136 } | |
137 | |
7386 | 138 /* we don't need this - use modify_ldt instead */ |
139 #if 0 | |
2067 | 140 #ifdef __linux__ |
141 /* XXX: why is this routine from libc redefined here? */ | |
142 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */ | |
143 static int LDT_Modify( int func, struct modify_ldt_ldt_s *ptr, | |
144 unsigned long count ) | |
145 { | |
146 int res; | |
147 #ifdef __PIC__ | |
148 __asm__ __volatile__( "pushl %%ebx\n\t" | |
149 "movl %2,%%ebx\n\t" | |
150 "int $0x80\n\t" | |
151 "popl %%ebx" | |
152 : "=a" (res) | |
153 : "0" (__NR_modify_ldt), | |
154 "r" (func), | |
155 "c" (ptr), | |
156 "d"(16)//sizeof(*ptr) from kernel point of view | |
157 :"esi" ); | |
158 #else | |
159 __asm__ __volatile__("int $0x80" | |
160 : "=a" (res) | |
161 : "0" (__NR_modify_ldt), | |
162 "b" (func), | |
163 "c" (ptr), | |
164 "d"(16) | |
165 :"esi"); | |
166 #endif /* __PIC__ */ | |
167 if (res >= 0) return res; | |
168 errno = -res; | |
169 return -1; | |
170 } | |
171 #endif | |
7386 | 172 #endif |
2067 | 173 |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
174 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) |
2067 | 175 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content ) |
176 { | |
177 *buffer++ = ((content->base_addr & 0x0000ffff) << 16) | | |
178 (content->limit & 0x0ffff); | |
179 *buffer = (content->base_addr & 0xff000000) | | |
180 ((content->base_addr & 0x00ff0000)>>16) | | |
181 (content->limit & 0xf0000) | | |
182 (content->contents << 10) | | |
183 ((content->read_exec_only == 0) << 9) | | |
184 ((content->seg_32bit != 0) << 22) | | |
185 ((content->limit_in_pages != 0) << 23) | | |
186 0xf000; | |
187 } | |
188 #endif | |
189 | |
8223 | 190 void* fs_seg=0; |
7386 | 191 |
192 ldt_fs_t* Setup_LDT_Keeper(void) | |
2067 | 193 { |
194 struct modify_ldt_ldt_s array; | |
195 int ret; | |
7386 | 196 ldt_fs_t* ldt_fs = (ldt_fs_t*) malloc(sizeof(ldt_fs_t)); |
2067 | 197 |
7386 | 198 if (!ldt_fs) |
199 return NULL; | |
2067 | 200 |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
201 #ifdef __APPLE__ |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
202 if (getenv("DYLD_BIND_AT_LAUNCH") == NULL) |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
203 mp_msg(MSGT_LOADER, MSGL_WARN, MSGTR_LOADER_DYLD_Warning); |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
204 #endif /* __APPLE__ */ |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
205 |
8223 | 206 fs_seg= |
21248 | 207 ldt_fs->fs_seg = mmap_anon(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, 0); |
7386 | 208 if (ldt_fs->fs_seg == (void*)-1) |
2067 | 209 { |
210 perror("ERROR: Couldn't allocate memory for fs segment"); | |
7386 | 211 free(ldt_fs); |
212 return NULL; | |
2067 | 213 } |
7386 | 214 *(void**)((char*)ldt_fs->fs_seg+0x18) = ldt_fs->fs_seg; |
14537 | 215 memset(&array, 0, sizeof(array)); |
7386 | 216 array.base_addr=(int)ldt_fs->fs_seg; |
2067 | 217 array.entry_number=TEB_SEL_IDX; |
218 array.limit=array.base_addr+getpagesize()-1; | |
219 array.seg_32bit=1; | |
220 array.read_exec_only=0; | |
221 array.seg_not_present=0; | |
222 array.contents=MODIFY_LDT_CONTENTS_DATA; | |
223 array.limit_in_pages=0; | |
224 #ifdef __linux__ | |
7386 | 225 //ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s)); |
226 ret=modify_ldt(0x1, &array, sizeof(struct modify_ldt_ldt_s)); | |
2067 | 227 if(ret<0) |
228 { | |
229 perror("install_fs"); | |
230 printf("Couldn't install fs segment, expect segfault\n"); | |
231 } | |
232 #endif /*linux*/ | |
233 | |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
234 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) |
2067 | 235 { |
236 unsigned long d[2]; | |
237 | |
238 LDT_EntryToBytes( d, &array ); | |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
239 #ifdef USE_LDT_AA |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
240 ret = i386_set_ldt(LDT_AUTO_ALLOC, (union descriptor *)d, 1); |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
241 array.entry_number = ret; |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
242 fs_ldt = ret; |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
243 #else |
2067 | 244 ret = i386_set_ldt(array.entry_number, (union descriptor *)d, 1); |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
245 #endif |
2067 | 246 if (ret < 0) |
247 { | |
248 perror("install_fs"); | |
249 printf("Couldn't install fs segment, expect segfault\n"); | |
250 printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n"); | |
17605 | 251 #ifdef __OpenBSD__ |
252 printf("On newer OpenBSD systems did you set machdep.userldt to 1?\n"); | |
253 #endif | |
2067 | 254 } |
255 } | |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
256 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __APPLE__ */ |
2067 | 257 |
258 #if defined(__svr4__) | |
2070
c1edbb8bfc0c
(solaris x86) C++ style variable declaration not at the start of a block does
jkeil
parents:
2069
diff
changeset
|
259 { |
2139 | 260 struct ssd ssd; |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
261 ssd.sel = LDT_SEL(TEB_SEL_IDX); |
2139 | 262 ssd.bo = array.base_addr; |
263 ssd.ls = array.limit - array.base_addr; | |
264 ssd.acc1 = ((array.read_exec_only == 0) << 1) | | |
265 (array.contents << 2) | | |
266 0xf0; /* P(resent) | DPL3 | S */ | |
267 ssd.acc2 = 0x4; /* byte limit, 32-bit segment */ | |
268 if (sysi86(SI86DSCR, &ssd) < 0) { | |
269 perror("sysi86(SI86DSCR)"); | |
270 printf("Couldn't install fs segment, expect segfault\n"); | |
271 } | |
2070
c1edbb8bfc0c
(solaris x86) C++ style variable declaration not at the start of a block does
jkeil
parents:
2069
diff
changeset
|
272 } |
2067 | 273 #endif |
274 | |
275 Setup_FS_Segment(); | |
276 | |
18878 | 277 ldt_fs->prev_struct = malloc(8); |
7386 | 278 *(void**)array.base_addr = ldt_fs->prev_struct; |
279 | |
280 return ldt_fs; | |
2067 | 281 } |
282 | |
7386 | 283 void Restore_LDT_Keeper(ldt_fs_t* ldt_fs) |
2067 | 284 { |
7386 | 285 if (ldt_fs == NULL || ldt_fs->fs_seg == 0) |
2067 | 286 return; |
7386 | 287 if (ldt_fs->prev_struct) |
288 free(ldt_fs->prev_struct); | |
289 munmap((char*)ldt_fs->fs_seg, getpagesize()); | |
290 ldt_fs->fs_seg = 0; | |
291 free(ldt_fs); | |
2067 | 292 } |