Mercurial > mplayer.hg
annotate loader/elfdll.c @ 34645:0bce77ccae9a
Fix compiling with osdep setenv
Since we have -Werror-implicit-function-declaration in CFLAGS,
we need a prototype for the osdep setenv() implementation.
Reported-by: redxii (in #mplayer IRC channel)
author | al |
---|---|
date | Sat, 18 Feb 2012 00:08:30 +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*/ |