Mercurial > mplayer.hg
annotate loader/elfdll.c @ 33884:514016233368
build: drop BeOS support
BeOS is dead and support has been dropped from FFmpeg/Libav a long time ago.
The support code that was added years ago adds considerable clutter while
not providing any benefit, so it's better to drop it outright.
Support for Haiku, the FOSS replacement of BeOS remains unaffected.
author | diego |
---|---|
date | Thu, 11 Aug 2011 17:45:43 +0000 |
parents | db0bb7511440 |
children |
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 * |
1 | 9 */ |
7386 | 10 #include "config.h" |
1 | 11 |
12 #ifdef HAVE_LIBDL | |
13 | |
7386 | 14 #include "wine/windef.h" |
15 #include "wine/module.h" | |
16 #include "wine/heap.h" | |
17 #include "wine/elfdll.h" | |
18 #include "wine/debugtools.h" | |
19 #include "wine/winerror.h" | |
25773 | 20 #include "debug.h" |
32077
db0bb7511440
Move local_wm extern variable declaration to loader.h, which is better suited.
diego
parents:
30911
diff
changeset
|
21 #include "loader.h" |
30901 | 22 #include "path.h" |
1 | 23 |
24 //DEFAULT_DEBUG_CHANNEL(elfdll) | |
25 | |
2139 | 26 #include <stdio.h> |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 #include <ctype.h> | |
1 | 30 #include <dlfcn.h> |
31 | |
32 | |
33 /*------------------ HACKS -----------------*/ | |
28051 | 34 DWORD fixup_imports(WINE_MODREF *wm); |
35 void dump_exports(HMODULE hModule); | |
1 | 36 /*---------------- END HACKS ---------------*/ |
37 | |
38 struct elfdll_image | |
39 { | |
40 HMODULE pe_module_start; | |
41 DWORD pe_module_size; | |
42 }; | |
43 | |
44 | |
45 /**************************************************************************** | |
46 * ELFDLL_dlopen | |
47 * | |
48 * Wrapper for dlopen to search the EXTRA_LD_LIBRARY_PATH from wine.conf | |
49 * manually because libdl.so caches the environment and does not accept our | |
50 * changes. | |
51 */ | |
52 void *ELFDLL_dlopen(const char *libname, int flags) | |
53 { | |
54 char buffer[256]; | |
55 int namelen; | |
56 void *handle; | |
57 char *ldpath; | |
58 | |
59 /* First try the default path search of dlopen() */ | |
60 handle = dlopen(libname, flags); | |
61 if(handle) | |
62 return handle; | |
63 | |
64 /* Now try to construct searches through our extra search-path */ | |
65 namelen = strlen(libname); | |
30907
b32527b30d17
Get rid of pointless def_path variable; use codec_path directly instead.
diego
parents:
30901
diff
changeset
|
66 ldpath = codec_path; |
1 | 67 while(ldpath && *ldpath) |
68 { | |
69 int len; | |
70 char *cptr; | |
71 char *from; | |
72 | |
73 from = ldpath; | |
74 cptr = strchr(ldpath, ':'); | |
75 if(!cptr) | |
76 { | |
77 len = strlen(ldpath); | |
78 ldpath = NULL; | |
79 } | |
80 else | |
81 { | |
82 len = cptr - ldpath; | |
83 ldpath = cptr + 1; | |
84 } | |
85 | |
86 if(len + namelen + 1 >= sizeof(buffer)) | |
87 { | |
88 ERR("Buffer overflow! Check EXTRA_LD_LIBRARY_PATH or increase buffer size.\n"); | |
89 return NULL; | |
90 } | |
91 | |
92 strncpy(buffer, from, len); | |
93 if(len) | |
94 { | |
95 buffer[len] = '/'; | |
96 strcpy(buffer + len + 1, libname); | |
97 } | |
98 else | |
99 strcpy(buffer + len, libname); | |
100 | |
101 TRACE("Trying dlopen('%s', %d)\n", buffer, flags); | |
102 | |
103 handle = dlopen(buffer, flags); | |
104 if(handle) | |
105 return handle; | |
106 } | |
107 return NULL; | |
108 } | |
109 | |
110 | |
111 /**************************************************************************** | |
112 * get_sobasename (internal) | |
113 * | |
114 */ | |
115 static LPSTR get_sobasename(LPCSTR path, LPSTR name) | |
116 { | |
117 char *cptr; | |
118 | |
119 /* Strip the path from the library name */ | |
120 if((cptr = strrchr(path, '/'))) | |
121 { | |
122 char *cp = strrchr(cptr+1, '\\'); | |
123 if(cp && cp > cptr) | |
124 cptr = cp; | |
125 } | |
126 else | |
127 cptr = strrchr(path, '\\'); | |
128 | |
129 if(!cptr) | |
130 cptr = (char *)path; /* No '/' nor '\\' in path */ | |
131 else | |
132 cptr++; | |
133 | |
134 strcpy(name, cptr); | |
135 cptr = strrchr(name, '.'); | |
136 if(cptr) | |
137 *cptr = '\0'; /* Strip extension */ | |
138 | |
139 /* Convert to lower case. | |
140 * This must be done manually because it is not sure that | |
141 * other modules are accessible. | |
142 */ | |
143 for(cptr = name; *cptr; cptr++) | |
144 *cptr = tolower(*cptr); | |
145 | |
146 return name; | |
147 } | |
148 | |
149 | |
150 /**************************************************************************** | |
151 * ELFDLL_CreateModref (internal) | |
152 * | |
153 * INPUT | |
154 * hModule - the header from the elf-dll's data-segment | |
155 * path - requested path from original call | |
156 * | |
157 * OUTPUT | |
158 * A WINE_MODREF pointer to the new object | |
159 * | |
160 * BUGS | |
161 * - Does not handle errors due to dependencies correctly | |
162 * - path can be wrong | |
163 */ | |
164 #define RVA(base, va) (((DWORD)base) + ((DWORD)va)) | |
165 | |
166 static WINE_MODREF *ELFDLL_CreateModref(HMODULE hModule, LPCSTR path) | |
167 { | |
168 // IMAGE_NT_HEADERS *nt = PE_HEADER(hModule); | |
24388 | 169 // IMAGE_DATA_DIRECTORY *dir; |
170 // IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL; | |
1 | 171 WINE_MODREF *wm; |
24388 | 172 // int len; |
1 | 173 HANDLE procheap = GetProcessHeap(); |
174 | |
175 wm = (WINE_MODREF *)HeapAlloc(procheap, HEAP_ZERO_MEMORY, sizeof(*wm)); | |
176 if(!wm) | |
177 return NULL; | |
178 | |
179 wm->module = hModule; | |
180 wm->type = MODULE32_ELF; /* FIXME */ | |
181 | |
182 // dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT; | |
183 // if(dir->Size) | |
184 // wm->binfmt.pe.pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(hModule, dir->VirtualAddress); | |
185 | |
186 // dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT; | |
187 // if(dir->Size) | |
188 // pe_import = wm->binfmt.pe.pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(hModule, dir->VirtualAddress); | |
189 | |
190 // dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE; | |
191 // if(dir->Size) | |
192 // wm->binfmt.pe.pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(hModule, dir->VirtualAddress); | |
193 | |
194 | |
30702 | 195 wm->filename = malloc(strlen(path)+1); |
1 | 196 strcpy(wm->filename, path); |
197 wm->modname = strrchr( wm->filename, '\\' ); | |
198 if (!wm->modname) wm->modname = wm->filename; | |
199 else wm->modname++; | |
200 /* | |
201 len = GetShortPathNameA( wm->filename, NULL, 0 ); | |
202 wm->short_filename = (char *)HeapAlloc( procheap, 0, len+1 ); | |
203 GetShortPathNameA( wm->filename, wm->short_filename, len+1 ); | |
204 wm->short_modname = strrchr( wm->short_filename, '\\' ); | |
205 if (!wm->short_modname) wm->short_modname = wm->short_filename; | |
206 else wm->short_modname++; | |
207 */ | |
208 /* Link MODREF into process list */ | |
209 | |
210 // EnterCriticalSection( &PROCESS_Current()->crit_section ); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28051
diff
changeset
|
211 |
1 | 212 if(local_wm) |
213 { | |
30702 | 214 local_wm->next = malloc(sizeof(modref_list)); |
1 | 215 local_wm->next->prev=local_wm; |
216 local_wm->next->next=NULL; | |
217 local_wm->next->wm=wm; | |
218 local_wm=local_wm->next; | |
219 } | |
220 else | |
221 { | |
30702 | 222 local_wm = malloc(sizeof(modref_list)); |
1 | 223 local_wm->next=local_wm->prev=NULL; |
224 local_wm->wm=wm; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28051
diff
changeset
|
225 } |
1 | 226 |
227 // LeaveCriticalSection( &PROCESS_Current()->crit_section ); | |
228 return wm; | |
229 } | |
230 | |
231 /**************************************************************************** | |
232 * ELFDLL_LoadLibraryExA (internal) | |
233 * | |
234 * Implementation of elf-dll loading for PE modules | |
235 */ | |
236 WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags) | |
237 { | |
238 LPVOID dlhandle; | |
24388 | 239 // struct elfdll_image *image; |
1 | 240 char name[129]; |
241 char soname[129]; | |
242 WINE_MODREF *wm; | |
243 | |
244 get_sobasename(path, name); | |
245 strcpy(soname, name); | |
246 strcat(soname, ".so"); | |
247 | |
248 /* Try to open the elf-dll */ | |
249 dlhandle = ELFDLL_dlopen(soname, RTLD_LAZY); | |
250 if(!dlhandle) | |
251 { | |
252 WARN("Could not load %s (%s)\n", soname, dlerror()); | |
253 SetLastError( ERROR_FILE_NOT_FOUND ); | |
254 return NULL; | |
255 } | |
256 | |
257 /* Get the 'dllname_elfdll_image' variable */ | |
258 /* strcpy(soname, name); | |
259 strcat(soname, "_elfdll_image"); | |
260 image = (struct elfdll_image *)dlsym(dlhandle, soname); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28051
diff
changeset
|
261 if(!image) |
1 | 262 { |
263 ERR("Could not get elfdll image descriptor %s (%s)\n", soname, dlerror()); | |
264 dlclose(dlhandle); | |
265 SetLastError( ERROR_BAD_FORMAT ); | |
266 return NULL; | |
267 } | |
268 | |
269 */ | |
270 wm = ELFDLL_CreateModref((int)dlhandle, path); | |
271 if(!wm) | |
272 { | |
273 ERR("Could not create WINE_MODREF for %s\n", path); | |
274 dlclose(dlhandle); | |
275 SetLastError( ERROR_OUTOFMEMORY ); | |
276 return NULL; | |
277 } | |
278 | |
279 return wm; | |
280 } | |
281 | |
282 | |
283 /**************************************************************************** | |
284 * ELFDLL_UnloadLibrary (internal) | |
285 * | |
286 * Unload an elf-dll completely from memory and deallocate the modref | |
287 */ | |
288 void ELFDLL_UnloadLibrary(WINE_MODREF *wm) | |
289 { | |
290 } | |
291 | |
292 #endif /*HAVE_LIBDL*/ |