Source code of Windows XP (NT5)
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.

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