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 "windef.h"
11 #include "module.h"
12 #include "heap.h"
13 #include "elfdll.h"
14 #include "debugtools.h"
15 #include "winerror.h"
16 #include "ext.h"
17 
18 //DEFAULT_DEBUG_CHANNEL(elfdll)
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <dlfcn.h>
25 
26 
27 //WINE_MODREF *local_wm=NULL;
28 extern modref_list* local_wm;
29 
30 
31 /*------------------ HACKS -----------------*/
32 extern DWORD fixup_imports(WINE_MODREF *wm);
33 extern void dump_exports(HMODULE hModule);
34 /*---------------- END HACKS ---------------*/
35 
36 //char *extra_ld_library_path = "/usr/lib/codecs";
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  */
ELFDLL_dlopen(const char * libname,int flags)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 = win32_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  */
get_sobasename(LPCSTR path,LPSTR name)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 
ELFDLL_CreateModref(HMODULE hModule,LPCSTR path)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 
195 	wm->filename = malloc(strlen(path)+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         {
214     	    local_wm->next=malloc(sizeof(modref_list));
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         {
222 	    local_wm=malloc(sizeof(modref_list));
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  */
ELFDLL_LoadLibraryExA(LPCSTR path,DWORD flags)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  */
ELFDLL_UnloadLibrary(WINE_MODREF * wm)288 void ELFDLL_UnloadLibrary(WINE_MODREF *wm)
289 {
290 }
291 
292 #endif /*HAVE_LIBDL*/
293