VirtualBox

source: vbox/trunk/src/VBox/Runtime/tools/RTLdrCheckImports.cpp@ 73172

Last change on this file since 73172 was 73097, checked in by vboxsync, 6 years ago

*: Made RT_UOFFSETOF, RT_OFFSETOF, RT_UOFFSETOF_ADD and RT_OFFSETOF_ADD work like builtin_offsetof() and require compile time resolvable requests, adding RT_UOFFSETOF_DYN for the dynamic questions that can only be answered at runtime.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.1 KB
Line 
1/* $Id: RTLdrCheckImports.cpp 73097 2018-07-12 21:06:33Z vboxsync $ */
2/** @file
3 * IPRT - Module dependency checker.
4 */
5
6/*
7 * Copyright (C) 2010-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/ctype.h>
32#include <iprt/err.h>
33#include <iprt/getopt.h>
34#include <iprt/buildconfig.h>
35#include <iprt/file.h>
36#include <iprt/initterm.h>
37#include <iprt/ldr.h>
38#include <iprt/mem.h>
39#include <iprt/message.h>
40#include <iprt/path.h>
41#include <iprt/string.h>
42#include <iprt/stream.h>
43#include <iprt/vfs.h>
44
45
46/*********************************************************************************************************************************
47* Structures and Typedefs *
48*********************************************************************************************************************************/
49/**
50 * Import checker options.
51 */
52typedef struct RTCHECKIMPORTSOPTS
53{
54 /** Number of paths to search. */
55 size_t cPaths;
56 /** Search directories. */
57 char **papszPaths;
58 /** The loader architecture. */
59 RTLDRARCH enmLdrArch;
60 /** Verbosity level. */
61 unsigned cVerbosity;
62 /** Whether to also list orinals in the export listing. */
63 bool fListOrdinals;
64} RTCHECKIMPORTSOPTS;
65/** Pointer to the checker options. */
66typedef RTCHECKIMPORTSOPTS *PRTCHECKIMPORTSOPTS;
67/** Pointer to the const checker options. */
68typedef RTCHECKIMPORTSOPTS const *PCRTCHECKIMPORTSOPTS;
69
70
71/**
72 * Import module.
73 */
74typedef struct RTCHECKIMPORTMODULE
75{
76 /** The module. If NIL, then we've got a export list (papszExports). */
77 RTLDRMOD hLdrMod;
78 /** Number of export in the export list. (Zero if hLdrMod is valid.) */
79 size_t cExports;
80 /** Export list. (NULL if hLdrMod is valid.) */
81 char **papszExports;
82 /** The module name. */
83 char szModule[256];
84} RTCHECKIMPORTMODULE;
85/** Pointer to an import module. */
86typedef RTCHECKIMPORTMODULE *PRTCHECKIMPORTMODULE;
87
88
89/**
90 * Import checker state (for each image being checked).
91 */
92typedef struct RTCHECKIMPORTSTATE
93{
94 /** The image we're processing. */
95 const char *pszImage;
96 /** The image we're processing. */
97 PCRTCHECKIMPORTSOPTS pOpts;
98 /** Status code. */
99 int iRc;
100 /** Import hint. */
101 uint32_t iHint;
102 /** Number modules. */
103 uint32_t cImports;
104 /** Import modules. */
105 RTCHECKIMPORTMODULE aImports[RT_FLEXIBLE_ARRAY];
106} RTCHECKIMPORTSTATE;
107/** Pointer to the import checker state. */
108typedef RTCHECKIMPORTSTATE *PRTCHECKIMPORTSTATE;
109
110
111
112/**
113 * Looks up a symbol/ordinal in the given import module.
114 *
115 * @returns IPRT status code.
116 * @param pModule The import module.
117 * @param pszSymbol The symbol name (NULL if not used).
118 * @param uSymbol The ordinal (~0 if unused).
119 * @param pValue Where to return a fake address.
120 */
121static int QuerySymbolFromImportModule(PRTCHECKIMPORTMODULE pModule, const char *pszSymbol, unsigned uSymbol, PRTLDRADDR pValue)
122{
123 if (pModule->hLdrMod != NIL_RTLDRMOD)
124 return RTLdrGetSymbolEx(pModule->hLdrMod, NULL, _128M, uSymbol, pszSymbol, pValue);
125
126 /*
127 * Search the export list. Ordinal imports are stringified: #<ordinal>
128 */
129 char szOrdinal[32];
130 if (!pszSymbol)
131 {
132 RTStrPrintf(szOrdinal, sizeof(szOrdinal), "#%u", uSymbol);
133 pszSymbol = szOrdinal;
134 }
135
136 size_t i = pModule->cExports;
137 while (i-- > 0)
138 if (strcmp(pModule->papszExports[i], pszSymbol) == 0)
139 {
140 *pValue = _128M + i*4;
141 return VINF_SUCCESS;
142 }
143 return VERR_SYMBOL_NOT_FOUND;
144}
145
146
147/**
148 * @callback_method_impl{FNRTLDRIMPORT}
149 */
150static DECLCALLBACK(int) GetImportCallback(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol,
151 unsigned uSymbol, PRTLDRADDR pValue, void *pvUser)
152{
153 PRTCHECKIMPORTSTATE pState = (PRTCHECKIMPORTSTATE)pvUser;
154 int rc;
155 NOREF(hLdrMod);
156
157 /*
158 * If a module is given, lookup the symbol/ordinal there.
159 */
160 if (pszModule)
161 {
162 uint32_t iModule = pState->iHint;
163 if ( iModule > pState->cImports
164 || strcmp(pState->aImports[iModule].szModule, pszModule) != 0)
165 {
166 for (iModule = 0; iModule < pState->cImports; iModule++)
167 if (strcmp(pState->aImports[iModule].szModule, pszModule) == 0)
168 break;
169 if (iModule >= pState->cImports)
170 return RTMsgErrorRc(VERR_MODULE_NOT_FOUND, "%s: Failed to locate import module '%s'", pState->pszImage, pszModule);
171 pState->iHint = iModule;
172 }
173
174 rc = QuerySymbolFromImportModule(&pState->aImports[iModule], pszSymbol, uSymbol, pValue);
175 if (RT_SUCCESS(rc))
176 { /* likely */ }
177 else if (rc == VERR_LDR_FORWARDER)
178 rc= VINF_SUCCESS;
179 else
180 {
181 if (pszSymbol)
182 RTMsgError("%s: Missing import '%s' from '%s'!", pState->pszImage, pszSymbol, pszModule);
183 else
184 RTMsgError("%s: Missing import #%u from '%s'!", pState->pszImage, uSymbol, pszModule);
185 pState->iRc = rc;
186 rc = VINF_SUCCESS;
187 *pValue = _128M + _4K;
188 }
189 }
190 /*
191 * Otherwise we need to scan all modules.
192 */
193 else
194 {
195 Assert(pszSymbol);
196 uint32_t iModule = pState->iHint;
197 if (iModule < pState->cImports)
198 rc = QuerySymbolFromImportModule(&pState->aImports[iModule], pszSymbol, uSymbol, pValue);
199 else
200 rc = VERR_SYMBOL_NOT_FOUND;
201 if (rc == VERR_SYMBOL_NOT_FOUND)
202 {
203 for (iModule = 0; iModule < pState->cImports; iModule++)
204 {
205 rc = QuerySymbolFromImportModule(&pState->aImports[iModule], pszSymbol, uSymbol, pValue);
206 if (rc != VERR_SYMBOL_NOT_FOUND)
207 break;
208 }
209 }
210 if (RT_FAILURE(rc))
211 {
212 RTMsgError("%s: Missing import '%s'!", pState->pszImage, pszSymbol);
213 pState->iRc = rc;
214 rc = VINF_SUCCESS;
215 *pValue = _128M + _4K;
216 }
217 }
218 return rc;
219}
220
221
222/**
223 * Loads an imported module.
224 *
225 * @returns IPRT status code.
226 * @param pOpts The check program options.
227 * @param pModule The import module.
228 * @param pErrInfo Error buffer (to avoid wasting stack).
229 * @param pszImage The image we're processing (for error messages).
230 */
231static int LoadImportModule(PCRTCHECKIMPORTSOPTS pOpts, PRTCHECKIMPORTMODULE pModule, PRTERRINFO pErrInfo, const char *pszImage)
232
233{
234 /*
235 * Look for real DLLs.
236 */
237 for (uint32_t iPath = 0; iPath < pOpts->cPaths; iPath++)
238 {
239 char szPath[RTPATH_MAX];
240 int rc = RTPathJoin(szPath, sizeof(szPath), pOpts->papszPaths[iPath], pModule->szModule);
241 if (RT_SUCCESS(rc))
242 {
243 uint32_t offError;
244 RTFSOBJINFO ObjInfo;
245 rc = RTVfsChainQueryInfo(szPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK, &offError, pErrInfo);
246 if (RT_SUCCESS(rc))
247 {
248 if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
249 {
250 RTLDRMOD hLdrMod;
251 rc = RTLdrOpenVfsChain(szPath, RTLDR_O_FOR_DEBUG, pOpts->enmLdrArch, &hLdrMod, &offError, pErrInfo);
252 if (RT_SUCCESS(rc))
253 {
254 pModule->hLdrMod = hLdrMod;
255 if (pOpts->cVerbosity > 0)
256 RTMsgInfo("Import '%s' -> '%s'\n", pModule->szModule, szPath);
257 }
258 else if (RTErrInfoIsSet(pErrInfo))
259 RTMsgError("%s: Failed opening import image '%s': %Rrc - %s", pszImage, szPath, rc, pErrInfo->pszMsg);
260 else
261 RTMsgError("%s: Failed opening import image '%s': %Rrc", pszImage, szPath, rc);
262 return rc;
263 }
264 }
265 else if ( rc != VERR_PATH_NOT_FOUND
266 && rc != VERR_FILE_NOT_FOUND)
267 RTVfsChainMsgError("RTVfsChainQueryInfo", szPath, rc, offError, pErrInfo);
268
269 /*
270 * Check for export file.
271 */
272 RTStrCat(szPath, sizeof(szPath), ".exports");
273 RTVFSFILE hVfsFile;
274 rc = RTVfsChainOpenFile(szPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hVfsFile, &offError, pErrInfo);
275 if (RT_SUCCESS(rc))
276 {
277 /* Read it into a memory buffer. */
278 uint64_t cbFile;
279 rc = RTVfsFileGetSize(hVfsFile, &cbFile);
280 if (RT_SUCCESS(rc))
281 {
282 if (cbFile < _4M)
283 {
284 char *pszFile = (char *)RTMemAlloc((size_t)cbFile + 1);
285 if (pszFile)
286 {
287 rc = RTVfsFileRead(hVfsFile, pszFile, (size_t)cbFile, NULL);
288 if (RT_SUCCESS(rc))
289 {
290 pszFile[(size_t)cbFile] = '\0';
291 rc = RTStrValidateEncoding(pszFile);
292 if (RT_SUCCESS(rc))
293 {
294 /*
295 * Parse it.
296 */
297 size_t iLine = 1;
298 size_t off = 0;
299 while (off < cbFile)
300 {
301 size_t const offStartLine = off;
302
303 /* skip leading blanks */
304 while (RT_C_IS_BLANK(pszFile[off]))
305 off++;
306
307 char ch = pszFile[off];
308 if ( ch != ';' /* comment */
309 && !RT_C_IS_CNTRL(ch))
310 {
311 /* find length of symbol */
312 size_t const offSymbol = off;
313 while ( (ch = pszFile[off]) != '\0'
314 && !RT_C_IS_SPACE(ch))
315 off++;
316 size_t const cchSymbol = off - offSymbol;
317
318 /* add it. */
319 if ((pModule->cExports & 127) == 0)
320 {
321 void *pvNew = RTMemRealloc(pModule->papszExports,
322 (pModule->cExports + 128) * sizeof(char *));
323 if (!pvNew)
324 {
325 rc = RTMsgErrorRc(VERR_NO_MEMORY, "%s: %s:%u: out of memory!", pszImage, szPath, iLine);
326 break;
327 }
328 pModule->papszExports = (char **)pvNew;
329 }
330 pModule->papszExports[pModule->cExports] = RTStrDupN(&pszFile[offSymbol], cchSymbol);
331 if (pModule->papszExports[pModule->cExports])
332 pModule->cExports++;
333 else
334 {
335 rc = RTMsgErrorRc(VERR_NO_MEMORY, "%s: %s:%u: out of memory!", pszImage, szPath, iLine);
336 break;
337 }
338
339 /* check what comes next is a comment or end of line/file */
340 while (RT_C_IS_BLANK(pszFile[off]))
341 off++;
342 ch = pszFile[off];
343 if ( ch != '\0'
344 && ch != '\n'
345 && ch != '\r'
346 && ch != ';')
347 rc = RTMsgErrorRc(VERR_PARSE_ERROR, "%s: %s:%u: Unexpected text at position %u!",
348 pszImage, szPath, iLine, off - offStartLine);
349 }
350
351 /* advance to the end of the the line */
352 while ( (ch = pszFile[off]) != '\0'
353 && ch != '\n')
354 off++;
355 off++;
356 iLine++;
357 }
358
359 if (pOpts->cVerbosity > 0)
360 RTMsgInfo("Import '%s' -> '%s' (%u exports)\n",
361 pModule->szModule, szPath, pModule->cExports);
362 }
363 else
364 RTMsgError("%s: %s: Invalid UTF-8 encoding in export file: %Rrc", pszImage, szPath, rc);
365 }
366 RTMemFree(pszFile);
367 }
368 else
369 rc = RTMsgErrorRc(VERR_NO_MEMORY, "%s: %s: Out of memory reading export file (%#RX64 bytes)",
370 pszImage, szPath, cbFile + 1);
371 }
372 else
373 rc = RTMsgErrorRc(VERR_NO_MEMORY, "%s: %s: Export file is too big: %#RX64 bytes, max 4MiB",
374 pszImage, szPath, cbFile);
375 }
376 else
377 RTMsgError("%s: %s: RTVfsFileGetSize failed on export file: %Rrc", pszImage, szPath, rc);
378 RTVfsFileRelease(hVfsFile);
379 return rc;
380 }
381 else if ( rc != VERR_PATH_NOT_FOUND
382 && rc != VERR_FILE_NOT_FOUND)
383 RTVfsChainMsgError("RTVfsChainOpenFile", szPath, rc, offError, pErrInfo);
384 }
385 }
386
387 return RTMsgErrorRc(VERR_MODULE_NOT_FOUND, "%s: Import module '%s' was not found!", pszImage, pModule->szModule);
388}
389
390
391/**
392 * Checks the imports for the given image.
393 *
394 * @returns IPRT status code.
395 * @param pOpts The check program options.
396 * @param pszImage The image to check.
397 */
398static int rtCheckImportsForImage(PCRTCHECKIMPORTSOPTS pOpts, const char *pszImage)
399{
400 if (pOpts->cVerbosity > 0)
401 RTMsgInfo("Checking '%s'...\n", pszImage);
402
403 /*
404 * Open the image.
405 */
406 uint32_t offError;
407 RTERRINFOSTATIC ErrInfo;
408 RTLDRMOD hLdrMod;
409 int rc = RTLdrOpenVfsChain(pszImage, 0 /*fFlags*/, RTLDRARCH_WHATEVER, &hLdrMod, &offError, RTErrInfoInitStatic(&ErrInfo));
410 if (RT_FAILURE(rc))
411 {
412 if (RT_FAILURE(rc) && RTErrInfoIsSet(&ErrInfo.Core))
413 return RTMsgErrorRc(rc, "Failed opening image '%s': %Rrc - %s", pszImage, rc, ErrInfo.Core.pszMsg);
414 return RTMsgErrorRc(rc, "Failed opening image '%s': %Rrc", pszImage, rc);
415 }
416
417 /*
418 * Do the import modules first.
419 */
420 uint32_t cImports = 0;
421 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_IMPORT_COUNT, &cImports, sizeof(cImports));
422 if (RT_SUCCESS(rc))
423 {
424 RTCHECKIMPORTSTATE *pState = (RTCHECKIMPORTSTATE *)RTMemAllocZ(RT_UOFFSETOF_DYN(RTCHECKIMPORTSTATE, aImports[cImports + 1]));
425 if (pState)
426 {
427 pState->pszImage = pszImage;
428 pState->pOpts = pOpts;
429 pState->cImports = cImports;
430 for (uint32_t iImport = 0; iImport < cImports; iImport++)
431 pState->aImports[iImport].hLdrMod = NIL_RTLDRMOD;
432
433 for (uint32_t iImport = 0; iImport < cImports; iImport++)
434 {
435 *(uint32_t *)&pState->aImports[iImport].szModule[0] = iImport;
436 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_IMPORT_MODULE, pState->aImports[iImport].szModule,
437 sizeof(pState->aImports[iImport].szModule));
438 if (RT_FAILURE(rc))
439 {
440 RTMsgError("%s: Error querying import #%u: %Rrc", pszImage, iImport, rc);
441 break;
442 }
443 rc = LoadImportModule(pOpts, &pState->aImports[iImport], &ErrInfo.Core, pszImage);
444 if (RT_FAILURE(rc))
445 break;
446 }
447 if (RT_SUCCESS(rc))
448 {
449 /*
450 * Get the image bits, indirectly resolving imports.
451 */
452 size_t cbImage = RTLdrSize(hLdrMod);
453 void *pvImage = RTMemAllocZ(cbImage);
454 if (pvImage)
455 {
456 pState->iRc = VINF_SUCCESS;
457 rc = RTLdrGetBits(hLdrMod, pvImage, _4M, GetImportCallback, pState);
458 if (RT_SUCCESS(rc))
459 rc = pState->iRc;
460 else
461 RTMsgError("%s: RTLdrGetBits failed: %Rrc", pszImage, rc);
462
463 RTMemFree(pvImage);
464 }
465 else
466 rc = RTMsgErrorRc(VERR_NO_MEMORY, "%s: out of memory", pszImage);
467 }
468
469 for (uint32_t iImport = 0; iImport < cImports; iImport++)
470 if (pState->aImports[iImport].hLdrMod != NIL_RTLDRMOD)
471 {
472 RTLdrClose(pState->aImports[iImport].hLdrMod);
473
474 size_t i = pState->aImports[iImport].cExports;
475 while (i-- > 0)
476 RTStrFree(pState->aImports[iImport].papszExports[i]);
477 RTMemFree(pState->aImports[iImport].papszExports);
478 }
479 RTMemFree(pState);
480 }
481 else
482 rc = RTMsgErrorRc(VERR_NO_MEMORY, "%s: out of memory", pszImage);
483 }
484 else
485 RTMsgError("%s: Querying RTLDRPROP_IMPORT_COUNT failed: %Rrc", pszImage, rc);
486 RTLdrClose(hLdrMod);
487 return rc;
488}
489
490
491/**
492 * @callback_method_impl{FNRTLDRENUMSYMS}
493 */
494static DECLCALLBACK(int) PrintSymbolForExportList(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol,
495 RTLDRADDR Value, void *pvUser)
496{
497 if (pszSymbol)
498 RTPrintf("%s\n", pszSymbol);
499 if (uSymbol != ~(unsigned)0 && (!pszSymbol || ((PCRTCHECKIMPORTSOPTS)pvUser)->fListOrdinals))
500 RTPrintf("#%u\n", uSymbol);
501 RT_NOREF(hLdrMod, Value, pvUser);
502 return VINF_SUCCESS;
503}
504
505
506/**
507 * Produces the export list for the given image.
508 *
509 * @returns IPRT status code.
510 * @param pOpts The check program options.
511 * @param pszImage Path to the image.
512 */
513static int ProduceExportList(PCRTCHECKIMPORTSOPTS pOpts, const char *pszImage)
514{
515 /*
516 * Open the image.
517 */
518 uint32_t offError;
519 RTERRINFOSTATIC ErrInfo;
520 RTLDRMOD hLdrMod;
521 int rc = RTLdrOpenVfsChain(pszImage, RTLDR_O_FOR_DEBUG, RTLDRARCH_WHATEVER, &hLdrMod, &offError, RTErrInfoInitStatic(&ErrInfo));
522 if (RT_SUCCESS(rc))
523 {
524 /*
525 * Some info about the file.
526 */
527 RTPrintf(";\n"
528 "; Generated from: %s\n", pszImage);
529
530 RTFSOBJINFO ObjInfo;
531 rc = RTVfsChainQueryInfo(pszImage, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK, NULL, NULL);
532 if (RT_SUCCESS(rc))
533 RTPrintf("; Size file: %#RX64 (%RU64)\n", ObjInfo.cbObject, ObjInfo.cbObject);
534
535 switch (RTLdrGetFormat(hLdrMod))
536 {
537 case RTLDRFMT_AOUT: RTPrintf("; Format: a.out\n"); break;
538 case RTLDRFMT_ELF: RTPrintf("; Format: ELF\n"); break;
539 case RTLDRFMT_LX: RTPrintf("; Format: LX\n"); break;
540 case RTLDRFMT_MACHO: RTPrintf("; Format: Mach-O\n"); break;
541 case RTLDRFMT_PE: RTPrintf("; Format: PE\n"); break;
542 default: RTPrintf("; Format: %u\n", RTLdrGetFormat(hLdrMod)); break;
543
544 }
545
546 RTPrintf("; Size of image: %#x (%u)\n", RTLdrSize(hLdrMod), RTLdrSize(hLdrMod));
547
548 switch (RTLdrGetArch(hLdrMod))
549 {
550 case RTLDRARCH_AMD64: RTPrintf("; Architecture: AMD64\n"); break;
551 case RTLDRARCH_X86_32: RTPrintf("; Architecture: X86\n"); break;
552 default: RTPrintf("; Architecture: %u\n", RTLdrGetArch(hLdrMod)); break;
553 }
554
555 uint64_t uTimestamp;
556 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &uTimestamp, sizeof(uTimestamp));
557 if (RT_SUCCESS(rc))
558 {
559 RTTIMESPEC Timestamp;
560 char szTime[128];
561 RTTimeSpecToString(RTTimeSpecSetSeconds(&Timestamp, uTimestamp), szTime, sizeof(szTime));
562 char *pszEnd = strchr(szTime, '\0');
563 while (pszEnd[0] != '.')
564 pszEnd--;
565 *pszEnd = '\0';
566 RTPrintf("; Timestamp: %#RX64 - %s\n", uTimestamp, szTime);
567 }
568
569 RTUUID ImageUuid;
570 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_UUID, &ImageUuid, sizeof(ImageUuid));
571 if (RT_SUCCESS(rc))
572 RTPrintf("; UUID: %RTuuid\n", &ImageUuid);
573
574 RTPrintf(";\n");
575
576 /*
577 * The list of exports.
578 */
579 rc = RTLdrEnumSymbols(hLdrMod, 0 /*fFlags*/, NULL, _4M, PrintSymbolForExportList, (void *)pOpts);
580 if (RT_FAILURE(rc))
581 RTMsgError("%s: RTLdrEnumSymbols failed: %Rrc", pszImage, rc);
582
583 /* done */
584 RTLdrClose(hLdrMod);
585 }
586 else if (RTErrInfoIsSet(&ErrInfo.Core))
587 RTMsgError("Failed opening image '%s': %Rrc - %s", pszImage, rc, ErrInfo.Core.pszMsg);
588 else
589 RTMsgError("Failed opening image '%s': %Rrc", pszImage, rc);
590 return rc;
591}
592
593
594int main(int argc, char **argv)
595{
596 int rc = RTR3InitExe(argc, &argv, 0);
597 if (RT_FAILURE(rc))
598 return RTMsgInitFailure(rc);
599
600 RTCHECKIMPORTSOPTS Opts;
601 Opts.cPaths = 0;
602 Opts.papszPaths = NULL;
603 Opts.enmLdrArch = RTLDRARCH_WHATEVER;
604 Opts.cVerbosity = 1;
605 Opts.fListOrdinals = false;
606
607 static const RTGETOPTDEF s_aOptions[] =
608 {
609 { "--path", 'p', RTGETOPT_REQ_STRING },
610 { "--export", 'e', RTGETOPT_REQ_STRING },
611 { "--list-ordinals", 'O', RTGETOPT_REQ_NOTHING },
612 { "--quiet", 'q', RTGETOPT_REQ_NOTHING },
613 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
614 };
615 RTGETOPTSTATE State;
616 rc = RTGetOptInit(&State, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
617 AssertRCReturn(rc, RTEXITCODE_FAILURE);
618
619 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
620 RTGETOPTUNION ValueUnion;
621 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
622 {
623 switch (rc)
624 {
625 case 'p':
626 if ((Opts.cPaths % 16) == 0)
627 {
628 void *pvNew = RTMemRealloc(Opts.papszPaths, sizeof(Opts.papszPaths[0]) * (Opts.cPaths + 16));
629 AssertRCReturn(rc, RTEXITCODE_FAILURE);
630 Opts.papszPaths = (char **)pvNew;
631 }
632 Opts.papszPaths[Opts.cPaths] = RTStrDup(ValueUnion.psz);
633 AssertReturn(Opts.papszPaths[Opts.cPaths], RTEXITCODE_FAILURE);
634 Opts.cPaths++;
635 break;
636
637 case 'e':
638 rc = ProduceExportList(&Opts, ValueUnion.psz);
639 if (RT_FAILURE(rc))
640 rcExit = RTEXITCODE_FAILURE;
641 break;
642
643 case 'O':
644 Opts.fListOrdinals = true;
645 break;
646
647 case 'q':
648 Opts.cVerbosity = 0;
649 break;
650
651 case 'v':
652 Opts.cVerbosity = 0;
653 break;
654
655 case VINF_GETOPT_NOT_OPTION:
656 rc = rtCheckImportsForImage(&Opts, ValueUnion.psz);
657 if (RT_FAILURE(rc))
658 rcExit = RTEXITCODE_FAILURE;
659 break;
660
661 case 'h':
662 RTPrintf("Usage: RTCheckImports [-p|--path <dir>] [-v|--verbose] [-q|--quiet] <image [..]>\n"
663 " or: RTCheckImports -e <image>\n"
664 " or: RTCheckImports <-h|--help>\n"
665 " or: RTCheckImports <-V|--version>\n"
666 "Checks library imports. VFS chain syntax supported.\n"
667 "\n"
668 "Options:\n"
669 " -p, --path <dir>\n"
670 " Search the specified directory for imported modules or their export lists.\n"
671 " -e, --export <image>\n"
672 " Write export list for the file to stdout. (Redirect to a .export file.)\n"
673 " -O, --list-ordinals\n"
674 " Whether to list ordinals as well as names in the export list.\n"
675 " -q, --quiet\n"
676 " Quiet execution.\n"
677 " -v, --verbose\n"
678 " Increases verbosity.\n"
679 ""
680 );
681 return RTEXITCODE_SUCCESS;
682
683#ifndef IPRT_IN_BUILD_TOOL
684 case 'V':
685 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
686 return RTEXITCODE_SUCCESS;
687#endif
688
689 default:
690 return RTGetOptPrintError(rc, &ValueUnion);
691 }
692 }
693
694 return rcExit;
695}
696
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette