]> sourceware.org Git - newlib-cygwin.git/blame - winsup/utils/ldd.cc
Cygwin: Ensure PSAPI_VERSION is 1 when building ldd
[newlib-cygwin.git] / winsup / utils / ldd.cc
CommitLineData
61522196 1/* Copyright (c) 2009, 2010, 2011, 2013 Chris Faylor
086dc27f
CF
2
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
6e623e93
CV
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
086dc27f
CF
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
15 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*/
26
27#include <errno.h>
28#include <getopt.h>
29#include <stdarg.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
2e13058e 33#include <wchar.h>
2e13058e 34#include <locale.h>
086dc27f 35#include <sys/cygwin.h>
92b499ac 36#include <cygwin/version.h>
086dc27f 37#include <unistd.h>
962acfe5 38#include <libgen.h>
086dc27f 39
d21b6359 40#define _WIN32_WINNT 0x0a00
a9c8050c 41#define PSAPI_VERSION 1
086dc27f 42#include <windows.h>
e3ca53d9 43#include <winternl.h>
086dc27f
CF
44#include <imagehlp.h>
45#include <psapi.h>
46
086dc27f
CF
47struct option longopts[] =
48{
92b499ac
CV
49 {"help", no_argument, NULL, 'h'},
50 {"verbose", no_argument, NULL, 'v'},
51 {"version", no_argument, NULL, 'V'},
086dc27f
CF
52 {"data-relocs", no_argument, NULL, 'd'},
53 {"function-relocs", no_argument, NULL, 'r'},
54 {"unused", no_argument, NULL, 'u'},
55 {0, no_argument, NULL, 0}
56};
92b499ac 57const char *opts = "dhruvV";
086dc27f 58
2e13058e 59static int process_file (const wchar_t *);
962acfe5 60
086dc27f 61static int
92b499ac 62error (const char *fmt, ...)
086dc27f
CF
63{
64 va_list ap;
65 va_start (ap, fmt);
66 fprintf (stderr, "ldd: ");
67 vfprintf (stderr, fmt, ap);
68 fprintf (stderr, "\nTry `ldd --help' for more information.\n");
69 exit (1);
70}
71
e7fca6f8 72static void __attribute__ ((__noreturn__))
92b499ac
CV
73usage ()
74{
75 printf ("Usage: %s [OPTION]... FILE...\n\
76\n\
77Print shared library dependencies\n\
78\n\
79 -h, --help print this help and exit\n\
80 -V, --version print version information and exit\n\
81 -r, --function-relocs process data and function relocations\n\
82 (currently unimplemented)\n\
83 -u, --unused print unused direct dependencies\n\
84 (currently unimplemented)\n\
85 -v, --verbose print all information\n\
86 (currently unimplemented)\n",
87 program_invocation_short_name);
e7fca6f8 88 exit (0);
92b499ac
CV
89}
90
91static void
92print_version ()
93{
94 printf ("ldd (cygwin) %d.%d.%d\n"
1b23b30b
CF
95 "Print shared library dependencies\n"
96 "Copyright (C) 2009 - %s Chris Faylor\n"
97 "This is free software; see the source for copying conditions. There is NO\n"
92b499ac 98 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
1b23b30b
CF
99 CYGWIN_VERSION_DLL_MAJOR / 1000,
100 CYGWIN_VERSION_DLL_MAJOR % 1000,
101 CYGWIN_VERSION_DLL_MINOR,
102 strrchr (__DATE__, ' ') + 1);
92b499ac
CV
103}
104
086dc27f
CF
105#define print_errno_error_and_return(__fn) \
106 do {\
107 fprintf (stderr, "ldd: %s: %s\n", (__fn), strerror (errno));\
108 return 1;\
109 } while (0)
110
111#define set_errno_and_return(x) \
112 do {\
113 cygwin_internal (CW_SETERRNO, __FILE__, __LINE__ - 2);\
114 return (x);\
115 } while (0)
116
117
118static HANDLE hProcess;
119
c8fe6dc4
CF
120static struct filelist
121{
122 struct filelist *next;
123 char *name;
124} *head;
125
126static bool
127saw_file (char *name)
128{
129 filelist *p;
130
131 for (p = head; p; p = p->next)
132 if (strcasecmp (name, p->name) == 0)
133 return true;
134
135 p = (filelist *) malloc(sizeof (struct filelist));
136 p->next = head;
137 p->name = strdup (name);
138 head = p;
139 return false;
140}
141
2e13058e 142static wchar_t *
d5e4f55b
CF
143get_module_filename (HANDLE hp, HMODULE hm)
144{
145 size_t len;
2e13058e 146 wchar_t *buf = NULL;
d5e4f55b 147 DWORD res;
2e13058e 148 for (len = 1024; (res = GetModuleFileNameExW (hp, hm, (buf = (wchar_t *) realloc (buf, len * sizeof (wchar_t))), len)) == len; len += 1024)
d5e4f55b
CF
149 continue;
150 if (!res)
151 {
152 free (buf);
153 buf = NULL;
154 }
155 return buf;
156}
157
2e13058e
CF
158static wchar_t *
159load_dll (const wchar_t *fn)
d5e4f55b 160{
2e13058e 161 wchar_t *buf = get_module_filename (GetCurrentProcess (), NULL);
d5e4f55b
CF
162 if (!buf)
163 {
61522196
CV
164 printf ("ldd: GetModuleFileName returned an error %u\n",
165 (unsigned int) GetLastError ());
d5e4f55b
CF
166 exit (1); /* FIXME */
167 }
d5e4f55b 168
2e13058e
CF
169 wchar_t *newbuf = (wchar_t *) malloc ((sizeof (L"\"\" -- ") + wcslen (buf) + wcslen (fn)) * sizeof (wchar_t));
170 newbuf[0] = L'"';
171 wcscpy (newbuf + 1, buf);
172 wchar_t *p = wcsstr (newbuf, L"\\ldd");
173 if (!p)
174 {
175 printf ("ldd: can't parse my own filename \"%ls\"\n", buf);
176 exit (1);
177 }
178 p[3] = L'h';
179 wcscat (newbuf, L"\" -- ");
180 wcscat (newbuf, fn);
181 free (buf);
182 return newbuf;
183}
d5e4f55b 184
086dc27f 185static int
2e13058e 186start_process (const wchar_t *fn, bool& isdll)
086dc27f 187{
2e13058e 188 STARTUPINFOW si = {};
086dc27f
CF
189 PROCESS_INFORMATION pi;
190 si.cb = sizeof (si);
2e13058e 191 wchar_t *cmd;
abd9714a
YS
192 /* OCaml natdynlink plugins (.cmxs) cannot be handled by ldd because they
193 can only be loaded by flexdll_dlopen() */
194 if (wcslen (fn) < 4 || (wcscasecmp (wcschr (fn, L'\0') - 4, L".dll") != 0
195 && wcscasecmp (wcschr (fn, L'\0') - 4, L".oct") != 0
196 && wcscasecmp (wcschr (fn, L'\0') - 3, L".so") != 0))
086dc27f 197 {
2e13058e 198 cmd = wcsdup (fn);
d5e4f55b
CF
199 isdll = false;
200 }
201 else
202 {
203 cmd = load_dll (fn);
204 isdll = true;
205 }
2e13058e 206 if (CreateProcessW (NULL, cmd, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi))
d5e4f55b
CF
207 {
208 free (cmd);
086dc27f
CF
209 hProcess = pi.hProcess;
210 DebugSetProcessKillOnExit (true);
211 return 0;
212 }
213
d5e4f55b 214 free (cmd);
086dc27f
CF
215 set_errno_and_return (1);
216}
217
086dc27f
CF
218struct dlls
219 {
220 LPVOID lpBaseOfDll;
e3ca53d9 221 HANDLE hFile;
086dc27f
CF
222 struct dlls *next;
223 };
224
962acfe5
CF
225#define SLOP strlen (" (?)")
226char *
2e13058e 227tocyg (wchar_t *win_fn)
962acfe5 228{
2e13058e 229 ssize_t cwlen = cygwin_conv_path (CCP_WIN_W_TO_POSIX, win_fn, NULL, 0);
962acfe5
CF
230 char *fn;
231 if (cwlen <= 0)
2e13058e
CF
232 {
233 int len = wcstombs (NULL, win_fn, 0) + 1;
234 if ((fn = (char *) malloc (len)))
235 wcstombs (fn, win_fn, len);
236 }
962acfe5
CF
237 else
238 {
239 char *fn_cyg = (char *) malloc (cwlen + SLOP + 1);
2e13058e 240 if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, win_fn, fn_cyg, cwlen) == 0)
962acfe5
CF
241 fn = fn_cyg;
242 else
243 {
244 free (fn_cyg);
2e13058e
CF
245 int len = wcstombs (NULL, win_fn, 0);
246 fn = (char *) malloc (len + SLOP + 1);
247 wcstombs (fn, win_fn, len + SLOP + 1);
962acfe5
CF
248 }
249 }
250 return fn;
251}
252
2e13058e 253#define CYGWIN_DLL_LEN (wcslen (L"\\cygwin1.dll"))
086dc27f 254static int
2e13058e 255print_dlls (dlls *dll, const wchar_t *dllfn, const wchar_t *process_fn)
086dc27f 256{
c8fe6dc4 257 head = NULL; /* FIXME: memory leak */
086dc27f
CF
258 while ((dll = dll->next))
259 {
260 char *fn;
2e13058e 261 wchar_t *fullpath = get_module_filename (hProcess, (HMODULE) dll->lpBaseOfDll);
d5e4f55b 262 if (!fullpath)
e3ca53d9
MG
263 {
264 // if no path found yet, try getting it from an open handle to the DLL
6462a084
CV
265 wchar_t dllname[PATH_MAX];
266 if (GetFinalPathNameByHandleW (dll->hFile, dllname, PATH_MAX, 0))
e3ca53d9
MG
267 {
268 fn = tocyg (dllname);
269 saw_file (basename (fn));
270 }
271 else
272 fn = strdup ("???");
273 }
2e13058e
CF
274 else if (dllfn && wcscmp (fullpath, dllfn) == 0)
275 {
276 free (fullpath);
277 continue;
278 }
086dc27f 279 else
d5e4f55b 280 {
2e13058e 281 fn = tocyg (fullpath);
c8fe6dc4 282 saw_file (basename (fn));
d5e4f55b
CF
283 free (fullpath);
284 }
962acfe5 285 printf ("\t%s => %s (%p)\n", basename (fn), fn, dll->lpBaseOfDll);
086dc27f
CF
286 free (fn);
287 }
962acfe5
CF
288 if (process_fn)
289 return process_file (process_fn);
086dc27f
CF
290 return 0;
291}
292
293static int
294report (const char *in_fn, bool multiple)
295{
296 if (multiple)
297 printf ("%s:\n", in_fn);
298 char *fn = realpath (in_fn, NULL);
962acfe5
CF
299 if (!fn)
300 print_errno_error_and_return (in_fn);
301
2e13058e 302 ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_W, fn, NULL, 0);
962acfe5
CF
303 if (len <= 0)
304 print_errno_error_and_return (fn);
305
d5e4f55b 306 bool isdll;
16e1c98c
CV
307 wchar_t fn_win[len + 1];
308 if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, fn, fn_win, len))
962acfe5
CF
309 print_errno_error_and_return (fn);
310
d5e4f55b 311 if (!fn || start_process (fn_win, isdll))
086dc27f
CF
312 print_errno_error_and_return (in_fn);
313
314 DEBUG_EVENT ev;
315
086dc27f
CF
316 dlls dll_list = {};
317 dlls *dll_last = &dll_list;
2e13058e 318 const wchar_t *process_fn = NULL;
a9da3e4e
JT
319
320 int res = 0;
321
086dc27f
CF
322 while (1)
323 {
2e13058e
CF
324 bool exitnow = false;
325 DWORD cont = DBG_CONTINUE;
326 if (!WaitForDebugEvent (&ev, INFINITE))
327 break;
086dc27f
CF
328 switch (ev.dwDebugEventCode)
329 {
85db2173
CV
330 case CREATE_PROCESS_DEBUG_EVENT:
331 if (!isdll)
332 {
333 PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER) alloca (4096);
334 PIMAGE_NT_HEADERS nt_header;
335 PVOID entry_point;
336 static const unsigned char int3 = 0xcc;
337 SIZE_T bytes;
338
339 if (!ReadProcessMemory (hProcess,
340 ev.u.CreateProcessInfo.lpBaseOfImage,
341 dos_header, 4096, &bytes))
342 print_errno_error_and_return (in_fn);
343
344 nt_header = PIMAGE_NT_HEADERS (PBYTE (dos_header)
345 + dos_header->e_lfanew);
346 entry_point = (PVOID)
347 ((caddr_t) ev.u.CreateProcessInfo.lpBaseOfImage
348 + nt_header->OptionalHeader.AddressOfEntryPoint);
349
350 if (!WriteProcessMemory (hProcess, entry_point, &int3, 1, &bytes))
351 print_errno_error_and_return (in_fn);
352 }
353 break;
086dc27f 354 case LOAD_DLL_DEBUG_EVENT:
086dc27f
CF
355 dll_last->next = (dlls *) malloc (sizeof (dlls));
356 dll_last->next->lpBaseOfDll = ev.u.LoadDll.lpBaseOfDll;
e3ca53d9 357 dll_last->next->hFile = ev.u.LoadDll.hFile;
086dc27f
CF
358 dll_last->next->next = NULL;
359 dll_last = dll_last->next;
360 break;
361 case EXCEPTION_DEBUG_EVENT:
d5e4f55b
CF
362 switch (ev.u.Exception.ExceptionRecord.ExceptionCode)
363 {
23ad79d7
CV
364 case STATUS_ENTRYPOINT_NOT_FOUND:
365 /* A STATUS_ENTRYPOINT_NOT_FOUND might be encountered right after
366 loading all DLLs. We have to handle it here, otherwise ldd
367 runs into an endless loop. */
368 goto print_and_exit;
d5e4f55b
CF
369 case STATUS_DLL_NOT_FOUND:
370 process_fn = fn_win;
371 break;
372 case STATUS_BREAKPOINT:
373 if (!isdll)
9f54cead 374 TerminateProcess (hProcess, 0);
d5e4f55b
CF
375 break;
376 }
a9da3e4e
JT
377 if (ev.u.Exception.ExceptionRecord.ExceptionFlags &
378 EXCEPTION_NONCONTINUABLE) {
379 res = 1;
380 goto print_and_exit;
381 }
d5e4f55b
CF
382 break;
383 case EXIT_PROCESS_DEBUG_EVENT:
f4a1b6ae
JT
384 if (ev.u.ExitProcess.dwExitCode != 0)
385 process_fn = fn_win;
23ad79d7 386print_and_exit:
2e13058e
CF
387 print_dlls (&dll_list, isdll ? fn_win : NULL, process_fn);
388 exitnow = true;
086dc27f
CF
389 break;
390 default:
391 break;
392 }
2e13058e 393 if (!ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId, cont))
086dc27f
CF
394 {
395 cygwin_internal (CW_SETERRNO, __FILE__, __LINE__ - 2);
396 print_errno_error_and_return (in_fn);
397 }
2e13058e
CF
398 if (exitnow)
399 break;
086dc27f
CF
400 }
401
a9da3e4e 402 return res;
086dc27f
CF
403}
404
086dc27f
CF
405int
406main (int argc, char **argv)
407{
408 int optch;
73535010
CV
409
410 /* Use locale from environment. If not set or set to "C", use UTF-8. */
411 setlocale (LC_CTYPE, "");
412 if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
413 setlocale (LC_CTYPE, "en_US.UTF-8");
92b499ac 414 while ((optch = getopt_long (argc, argv, opts, longopts, NULL)) != -1)
086dc27f
CF
415 switch (optch)
416 {
417 case 'd':
418 case 'r':
419 case 'u':
92b499ac 420 error ("option not implemented `-%c'", optch);
086dc27f 421 exit (1);
92b499ac
CV
422 case 'h':
423 usage ();
92b499ac
CV
424 case 'V':
425 print_version ();
426 return 0;
427 default:
428 fprintf (stderr, "Try `%s --help' for more information.\n",
429 program_invocation_short_name);
430 return 1;
086dc27f
CF
431 }
432 argv += optind;
433 if (!*argv)
92b499ac 434 error ("missing file arguments");
086dc27f
CF
435
436 int ret = 0;
437 bool multiple = !!argv[1];
438 char *fn;
439 while ((fn = *argv++))
440 if (report (fn, multiple))
441 ret = 1;
442 exit (ret);
443}
962acfe5 444
962acfe5
CF
445static bool printing = false;
446
962acfe5
CF
447
448/* dump of import directory
449 section begins at pointer 'section base'
450 section RVA is 'section_rva'
451 import directory begins at pointer 'imp' */
452static int
453dump_import_directory (const void *const section_base,
454 const DWORD section_rva,
455 const IMAGE_IMPORT_DESCRIPTOR *imp)
456{
457 /* get memory address given the RVA */
458 #define adr(rva) ((const void*) ((char*) section_base+((DWORD) (rva))-section_rva))
459
460 /* continue until address inaccessible or there's no DLL name */
461 for (; !IsBadReadPtr (imp, sizeof (*imp)) && imp->Name; imp++)
462 {
2e13058e
CF
463 wchar_t full_path[PATH_MAX];
464 wchar_t *dummy;
962acfe5
CF
465 char *fn = (char *) adr (imp->Name);
466
467 if (saw_file (fn))
468 continue;
469
2e13058e
CF
470 int len = mbstowcs (NULL, fn, 0);
471 if (len <= 0)
1b23b30b 472 continue;
2e13058e
CF
473 wchar_t fnw[len + 1];
474 mbstowcs (fnw, fn, len + 1);
962acfe5
CF
475 /* output DLL's name */
476 char *print_fn;
2e13058e 477 if (!SearchPathW (NULL, fnw, NULL, PATH_MAX, full_path, &dummy))
962acfe5
CF
478 {
479 print_fn = strdup ("not found");
480 printing = true;
481 }
482 else if (!printing)
483 continue;
484 else
485 {
486 print_fn = tocyg (full_path);
487 strcat (print_fn, " (?)");
488 }
489
490 printf ("\t%s => %s\n", (char *) fn, print_fn);
491 free (print_fn);
492 }
493 #undef adr
494
495 return 0;
496}
497
498/* load a file in RAM (memory-mapped)
499 return pointer to loaded file
500 0 if no success */
501static void *
2e13058e 502map_file (const wchar_t *filename)
962acfe5
CF
503{
504 HANDLE hFile, hMapping;
505 void *basepointer;
2e13058e 506 if ((hFile = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
962acfe5
CF
507 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)
508 {
2e13058e 509 fprintf (stderr, "couldn't open %ls\n", filename);
962acfe5
CF
510 return 0;
511 }
512 if (!(hMapping = CreateFileMapping (hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
513 {
61522196
CV
514 fprintf (stderr, "CreateFileMapping failed with windows error %u\n",
515 (unsigned int) GetLastError ());
962acfe5
CF
516 CloseHandle (hFile);
517 return 0;
518 }
519 if (!(basepointer = MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, 0)))
520 {
61522196
CV
521 fprintf (stderr, "MapViewOfFile failed with windows error %u\n",
522 (unsigned int) GetLastError ());
962acfe5
CF
523 CloseHandle (hMapping);
524 CloseHandle (hFile);
525 return 0;
526 }
1b23b30b 527
962acfe5
CF
528 CloseHandle (hMapping);
529 CloseHandle (hFile);
530
531 return basepointer;
532}
533
534
535/* this will return a pointer immediatly behind the DOS-header
536 0 if error */
537static void *
538skip_dos_stub (const IMAGE_DOS_HEADER *dos_ptr)
539{
540 /* look there's enough space for a DOS-header */
541 if (IsBadReadPtr (dos_ptr, sizeof (*dos_ptr)))
542 {
543 fprintf (stderr, "not enough space for DOS-header\n");
544 return 0;
545 }
546
547 /* validate MZ */
548 if (dos_ptr->e_magic != IMAGE_DOS_SIGNATURE)
549 {
550 fprintf (stderr, "not a DOS-stub\n");
551 return 0;
552 }
553
554 /* ok, then, go get it */
555 return (char*) dos_ptr + dos_ptr->e_lfanew;
556}
557
558
559/* find the directory's section index given the RVA
560 Returns -1 if impossible */
561static int
562get_directory_index (const unsigned dir_rva,
563 const unsigned dir_length,
564 const int number_of_sections,
565 const IMAGE_SECTION_HEADER *sections)
566{
567 int sect;
568 for (sect = 0; sect < number_of_sections; sect++)
569 {
570 /* compare directory RVA to section RVA */
571 if (sections[sect].VirtualAddress <= dir_rva
572 && dir_rva < sections[sect].VirtualAddress+sections[sect].SizeOfRawData)
573 return sect;
574 }
575
576 return -1;
577}
578
579/* dump imports of a single file
580 Returns 0 if successful, !=0 else */
581static int
2e13058e 582process_file (const wchar_t *filename)
962acfe5
CF
583{
584 void *basepointer; /* Points to loaded PE file
585 * This is memory mapped stuff
586 */
587 int number_of_sections;
588 DWORD import_rva; /* RVA of import directory */
589 DWORD import_length; /* length of import directory */
590 int import_index; /* index of section with import directory */
591
592 /* ensure byte-alignment for struct tag_header */
593 #include <pshpack1.h>
594
595 const struct tag_header
596 {
597 DWORD signature;
598 IMAGE_FILE_HEADER file_head;
599 IMAGE_OPTIONAL_HEADER opt_head;
c8fe6dc4 600 IMAGE_SECTION_HEADER section_header[1]; /* an array of unknown length */
962acfe5
CF
601 } *header;
602
603 /* revert to regular alignment */
604 #include <poppack.h>
605
962acfe5
CF
606 printing = false;
607
608 /* first, load file */
609 basepointer = map_file (filename);
610 if (!basepointer)
611 {
612 puts ("cannot load file");
613 return 1;
614 }
615
616 /* get header pointer; validate a little bit */
c8fe6dc4 617 header = (tag_header *) skip_dos_stub ((IMAGE_DOS_HEADER *) basepointer);
962acfe5
CF
618 if (!header)
619 {
620 puts ("cannot skip DOS stub");
621 UnmapViewOfFile (basepointer);
622 return 2;
623 }
624
625 /* look there's enough space for PE headers */
626 if (IsBadReadPtr (header, sizeof (*header)))
627 {
628 puts ("not enough space for PE headers");
629 UnmapViewOfFile (basepointer);
630 return 3;
631 }
632
633 /* validate PE signature */
c8fe6dc4 634 if (header->signature != IMAGE_NT_SIGNATURE)
962acfe5
CF
635 {
636 puts ("not a PE file");
637 UnmapViewOfFile (basepointer);
638 return 4;
639 }
640
641 /* get number of sections */
642 number_of_sections = header->file_head.NumberOfSections;
643
644 /* check there are sections... */
c8fe6dc4 645 if (number_of_sections < 1)
962acfe5
CF
646 {
647 UnmapViewOfFile (basepointer);
648 return 5;
649 }
650
651 /* validate there's enough space for section headers */
652 if (IsBadReadPtr (header->section_header, number_of_sections*sizeof (IMAGE_SECTION_HEADER)))
653 {
654 puts ("not enough space for section headers");
655 UnmapViewOfFile (basepointer);
656 return 6;
657 }
658
659 /* get RVA and length of import directory */
660 import_rva = header->opt_head.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
661 import_length = header->opt_head.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
662
663 /* check there's stuff to care about */
664 if (!import_rva || !import_length)
665 {
666 UnmapViewOfFile (basepointer);
667 return 0; /* success! */
668 }
669
670 /* get import directory pointer */
671 import_index = get_directory_index (import_rva,import_length,number_of_sections,header->section_header);
672
673 /* check directory was found */
c8fe6dc4 674 if (import_index < 0)
962acfe5
CF
675 {
676 puts ("couldn't find import directory in sections");
677 UnmapViewOfFile (basepointer);
678 return 7;
679 }
680
c8fe6dc4
CF
681 /* The pointer to the start of the import directory's section */
682 const void *section_address = (char*) basepointer + header->section_header[import_index].PointerToRawData;
683 if (dump_import_directory (section_address,
684 header->section_header[import_index].VirtualAddress,
685 /* the last parameter is the pointer to the import directory:
686 section address + (import RVA - section RVA)
687 The difference is the offset of the import directory in the section */
688 (const IMAGE_IMPORT_DESCRIPTOR *) ((char *) section_address+import_rva-header->section_header[import_index].VirtualAddress)))
689 {
690 UnmapViewOfFile (basepointer);
691 return 8;
692 }
1b23b30b 693
962acfe5
CF
694 UnmapViewOfFile (basepointer);
695 return 0;
696}
This page took 0.245396 seconds and 5 git commands to generate.