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