1
|
1 /*
|
|
2 * Elf-dll loader functions
|
|
3 *
|
|
4 * Copyright 1999 Bertho A. Stultiens
|
|
5 */
|
7386
|
6 #include "config.h"
|
1
|
7
|
|
8 #ifdef HAVE_LIBDL
|
|
9
|
7386
|
10 #include "wine/windef.h"
|
|
11 #include "wine/module.h"
|
|
12 #include "wine/heap.h"
|
|
13 #include "wine/elfdll.h"
|
|
14 #include "wine/debugtools.h"
|
|
15 #include "wine/winerror.h"
|
1
|
16
|
|
17 //DEFAULT_DEBUG_CHANNEL(elfdll)
|
|
18
|
2139
|
19 #include <stdio.h>
|
|
20 #include <stdlib.h>
|
|
21 #include <string.h>
|
|
22 #include <ctype.h>
|
1
|
23 #include <dlfcn.h>
|
|
24
|
|
25
|
|
26 //WINE_MODREF *local_wm=NULL;
|
|
27 extern modref_list* local_wm;
|
|
28
|
|
29
|
|
30 /*------------------ HACKS -----------------*/
|
|
31 extern DWORD fixup_imports(WINE_MODREF *wm);
|
|
32 extern void dump_exports(HMODULE hModule);
|
|
33 /*---------------- END HACKS ---------------*/
|
|
34
|
|
35 //char *extra_ld_library_path = "/usr/lib/win32";
|
|
36 extern char* def_path;
|
|
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);
|
|
66 ldpath = def_path;
|
|
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);
|
|
169 IMAGE_DATA_DIRECTORY *dir;
|
|
170 IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL;
|
|
171 WINE_MODREF *wm;
|
|
172 int len;
|
|
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
|
7386
|
195 wm->filename = (char*) 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 );
|
|
211
|
|
212 if(local_wm)
|
|
213 {
|
7386
|
214 local_wm->next = (modref_list*) 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 {
|
7386
|
222 local_wm = (modref_list*) malloc(sizeof(modref_list));
|
1
|
223 local_wm->next=local_wm->prev=NULL;
|
|
224 local_wm->wm=wm;
|
|
225 }
|
|
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;
|
|
239 struct elfdll_image *image;
|
|
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);
|
|
261 if(!image)
|
|
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*/
|