Mercurial > mplayer.hg
annotate loader/elfdll.c @ 21969:ae6aa1d099ff
r21959: Apply ancient double-click patch that nobody cares to comment on.
author | voroshil |
---|---|
date | Sun, 21 Jan 2007 20:08:06 +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*/ |