|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
rebase.c
Abstract:
Source file for the REBASE utility that takes a group of image files and rebases them so they are packed as closely together in the virtual address space as possible.
Author:
Mark Lucovsky (markl) 30-Apr-1993
Revision History:
--*/
#include <private.h>
#define ROUNDUP(x, y) ((x + (y-1)) & ~(y-1))
VOID RemoveRelocations( PCHAR ImageName );
#define REBASE_ERR 99
#define REBASE_OK 0
ULONG ReturnCode = REBASE_OK;
#define ROUND_UP( Size, Amount ) (((ULONG)(Size) + ((Amount) - 1)) & ~((Amount) - 1))
BOOL fVerbose; BOOL fQuiet; BOOL fGoingDown; BOOL fSumOnly; BOOL fRebaseSysfileOk; BOOL fShowAllBases; BOOL fCoffBaseIncExt; FILE *CoffBaseDotTxt; FILE *BaseAddrFile; FILE *RebaseLog; ULONG SplitFlags; BOOL fRemoveRelocs; BOOL fUpdateSymbolsOnly;
LPSTR BaseAddrFileName;
BOOL ProcessGroupList( LPSTR ImagesRoot, LPSTR GroupListFName, BOOL fReBase, BOOL fOverlay );
BOOL FindInIgnoreList( LPSTR chName );
ULONG64 FindInBaseAddrFile( LPSTR Name, PULONG pulSize );
VOID ReBaseFile( LPSTR pstrName, BOOL fReBase );
VOID ParseSwitch( CHAR chSwitch, int *pArgc, char **pArgv[] );
VOID ShowUsage( VOID );
typedef struct _GROUPNODE { struct _GROUPNODE *pgnNext; PCHAR chName; } GROUPNODE, *PGROUPNODE;
PGROUPNODE pgnIgnoreListHdr, pgnIgnoreListEnd;
typedef BOOL (__stdcall *REBASEIMAGE64) ( IN PSTR CurrentImageName, IN PSTR SymbolPath, IN BOOL fReBase, // TRUE if actually rebasing, false if only summing
IN BOOL fRebaseSysfileOk, // TRUE is system images s/b rebased
IN BOOL fGoingDown, // TRUE if the image s/b rebased below the given base
IN ULONG CheckImageSize, // Max size allowed (0 if don't care)
OUT ULONG *OldImageSize, // Returned from the header
OUT ULONG64 *OldImageBase, // Returned from the header
OUT ULONG *NewImageSize, // Image size rounded to next separation boundary
IN OUT ULONG64 *NewImageBase, // (in) Desired new address.
// (out) Next address (actual if going down)
IN ULONG TimeStamp // new timestamp for image, if non-zero
);
REBASEIMAGE64 pReBaseImage64;
UCHAR ImagesRoot[ MAX_PATH+1 ]; PCHAR SymbolPath; UCHAR DebugFilePath[ MAX_PATH+1 ];
ULONG64 OriginalImageBase; ULONG OriginalImageSize; ULONG64 NewImageBase; ULONG NewImageSize;
ULONG64 InitialBase = 0; ULONG64 MinBase = (~((ULONG64)0)); ULONG64 TotalSize;
ULONG SizeAdjustment;
int __cdecl main( int argc, char *argv[], char *envp[] ) {
char chChar, *pchChar; envp; _tzset();
pgnIgnoreListHdr = (PGROUPNODE) malloc( sizeof ( GROUPNODE ) ); pgnIgnoreListHdr->chName = NULL; pgnIgnoreListHdr->pgnNext = NULL; pgnIgnoreListEnd = pgnIgnoreListHdr;
pReBaseImage64 = (REBASEIMAGE64) GetProcAddress(GetModuleHandle("imagehlp.dll"), "ReBaseImage64"); if (!pReBaseImage64) { puts("REBASE: Warning\n" "REBASE: Warning - unable to correctly rebase 64-bit images - update your imagehlp.dll\n" "REBASE: Warning"); pReBaseImage64 = (REBASEIMAGE64) GetProcAddress(GetModuleHandle("imagehlp.dll"), "ReBaseImage"); }
fVerbose = FALSE; fQuiet = FALSE; fGoingDown = FALSE; fSumOnly = FALSE; fRebaseSysfileOk = FALSE; fShowAllBases = FALSE;
ImagesRoot[ 0 ] = '\0';
if (argc <= 1) { ShowUsage(); }
while (--argc) { pchChar = *++argv; if (*pchChar == '/' || *pchChar == '-') { while (chChar = *++pchChar) { ParseSwitch( chChar, &argc, &argv ); } } else { if (*pchChar == '@') { // Inline response file with a list of files to rebase.
FILE *hFiles =fopen(pchChar+1, "rt"); int ScanRet; CHAR pchFileName[_MAX_PATH]; if (hFiles == NULL) { fprintf( stderr, "REBASE: fopen %s failed %d\n", pchChar+1, errno ); ExitProcess( REBASE_ERR ); }
ScanRet = fscanf( hFiles, "%s", pchFileName ); while (ScanRet && ScanRet != EOF) { if ( !FindInIgnoreList( pchFileName ) ) { ReBaseFile( pchFileName, TRUE ); } ScanRet = fscanf( hFiles, "%s", pchFileName ); } fclose(hFiles); } else { if ( !FindInIgnoreList( pchChar ) ) { ReBaseFile( pchChar, TRUE ); } } } }
if ( !fQuiet ) {
if ( BaseAddrFile ) { InitialBase = MinBase; }
if ( fGoingDown ) { TotalSize = InitialBase - NewImageBase; } else { TotalSize = NewImageBase - InitialBase; }
fprintf( stdout, "\n" ); fprintf( stdout, "REBASE: Total Size of mapping 0x%016I64x\n", TotalSize ); fprintf( stdout, "REBASE: Range 0x%016I64x -0x%016I64x\n", min(NewImageBase, InitialBase), max(NewImageBase, InitialBase));
if (RebaseLog) { fprintf( RebaseLog, "\nTotal Size of mapping 0x%016I64x\n", TotalSize ); fprintf( RebaseLog, "Range 0x%016I64x -0x%016I64x\n\n", min(NewImageBase, InitialBase), max(NewImageBase, InitialBase)); } }
if (RebaseLog) { fclose(RebaseLog); }
if (BaseAddrFile){ fclose(BaseAddrFile); }
if (CoffBaseDotTxt){ fclose(CoffBaseDotTxt); }
return ReturnCode; }
VOID ShowUsage( VOID ) { fputs( "usage: REBASE [switches]\n" " [-R image-root [-G filename] [-O filename] [-N filename]]\n" " image-names... \n" "\n" " One of -b and -i switches are mandatory.\n" "\n" " [-a] Does nothing\n" " [-b InitialBase] specify initial base address\n" " [-c coffbase_filename] generate coffbase.txt\n" " -C includes filename extensions, -c does not\n" " [-d] top down rebase\n" " [-e SizeAdjustment] specify extra size to allow for image growth\n" " [-f] Strip relocs after rebasing the image\n" " [-i coffbase_filename] get base addresses from coffbase_filename\n" " [-l logFilePath] write image bases to log file.\n" " [-p] Does nothing\n" " [-q] minimal output\n" " [-s] just sum image range\n" " [-u symbol_dir] Update debug info in .DBG along this path\n" " [-v] verbose output\n" " [-x symbol_dir] Same as -u\n" " [-z] allow system file rebasing\n" " [-?] display this message\n" "\n" " [-R image_root] set image root for use by -G, -O, -N\n" " [-G filename] group images together in address space\n" " [-O filename] overlay images in address space\n" " [-N filename] leave images at their origional address\n" " -G, -O, -N, may occur multiple times. File \"filename\"\n" " contains a list of files (relative to \"image-root\")\n" , stderr );
exit( REBASE_ERR ); }
VOID ParseSwitch( CHAR chSwitch, int *pArgc, char **pArgv[] ) {
switch (toupper( chSwitch )) {
case '?': ShowUsage(); break;
case 'A': break;
case 'B': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; if (sscanf(**pArgv, "%I64x", &InitialBase) == 1) { NewImageBase = InitialBase; } break;
case 'C': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; fCoffBaseIncExt = (chSwitch == 'C'); CoffBaseDotTxt = fopen( *(*pArgv), "at" ); if ( !CoffBaseDotTxt ) { fprintf( stderr, "REBASE: fopen %s failed %d\n", *(*pArgv), errno ); ExitProcess( REBASE_ERR ); } break;
case 'D': fGoingDown = TRUE; break;
case 'E': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; if (sscanf(**pArgv, "%x", &SizeAdjustment) != 1) { ShowUsage(); } break;
case 'F': fRemoveRelocs = TRUE; break;
case 'G': case 'O': case 'N': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; if (!ImagesRoot[0]) { fprintf( stderr, "REBASE: -R must preceed -%c\n", chSwitch ); exit( REBASE_ERR ); } ProcessGroupList( (PCHAR) ImagesRoot, *(*pArgv), toupper(chSwitch) != 'N', toupper(chSwitch) == 'O'); break;
case 'I': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; BaseAddrFileName = *(*pArgv); BaseAddrFile = fopen( *(*pArgv), "rt" ); if ( !BaseAddrFile ) { fprintf( stderr, "REBASE: fopen %s failed %d\n", *(*pArgv), errno ); ExitProcess( REBASE_ERR ); } break;
case 'L': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; RebaseLog = fopen( *(*pArgv), "at" ); if ( !RebaseLog ) { fprintf( stderr, "REBASE: fopen %s failed %d\n", *(*pArgv), errno ); ExitProcess( REBASE_ERR ); } break;
case 'P': break;
case 'Q': fQuiet = TRUE; break;
case 'R': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; strcpy( (PCHAR) ImagesRoot, *(*pArgv) ); break;
case 'S': fprintf(stdout,"\n"); fSumOnly = TRUE; break;
case 'U': case 'X': if (!--(*pArgc)) { ShowUsage(); } (*pArgv)++; fUpdateSymbolsOnly = TRUE; SymbolPath = **pArgv; break;
case 'V': fVerbose = TRUE; break;
case 'Z': fRebaseSysfileOk = TRUE; break;
default: fprintf( stderr, "REBASE: Invalid switch - /%c\n", chSwitch ); ShowUsage(); break;
} }
BOOL ProcessGroupList( LPSTR ImagesRoot, LPSTR GroupListFName, BOOL fReBase, BOOL fOverlay ) {
PGROUPNODE pgn; FILE *GroupList;
CHAR chName[MAX_PATH+1]; int ateof; ULONG64 SavedImageBase; ULONG MaxImageSize=0;
DWORD dw; CHAR Buffer[ MAX_PATH+1 ]; LPSTR FilePart;
if (RebaseLog) { fprintf( RebaseLog, "*** %s\n", GroupListFName ); }
GroupList = fopen( GroupListFName, "rt" ); if ( !GroupList ) { fprintf( stderr, "REBASE: fopen %s failed %d\n", GroupListFName, errno ); ExitProcess( REBASE_ERR ); }
ateof = fscanf( GroupList, "%s", chName );
SavedImageBase = NewImageBase;
while ( ateof && ateof != EOF ) {
dw = SearchPath( ImagesRoot, chName, NULL, sizeof(Buffer), Buffer, &FilePart ); if ( dw == 0 || dw > sizeof( Buffer ) ) { if (!fQuiet) { fprintf( stderr, "REBASE: Could Not Find %s\\%s\n", ImagesRoot, chName ); } } else {
_strlwr( Buffer ); // Lowercase for consistency when displayed.
pgn = (PGROUPNODE) malloc( sizeof( GROUPNODE ) ); if ( NULL == pgn ) { fprintf( stderr, "REBASE: *** malloc failed.\n" ); ExitProcess( REBASE_ERR ); } pgn->chName = _strdup( Buffer ); if ( NULL == pgn->chName ) { fprintf( stderr, "REBASE: *** strdup failed (%s).\n", Buffer ); ExitProcess( REBASE_ERR ); } pgn->pgnNext = NULL; pgnIgnoreListEnd->pgnNext = pgn; pgnIgnoreListEnd = pgn;
ReBaseFile( Buffer, fReBase );
if ( fOverlay ) { if ( MaxImageSize < NewImageSize ) { MaxImageSize = NewImageSize; } NewImageBase = SavedImageBase; } }
ateof = fscanf( GroupList, "%s", chName ); }
fclose( GroupList );
if ( fOverlay ) { if ( fGoingDown ) { NewImageBase -= ROUND_UP( MaxImageSize, IMAGE_SEPARATION ); } else { NewImageBase += ROUND_UP( MaxImageSize, IMAGE_SEPARATION ); } }
if (RebaseLog) { fprintf( RebaseLog, "\n" ); }
return TRUE; }
BOOL FindInIgnoreList( LPSTR chName ) { PGROUPNODE pgn;
DWORD dw; CHAR Buffer[ MAX_PATH+1 ]; LPSTR FilePart;
dw = GetFullPathName( chName, sizeof(Buffer), Buffer, &FilePart ); if ( dw == 0 || dw > sizeof( Buffer ) ) { fprintf( stderr, "REBASE: *** GetFullPathName failed (%s).\n", chName ); ExitProcess( REBASE_ERR ); }
for (pgn = pgnIgnoreListHdr->pgnNext; pgn != NULL; pgn = pgn->pgnNext) {
if (!_stricmp( Buffer, pgn->chName ) ) { return TRUE; }
}
return FALSE; }
/////////////////////////////////////////////////////////////////////////////
/*
****************************************************************************** On a Hydra System, we don't want imaghlp.dll to load user32.dll since it prevents CSRSS from exiting when running a under a debugger. The following function has been copied from user32.dll so that we don't link to user32.dll. ****************************************************************************** */
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
VOID ReBaseFile( LPSTR CurrentImageName, BOOL fReBase ) { DWORD dw; CHAR Buffer[ MAX_PATH+1 ]; CHAR Buffer2[ MAX_PATH+1 ]; LPSTR FilePart; LPSTR LocalSymbolPath; ULONG ThisImageExpectedSize = 0; ULONG64 ThisImageRequestedBase = NewImageBase; ULONG TimeStamp; static char LastName = '\0'; static ULONG LastTimeStamp = 0; BOOL FirstPass = TRUE;
if ( !InitialBase && !BaseAddrFile ) { fprintf( stderr, "REBASE: -b switch must specify a non-zero base --or--\n" ); fprintf( stderr, " -i must specify a filename\n" ); exit( REBASE_ERR ); }
if ( BaseAddrFile && ( InitialBase || fGoingDown || CoffBaseDotTxt ) ) { fprintf( stderr, "REBASE: -i is incompatible with -b, -d, and -c\n" ); exit( REBASE_ERR ); }
dw = GetFullPathName( CurrentImageName, sizeof(Buffer), Buffer, &FilePart ); if ( dw == 0 || dw > sizeof(Buffer) ) { FilePart = CurrentImageName; } _strlwr( FilePart ); // Lowercase for consistency when displayed.
if ( BaseAddrFile && !(NewImageBase = ThisImageRequestedBase = FindInBaseAddrFile( FilePart, &ThisImageExpectedSize )) ) { fprintf( stdout, "REBASE: %-16s Not listed in %s\n", FilePart, BaseAddrFileName ); }
if (fUpdateSymbolsOnly) { // On update, the symbol path is a semi-colon delimited path. Find the one we want and
// then fix the path for RebaseImage.
HANDLE hDebugFile; CHAR Drive[_MAX_DRIVE]; CHAR Dir[_MAX_DIR]; PCHAR s; hDebugFile = FindDebugInfoFile(CurrentImageName, SymbolPath, DebugFilePath); if ( hDebugFile ) { CloseHandle(hDebugFile); _splitpath(DebugFilePath, Drive, Dir, NULL, NULL); _makepath(Buffer2, Drive, Dir, NULL, NULL); s = Buffer2 + strlen(Buffer2); s = CharPrev(Buffer2, s); if (*s == '\\') { *s = '\0'; } LocalSymbolPath = Buffer2; } else { LocalSymbolPath = NULL; } } else { LocalSymbolPath = SymbolPath; }
NewImageSize = (ULONG) -1; // Hack so we can tell when system images are skipped.
time( (time_t *) &TimeStamp );
// Ensure all images with the same first letter have unique timestamps.
if (!LastTimeStamp) LastTimeStamp = TimeStamp;
if (LastName == *FilePart) { TimeStamp = LastTimeStamp++; } else { LastTimeStamp = TimeStamp; LastName = *FilePart; }
RebaseAgain:
if (!(*pReBaseImage64)( CurrentImageName, (PCHAR) LocalSymbolPath, fReBase && !fSumOnly, fRebaseSysfileOk, fGoingDown, ThisImageExpectedSize, &OriginalImageSize, &OriginalImageBase, &NewImageSize, &ThisImageRequestedBase, TimeStamp ) ) {
if (ThisImageRequestedBase == 0) { fprintf(stderr, "REBASE: %-16s ***Grew too large (Size=0x%x; ExpectedSize=0x%x)\n", FilePart, OriginalImageSize, ThisImageExpectedSize); } else { if (GetLastError() == ERROR_BAD_EXE_FORMAT) { if (fVerbose) { fprintf( stderr, "REBASE: %-16s DOS or OS/2 image ignored\n", FilePart ); } } else if (GetLastError() == ERROR_INVALID_ADDRESS) { fprintf( stderr, "REBASE: %-16s Rebase failed. Relocations are missing or new address is invalid\n", FilePart ); if (RebaseLog) { fprintf( RebaseLog, "%16s based at 0x%016I64x (size 0x%08x) Unable to rebase. (missing relocations or new address is invalid)\n", FilePart, OriginalImageBase, OriginalImageSize); } } else { fprintf( stderr, "REBASE: *** RelocateImage failed (%s). Image may be corrupted\n", FilePart ); } }
ReturnCode = REBASE_ERR; return;
} else { if (GetLastError() == ERROR_INVALID_DATA) { fprintf(stderr, "REBASE: Warning: DBG checksum did not match image.\n"); } }
// Keep track of the lowest base address.
if (MinBase > NewImageBase) { MinBase = NewImageBase; }
if ( fSumOnly || !fReBase ) { if (!fQuiet) { fprintf( stdout, "REBASE: %16s mapped at %016I64x (size 0x%08x)\n", FilePart, OriginalImageBase, OriginalImageSize); } } else { if (SizeAdjustment && FirstPass && (NewImageSize != (ULONG) -1)) { if ((OriginalImageSize + SizeAdjustment) > NewImageSize) { // If we were to add SizeAdjustment to the image (say as a ServicePack or QFE fix), we'd blow
// out our space. Make room so this isn't necessary.
if (fGoingDown) { // Going down - the requested base is where we need our image
// to end - adjust it down so we have room to grow and go again.
FirstPass = FALSE; NewImageBase -= IMAGE_SEPARATION; ThisImageRequestedBase = NewImageBase; goto RebaseAgain; } else { // Going up. Move the next guy up so we can grow.
ThisImageRequestedBase += IMAGE_SEPARATION; } } } if (RebaseLog) { fprintf( RebaseLog, "%16s rebased to 0x%016I64x (size 0x%08x)\n", FilePart, fGoingDown ? ThisImageRequestedBase : NewImageBase, NewImageSize); }
if ((NewImageSize != (ULONG) -1) && (OriginalImageBase != (fGoingDown ? ThisImageRequestedBase : NewImageBase)) && ( fVerbose || fQuiet ) ) { if ( fVerbose ) { fprintf( stdout, "REBASE: %16s initial base at 0x%016I64x (size 0x%08x)\n", FilePart, OriginalImageBase, OriginalImageSize); }
fprintf( stdout, "REBASE: %16s rebased to 0x%016I64x (size 0x%08x)\n", FilePart, fGoingDown ? ThisImageRequestedBase : NewImageBase, NewImageSize);
if ( fVerbose && fUpdateSymbolsOnly && DebugFilePath[0]) { char szExt[_MAX_EXT]; _splitpath(DebugFilePath, NULL, NULL, NULL, szExt); if (_stricmp(szExt, ".pdb")) { fprintf( stdout, "REBASE: %16s updated image base in %s\n", FilePart, DebugFilePath ); } } }
if (fRemoveRelocs) { RemoveRelocations(CurrentImageName); } }
if ( CoffBaseDotTxt ) { if ( !fCoffBaseIncExt ) { char *n; if ( n = strrchr(FilePart,'.') ) { *n = '\0'; } }
fprintf( CoffBaseDotTxt, "%-16s 0x%016I64x 0x%08x\n", FilePart, fSumOnly ? OriginalImageBase : (fGoingDown ? ThisImageRequestedBase : NewImageBase), NewImageSize); }
NewImageBase = ThisImageRequestedBase; // Set up the next one...
}
ULONG64 FindInBaseAddrFile( LPSTR Name, PULONG pulSize ) {
struct { CHAR Name[MAX_PATH+1]; ULONG64 Base; ULONG Size; } BAFileEntry;
CHAR NameNoExt[MAX_PATH+1]; // PCHAR pchExt;
int ateof;
strcpy(NameNoExt,Name); // if (pchExt = strrchr(NameNoExt,'.')) {
// *pchExt = '\0';
// }
if (fseek(BaseAddrFile, 0, SEEK_SET)) { return 0; }
ateof = fscanf(BaseAddrFile,"%s %I64x %x",BAFileEntry.Name,&BAFileEntry.Base,&BAFileEntry.Size); while ( ateof && ateof != EOF ) { if ( !_stricmp(NameNoExt,BAFileEntry.Name) ) { *pulSize = BAFileEntry.Size; return BAFileEntry.Base; } ateof = fscanf(BaseAddrFile,"%s %I64x %x",BAFileEntry.Name,&BAFileEntry.Base,&BAFileEntry.Size); }
*pulSize = 0; return 0; }
VOID RemoveRelocations( PCHAR ImageName ) { // UnSafe...
LOADED_IMAGE li; IMAGE_SECTION_HEADER RelocSectionHdr, *Section, *pRelocSecHdr; PIMAGE_DEBUG_DIRECTORY DebugDirectory; ULONG DebugDirectorySize, i, RelocSecNum; PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL; PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL; PIMAGE_FILE_HEADER FileHeader;
if (!MapAndLoad(ImageName, NULL, &li, FALSE, FALSE)) { return; }
FileHeader = &li.FileHeader->FileHeader;
OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)li.FileHeader, &OptionalHeader32, &OptionalHeader64); if (!OptionalHeader32 && !OptionalHeader64) return;
// See if the image has already been stripped or there are no relocs.
if ((FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || (!OPTIONALHEADER(DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size))) { UnMapAndLoad(&li); return; }
for (Section = li.Sections, i = 0; i < li.NumberOfSections; Section++, i++) { if (Section->PointerToRawData != 0) { if (!_stricmp( (char *) Section->Name, ".reloc" )) { RelocSectionHdr = *Section; pRelocSecHdr = Section; RelocSecNum = i + 1; } } }
RelocSectionHdr.Misc.VirtualSize = ROUNDUP(RelocSectionHdr.Misc.VirtualSize, OPTIONALHEADER(SectionAlignment)); RelocSectionHdr.SizeOfRawData = ROUNDUP(RelocSectionHdr.SizeOfRawData, OPTIONALHEADER(FileAlignment));
if (RelocSecNum != li.NumberOfSections) { // Move everything else up and fixup old addresses.
for (i = RelocSecNum - 1, Section = pRelocSecHdr;i < li.NumberOfSections - 1; Section++, i++) { *Section = *(Section + 1); Section->VirtualAddress -= RelocSectionHdr.Misc.VirtualSize; Section->PointerToRawData -= RelocSectionHdr.SizeOfRawData; } }
// Zero out the last one.
RtlZeroMemory(Section, sizeof(IMAGE_SECTION_HEADER));
// Reduce the section count.
FileHeader->NumberOfSections--;
// Set the strip bit in the header
FileHeader->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
// If there's a pointer to the coff symbol table, move it back.
if (FileHeader->PointerToSymbolTable) { FileHeader->PointerToSymbolTable -= RelocSectionHdr.SizeOfRawData; }
// Clear out the base reloc entry in the data dir.
OPTIONALHEADER_LV(DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) = 0; OPTIONALHEADER_LV(DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) = 0;
// Reduce the Init Data size.
OPTIONALHEADER_LV(SizeOfInitializedData) -= RelocSectionHdr.Misc.VirtualSize;
// Reduce the image size.
OPTIONALHEADER_LV(SizeOfImage) -= ((RelocSectionHdr.SizeOfRawData + (OPTIONALHEADER(SectionAlignment) - 1) ) & ~(OPTIONALHEADER(SectionAlignment) - 1));
// Move the debug info up (if there is any).
DebugDirectory = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData( li.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &DebugDirectorySize ); if (DebugDirectoryIsUseful(DebugDirectory, DebugDirectorySize)) { for (i = 0; i < (DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY)); i++) { RtlMoveMemory(li.MappedAddress + DebugDirectory->PointerToRawData - RelocSectionHdr.SizeOfRawData, li.MappedAddress + DebugDirectory->PointerToRawData, DebugDirectory->SizeOfData);
DebugDirectory->PointerToRawData -= RelocSectionHdr.SizeOfRawData;
if (DebugDirectory->AddressOfRawData) { DebugDirectory->AddressOfRawData -= RelocSectionHdr.Misc.VirtualSize; }
DebugDirectory++; } }
// Truncate the image size
li.SizeOfImage -= RelocSectionHdr.SizeOfRawData;
// And we're done.
UnMapAndLoad(&li); }
|