Mercurial > mplayer.hg
annotate loader/elfdll.c @ 24131:30028bbcb9e8
Use a single select() for both key and slave input
Previous code used two separate select() calls one after another, so
that whenever it was running select() on one set of fds events in the
other set would go unnoticed until later. Now there's a single select()
which allows reacting immediately to any input source.
The behavior of the new code differs somewhat from the old; for example
multiple fds that stay readable are no longer handled in a round-robin
fashion and the total amount the process sleeps can differ. Some tuning
might be required later.
author | uau |
---|---|
date | Sat, 25 Aug 2007 04:28:11 +0000 |
parents | 0783dd397f74 |
children | 7cfc461fa31f |
rev | line source |
---|---|
1 | 1 /* |
2 * Elf-dll loader functions | |
3 * | |
4 * Copyright 1999 Bertho A. Stultiens | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
7386
diff
changeset
|
5 * |
18783 | 6 * Modified for use with MPlayer, detailed changelog at |
7 * http://svn.mplayerhq.hu/mplayer/trunk/ | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
7386
diff
changeset
|
8 * $Id$ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
7386
diff
changeset
|
9 * |
1 | 10 */ |
7386 | 11 #include "config.h" |
1 | 12 |
13 #ifdef HAVE_LIBDL | |
14 | |
7386 | 15 #include "wine/windef.h" |
16 #include "wine/module.h" | |
17 #include "wine/heap.h" | |
18 #include "wine/elfdll.h" | |
19 #include "wine/debugtools.h" | |
20 #include "wine/winerror.h" | |
1 | 21 |
22 //DEFAULT_DEBUG_CHANNEL(elfdll) | |
23 | |
2139 | 24 #include <stdio.h> |
25 #include <stdlib.h> | |
26 #include <string.h> | |
27 #include <ctype.h> | |
1 | 28 #include <dlfcn.h> |
29 | |
30 | |
31 //WINE_MODREF *local_wm=NULL; | |
32 extern modref_list* local_wm; | |
33 | |
34 | |
35 /*------------------ HACKS -----------------*/ | |
36 extern DWORD fixup_imports(WINE_MODREF *wm); | |
37 extern void dump_exports(HMODULE hModule); | |
38 /*---------------- END HACKS ---------------*/ | |
39 | |
40 //char *extra_ld_library_path = "/usr/lib/win32"; | |
41 extern char* def_path; | |
42 | |
43 struct elfdll_image | |
44 { | |
45 HMODULE pe_module_start; | |
46 DWORD pe_module_size; | |
47 }; | |
48 | |
49 | |
50 /**************************************************************************** | |
51 * ELFDLL_dlopen | |
52 * | |
53 * Wrapper for dlopen to search the EXTRA_LD_LIBRARY_PATH from wine.conf | |
54 * manually because libdl.so caches the environment and does not accept our | |
55 * changes. | |
56 */ | |
57 void *ELFDLL_dlopen(const char *libname, int flags) | |
58 { | |
59 char buffer[256]; | |
60 int namelen; | |
61 void *handle; | |
62 char *ldpath; | |
63 | |
64 /* First try the default path search of dlopen() */ | |
65 handle = dlopen(libname, flags); | |
66 if(handle) | |
67 return handle; | |
68 | |
69 /* Now try to construct searches through our extra search-path */ | |
70 namelen = strlen(libname); | |
71 ldpath = def_path; | |
72 while(ldpath && *ldpath) | |
73 { | |
74 int len; | |
75 char *cptr; | |
76 char *from; | |
77 | |
78 from = ldpath; | |
79 cptr = strchr(ldpath, ':'); | |
80 if(!cptr) | |
81 { | |
82 len = strlen(ldpath); | |
83 ldpath = NULL; | |
84 } | |
85 else | |
86 { | |
87 len = cptr - ldpath; | |
88 ldpath = cptr + 1; | |
89 } | |
90 | |
91 if(len + namelen + 1 >= sizeof(buffer)) | |
92 { | |
93 ERR("Buffer overflow! Check EXTRA_LD_LIBRARY_PATH or increase buffer size.\n"); | |
94 return NULL; | |
95 } | |
96 | |
97 strncpy(buffer, from, len); | |
98 if(len) | |
99 { | |
100 buffer[len] = '/'; | |
101 strcpy(buffer + len + 1, libname); | |
102 } | |
103 else | |
104 strcpy(buffer + len, libname); | |
105 | |
106 TRACE("Trying dlopen('%s', %d)\n", buffer, flags); | |
107 | |
108 handle = dlopen(buffer, flags); | |
109 if(handle) | |
110 return handle; | |
111 } | |
112 return NULL; | |
113 } | |
114 | |
115 | |
116 /**************************************************************************** | |
117 * get_sobasename (internal) | |
118 * | |
119 */ | |
120 static LPSTR get_sobasename(LPCSTR path, LPSTR name) | |
121 { | |
122 char *cptr; | |
123 | |
124 /* Strip the path from the library name */ | |
125 if((cptr = strrchr(path, '/'))) | |
126 { | |
127 char *cp = strrchr(cptr+1, '\\'); | |
128 if(cp && cp > cptr) | |
129 cptr = cp; | |
130 } | |
131 else | |
132 cptr = strrchr(path, '\\'); | |
133 | |
134 if(!cptr) | |
135 cptr = (char *)path; /* No '/' nor '\\' in path */ | |
136 else | |
137 cptr++; | |
138 | |
139 strcpy(name, cptr); | |
140 cptr = strrchr(name, '.'); | |
141 if(cptr) | |
142 *cptr = '\0'; /* Strip extension */ | |
143 | |
144 /* Convert to lower case. | |
145 * This must be done manually because it is not sure that | |
146 * other modules are accessible. | |
147 */ | |
148 for(cptr = name; *cptr; cptr++) | |
149 *cptr = tolower(*cptr); | |
150 | |
151 return name; | |
152 } | |
153 | |
154 | |
155 /**************************************************************************** | |
156 * ELFDLL_CreateModref (internal) | |
157 * | |
158 * INPUT | |
159 * hModule - the header from the elf-dll's data-segment | |
160 * path - requested path from original call | |
161 * | |
162 * OUTPUT | |
163 * A WINE_MODREF pointer to the new object | |
164 * | |
165 * BUGS | |
166 * - Does not handle errors due to dependencies correctly | |
167 * - path can be wrong | |
168 */ | |
169 #define RVA(base, va) (((DWORD)base) + ((DWORD)va)) | |
170 | |
171 static WINE_MODREF *ELFDLL_CreateModref(HMODULE hModule, LPCSTR path) | |
172 { | |
173 // IMAGE_NT_HEADERS *nt = PE_HEADER(hModule); | |
174 IMAGE_DATA_DIRECTORY *dir; | |
175 IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL; | |
176 WINE_MODREF *wm; | |
177 int len; | |
178 HANDLE procheap = GetProcessHeap(); | |
179 | |
180 wm = (WINE_MODREF *)HeapAlloc(procheap, HEAP_ZERO_MEMORY, sizeof(*wm)); | |
181 if(!wm) | |
182 return NULL; | |
183 | |
184 wm->module = hModule; | |
185 wm->type = MODULE32_ELF; /* FIXME */ | |
186 | |
187 // dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT; | |
188 // if(dir->Size) | |
189 // wm->binfmt.pe.pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(hModule, dir->VirtualAddress); | |
190 | |
191 // dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT; | |
192 // if(dir->Size) | |
193 // pe_import = wm->binfmt.pe.pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(hModule, dir->VirtualAddress); | |
194 | |
195 // dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE; | |
196 // if(dir->Size) | |
197 // wm->binfmt.pe.pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(hModule, dir->VirtualAddress); | |
198 | |
199 | |
7386 | 200 wm->filename = (char*) malloc(strlen(path)+1); |
1 | 201 strcpy(wm->filename, path); |
202 wm->modname = strrchr( wm->filename, '\\' ); | |
203 if (!wm->modname) wm->modname = wm->filename; | |
204 else wm->modname++; | |
205 /* | |
206 len = GetShortPathNameA( wm->filename, NULL, 0 ); | |
207 wm->short_filename = (char *)HeapAlloc( procheap, 0, len+1 ); | |
208 GetShortPathNameA( wm->filename, wm->short_filename, len+1 ); | |
209 wm->short_modname = strrchr( wm->short_filename, '\\' ); | |
210 if (!wm->short_modname) wm->short_modname = wm->short_filename; | |
211 else wm->short_modname++; | |
212 */ | |
213 /* Link MODREF into process list */ | |
214 | |
215 // EnterCriticalSection( &PROCESS_Current()->crit_section ); | |
216 | |
217 if(local_wm) | |
218 { | |
7386 | 219 local_wm->next = (modref_list*) malloc(sizeof(modref_list)); |
1 | 220 local_wm->next->prev=local_wm; |
221 local_wm->next->next=NULL; | |
222 local_wm->next->wm=wm; | |
223 local_wm=local_wm->next; | |
224 } | |
225 else | |
226 { | |
7386 | 227 local_wm = (modref_list*) malloc(sizeof(modref_list)); |
1 | 228 local_wm->next=local_wm->prev=NULL; |
229 local_wm->wm=wm; | |
230 } | |
231 | |
232 // LeaveCriticalSection( &PROCESS_Current()->crit_section ); | |
233 return wm; | |
234 } | |
235 | |
236 /**************************************************************************** | |
237 * ELFDLL_LoadLibraryExA (internal) | |
238 * | |
239 * Implementation of elf-dll loading for PE modules | |
240 */ | |
241 WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags) | |
242 { | |
243 LPVOID dlhandle; | |
244 struct elfdll_image *image; | |
245 char name[129]; | |
246 char soname[129]; | |
247 WINE_MODREF *wm; | |
248 | |
249 get_sobasename(path, name); | |
250 strcpy(soname, name); | |
251 strcat(soname, ".so"); | |
252 | |
253 /* Try to open the elf-dll */ | |
254 dlhandle = ELFDLL_dlopen(soname, RTLD_LAZY); | |
255 if(!dlhandle) | |
256 { | |
257 WARN("Could not load %s (%s)\n", soname, dlerror()); | |
258 SetLastError( ERROR_FILE_NOT_FOUND ); | |
259 return NULL; | |
260 } | |
261 | |
262 /* Get the 'dllname_elfdll_image' variable */ | |
263 /* strcpy(soname, name); | |
264 strcat(soname, "_elfdll_image"); | |
265 image = (struct elfdll_image *)dlsym(dlhandle, soname); | |
266 if(!image) | |
267 { | |
268 ERR("Could not get elfdll image descriptor %s (%s)\n", soname, dlerror()); | |
269 dlclose(dlhandle); | |
270 SetLastError( ERROR_BAD_FORMAT ); | |
271 return NULL; | |
272 } | |
273 | |
274 */ | |
275 wm = ELFDLL_CreateModref((int)dlhandle, path); | |
276 if(!wm) | |
277 { | |
278 ERR("Could not create WINE_MODREF for %s\n", path); | |
279 dlclose(dlhandle); | |
280 SetLastError( ERROR_OUTOFMEMORY ); | |
281 return NULL; | |
282 } | |
283 | |
284 return wm; | |
285 } | |
286 | |
287 | |
288 /**************************************************************************** | |
289 * ELFDLL_UnloadLibrary (internal) | |
290 * | |
291 * Unload an elf-dll completely from memory and deallocate the modref | |
292 */ | |
293 void ELFDLL_UnloadLibrary(WINE_MODREF *wm) | |
294 { | |
295 } | |
296 | |
297 #endif /*HAVE_LIBDL*/ |