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