Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1040 lines
32 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. rebase.c
  5. Abstract:
  6. Source file for the REBASE utility that takes a group of image files and
  7. rebases them so they are packed as closely together in the virtual address
  8. space as possible.
  9. Author:
  10. Mark Lucovsky (markl) 30-Apr-1993
  11. Revision History:
  12. --*/
  13. #include <private.h>
  14. #define STANDALONE_REBASE
  15. #include <rebasei.c>
  16. #include <strsafe.h>
  17. #define ROUNDUP(x, y) ((x + (y-1)) & ~(y-1))
  18. VOID
  19. RemoveRelocations(
  20. PCHAR ImageName
  21. );
  22. #define REBASE_ERR 99
  23. #define REBASE_OK 0
  24. ULONG ReturnCode = REBASE_OK;
  25. #define ROUND_UP( Size, Amount ) (((ULONG)(Size) + ((Amount) - 1)) & ~((Amount) - 1))
  26. BOOL fVerbose;
  27. BOOL fQuiet;
  28. BOOL fGoingDown;
  29. BOOL fSumOnly;
  30. BOOL fRebaseSysfileOk;
  31. BOOL fShowAllBases;
  32. BOOL fCoffBaseIncExt;
  33. FILE *CoffBaseDotTxt;
  34. FILE *BaseAddrFile;
  35. FILE *RebaseLog;
  36. ULONG SplitFlags;
  37. BOOL fRemoveRelocs;
  38. BOOL fUpdateSymbolsOnly;
  39. LPSTR BaseAddrFileName;
  40. BOOL
  41. ProcessGroupList(
  42. LPSTR ImagesRoot,
  43. LPSTR GroupListFName,
  44. BOOL fReBase,
  45. BOOL fOverlay
  46. );
  47. BOOL
  48. FindInIgnoreList(
  49. LPSTR chName
  50. );
  51. ULONG64
  52. FindInBaseAddrFile(
  53. LPSTR Name,
  54. PULONG pulSize
  55. );
  56. VOID
  57. ReBaseFile(
  58. LPSTR pstrName,
  59. BOOL fReBase
  60. );
  61. VOID
  62. ParseSwitch(
  63. CHAR chSwitch,
  64. int *pArgc,
  65. char **pArgv[]
  66. );
  67. VOID
  68. ShowUsage(
  69. VOID
  70. );
  71. typedef struct _GROUPNODE {
  72. struct _GROUPNODE *pgnNext;
  73. PCHAR chName;
  74. } GROUPNODE, *PGROUPNODE;
  75. PGROUPNODE pgnIgnoreListHdr, pgnIgnoreListEnd;
  76. typedef BOOL (__stdcall *REBASEIMAGE64) (
  77. IN PSTR CurrentImageName,
  78. IN PSTR SymbolPath,
  79. IN BOOL fReBase, // TRUE if actually rebasing, false if only summing
  80. IN BOOL fRebaseSysfileOk, // TRUE is system images s/b rebased
  81. IN BOOL fGoingDown, // TRUE if the image s/b rebased below the given base
  82. IN ULONG CheckImageSize, // Max size allowed (0 if don't care)
  83. OUT ULONG *OldImageSize, // Returned from the header
  84. OUT ULONG64 *OldImageBase, // Returned from the header
  85. OUT ULONG *NewImageSize, // Image size rounded to next separation boundary
  86. IN OUT ULONG64 *NewImageBase, // (in) Desired new address.
  87. // (out) Next address (actual if going down)
  88. IN ULONG TimeStamp // new timestamp for image, if non-zero
  89. );
  90. REBASEIMAGE64 pReBaseImage64;
  91. UCHAR ImagesRoot[ MAX_PATH+1 ];
  92. PCHAR SymbolPath;
  93. UCHAR DebugFilePath[ MAX_PATH+1 ];
  94. ULONG64 OriginalImageBase;
  95. ULONG OriginalImageSize;
  96. ULONG64 NewImageBase;
  97. ULONG NewImageSize;
  98. ULONG64 InitialBase = 0;
  99. ULONG64 MinBase = (~((ULONG64)0));
  100. ULONG64 TotalSize;
  101. ULONG SizeAdjustment;
  102. int __cdecl
  103. main(
  104. int argc,
  105. char *argv[],
  106. char *envp[]
  107. )
  108. {
  109. char chChar, *pchChar;
  110. envp;
  111. _tzset();
  112. pgnIgnoreListHdr = (PGROUPNODE) malloc( sizeof ( GROUPNODE ) );
  113. if (!pgnIgnoreListHdr)
  114. return REBASE_ERR;
  115. pgnIgnoreListHdr->chName = NULL;
  116. pgnIgnoreListHdr->pgnNext = NULL;
  117. pgnIgnoreListEnd = pgnIgnoreListHdr;
  118. #ifdef STANDALONE_REBASE
  119. pReBaseImage64 = ReBaseImage64;
  120. #else
  121. pReBaseImage64 = (REBASEIMAGE64) GetProcAddress(GetModuleHandle("imagehlp.dll"), "ReBaseImage64");
  122. if (!pReBaseImage64) {
  123. puts("REBASE: Warning\n"
  124. "REBASE: Warning - unable to correctly rebase 64-bit images - update your imagehlp.dll\n"
  125. "REBASE: Warning");
  126. pReBaseImage64 = (REBASEIMAGE64) GetProcAddress(GetModuleHandle("imagehlp.dll"), "ReBaseImage");
  127. }
  128. #endif
  129. fVerbose = FALSE;
  130. fQuiet = FALSE;
  131. fGoingDown = FALSE;
  132. fSumOnly = FALSE;
  133. fRebaseSysfileOk = FALSE;
  134. fShowAllBases = FALSE;
  135. ImagesRoot[ 0 ] = '\0';
  136. if (argc <= 1) {
  137. ShowUsage();
  138. }
  139. while (--argc) {
  140. pchChar = *++argv;
  141. if (*pchChar == '/' || *pchChar == '-') {
  142. while (chChar = *++pchChar) {
  143. ParseSwitch( chChar, &argc, &argv );
  144. }
  145. }
  146. else {
  147. if (*pchChar == '@') {
  148. // Inline response file with a list of files to rebase.
  149. FILE *hFiles;
  150. int ScanRet;
  151. CHAR pchFileName[_MAX_PATH];
  152. BOOL JustFileNames=TRUE;
  153. pchChar++;
  154. if (*pchChar == '@') {
  155. JustFileNames=FALSE;
  156. pchChar++;
  157. }
  158. hFiles=fopen(pchChar, "rt");
  159. if (hFiles == NULL) {
  160. fprintf( stderr, "REBASE: fopen %s failed %d\n", pchChar, errno );
  161. ExitProcess( REBASE_ERR );
  162. }
  163. if (JustFileNames) {
  164. ScanRet = fscanf( hFiles, "%s", pchFileName);
  165. while (ScanRet && ScanRet != EOF) {
  166. if ( !FindInIgnoreList( pchFileName ) ) {
  167. ReBaseFile( pchFileName, TRUE );
  168. }
  169. ScanRet = fscanf( hFiles, "%s", pchFileName );
  170. }
  171. } else {
  172. ULONGLONG PreferedImageBase;
  173. ULONG MaxImageSize;
  174. fRebaseSysfileOk = TRUE;
  175. ScanRet = fscanf( hFiles, "%I64x %x %s", &PreferedImageBase, &MaxImageSize, pchFileName);
  176. while (ScanRet && ScanRet != EOF) {
  177. if (!FindInIgnoreList(pchFileName) ){
  178. InitialBase = NewImageBase = PreferedImageBase;
  179. ReBaseFile( pchFileName, TRUE );
  180. if ((NewImageSize != -1) && (NewImageSize > MaxImageSize)) {
  181. fprintf( stderr, "REBASE: Image: %s baseed at: %I64x exceeded Max size: %x (real size is %x)\n", pchFileName, PreferedImageBase, MaxImageSize, NewImageSize);
  182. }
  183. }
  184. ScanRet = fscanf( hFiles, "%I64x %x %s", &PreferedImageBase, &MaxImageSize, pchFileName );
  185. }
  186. }
  187. fclose(hFiles);
  188. } else {
  189. if ( !FindInIgnoreList( pchChar ) ) {
  190. ReBaseFile( pchChar, TRUE );
  191. }
  192. }
  193. }
  194. }
  195. if ( !fQuiet ) {
  196. if ( BaseAddrFile ) {
  197. InitialBase = MinBase;
  198. }
  199. if ( fGoingDown ) {
  200. TotalSize = InitialBase - NewImageBase;
  201. }
  202. else {
  203. TotalSize = NewImageBase - InitialBase;
  204. }
  205. fprintf( stdout, "\n" );
  206. fprintf( stdout, "REBASE: Total Size of mapping 0x%016I64x\n", TotalSize );
  207. fprintf( stdout, "REBASE: Range 0x%016I64x -0x%016I64x\n",
  208. min(NewImageBase, InitialBase), max(NewImageBase, InitialBase));
  209. if (RebaseLog) {
  210. fprintf( RebaseLog, "\nTotal Size of mapping 0x%016I64x\n", TotalSize );
  211. fprintf( RebaseLog, "Range 0x%016I64x -0x%016I64x\n\n",
  212. min(NewImageBase, InitialBase), max(NewImageBase, InitialBase));
  213. }
  214. }
  215. if (RebaseLog) {
  216. fclose(RebaseLog);
  217. }
  218. if (BaseAddrFile){
  219. fclose(BaseAddrFile);
  220. }
  221. if (CoffBaseDotTxt){
  222. fclose(CoffBaseDotTxt);
  223. }
  224. return ReturnCode;
  225. }
  226. VOID
  227. ShowUsage(
  228. VOID
  229. )
  230. {
  231. fputs( "usage: REBASE [switches]\n"
  232. " [-R image-root [-G filename] [-O filename] [-N filename]]\n"
  233. " image-names... \n"
  234. "\n"
  235. " One of -b and -i switches are mandatory.\n"
  236. "\n"
  237. " [-a] Does nothing\n"
  238. " [-b InitialBase] specify initial base address\n"
  239. " [-c coffbase_filename] generate coffbase.txt\n"
  240. " -C includes filename extensions, -c does not\n"
  241. " [-d] top down rebase\n"
  242. " [-e SizeAdjustment] specify extra size to allow for image growth\n"
  243. " [-f] Strip relocs after rebasing the image\n"
  244. " [-i coffbase_filename] get base addresses from coffbase_filename\n"
  245. " [-l logFilePath] write image bases to log file.\n"
  246. " [-p] Does nothing\n"
  247. " [-q] minimal output\n"
  248. " [-s] just sum image range\n"
  249. " [-u symbol_dir] Update debug info in .DBG along this path\n"
  250. " [-v] verbose output\n"
  251. " [-x symbol_dir] Same as -u\n"
  252. " [-z] allow system file rebasing\n"
  253. " [-?] display this message\n"
  254. "\n"
  255. " [-R image_root] set image root for use by -G, -O, -N\n"
  256. " [-G filename] group images together in address space\n"
  257. " [-O filename] overlay images in address space\n"
  258. " [-N filename] leave images at their origional address\n"
  259. " -G, -O, -N, may occur multiple times. File \"filename\"\n"
  260. " contains a list of files (relative to \"image-root\")\n"
  261. "\n"
  262. " 'image-names' can be either a file (foo.dll) or files (*.dll)\n"
  263. " or a file that lists other files (@files.txt).\n"
  264. " If you want to rebase to a fixed address (ala QFE)\n"
  265. " use the @@files.txt format where files.txt contains\n"
  266. " address/size combos in addition to the filename\n",
  267. stderr );
  268. exit( REBASE_ERR );
  269. }
  270. VOID
  271. ParseSwitch(
  272. CHAR chSwitch,
  273. int *pArgc,
  274. char **pArgv[]
  275. )
  276. {
  277. switch (toupper( chSwitch )) {
  278. case '?':
  279. ShowUsage();
  280. break;
  281. case 'A':
  282. break;
  283. case 'B':
  284. if (!--(*pArgc)) {
  285. ShowUsage();
  286. }
  287. (*pArgv)++;
  288. if (sscanf(**pArgv, "%I64x", &InitialBase) == 1) {
  289. NewImageBase = InitialBase;
  290. }
  291. break;
  292. case 'C':
  293. if (!--(*pArgc)) {
  294. ShowUsage();
  295. }
  296. (*pArgv)++;
  297. fCoffBaseIncExt = (chSwitch == 'C');
  298. CoffBaseDotTxt = fopen( *(*pArgv), "at" );
  299. if ( !CoffBaseDotTxt ) {
  300. fprintf( stderr, "REBASE: fopen %s failed %d\n", *(*pArgv), errno );
  301. ExitProcess( REBASE_ERR );
  302. }
  303. break;
  304. case 'D':
  305. fGoingDown = TRUE;
  306. break;
  307. case 'E':
  308. if (!--(*pArgc)) {
  309. ShowUsage();
  310. }
  311. (*pArgv)++;
  312. if (sscanf(**pArgv, "%x", &SizeAdjustment) != 1) {
  313. ShowUsage();
  314. }
  315. break;
  316. case 'F':
  317. fRemoveRelocs = TRUE;
  318. break;
  319. case 'G':
  320. case 'O':
  321. case 'N':
  322. if (!--(*pArgc)) {
  323. ShowUsage();
  324. }
  325. (*pArgv)++;
  326. if (!ImagesRoot[0]) {
  327. fprintf( stderr, "REBASE: -R must preceed -%c\n", chSwitch );
  328. exit( REBASE_ERR );
  329. }
  330. ProcessGroupList( (PCHAR) ImagesRoot,
  331. *(*pArgv),
  332. toupper(chSwitch) != 'N',
  333. toupper(chSwitch) == 'O');
  334. break;
  335. case 'I':
  336. if (!--(*pArgc)) {
  337. ShowUsage();
  338. }
  339. (*pArgv)++;
  340. BaseAddrFileName = *(*pArgv);
  341. BaseAddrFile = fopen( *(*pArgv), "rt" );
  342. if ( !BaseAddrFile ) {
  343. fprintf( stderr, "REBASE: fopen %s failed %d\n", *(*pArgv), errno );
  344. ExitProcess( REBASE_ERR );
  345. }
  346. break;
  347. case 'L':
  348. if (!--(*pArgc)) {
  349. ShowUsage();
  350. }
  351. (*pArgv)++;
  352. RebaseLog = fopen( *(*pArgv), "at" );
  353. if ( !RebaseLog ) {
  354. fprintf( stderr, "REBASE: fopen %s failed %d\n", *(*pArgv), errno );
  355. ExitProcess( REBASE_ERR );
  356. }
  357. break;
  358. case 'P':
  359. break;
  360. case 'Q':
  361. fQuiet = TRUE;
  362. break;
  363. case 'R':
  364. if (!--(*pArgc)) {
  365. ShowUsage();
  366. }
  367. (*pArgv)++;
  368. StringCchCopy((PCHAR)ImagesRoot, MAX_PATH, *(*pArgv) );
  369. break;
  370. case 'S':
  371. fprintf(stdout,"\n");
  372. fSumOnly = TRUE;
  373. break;
  374. case 'U':
  375. case 'X':
  376. if (!--(*pArgc)) {
  377. ShowUsage();
  378. }
  379. (*pArgv)++;
  380. fUpdateSymbolsOnly = TRUE;
  381. SymbolPath = **pArgv;
  382. break;
  383. case 'V':
  384. fVerbose = TRUE;
  385. break;
  386. case 'Z':
  387. fRebaseSysfileOk = TRUE;
  388. break;
  389. default:
  390. fprintf( stderr, "REBASE: Invalid switch - /%c\n", chSwitch );
  391. ShowUsage();
  392. break;
  393. }
  394. }
  395. BOOL
  396. ProcessGroupList(
  397. LPSTR ImagesRoot,
  398. LPSTR GroupListFName,
  399. BOOL fReBase,
  400. BOOL fOverlay
  401. )
  402. {
  403. PGROUPNODE pgn;
  404. FILE *GroupList;
  405. CHAR chName[MAX_PATH+1];
  406. int ateof;
  407. ULONG64 SavedImageBase;
  408. ULONG MaxImageSize=0;
  409. DWORD dw;
  410. CHAR Buffer[ MAX_PATH+1 ];
  411. LPSTR FilePart;
  412. if (RebaseLog) {
  413. fprintf( RebaseLog, "*** %s\n", GroupListFName );
  414. }
  415. GroupList = fopen( GroupListFName, "rt" );
  416. if ( !GroupList ) {
  417. fprintf( stderr, "REBASE: fopen %s failed %d\n", GroupListFName, errno );
  418. ExitProcess( REBASE_ERR );
  419. }
  420. ateof = fscanf( GroupList, "%s", chName );
  421. SavedImageBase = NewImageBase;
  422. while ( ateof && ateof != EOF ) {
  423. dw = SearchPath( ImagesRoot, chName, NULL, sizeof(Buffer), Buffer, &FilePart );
  424. if ( dw == 0 || dw > sizeof( Buffer ) ) {
  425. if (!fQuiet) {
  426. fprintf( stderr, "REBASE: Could Not Find %s\\%s\n", ImagesRoot, chName );
  427. }
  428. }
  429. else {
  430. _strlwr( Buffer ); // Lowercase for consistency when displayed.
  431. if (fReBase) {
  432. if (!FindInIgnoreList(Buffer)) {
  433. // If the file hasn't already been listed in another group (either to ignore
  434. // or to group/overlay somewhere else), rebase it.
  435. ReBaseFile( Buffer, TRUE );
  436. }
  437. if ( fOverlay ) {
  438. if ( MaxImageSize < NewImageSize ) {
  439. MaxImageSize = NewImageSize;
  440. }
  441. NewImageBase = SavedImageBase;
  442. }
  443. }
  444. pgn = (PGROUPNODE) malloc( sizeof( GROUPNODE ) );
  445. if ( NULL == pgn ) {
  446. fprintf( stderr, "REBASE: *** malloc failed.\n" );
  447. ExitProcess( REBASE_ERR );
  448. }
  449. pgn->chName = _strdup( Buffer );
  450. if ( NULL == pgn->chName ) {
  451. fprintf( stderr, "REBASE: *** strdup failed (%s).\n", Buffer );
  452. ExitProcess( REBASE_ERR );
  453. }
  454. pgn->pgnNext = NULL;
  455. pgnIgnoreListEnd->pgnNext = pgn;
  456. pgnIgnoreListEnd = pgn;
  457. }
  458. ateof = fscanf( GroupList, "%s", chName );
  459. }
  460. fclose( GroupList );
  461. if ( fOverlay ) {
  462. if ( fGoingDown ) {
  463. NewImageBase -= ROUND_UP( MaxImageSize, IMAGE_SEPARATION );
  464. }
  465. else {
  466. NewImageBase += ROUND_UP( MaxImageSize, IMAGE_SEPARATION );
  467. }
  468. }
  469. if (RebaseLog) {
  470. fprintf( RebaseLog, "\n" );
  471. }
  472. return TRUE;
  473. }
  474. BOOL
  475. FindInIgnoreList(
  476. LPSTR chName
  477. )
  478. {
  479. PGROUPNODE pgn;
  480. DWORD dw;
  481. CHAR Buffer[ MAX_PATH+1 ];
  482. LPSTR FilePart;
  483. dw = GetFullPathName( chName, sizeof(Buffer), Buffer, &FilePart );
  484. if ( dw == 0 || dw > sizeof( Buffer ) ) {
  485. fprintf( stderr, "REBASE: *** GetFullPathName failed (%s).\n", chName );
  486. ExitProcess( REBASE_ERR );
  487. }
  488. for (pgn = pgnIgnoreListHdr->pgnNext;
  489. pgn != NULL;
  490. pgn = pgn->pgnNext) {
  491. if (!_stricmp( Buffer, pgn->chName ) ) {
  492. return TRUE;
  493. }
  494. }
  495. return FALSE;
  496. }
  497. /////////////////////////////////////////////////////////////////////////////
  498. /*
  499. ******************************************************************************
  500. On a Hydra System, we don't want imaghlp.dll to load user32.dll since it
  501. prevents CSRSS from exiting when running a under a debugger.
  502. The following function has been copied from user32.dll so that we don't
  503. link to user32.dll.
  504. ******************************************************************************
  505. */
  506. /////////////////////////////////////////////////////////////////////////////
  507. /////////////////////////////////////////////////////////////////////////////
  508. VOID
  509. ReBaseFile(
  510. LPSTR CurrentImageName,
  511. BOOL fReBase
  512. )
  513. {
  514. DWORD dw;
  515. CHAR Buffer[ MAX_PATH+1 ];
  516. CHAR Buffer2[ MAX_PATH+1 ];
  517. LPSTR FilePart = NULL;
  518. LPSTR LocalSymbolPath;
  519. ULONG ThisImageExpectedSize = 0;
  520. ULONG64 ThisImageRequestedBase = NewImageBase;
  521. ULONG TimeStamp;
  522. static char LastName = '\0';
  523. static ULONG LastTimeStamp = 0;
  524. if ( !InitialBase && !BaseAddrFile ) {
  525. fprintf( stderr, "REBASE: -b switch must specify a non-zero base --or--\n" );
  526. fprintf( stderr, " -i must specify a filename\n" );
  527. exit( REBASE_ERR );
  528. }
  529. if ( BaseAddrFile && ( InitialBase || fGoingDown || CoffBaseDotTxt ) ) {
  530. fprintf( stderr, "REBASE: -i is incompatible with -b, -d, and -c\n" );
  531. exit( REBASE_ERR );
  532. }
  533. dw = GetFullPathName( CurrentImageName, sizeof(Buffer), Buffer, &FilePart );
  534. if ( dw == 0 || dw > sizeof(Buffer) || !FilePart ) {
  535. FilePart = CurrentImageName;
  536. }
  537. _strlwr( FilePart ); // Lowercase for consistency when displayed.
  538. if ( BaseAddrFile && !(NewImageBase = ThisImageRequestedBase = FindInBaseAddrFile( FilePart, &ThisImageExpectedSize )) ) {
  539. fprintf( stdout, "REBASE: %-16s Not listed in %s\n", FilePart, BaseAddrFileName );
  540. }
  541. if (fUpdateSymbolsOnly) {
  542. // On update, the symbol path is a semi-colon delimited path. Find the one we want and
  543. // then fix the path for RebaseImage.
  544. HANDLE hDebugFile;
  545. CHAR Drive[_MAX_DRIVE];
  546. CHAR Dir[_MAX_DIR];
  547. PCHAR s;
  548. hDebugFile = FindDebugInfoFile(CurrentImageName, SymbolPath, DebugFilePath);
  549. if ( hDebugFile ) {
  550. CloseHandle(hDebugFile);
  551. _splitpath(DebugFilePath, Drive, Dir, NULL, NULL);
  552. _makepath(Buffer2, Drive, Dir, NULL, NULL);
  553. s = Buffer2 + strlen(Buffer2);
  554. s = CharPrev(Buffer2, s);
  555. if (*s == '\\') {
  556. *s = '\0';
  557. }
  558. LocalSymbolPath = Buffer2;
  559. } else {
  560. LocalSymbolPath = NULL;
  561. }
  562. } else {
  563. LocalSymbolPath = SymbolPath;
  564. }
  565. NewImageSize = (ULONG) -1; // Hack so we can tell when system images are skipped.
  566. time( (time_t *) &TimeStamp );
  567. // Ensure all images with the same first letter have unique timestamps.
  568. if (!LastTimeStamp)
  569. LastTimeStamp = TimeStamp;
  570. if (LastName == *FilePart) {
  571. TimeStamp = LastTimeStamp++;
  572. } else {
  573. LastTimeStamp = TimeStamp;
  574. LastName = *FilePart;
  575. }
  576. if (SizeAdjustment && fGoingDown && !fSumOnly && fReBase) {
  577. if ((*pReBaseImage64)( CurrentImageName,
  578. (PCHAR) LocalSymbolPath,
  579. FALSE,
  580. fRebaseSysfileOk,
  581. TRUE,
  582. ThisImageExpectedSize,
  583. &OriginalImageSize,
  584. &OriginalImageBase,
  585. &NewImageSize,
  586. &ThisImageRequestedBase,
  587. TimeStamp ) ) {
  588. if (NewImageSize != (ULONG) -1) {
  589. if ((OriginalImageSize + SizeAdjustment) > NewImageSize) {
  590. // If we were to add SizeAdjustment to the image (say as a ServicePack or QFE fix), we'd blow
  591. // out our space. Make room so this isn't necessary.
  592. NewImageBase -= IMAGE_SEPARATION;
  593. ThisImageRequestedBase = NewImageBase;
  594. }
  595. }
  596. }
  597. }
  598. if (!(*pReBaseImage64)( CurrentImageName,
  599. (PCHAR) LocalSymbolPath,
  600. fReBase && !fSumOnly,
  601. fRebaseSysfileOk,
  602. fGoingDown,
  603. ThisImageExpectedSize,
  604. &OriginalImageSize,
  605. &OriginalImageBase,
  606. &NewImageSize,
  607. &ThisImageRequestedBase,
  608. TimeStamp ) ) {
  609. if (ThisImageRequestedBase == 0) {
  610. fprintf(stderr,
  611. "REBASE: %-16s ***Grew too large (Size=0x%x; ExpectedSize=0x%x)\n",
  612. FilePart,
  613. OriginalImageSize,
  614. ThisImageExpectedSize);
  615. } else {
  616. switch(GetLastError()) {
  617. case ERROR_BAD_EXE_FORMAT:
  618. if (fVerbose) {
  619. fprintf( stderr,
  620. "REBASE: %-16s DOS or OS/2 image ignored\n",
  621. FilePart );
  622. }
  623. break;
  624. case ERROR_INVALID_ADDRESS:
  625. fprintf( stderr,
  626. "REBASE: %-16s Rebase failed. Relocations are missing or new address is invalid\n",
  627. FilePart );
  628. if (RebaseLog) {
  629. fprintf( RebaseLog,
  630. "%16s based at 0x%016I64x (size 0x%08x) Unable to rebase. (missing relocations or new address is invalid)\n",
  631. FilePart,
  632. OriginalImageBase,
  633. OriginalImageSize);
  634. }
  635. break;
  636. case ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY:
  637. if (fVerbose) {
  638. fprintf( stderr,
  639. "REBASE: %-16s Rebase failed. Signed images can not be rebased.\n",
  640. FilePart );
  641. }
  642. break;
  643. case ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY:
  644. if (fVerbose) {
  645. fprintf( stderr,
  646. "REBASE: %-16s Rebase failed. Strong signed images can not be rebased.\n",
  647. FilePart );
  648. }
  649. break;
  650. default:
  651. fprintf( stderr,
  652. "REBASE: *** RelocateImage failed (%s). Image may be corrupted\n",
  653. FilePart );
  654. break;
  655. }
  656. }
  657. ReturnCode = REBASE_ERR;
  658. return;
  659. } else {
  660. if (GetLastError() == ERROR_INVALID_DATA) {
  661. fprintf(stderr, "REBASE: Warning: DBG checksum did not match image.\n");
  662. }
  663. }
  664. // Keep track of the lowest base address.
  665. if (MinBase > NewImageBase) {
  666. MinBase = NewImageBase;
  667. }
  668. if ( fSumOnly || !fReBase ) {
  669. if (!fQuiet) {
  670. fprintf( stdout,
  671. "REBASE: %16s mapped at %016I64x (size 0x%08x)\n",
  672. FilePart,
  673. OriginalImageBase,
  674. OriginalImageSize);
  675. }
  676. } else {
  677. if (!fGoingDown && SizeAdjustment && (NewImageSize != (ULONG) -1)) {
  678. if ((OriginalImageSize + SizeAdjustment) > NewImageSize) {
  679. // If we were to add SizeAdjustment to the image (say as a ServicePack or QFE fix), we'd blow
  680. // out our space. Make room so this isn't necessary.
  681. ThisImageRequestedBase += IMAGE_SEPARATION;
  682. }
  683. }
  684. if (RebaseLog) {
  685. fprintf( RebaseLog,
  686. "%16s rebased to 0x%016I64x (size 0x%08x)\n",
  687. FilePart,
  688. fGoingDown ? ThisImageRequestedBase : NewImageBase,
  689. NewImageSize);
  690. }
  691. if ((NewImageSize != (ULONG) -1) &&
  692. (OriginalImageBase != (fGoingDown ? ThisImageRequestedBase : NewImageBase)) &&
  693. ( fVerbose || fQuiet )
  694. ) {
  695. if ( fVerbose ) {
  696. fprintf( stdout,
  697. "REBASE: %16s initial base at 0x%016I64x (size 0x%08x)\n",
  698. FilePart,
  699. OriginalImageBase,
  700. OriginalImageSize);
  701. }
  702. fprintf( stdout,
  703. "REBASE: %16s rebased to 0x%016I64x (size 0x%08x)\n",
  704. FilePart,
  705. fGoingDown ? ThisImageRequestedBase : NewImageBase,
  706. NewImageSize);
  707. if ( fVerbose && fUpdateSymbolsOnly && DebugFilePath[0]) {
  708. char szExt[_MAX_EXT];
  709. _splitpath(DebugFilePath, NULL, NULL, NULL, szExt);
  710. if (_stricmp(szExt, ".pdb")) {
  711. fprintf( stdout, "REBASE: %16s updated image base in %s\n", FilePart, DebugFilePath );
  712. }
  713. }
  714. }
  715. if (fRemoveRelocs) {
  716. RemoveRelocations(CurrentImageName);
  717. }
  718. }
  719. if ( CoffBaseDotTxt ) {
  720. if ( !fCoffBaseIncExt ) {
  721. char *n;
  722. if ( n = strrchr(FilePart,'.') ) {
  723. *n = '\0';
  724. }
  725. }
  726. fprintf( CoffBaseDotTxt,
  727. "%-16s 0x%016I64x 0x%08x\n",
  728. FilePart,
  729. fSumOnly ? OriginalImageBase : (fGoingDown ? ThisImageRequestedBase : NewImageBase),
  730. NewImageSize);
  731. }
  732. NewImageBase = ThisImageRequestedBase; // Set up the next one...
  733. }
  734. ULONG64
  735. FindInBaseAddrFile(
  736. LPSTR Name,
  737. PULONG pulSize
  738. )
  739. {
  740. struct {
  741. CHAR Name[MAX_PATH+1];
  742. ULONG64 Base;
  743. ULONG Size;
  744. } BAFileEntry;
  745. CHAR NameNoExt[MAX_PATH+1];
  746. // PCHAR pchExt;
  747. int ateof;
  748. StringCchCopy(NameNoExt, MAX_PATH, Name);
  749. // if (pchExt = strrchr(NameNoExt,'.')) {
  750. // *pchExt = '\0';
  751. // }
  752. if (fseek(BaseAddrFile, 0, SEEK_SET)) {
  753. return 0;
  754. }
  755. ateof = fscanf(BaseAddrFile,"%s %I64x %x",BAFileEntry.Name,&BAFileEntry.Base,&BAFileEntry.Size);
  756. while ( ateof && ateof != EOF ) {
  757. if ( !_stricmp(NameNoExt,BAFileEntry.Name) ) {
  758. *pulSize = BAFileEntry.Size;
  759. return BAFileEntry.Base;
  760. }
  761. ateof = fscanf(BaseAddrFile,"%s %I64x %x",BAFileEntry.Name,&BAFileEntry.Base,&BAFileEntry.Size);
  762. }
  763. *pulSize = 0;
  764. return 0;
  765. }
  766. VOID
  767. RemoveRelocations(
  768. PCHAR ImageName
  769. )
  770. {
  771. // UnSafe...
  772. LOADED_IMAGE li;
  773. IMAGE_SECTION_HEADER RelocSectionHdr, *Section, *pRelocSecHdr;
  774. PIMAGE_DEBUG_DIRECTORY DebugDirectory;
  775. ULONG DebugDirectorySize, i, RelocSecNum;
  776. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  777. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  778. PIMAGE_FILE_HEADER FileHeader;
  779. if (!MapAndLoad(ImageName, NULL, &li, FALSE, FALSE)) {
  780. return;
  781. }
  782. FileHeader = &li.FileHeader->FileHeader;
  783. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)li.FileHeader, &OptionalHeader32, &OptionalHeader64);
  784. if (!OptionalHeader32 && !OptionalHeader64)
  785. return;
  786. // See if the image has already been stripped or there are no relocs.
  787. if ((FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) ||
  788. (!OPTIONALHEADER(DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size))) {
  789. UnMapAndLoad(&li);
  790. return;
  791. }
  792. for (Section = li.Sections, i = 0; i < li.NumberOfSections; Section++, i++) {
  793. if (Section->PointerToRawData != 0) {
  794. if (!_stricmp( (char *) Section->Name, ".reloc" )) {
  795. RelocSectionHdr = *Section;
  796. pRelocSecHdr = Section;
  797. RelocSecNum = i + 1;
  798. }
  799. }
  800. }
  801. RelocSectionHdr.Misc.VirtualSize = ROUNDUP(RelocSectionHdr.Misc.VirtualSize, OPTIONALHEADER(SectionAlignment));
  802. RelocSectionHdr.SizeOfRawData = ROUNDUP(RelocSectionHdr.SizeOfRawData, OPTIONALHEADER(FileAlignment));
  803. if (RelocSecNum != li.NumberOfSections) {
  804. // Move everything else up and fixup old addresses.
  805. for (i = RelocSecNum - 1, Section = pRelocSecHdr;i < li.NumberOfSections - 1; Section++, i++) {
  806. *Section = *(Section + 1);
  807. Section->VirtualAddress -= RelocSectionHdr.Misc.VirtualSize;
  808. Section->PointerToRawData -= RelocSectionHdr.SizeOfRawData;
  809. }
  810. }
  811. // Zero out the last one.
  812. RtlZeroMemory(Section, sizeof(IMAGE_SECTION_HEADER));
  813. // Reduce the section count.
  814. FileHeader->NumberOfSections--;
  815. // Set the strip bit in the header
  816. FileHeader->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
  817. // If there's a pointer to the coff symbol table, move it back.
  818. if (FileHeader->PointerToSymbolTable) {
  819. FileHeader->PointerToSymbolTable -= RelocSectionHdr.SizeOfRawData;
  820. }
  821. // Clear out the base reloc entry in the data dir.
  822. OPTIONALHEADER_LV(DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) = 0;
  823. OPTIONALHEADER_LV(DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) = 0;
  824. // Reduce the Init Data size.
  825. OPTIONALHEADER_LV(SizeOfInitializedData) -= RelocSectionHdr.Misc.VirtualSize;
  826. // Reduce the image size.
  827. OPTIONALHEADER_LV(SizeOfImage) -=
  828. ((RelocSectionHdr.SizeOfRawData +
  829. (OPTIONALHEADER(SectionAlignment) - 1)
  830. ) & ~(OPTIONALHEADER(SectionAlignment) - 1));
  831. // Move the debug info up (if there is any).
  832. DebugDirectory = (PIMAGE_DEBUG_DIRECTORY)
  833. ImageDirectoryEntryToData( li.MappedAddress,
  834. FALSE,
  835. IMAGE_DIRECTORY_ENTRY_DEBUG,
  836. &DebugDirectorySize
  837. );
  838. if (DebugDirectoryIsUseful(DebugDirectory, DebugDirectorySize)) {
  839. for (i = 0; i < (DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY)); i++) {
  840. RtlMoveMemory(li.MappedAddress + DebugDirectory->PointerToRawData - RelocSectionHdr.SizeOfRawData,
  841. li.MappedAddress + DebugDirectory->PointerToRawData,
  842. DebugDirectory->SizeOfData);
  843. DebugDirectory->PointerToRawData -= RelocSectionHdr.SizeOfRawData;
  844. if (DebugDirectory->AddressOfRawData) {
  845. DebugDirectory->AddressOfRawData -= RelocSectionHdr.Misc.VirtualSize;
  846. }
  847. DebugDirectory++;
  848. }
  849. }
  850. // Truncate the image size
  851. li.SizeOfImage -= RelocSectionHdr.SizeOfRawData;
  852. // And we're done.
  853. UnMapAndLoad(&li);
  854. }
  855. #define STANDALONE_MAP
  856. #include <mapi.c>