Mercurial > mplayer.hg
annotate loader/ldt_keeper.c @ 28241:898051d5d9b4
Support loading font faces other then the first one in a font file.
With -fontconfig, it is possible to select a face with index higher than
0 in a multi-face font file. Currently, with the old rendering code,
this information is lost and the first face is loaded. With this change,
index supplied by fontconfig is used for font loading.
Patch by Adrian Stutz, adrian sttz ch.
author | eugeni |
---|---|
date | Tue, 06 Jan 2009 16:44:47 +0000 |
parents | b5a46071062a |
children | 0f1b5b68af32 |
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 */ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
14537
diff
changeset
|
19 |
26105 | 20 #include "config.h" |
2139 | 21 #include "ldt_keeper.h" |
22 | |
2067 | 23 #include <string.h> |
24 #include <stdlib.h> | |
25 #include <errno.h> | |
26 #include <fcntl.h> | |
26105 | 27 #ifdef HAVE_SYS_MMAN_H |
2067 | 28 #include <sys/mman.h> |
26111
eb82d1524b6d
#include osdep/mman.h if sys/mman.h is not available.
diego
parents:
26105
diff
changeset
|
29 #else |
eb82d1524b6d
#include osdep/mman.h if sys/mman.h is not available.
diego
parents:
26105
diff
changeset
|
30 #include "osdep/mmap.h" |
26105 | 31 #endif |
2067 | 32 #include <sys/types.h> |
33 #include <stdio.h> | |
34 #include <unistd.h> | |
21187
d9cedf7b8069
added mmap_anon to osdep lib. Used in loader for now
nplourde
parents:
18878
diff
changeset
|
35 #include "osdep/mmap_anon.h" |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
36 #include "mp_msg.h" |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
37 #include "help_mp.h" |
2067 | 38 #ifdef __linux__ |
39 #include <asm/unistd.h> | |
40 #include <asm/ldt.h> | |
8213 | 41 // 2.5.xx+ calls this user_desc: |
42 #include <linux/version.h> | |
43 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,47) | |
44 #define modify_ldt_ldt_s user_desc | |
45 #endif | |
7386 | 46 /* prototype it here, so we won't depend on kernel headers */ |
47 #ifdef __cplusplus | |
48 extern "C" { | |
49 #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
|
50 /// declare modify_ldt with the _syscall3 macro for older glibcs |
13361 | 51 #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
|
52 _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
|
53 #else |
7386 | 54 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
|
55 #endif |
7386 | 56 #ifdef __cplusplus |
57 } | |
58 #endif | |
2067 | 59 #else |
15566 | 60 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) |
5872 | 61 #include <machine/segments.h> |
2067 | 62 #include <machine/sysarch.h> |
63 #endif | |
64 | |
26054
d9b11d83367f
Add missing #includes for Mac OS X, fixes the warning
diego
parents:
25849
diff
changeset
|
65 #if defined(__APPLE__) |
d9b11d83367f
Add missing #includes for Mac OS X, fixes the warning
diego
parents:
25849
diff
changeset
|
66 #include <architecture/i386/table.h> |
d9b11d83367f
Add missing #includes for Mac OS X, fixes the warning
diego
parents:
25849
diff
changeset
|
67 #include <i386/user_ldt.h> |
d9b11d83367f
Add missing #includes for Mac OS X, fixes the warning
diego
parents:
25849
diff
changeset
|
68 #endif |
d9b11d83367f
Add missing #includes for Mac OS X, fixes the warning
diego
parents:
25849
diff
changeset
|
69 |
2067 | 70 #ifdef __svr4__ |
71 #include <sys/segment.h> | |
72 #include <sys/sysi86.h> | |
73 | |
22715
363c84953547
check that definition of prototype of sysi86(int, void*) doesn't conflict; fixed compilation in opensolaris
nicodvb
parents:
21290
diff
changeset
|
74 /* 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
|
75 #ifdef HAVE_SYSI86_iv |
2067 | 76 #ifdef __cplusplus |
77 extern "C" { | |
78 #endif | |
7386 | 79 int sysi86(int, void*); |
2067 | 80 #ifdef __cplusplus |
81 } | |
82 #endif | |
18362
29b2221982b3
Add a check for sysi86() on Solaris systems, solving a build failure on Solaris
diego
parents:
17605
diff
changeset
|
83 #endif |
2067 | 84 |
2139 | 85 #ifndef NUMSYSLDTS /* SunOS 2.5.1 does not define NUMSYSLDTS */ |
86 #define NUMSYSLDTS 6 /* Let's hope the SunOS 5.8 value is OK */ | |
2067 | 87 #endif |
88 | |
89 #define TEB_SEL_IDX NUMSYSLDTS | |
90 #endif | |
91 | |
92 #define LDT_ENTRIES 8192 | |
93 #define LDT_ENTRY_SIZE 8 | |
94 #pragma pack(4) | |
95 struct modify_ldt_ldt_s { | |
96 unsigned int entry_number; | |
97 unsigned long base_addr; | |
98 unsigned int limit; | |
99 unsigned int seg_32bit:1; | |
100 unsigned int contents:2; | |
101 unsigned int read_exec_only:1; | |
102 unsigned int limit_in_pages:1; | |
103 unsigned int seg_not_present:1; | |
104 unsigned int useable:1; | |
105 }; | |
106 | |
107 #define MODIFY_LDT_CONTENTS_DATA 0 | |
108 #define MODIFY_LDT_CONTENTS_STACK 1 | |
109 #define MODIFY_LDT_CONTENTS_CODE 2 | |
110 #endif | |
111 | |
112 | |
113 /* user level (privilege level: 3) ldt (1<<2) segment selector */ | |
114 #define LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3) | |
115 | |
7386 | 116 /* 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
|
117 #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
|
118 #define TEB_SEL_IDX LDT_AUTO_ALLOC |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
119 #define USE_LDT_AA |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
120 #endif |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
121 |
2067 | 122 #ifndef TEB_SEL_IDX |
7386 | 123 #define TEB_SEL_IDX 17 |
2067 | 124 #endif |
7386 | 125 |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
126 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
|
127 |
2067 | 128 |
129 /** | |
130 * here is a small logical problem with Restore for multithreaded programs - | |
131 * in C++ we use static class for this... | |
132 */ | |
133 | |
134 #ifdef __cplusplus | |
135 extern "C" | |
136 #endif | |
137 void Setup_FS_Segment(void) | |
138 { | |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
139 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
|
140 |
27757
b5a46071062a
Replace all occurrences of '__volatile__' and '__volatile' by plain 'volatile'.
diego
parents:
26111
diff
changeset
|
141 __asm__ volatile( |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
142 "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
|
143 :"eax" |
2067 | 144 ); |
145 } | |
146 | |
7386 | 147 /* we don't need this - use modify_ldt instead */ |
148 #if 0 | |
2067 | 149 #ifdef __linux__ |
150 /* XXX: why is this routine from libc redefined here? */ | |
151 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */ | |
152 static int LDT_Modify( int func, struct modify_ldt_ldt_s *ptr, | |
153 unsigned long count ) | |
154 { | |
155 int res; | |
156 #ifdef __PIC__ | |
27757
b5a46071062a
Replace all occurrences of '__volatile__' and '__volatile' by plain 'volatile'.
diego
parents:
26111
diff
changeset
|
157 __asm__ volatile( "pushl %%ebx\n\t" |
2067 | 158 "movl %2,%%ebx\n\t" |
159 "int $0x80\n\t" | |
160 "popl %%ebx" | |
161 : "=a" (res) | |
162 : "0" (__NR_modify_ldt), | |
163 "r" (func), | |
164 "c" (ptr), | |
165 "d"(16)//sizeof(*ptr) from kernel point of view | |
166 :"esi" ); | |
167 #else | |
27757
b5a46071062a
Replace all occurrences of '__volatile__' and '__volatile' by plain 'volatile'.
diego
parents:
26111
diff
changeset
|
168 __asm__ volatile("int $0x80" |
2067 | 169 : "=a" (res) |
170 : "0" (__NR_modify_ldt), | |
171 "b" (func), | |
172 "c" (ptr), | |
173 "d"(16) | |
174 :"esi"); | |
175 #endif /* __PIC__ */ | |
176 if (res >= 0) return res; | |
177 errno = -res; | |
178 return -1; | |
179 } | |
180 #endif | |
7386 | 181 #endif |
2067 | 182 |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
183 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) |
2067 | 184 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content ) |
185 { | |
186 *buffer++ = ((content->base_addr & 0x0000ffff) << 16) | | |
187 (content->limit & 0x0ffff); | |
188 *buffer = (content->base_addr & 0xff000000) | | |
189 ((content->base_addr & 0x00ff0000)>>16) | | |
190 (content->limit & 0xf0000) | | |
191 (content->contents << 10) | | |
192 ((content->read_exec_only == 0) << 9) | | |
193 ((content->seg_32bit != 0) << 22) | | |
194 ((content->limit_in_pages != 0) << 23) | | |
195 0xf000; | |
196 } | |
197 #endif | |
198 | |
8223 | 199 void* fs_seg=0; |
7386 | 200 |
201 ldt_fs_t* Setup_LDT_Keeper(void) | |
2067 | 202 { |
203 struct modify_ldt_ldt_s array; | |
204 int ret; | |
7386 | 205 ldt_fs_t* ldt_fs = (ldt_fs_t*) malloc(sizeof(ldt_fs_t)); |
2067 | 206 |
7386 | 207 if (!ldt_fs) |
208 return NULL; | |
2067 | 209 |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
210 #ifdef __APPLE__ |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
211 if (getenv("DYLD_BIND_AT_LAUNCH") == NULL) |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
212 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
|
213 #endif /* __APPLE__ */ |
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
214 |
8223 | 215 fs_seg= |
21248 | 216 ldt_fs->fs_seg = mmap_anon(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, 0); |
7386 | 217 if (ldt_fs->fs_seg == (void*)-1) |
2067 | 218 { |
219 perror("ERROR: Couldn't allocate memory for fs segment"); | |
7386 | 220 free(ldt_fs); |
221 return NULL; | |
2067 | 222 } |
7386 | 223 *(void**)((char*)ldt_fs->fs_seg+0x18) = ldt_fs->fs_seg; |
14537 | 224 memset(&array, 0, sizeof(array)); |
7386 | 225 array.base_addr=(int)ldt_fs->fs_seg; |
2067 | 226 array.entry_number=TEB_SEL_IDX; |
227 array.limit=array.base_addr+getpagesize()-1; | |
228 array.seg_32bit=1; | |
229 array.read_exec_only=0; | |
230 array.seg_not_present=0; | |
231 array.contents=MODIFY_LDT_CONTENTS_DATA; | |
232 array.limit_in_pages=0; | |
233 #ifdef __linux__ | |
7386 | 234 //ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s)); |
235 ret=modify_ldt(0x1, &array, sizeof(struct modify_ldt_ldt_s)); | |
2067 | 236 if(ret<0) |
237 { | |
238 perror("install_fs"); | |
239 printf("Couldn't install fs segment, expect segfault\n"); | |
240 } | |
241 #endif /*linux*/ | |
242 | |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
243 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) |
2067 | 244 { |
245 unsigned long d[2]; | |
246 | |
247 LDT_EntryToBytes( d, &array ); | |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
248 #ifdef USE_LDT_AA |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
249 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
|
250 array.entry_number = ret; |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
251 fs_ldt = ret; |
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
252 #else |
2067 | 253 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
|
254 #endif |
2067 | 255 if (ret < 0) |
256 { | |
257 perror("install_fs"); | |
258 printf("Couldn't install fs segment, expect segfault\n"); | |
259 printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n"); | |
17605 | 260 #ifdef __OpenBSD__ |
261 printf("On newer OpenBSD systems did you set machdep.userldt to 1?\n"); | |
262 #endif | |
2067 | 263 } |
264 } | |
21290
efc774a1e5a4
fix compilation for win32 dll codec support for intel osx
nplourde
parents:
21248
diff
changeset
|
265 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __APPLE__ */ |
2067 | 266 |
267 #if defined(__svr4__) | |
2070
c1edbb8bfc0c
(solaris x86) C++ style variable declaration not at the start of a block does
jkeil
parents:
2069
diff
changeset
|
268 { |
2139 | 269 struct ssd ssd; |
10821
e9e5dca4af9e
FreeBSD 5.0 (libkse/libthr) support by Dan Eischen <eischen@vigrid.com>
alex
parents:
8223
diff
changeset
|
270 ssd.sel = LDT_SEL(TEB_SEL_IDX); |
2139 | 271 ssd.bo = array.base_addr; |
272 ssd.ls = array.limit - array.base_addr; | |
273 ssd.acc1 = ((array.read_exec_only == 0) << 1) | | |
274 (array.contents << 2) | | |
275 0xf0; /* P(resent) | DPL3 | S */ | |
276 ssd.acc2 = 0x4; /* byte limit, 32-bit segment */ | |
277 if (sysi86(SI86DSCR, &ssd) < 0) { | |
278 perror("sysi86(SI86DSCR)"); | |
279 printf("Couldn't install fs segment, expect segfault\n"); | |
280 } | |
2070
c1edbb8bfc0c
(solaris x86) C++ style variable declaration not at the start of a block does
jkeil
parents:
2069
diff
changeset
|
281 } |
2067 | 282 #endif |
283 | |
284 Setup_FS_Segment(); | |
285 | |
18878 | 286 ldt_fs->prev_struct = malloc(8); |
7386 | 287 *(void**)array.base_addr = ldt_fs->prev_struct; |
288 | |
289 return ldt_fs; | |
2067 | 290 } |
291 | |
7386 | 292 void Restore_LDT_Keeper(ldt_fs_t* ldt_fs) |
2067 | 293 { |
7386 | 294 if (ldt_fs == NULL || ldt_fs->fs_seg == 0) |
2067 | 295 return; |
7386 | 296 if (ldt_fs->prev_struct) |
297 free(ldt_fs->prev_struct); | |
298 munmap((char*)ldt_fs->fs_seg, getpagesize()); | |
299 ldt_fs->fs_seg = 0; | |
300 free(ldt_fs); | |
2067 | 301 } |