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