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>
|
|
12 #include <stdlib.h>
|
|
13
|
|
14 #include <wine/config.h>
|
|
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*/
|