summaryrefslogtreecommitdiff
path: root/src/lib/evil
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2015-04-29 10:50:11 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-05-07 09:53:12 +0200
commit92ff90ecca98f9e8e66a1f7a3ecf4e46f65913d4 (patch)
tree3da7d8cbc50d35dd472c3e8cc5fddb5b17602ac8 /src/lib/evil
parent00a3de5c1f3268c9b7c98e5be39c3947b105ee6e (diff)
evil: fix dladdr() implementation, add 2 unit tests for evil.
@fix Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to 'src/lib/evil')
-rw-r--r--src/lib/evil/dlfcn.c173
-rw-r--r--src/lib/evil/dlfcn.h45
2 files changed, 170 insertions, 48 deletions
diff --git a/src/lib/evil/dlfcn.c b/src/lib/evil/dlfcn.c
index c220003de6..ae8687ebf5 100644
--- a/src/lib/evil/dlfcn.c
+++ b/src/lib/evil/dlfcn.c
@@ -171,21 +171,67 @@ dlsym(void *handle, const char *symbol)
171 return fp; 171 return fp;
172} 172}
173 173
174char *
175dlerror (void)
176{
177 if (!_dl_err_viewed)
178 {
179 _dl_err_viewed = 1;
180 return _dl_err;
181 }
182 else
183 {
184 if (_dl_err)
185 free(_dl_err);
186 return NULL;
187 }
188}
189
190#ifdef _GNU_SOURCE
191
192static char _dli_fname[MAX_PATH];
193static char _dli_sname[MAX_PATH]; /* a symbol should have at most 255 char */
194
195static int
196_dladdr_comp(const void *p1, const void *p2)
197{
198 return ( *(int *)p1 - *(int *)p2);
199}
200
174int 201int
175dladdr (const void *addr EVIL_UNUSED, Dl_info *info) 202dladdr (const void *addr EVIL_UNUSED, Dl_info *info)
176{ 203{
177 TCHAR tpath[PATH_MAX]; 204 TCHAR tpath[PATH_MAX];
178 MEMORY_BASIC_INFORMATION mbi; 205 MEMORY_BASIC_INFORMATION mbi;
179 char *path; 206 unsigned char *base;
207 char *path;
180 size_t length; 208 size_t length;
181 int ret = 0; 209
210 IMAGE_NT_HEADERS *nth;
211 IMAGE_EXPORT_DIRECTORY *ied;
212 DWORD *addresses;
213 WORD *ordinals;
214 DWORD *names;
215 DWORD *tmp;
216 DWORD res;
217 DWORD rva_addr;
218 DWORD i;
182 219
183 if (!info) 220 if (!info)
184 return 0; 221 return 0;
185 222
186 length = VirtualQuery(addr, &mbi, sizeof(mbi)); 223 info->dli_fname = NULL;
187 if (!length) 224 info->dli_fbase = NULL;
188 return 0; 225 info->dli_sname = NULL;
226 info->dli_saddr = NULL;
227
228 /* Get the name and base address of the module */
229
230 if (!VirtualQuery(addr, &mbi, sizeof(mbi)))
231 {
232 _dl_get_last_error("VirtualQuery returned: ");
233 return 0;
234 }
189 235
190 if (mbi.State != MEM_COMMIT) 236 if (mbi.State != MEM_COMMIT)
191 return 0; 237 return 0;
@@ -193,49 +239,110 @@ dladdr (const void *addr EVIL_UNUSED, Dl_info *info)
193 if (!mbi.AllocationBase) 239 if (!mbi.AllocationBase)
194 return 0; 240 return 0;
195 241
196 ret = GetModuleFileName((HMODULE)mbi.AllocationBase, (LPTSTR)&tpath, PATH_MAX); 242 base = (unsigned char *)mbi.AllocationBase;
197 if (!ret)
198 return 0;
199 243
200#ifdef UNICODE 244 if (!GetModuleFileName((HMODULE)base, (LPTSTR)&tpath, PATH_MAX))
245 {
246 _dl_get_last_error("GetModuleFileName returned: ");
247 return 0;
248 }
249
250# ifdef UNICODE
201 path = evil_wchar_to_char(tpath); 251 path = evil_wchar_to_char(tpath);
202#else 252# else
203 path = tpath; 253 path = tpath;
204#endif /* ! UNICODE */ 254# endif /* ! UNICODE */
205 255
206 length = strlen (path); 256 length = strlen(path);
207 if (length >= PATH_MAX) 257 if (length >= PATH_MAX)
208 { 258 {
209 length = PATH_MAX - 1; 259 length = PATH_MAX - 1;
210 path[PATH_MAX - 1] = '\0'; 260 path[PATH_MAX - 1] = '\0';
211 } 261 }
212 262
213 EVIL_PATH_SEP_UNIX_TO_WIN32(path); 263 memcpy(_dli_fname, path, length + 1);
264 info->dli_fname = (const char *)_dli_fname;
265 info->dli_fbase = base;
214 266
215 memcpy (info->dli_fname, path, length + 1); 267# ifdef UNICODE
216 info->dli_fbase = NULL; 268 free(path);
217 info->dli_sname = NULL; 269# endif /* ! UNICODE */
218 info->dli_saddr = NULL;
219 270
220#ifdef UNICODE 271 /* get the name and the address of the required symbol */
221 free (path);
222#endif /* ! UNICODE */
223 272
224 return 1; 273 if (((IMAGE_DOS_HEADER *)base)->e_magic != IMAGE_DOS_SIGNATURE)
225} 274 {
275 SetLastError(1276);
276 return 0;
277 }
226 278
227char * 279 nth = (IMAGE_NT_HEADERS *)(base + ((IMAGE_DOS_HEADER *)base)->e_lfanew);
228dlerror (void) 280 if (nth->Signature != IMAGE_NT_SIGNATURE)
229{
230 if (!_dl_err_viewed)
231 { 281 {
232 _dl_err_viewed = 1; 282 SetLastError(1276);
233 return _dl_err; 283 return 0;
234 } 284 }
235 else 285
286 /* no exported symbols ? it's an EXE and we exit without error */
287 if (nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
236 { 288 {
237 if (_dl_err) 289 return 1;
238 free(_dl_err); 290 }
239 return NULL; 291
292 /* we assume now that the PE file is well-formed, so checks only when needed */
293 ied = (IMAGE_EXPORT_DIRECTORY *)(base + nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
294 addresses = (DWORD *)(base + ied->AddressOfFunctions);
295 ordinals = (WORD *)(base + ied->AddressOfNameOrdinals);
296 names = (DWORD *)(base + ied->AddressOfNames);
297
298 /* the addresses are not ordered, so we need to order them */
299 tmp = malloc(ied->NumberOfFunctions * sizeof(DWORD));
300 if (!tmp)
301 {
302 SetLastError(8);
303 return 0;
304 }
305
306 memcpy(tmp, addresses, ied->NumberOfFunctions * sizeof(DWORD));
307 qsort(tmp, ied->NumberOfFunctions, sizeof(DWORD), _dladdr_comp);
308 rva_addr = (unsigned char *)addr - base;
309 res = (DWORD)(-1);
310 for (i = 0; i < ied->NumberOfFunctions; i++)
311 {
312 if (tmp[i] < rva_addr)
313 continue;
314
315 res = tmp[i];
316 break;
240 } 317 }
318
319 /* if rva_addr is too high, we store the latest address */
320 if (res == (DWORD)(-1))
321 res = tmp[ied->NumberOfFunctions - 1];
322
323 free(tmp);
324
325 for (i = 0; i < ied->NumberOfNames; i++)
326 {
327 if (addresses[ordinals[i]] == res)
328 {
329 char *name;
330
331 name = (char *)(base + names[i]);
332 length = strlen(name);
333 if (length >= PATH_MAX)
334 {
335 length = PATH_MAX - 1;
336 name[PATH_MAX - 1] = '\0';
337 }
338 memcpy(_dli_sname, name, length + 1);
339 info->dli_sname = (const char *)_dli_sname;
340 info->dli_saddr = base + res;
341 return 1;
342 }
343 }
344
345 return 0;
241} 346}
347
348#endif /* _GNU_SOURCE */
diff --git a/src/lib/evil/dlfcn.h b/src/lib/evil/dlfcn.h
index 21de0b8ccc..349a9b4356 100644
--- a/src/lib/evil/dlfcn.h
+++ b/src/lib/evil/dlfcn.h
@@ -64,30 +64,40 @@ x * This header provides functions to load and unload dynamic-link
64 */ 64 */
65#define RTLD_NODELETE 0x01000 /* do not delete object when closed. */ 65#define RTLD_NODELETE 0x01000 /* do not delete object when closed. */
66 66
67#ifdef _GNU_SOURCE
68
67/** 69/**
68 * @def RTLD_DEFAULT 70 * @def RTLD_DEFAULT
69 * Symbols are searched in all the DLL opened by the current process. 71 * Symbols are searched in all the DLL opened by the current process.
72 * This symbol is defined only when _GNU_SOURCE was defined before
73 * including dlfcn.h.
70 */ 74 */
71#define RTLD_DEFAULT ((void*)1) /* search the symbol on all the DLL of the current process */ 75#define RTLD_DEFAULT ((void*)1) /* search the symbol on all the DLL of the current process */
72 76
73/** 77/**
74 * @typedef Dl_info 78 * @typedef Dl_info
75 * @brief A structure that stores infomation of a calling process. 79 * @brief A structure that stores infomation of a calling process.
80 * This typedef is defined only when _GNU_SOURCE was defined before
81 * including dlfcn.h.
76 */ 82 */
77typedef struct Dl_info Dl_info; 83typedef struct Dl_info Dl_info;
78 84
79/** 85/**
80 * @struct Dl_info 86 * @struct Dl_info
81 * @brief A structure that stores infomation of a calling process. 87 * @brief A structure that stores infomation of a calling process.
88 * This structure is defined only when _GNU_SOURCE was defined before
89 * including dlfcn.h.
82 */ 90 */
83struct Dl_info 91struct Dl_info
84{ 92{
85 char dli_fname[PATH_MAX]; /**< Filename of defining object */ 93 const char *dli_fname; /**< Filename of defining object */
86 void *dli_fbase; /**< Load address of that object */ 94 void *dli_fbase; /**< Load address of that object */
87 const char *dli_sname; /**< Name of nearest lower symbol */ 95 const char *dli_sname; /**< Name of nearest lower symbol */
88 void *dli_saddr; /**< Exact value of nearest symbol */ 96 void *dli_saddr; /**< Exact value of nearest symbol */
89}; 97};
90 98
99#endif /* _GNU_SOURCE */
100
91/** 101/**
92 * @brief Map a specified executable module (either a .dll or .exe file) 102 * @brief Map a specified executable module (either a .dll or .exe file)
93 * into the address space of the user process. 103 * into the address space of the user process.
@@ -197,30 +207,35 @@ EAPI int dlclose(void* handle);
197 */ 207 */
198EAPI void *dlsym(void* handle, const char* symbol); 208EAPI void *dlsym(void* handle, const char* symbol);
199 209
210#ifdef _GNU_SOURCE
211
200/** 212/**
201 * @brief Get the location of the current process (.exe) 213 * @brief Resolve module and function pointers from the given function
214 * pointer address.
202 * 215 *
203 * @param addr Unused. 216 * @param addr A function pointer.
204 * @param info Pointer to the Dl_info to fill. 217 * @param info Pointer to the #Dl_info to fill.
205 * @return 1 on success, 0 otherwise. 218 * @return 1 on success, 0 otherwise.
206 * 219 *
207 * Fill the dli_fname member of @p info with the absolute name 220 * Fill @p info with the absolute name of the module which has the
208 * of the current calling process (.exe file that is executed). 221 * fonction pointer @p addr, the base address of that module, the name
209 * All other members are set to @c NULL. 222 * and address of the symbol. If no symbol matching @p addr could be
223 * found (as in an EXE file), then dli_sname and dli_saddr are set to
224 * NULL and the function returns 1. See #Dl_info for more informations.
210 * 225 *
211 * Contrary to the unix function, the full name of the shared 226 * This function is available only when _GNU_SOURCE was defined before
212 * library is not returned, but insted the full name of the current 227 * including dlfcn.h.
213 * calling process (.exe file).
214 * 228 *
215 * Conformity: None. 229 * Conformity: None.
216 * 230 *
217 * Supported OS: Windows Vista, Windows XP or Windows 2000 231 * Supported OS: Windows Vista, Windows XP.
218 * Professional.
219 * 232 *
220 * @ingroup Evil_Dlfcn 233 * @ingroup Evil_Dlfcn
221 */ 234 */
222EAPI int dladdr (const void *addr, Dl_info *info); 235EAPI int dladdr (const void *addr, Dl_info *info);
223 236
237#endif /* _GNU_SOURCE */
238
224/** 239/**
225 * @brief Get diagnostic information 240 * @brief Get diagnostic information
226 * 241 *