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